diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 10:54:16 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 10:54:16 +0000 |
commit | 485f6ecd453d8a2fd8b9b9fadea03159d8b50797 (patch) | |
tree | 32451fa3cdd9321fb2591fada9891b2cb70a9cd1 /grub-core/lib | |
parent | Initial commit. (diff) | |
download | grub2-upstream.tar.xz grub2-upstream.zip |
Adding upstream version 2.06.upstream/2.06upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'grub-core/lib')
653 files changed, 218382 insertions, 0 deletions
diff --git a/grub-core/lib/LzFind.c b/grub-core/lib/LzFind.c new file mode 100644 index 0000000..dcb20d9 --- /dev/null +++ b/grub-core/lib/LzFind.c @@ -0,0 +1,777 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (c) 1999-2008 Igor Pavlov + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * This code was taken from LZMA SDK 4.58 beta, and was slightly modified + * to adapt it to GRUB's requirement. + * + * See <http://www.7-zip.org>, for more information about LZMA. + */ + + +#include <config.h> + +#include <string.h> + +#include <grub/lib/LzFind.h> +#include <grub/lib/LzHash.h> + +#define kEmptyHashValue 0 +#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) +#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ +#define kNormalizeMask (~(kNormalizeStepMin - 1)) +#define kMaxHistorySize ((UInt32)3 << 30) + +#define kStartMaxLen 3 + +static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + if (!p->directInput) + { + alloc->Free(alloc, p->bufferBase); + p->bufferBase = 0; + } +} + +/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ + +static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) +{ + UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; + if (p->directInput) + { + p->blockSize = blockSize; + return 1; + } + if (p->bufferBase == 0 || p->blockSize != blockSize) + { + LzInWindow_Free(p, alloc); + p->blockSize = blockSize; + p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); + } + return (p->bufferBase != 0); +} + +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +static Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 curindex) { return p->buffer[curindex]; } + +static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } + +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) +{ + p->posLimit -= subValue; + p->pos -= subValue; + p->streamPos -= subValue; +} + +static void MatchFinder_ReadBlock(CMatchFinder *p) +{ + if (p->streamEndWasReached || p->result != SZ_OK) + return; + for (;;) + { + Byte *dest = p->buffer + (p->streamPos - p->pos); + size_t size = (p->bufferBase + p->blockSize - dest); + if (size == 0) + return; + p->result = p->stream->Read(p->stream, dest, &size); + if (p->result != SZ_OK) + return; + if (size == 0) + { + p->streamEndWasReached = 1; + return; + } + p->streamPos += (UInt32)size; + if (p->streamPos - p->pos > p->keepSizeAfter) + return; + } +} + +void MatchFinder_MoveBlock(CMatchFinder *p) +{ + memmove(p->bufferBase, + p->buffer - p->keepSizeBefore, + (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); + p->buffer = p->bufferBase + p->keepSizeBefore; +} + +int MatchFinder_NeedMove(CMatchFinder *p) +{ + /* if (p->streamEndWasReached) return 0; */ + return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); +} + +void MatchFinder_ReadIfRequired(CMatchFinder *p) +{ + if (p->streamEndWasReached) + return; + if (p->keepSizeAfter >= p->streamPos - p->pos) + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) +{ + if (MatchFinder_NeedMove(p)) + MatchFinder_MoveBlock(p); + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_SetDefaultSettings(CMatchFinder *p) +{ + p->cutValue = 32; + p->btMode = 1; + p->numHashBytes = 4; + /* p->skipModeBits = 0; */ + p->directInput = 0; + p->bigHash = 0; +} + +#define kCrcPoly 0xEDB88320 + +void MatchFinder_Construct(CMatchFinder *p) +{ + UInt32 i; + p->bufferBase = 0; + p->directInput = 0; + p->hash = 0; + MatchFinder_SetDefaultSettings(p); + + for (i = 0; i < 256; i++) + { + UInt32 r = i; + int j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); + p->crc[i] = r; + } +} + +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->hash); + p->hash = 0; +} + +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + MatchFinder_FreeThisClassMemory(p, alloc); + LzInWindow_Free(p, alloc); +} + +static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) +{ + size_t sizeInBytes = (size_t)num * sizeof(CLzRef); + if (sizeInBytes / sizeof(CLzRef) != num) + return 0; + return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); +} + +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc) +{ + UInt32 sizeReserv; + if (historySize > kMaxHistorySize) + { + MatchFinder_Free(p, alloc); + return 0; + } + sizeReserv = historySize >> 1; + if (historySize > ((UInt32)2 << 30)) + sizeReserv = historySize >> 2; + sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); + + p->keepSizeBefore = historySize + keepAddBufferBefore + 1; + p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; + /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ + if (LzInWindow_Create(p, sizeReserv, alloc)) + { + UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; + UInt32 hs; + p->matchMaxLen = matchMaxLen; + { + p->fixedHashSize = 0; + if (p->numHashBytes == 2) + hs = (1 << 16) - 1; + else + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + /* hs >>= p->skipModeBits; */ + hs |= 0xFFFF; /* don't change it! It's required for Deflate */ + if (hs > (1 << 24)) + { + if (p->numHashBytes == 3) + hs = (1 << 24) - 1; + else + hs >>= 1; + } + } + p->hashMask = hs; + hs++; + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; + if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; + if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; + hs += p->fixedHashSize; + } + + { + UInt32 prevSize = p->hashSizeSum + p->numSons; + UInt32 newSize; + p->historySize = historySize; + p->hashSizeSum = hs; + p->cyclicBufferSize = newCyclicBufferSize; + p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); + newSize = p->hashSizeSum + p->numSons; + if (p->hash != 0 && prevSize == newSize) + return 1; + MatchFinder_FreeThisClassMemory(p, alloc); + p->hash = AllocRefs(newSize, alloc); + if (p->hash != 0) + { + p->son = p->hash + p->hashSizeSum; + return 1; + } + } + } + MatchFinder_Free(p, alloc); + return 0; +} + +static void MatchFinder_SetLimits(CMatchFinder *p) +{ + UInt32 limit = kMaxValForNormalize - p->pos; + UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; + if (limit2 < limit) + limit = limit2; + limit2 = p->streamPos - p->pos; + if (limit2 <= p->keepSizeAfter) + { + if (limit2 > 0) + limit2 = 1; + } + else + limit2 -= p->keepSizeAfter; + if (limit2 < limit) + limit = limit2; + { + UInt32 lenLimit = p->streamPos - p->pos; + if (lenLimit > p->matchMaxLen) + lenLimit = p->matchMaxLen; + p->lenLimit = lenLimit; + } + p->posLimit = p->pos + limit; +} + +void MatchFinder_Init(CMatchFinder *p) +{ + UInt32 i; + for(i = 0; i < p->hashSizeSum; i++) + p->hash[i] = kEmptyHashValue; + p->cyclicBufferPos = 0; + p->buffer = p->bufferBase; + p->pos = p->streamPos = p->cyclicBufferSize; + p->result = SZ_OK; + p->streamEndWasReached = 0; + MatchFinder_ReadBlock(p); + MatchFinder_SetLimits(p); +} + +static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) +{ + return (p->pos - p->historySize - 1) & kNormalizeMask; +} + +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) +{ + UInt32 i; + for (i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } +} + +static void MatchFinder_Normalize(CMatchFinder *p) +{ + UInt32 subValue = MatchFinder_GetSubValue(p); + MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); + MatchFinder_ReduceOffsets(p, subValue); +} + +static void MatchFinder_CheckLimits(CMatchFinder *p) +{ + if (p->pos == kMaxValForNormalize) + MatchFinder_Normalize(p); + if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) + MatchFinder_CheckAndMoveAndRead(p); + if (p->cyclicBufferPos == p->cyclicBufferSize) + p->cyclicBufferPos = 0; + MatchFinder_SetLimits(p); +} + +static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + son[_cyclicBufferPos] = curMatch; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + return distances; + { + const Byte *pb = cur - delta; + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; + if (pb[maxLen] == cur[maxLen] && *pb == *cur) + { + UInt32 len = 0; + while(++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + return distances; + } + } + } + } +} + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return distances; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while(++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return distances; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + while(++len != lenLimit) + if (pb[len] != cur[len]) + break; + { + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +#define MOVE_POS \ + ++p->cyclicBufferPos; \ + p->buffer++; \ + if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); + +#define MOVE_POS_RET MOVE_POS return offset; + +static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } + +#define GET_MATCHES_HEADER2(minLen, ret_op) \ + UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ + lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ + cur = p->buffer; + +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) +#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) + +#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue + +#define GET_MATCHES_FOOTER(offset, maxLen) \ + offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ + distances + offset, maxLen) - distances); MOVE_POS_RET; + +#define SKIP_FOOTER \ + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; + +static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 1) +} + +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 2) +} + +static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, delta2, maxLen, offset; + GET_MATCHES_HEADER(3) + + HASH3_CALC; + + delta2 = p->pos - p->hash[hash2Value]; + curMatch = p->hash[kFix3HashSize + hashValue]; + + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + + + maxLen = 2; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[0] = maxLen; + distances[1] = delta2 - 1; + offset = 2; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances + offset, maxLen) - (distances)); + MOVE_POS_RET +} + +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances, 2) - (distances)); + MOVE_POS_RET +} + +static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value; + SKIP_HEADER(3) + HASH3_CALC; + curMatch = p->hash[kFix3HashSize + hashValue]; + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = p->pos; + p->hash[kFix4HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinder_Init; + vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; + if (!p->btMode) + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; + } + else if (p->numHashBytes == 2) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; + } + else if (p->numHashBytes == 3) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; + } + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; + } +} diff --git a/grub-core/lib/LzmaDec.c b/grub-core/lib/LzmaDec.c new file mode 100644 index 0000000..952edb3 --- /dev/null +++ b/grub-core/lib/LzmaDec.c @@ -0,0 +1,1037 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (c) 1999-2008 Igor Pavlov + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * This code was taken from LZMA SDK 4.58 beta, and was slightly modified + * to adapt it to GRUB's requirement. + * + * See <http://www.7-zip.org>, for more information about LZMA. + */ + +#include <grub/lib/LzmaDec.h> + +#pragma GCC diagnostic ignored "-Wshadow" +#include <grub/misc.h> +#define memcpy grub_memcpy + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_INIT_SIZE 5 + +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ + { UPDATE_0(p); i = (i + i); A0; } else \ + { UPDATE_1(p); i = (i + i) + 1; A1; } +#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) + +#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } +#define TREE_DECODE(probs, limit, i) \ + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } + +/* #define _LZMA_SIZE_OPT */ + +#ifdef _LZMA_SIZE_OPT +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +#else +#define TREE_6_DECODE(probs, i) \ + { i = 1; \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + i -= 0x40; } +#endif + +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0_CHECK range = bound; +#define UPDATE_1_CHECK range -= bound; code -= bound; +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ + { UPDATE_0_CHECK; i = (i + i); A0; } else \ + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +#define TREE_DECODE_CHECK(probs, limit, i) \ + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while(i < limit); i -= limit; } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +/* +#define LZMA_STREAM_WAS_FINISHED_ID (-1) +#define LZMA_SPEC_LEN_OFFSET (-3) +*/ + +Byte kLiteralNextStates[kNumStates * 2] = +{ + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, + 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 +}; + +#define LZMA_DIC_MIN (1 << 12) + +/* First LZMA-symbol is always decoded. +And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization +Out: + Result: + 0 - OK + 1 - Error + p->remainLen: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished + = kMatchSpecLenStart + 1 : Flush marker + = kMatchSpecLenStart + 2 : State Init Marker +*/ + +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = p->probs; + + unsigned state = p->state; + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; + unsigned lc = p->prop.lc; + + Byte *dic = p->dic; + SizeT dicBufSize = p->dicBufSize; + SizeT dicPos = p->dicPos; + + UInt32 processedPos = p->processedPos; + UInt32 checkDicSize = p->checkDicSize; + unsigned len = 0; + + const Byte *buf = p->buf; + UInt32 range = p->range; + UInt32 code = p->code; + + do + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = processedPos & pbMask; + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (checkDicSize != 0 || processedPos != 0) + prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); + + if (state < kNumLitStates) + { + symbol = 1; + do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + unsigned offs = 0x100; + symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + dic[dicPos++] = (Byte)symbol; + processedPos++; + + state = kLiteralNextStates[state]; + /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ + continue; + } + else + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + if (checkDicSize == 0 && processedPos == 0) + return SZ_ERROR_DATA; + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + UPDATE_0(prob); + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + processedPos++; + state = state < kNumLitStates ? 9 : 11; + continue; + } + UPDATE_1(prob); + } + else + { + UInt32 distance; + UPDATE_1(prob); + prob = probs + IsRepG1 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep1; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG2 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep2; + } + else + { + UPDATE_1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = (1 << kLenNumMidBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, limit, len); + len += offset; + } + + if (state >= kNumStates) + { + UInt32 distance; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + TREE_6_DECODE(prob, distance); + if (distance >= kStartPosModelIndex) + { + unsigned posSlot = (unsigned)distance; + int numDirectBits = (int)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos + distance - posSlot - 1; + { + UInt32 mask = 1; + unsigned i = 1; + do + { + GET_BIT2(prob + i, i, ; , distance |= mask); + mask <<= 1; + } + while(--numDirectBits != 0); + } + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE + range >>= 1; + + { + UInt32 t; + code -= range; + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ + distance = (distance << 1) + (t + 1); + code += range & t; + } + /* + distance <<= 1; + if (code >= range) + { + code -= range; + distance |= 1; + } + */ + } + while (--numDirectBits != 0); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + GET_BIT2(prob + i, i, ; , distance |= 1); + GET_BIT2(prob + i, i, ; , distance |= 2); + GET_BIT2(prob + i, i, ; , distance |= 4); + GET_BIT2(prob + i, i, ; , distance |= 8); + } + if (distance == (UInt32)0xFFFFFFFF) + { + len += kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + if (checkDicSize == 0) + { + if (distance >= processedPos) + return SZ_ERROR_DATA; + } + else if (distance >= checkDicSize) + return SZ_ERROR_DATA; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + /* state = kLiteralNextStates[state]; */ + } + + len += kMatchMinLen; + + { + SizeT rem = limit - dicPos; + unsigned curLen = ((rem < len) ? (unsigned)rem : len); + SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); + + processedPos += curLen; + + len -= curLen; + if (pos + curLen <= dicBufSize) + { + Byte *dest = dic + dicPos; + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + const Byte *lim = dest + curLen; + dicPos += curLen; + do + *(dest) = (Byte)*(dest + src); + while (++dest != lim); + } + else + { + do + { + dic[dicPos++] = dic[pos]; + if (++pos == dicBufSize) + pos = 0; + } + while (--curLen != 0); + } + } + } + } + while (dicPos < limit && buf < bufLimit); + NORMALIZE; + p->buf = buf; + p->range = range; + p->code = code; + p->remainLen = len; + p->dicPos = dicPos; + p->processedPos = processedPos; + p->reps[0] = rep0; + p->reps[1] = rep1; + p->reps[2] = rep2; + p->reps[3] = rep3; + p->state = state; + + return SZ_OK; +} + +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +{ + if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + { + Byte *dic = p->dic; + SizeT dicPos = p->dicPos; + SizeT dicBufSize = p->dicBufSize; + unsigned len = p->remainLen; + UInt32 rep0 = p->reps[0]; + if (limit - dicPos < len) + len = (unsigned)(limit - dicPos); + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += len; + p->remainLen -= len; + while (len-- != 0) + { + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + } + p->dicPos = dicPos; + } +} + +/* LzmaDec_DecodeReal2 decodes LZMA-symbols and sets p->needFlush and p->needInit, if required. */ + +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + do + { + SizeT limit2 = limit; + if (p->checkDicSize == 0) + { + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit2 = p->dicPos + rem; + } + RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); + if (p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + LzmaDec_WriteRem(p, limit); + } + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); + + if (p->remainLen > kMatchSpecLenStart) + { + p->remainLen = kMatchSpecLenStart; + } + return 0; +} + +typedef enum +{ + DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_LIT, + DUMMY_MATCH, + DUMMY_REP +} ELzmaDummy; + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) +{ + UInt32 range = p->range; + UInt32 code = p->code; + const Byte *bufLimit = buf + inSize; + CLzmaProb *probs = p->probs; + unsigned state = p->state; + ELzmaDummy res; + + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK + + /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ + + prob = probs + Literal; + if (p->checkDicSize != 0 || p->processedPos != 0) + prob += (LZMA_LIT_SIZE * + ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + + if (state < kNumLitStates) + { + unsigned symbol = 1; + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; + unsigned offs = 0x100; + unsigned symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + res = DUMMY_LIT; + } + else + { + unsigned len; + UPDATE_1_CHECK; + + prob = probs + IsRep + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + state = 0; + prob = probs + LenCoder; + res = DUMMY_MATCH; + } + else + { + UPDATE_1_CHECK; + res = DUMMY_REP; + prob = probs + IsRepG0 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + NORMALIZE_CHECK; + return DUMMY_REP; + } + else + { + UPDATE_1_CHECK; + } + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG1 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG2 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + } + } + } + state = kNumStates; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumMidBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits != 0); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + do + { + GET_BIT_CHECK(prob + i, i); + } + while(--numDirectBits != 0); + } + } + } + } + } + NORMALIZE_CHECK; + return res; +} + + +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) +{ + p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); + p->range = 0xFFFFFFFF; + p->needFlush = 0; +} + +static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +{ + p->needFlush = 1; + p->remainLen = 0; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->needInitState = 1; + } + if (initState) + p->needInitState = 1; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + +static void LzmaDec_InitStateReal(CLzmaDec *p) +{ + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); + UInt32 i; + CLzmaProb *probs = p->probs; + for (i = 0; i < numProbs; i++) + probs[i] = kBitModelTotal >> 1; + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; + p->state = 0; + p->needInitState = 0; +} + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + LzmaDec_WriteRem(p, dicLimit); + + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->remainLen != kMatchSpecLenStart) + { + int checkEndMarkNow; + + if (p->needFlush != 0) + { + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + + LzmaDec_InitRc(p, p->tempBuf); + p->tempBufSize = 0; + } + + checkEndMarkNow = 0; + if (p->dicPos >= dicLimit) + { + if (p->remainLen == 0 && p->code == 0) + { + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; + return SZ_OK; + } + if (finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->remainLen != 0) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + checkEndMarkNow = 1; + } + + if (p->needInitState) + LzmaDec_InitStateReal(p); + + if (p->tempBufSize == 0) + { + SizeT processed; + const Byte *bufLimit; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, src, inSize); + if (dummyRes == DUMMY_ERROR) + { + memcpy(p->tempBuf, src, inSize); + p->tempBufSize = (unsigned)inSize; + (*srcLen) += inSize; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + bufLimit = src; + } + else + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; + if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) + return SZ_ERROR_DATA; + processed = p->buf - src; + (*srcLen) += processed; + src += processed; + inSize -= processed; + } + else + { + unsigned rem = p->tempBufSize, lookAhead = 0; + while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) + p->tempBuf[rem++] = src[lookAhead++]; + p->tempBufSize = rem; + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); + if (dummyRes == DUMMY_ERROR) + { + (*srcLen) += lookAhead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + } + p->buf = p->tempBuf; + if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) + return SZ_ERROR_DATA; + lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); + (*srcLen) += lookAhead; + src += lookAhead; + inSize -= lookAhead; + p->tempBufSize = 0; + } + } + if (p->code == 0) + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; +} + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen; + SizeT inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT inSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->dicPos == p->dicBufSize) + p->dicPos = 0; + dicPos = p->dicPos; + if (outSize > p->dicBufSize - dicPos) + { + outSizeCur = p->dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); + src += inSizeCur; + inSize -= inSizeCur; + *srcLen += inSizeCur; + outSizeCur = p->dicPos - dicPos; + memcpy(dest, p->dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->probs); + p->probs = 0; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->dic); + p->dic = 0; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) +{ + LzmaDec_FreeProbs(p, alloc); + LzmaDec_FreeDict(p, alloc); +} + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +{ + UInt32 dicSize; + Byte d; + + if (size < LZMA_PROPS_SIZE) + return SZ_ERROR_UNSUPPORTED; + else + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); + + if (dicSize < LZMA_DIC_MIN) + dicSize = LZMA_DIC_MIN; + p->dicSize = dicSize; + + d = data[0]; + if (d >= (9 * 5 * 5)) + return SZ_ERROR_UNSUPPORTED; + + p->lc = d % 9; + d /= 9; + p->pb = d / 5; + p->lp = d % 5; + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) +{ + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); + if (p->probs == 0 || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); + p->numProbs = numProbs; + if (p->probs == 0) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + dicBufSize = propNew.dicSize; + if (p->dic == 0 || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); + if (p->dic == 0) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzmaDec p; + SRes res; + SizeT inSize = *srcLen; + SizeT outSize = *destLen; + *srcLen = *destLen = 0; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + + LzmaDec_Construct(&p); + res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); + if (res != 0) + return res; + p.dic = dest; + p.dicBufSize = outSize; + + LzmaDec_Init(&p); + + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + + (*destLen) = p.dicPos; + LzmaDec_FreeProbs(&p, alloc); + return res; +} diff --git a/grub-core/lib/LzmaEnc.c b/grub-core/lib/LzmaEnc.c new file mode 100644 index 0000000..52b3315 --- /dev/null +++ b/grub-core/lib/LzmaEnc.c @@ -0,0 +1,2250 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (c) 1999-2008 Igor Pavlov + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * This code was taken from LZMA SDK 4.58 beta, and was slightly modified + * to adapt it to GRUB's requirement. + * + * See <http://www.7-zip.org>, for more information about LZMA. + */ + +#include <config.h> + +#include <stdio.h> +#include <string.h> + +#include <grub/lib/LzmaEnc.h> + +#include <grub/lib/LzFind.h> +#ifdef COMPRESS_MF_MT +#include <grub/lib/LzFindMt.h> +#endif + +/* #define SHOW_STAT */ +/* #define SHOW_STAT2 */ + +#ifdef SHOW_STAT +static int ttt = 0; +#endif + +#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) + +#define kBlockSize (9 << 10) +#define kUnpackBlockSize (1 << 18) +#define kMatchArraySize (1 << 21) +#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) + +#define kNumMaxDirectBits (31) + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 +#define kProbInitValue (kBitModelTotal >> 1) + +#define kNumMoveReducingBits 4 +#define kNumBitPriceShiftBits 4 +#define kBitPrice (1 << kNumBitPriceShiftBits) + +void LzmaEncProps_Init(CLzmaEncProps *p) +{ + p->level = 5; + p->dictSize = p->mc = 0; + p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; + p->writeEndMark = 0; +} + +void LzmaEncProps_Normalize(CLzmaEncProps *p) +{ + int level = p->level; + if (level < 0) level = 5; + p->level = level; + if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); + if (p->lc < 0) p->lc = 3; + if (p->lp < 0) p->lp = 0; + if (p->pb < 0) p->pb = 2; + if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); + if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); + if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); + if (p->numHashBytes < 0) p->numHashBytes = 4; + if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); + if (p->numThreads < 0) p->numThreads = ((p->btMode && p->algo) ? 2 : 1); +} + +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) +{ + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + return props.dictSize; +} + +/* #define LZMA_LOG_BSR */ +/* Define it for Intel's CPU */ + + +#ifdef LZMA_LOG_BSR + +#define kDicLogSizeMaxCompress 30 + +#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } + +UInt32 GetPosSlot1(UInt32 pos) +{ + UInt32 res; + BSR2_RET(pos, res); + return res; +} +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } + +#else + +#define kNumLogBits (9 + (int)sizeof(size_t) / 2) +#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) + +static void LzmaEnc_FastPosInit(Byte *g_FastPos) +{ + int c = 2, slotFast; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + + for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) + { + UInt32 k = (1 << ((slotFast >> 1) - 1)); + UInt32 j; + for (j = 0; j < k; j++, c++) + g_FastPos[c] = (Byte)slotFast; + } +} + +#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ + res = p->g_FastPos[pos >> i] + (i * 2); } +/* +#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ + p->g_FastPos[pos >> 6] + 12 : \ + p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } +*/ + +#define GetPosSlot1(pos) p->g_FastPos[pos] +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } + +#endif + + +#define LZMA_NUM_REPS 4 + +typedef unsigned CState; + +typedef struct _COptimal +{ + UInt32 price; + + CState state; + int prev1IsChar; + int prev2; + + UInt32 posPrev2; + UInt32 backPrev2; + + UInt32 posPrev; + UInt32 backPrev; + UInt32 backs[LZMA_NUM_REPS]; +} COptimal; + +#define kNumOpts (1 << 12) + +#define kNumLenToPosStates 4 +#define kNumPosSlotBits 6 +#define kDicLogSizeMin 0 +#define kDicLogSizeMax 32 +#define kDistTableSizeMax (kDicLogSizeMax * 2) + + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) +#define kAlignMask (kAlignTableSize - 1) + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) + +#define kNumFullDistances (1 << (kEndPosModelIndex / 2)) + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + +#define LZMA_PB_MAX 4 +#define LZMA_LC_MAX 8 +#define LZMA_LP_MAX 4 + +#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) + + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define LZMA_MATCH_LEN_MIN 2 +#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) + +#define kNumStates 12 + +typedef struct +{ + CLzmaProb choice; + CLzmaProb choice2; + CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; + CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; + CLzmaProb high[kLenNumHighSymbols]; +} CLenEnc; + +typedef struct +{ + CLenEnc p; + UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; + UInt32 tableSize; + UInt32 counters[LZMA_NUM_PB_STATES_MAX]; +} CLenPriceEnc; + +typedef struct _CRangeEnc +{ + UInt32 range; + Byte cache; + UInt64 low; + UInt64 cacheSize; + Byte *buf; + Byte *bufLim; + Byte *bufBase; + ISeqOutStream *outStream; + UInt64 processed; + SRes res; +} CRangeEnc; + +typedef struct _CSeqInStreamBuf +{ + ISeqInStream funcTable; + const Byte *data; + SizeT rem; +} CSeqInStreamBuf; + +static SRes MyRead(void *pp, void *data, size_t *size) +{ + size_t curSize = *size; + CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; + if (p->rem < curSize) + curSize = p->rem; + memcpy(data, p->data, curSize); + p->rem -= curSize; + p->data += curSize; + *size = curSize; + return SZ_OK; +} + +typedef struct +{ + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; +} CSaveState; + +typedef struct _CLzmaEnc +{ + IMatchFinder matchFinder; + void *matchFinderObj; + + #ifdef COMPRESS_MF_MT + Bool mtMode; + CMatchFinderMt matchFinderMt; + #endif + + CMatchFinder matchFinderBase; + + #ifdef COMPRESS_MF_MT + Byte pad[128]; + #endif + + UInt32 optimumEndIndex; + UInt32 optimumCurrentIndex; + + Bool longestMatchWasFound; + UInt32 longestMatchLength; + UInt32 numDistancePairs; + + COptimal opt[kNumOpts]; + + #ifndef LZMA_LOG_BSR + Byte g_FastPos[1 << kNumLogBits]; + #endif + + UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + UInt32 matchDistances[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; + UInt32 numFastBytes; + UInt32 additionalOffset; + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; + + UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; + UInt32 alignPrices[kAlignTableSize]; + UInt32 alignPriceCount; + + UInt32 distTableSize; + + unsigned lc, lp, pb; + unsigned lpMask, pbMask; + + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + unsigned lclp; + + Bool fastMode; + + CRangeEnc rc; + + Bool writeEndMark; + UInt64 nowPos64; + UInt32 matchPriceCount; + Bool finished; + Bool multiThread; + + SRes result; + UInt32 dictSize; + UInt32 matchFinderCycles; + + ISeqInStream *inStream; + CSeqInStreamBuf seqBufInStream; + + CSaveState saveState; +} CLzmaEnc; + +SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + + if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || + props.dictSize > (1U << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) + return SZ_ERROR_PARAM; + p->dictSize = props.dictSize; + p->matchFinderCycles = props.mc; + { + unsigned fb = props.fb; + if (fb < 5) + fb = 5; + if (fb > LZMA_MATCH_LEN_MAX) + fb = LZMA_MATCH_LEN_MAX; + p->numFastBytes = fb; + } + p->lc = props.lc; + p->lp = props.lp; + p->pb = props.pb; + p->fastMode = (props.algo == 0); + p->matchFinderBase.btMode = props.btMode; + { + UInt32 numHashBytes = 4; + if (props.btMode) + { + if (props.numHashBytes < 2) + numHashBytes = 2; + else if (props.numHashBytes < 4) + numHashBytes = props.numHashBytes; + } + p->matchFinderBase.numHashBytes = numHashBytes; + } + + p->matchFinderBase.cutValue = props.mc; + + p->writeEndMark = props.writeEndMark; + + #ifdef COMPRESS_MF_MT + /* + if (newMultiThread != _multiThread) + { + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + */ + p->multiThread = (props.numThreads > 1); + #endif + + return SZ_OK; +} + +static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +/* + void UpdateChar() { Index = kLiteralNextStates[Index]; } + void UpdateMatch() { Index = kMatchNextStates[Index]; } + void UpdateRep() { Index = kRepNextStates[Index]; } + void UpdateShortRep() { Index = kShortRepNextStates[Index]; } +*/ + +#define IsCharState(s) ((s) < 7) + + +#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) + +#define kInfinityPrice (1 << 30) + +static void RangeEnc_Construct(CRangeEnc *p) +{ + p->outStream = 0; + p->bufBase = 0; +} + +#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) + +#define RC_BUF_SIZE (1 << 16) +static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) +{ + if (p->bufBase == 0) + { + p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); + if (p->bufBase == 0) + return 0; + p->bufLim = p->bufBase + RC_BUF_SIZE; + } + return 1; +} + +static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->bufBase); + p->bufBase = 0; +} + +static void RangeEnc_Init(CRangeEnc *p) +{ + /* Stream.Init(); */ + p->low = 0; + p->range = 0xFFFFFFFF; + p->cacheSize = 1; + p->cache = 0; + + p->buf = p->bufBase; + + p->processed = 0; + p->res = SZ_OK; +} + +static void RangeEnc_FlushStream(CRangeEnc *p) +{ + size_t num; + if (p->res != SZ_OK) + return; + num = p->buf - p->bufBase; + if (num != p->outStream->Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + p->processed += num; + p->buf = p->bufBase; +} + +static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) +{ + if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) + { + Byte temp = p->cache; + do + { + Byte *buf = p->buf; + *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + temp = 0xFF; + } + while (--p->cacheSize != 0); + p->cache = (Byte)((UInt32)p->low >> 24); + } + p->cacheSize++; + p->low = (UInt32)p->low << 8; +} + +static void RangeEnc_FlushData(CRangeEnc *p) +{ + int i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + +static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) +{ + do + { + p->range >>= 1; + p->low += p->range & (0 - ((value >> --numBits) & 1)); + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } + } + while (numBits != 0); +} + +static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) +{ + UInt32 ttt = *prob; + UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; + if (symbol == 0) + { + p->range = newBound; + ttt += (kBitModelTotal - ttt) >> kNumMoveBits; + } + else + { + p->low += newBound; + p->range -= newBound; + ttt -= ttt >> kNumMoveBits; + } + *prob = (CLzmaProb)ttt; + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) +{ + symbol |= 0x100; + do + { + RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); +} + +static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) +{ + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); +} + +static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) +{ + UInt32 i; + for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) + { + const int kCyclesBits = kNumBitPriceShiftBits; + UInt32 w = i; + UInt32 bitCount = 0; + int j; + for (j = 0; j < kCyclesBits; j++) + { + w = w * w; + bitCount <<= 1; + while (w >= ((UInt32)1 << 16)) + { + w >>= 1; + bitCount++; + } + } + ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); + } +} + + +#define GET_PRICE(prob, symbol) \ + p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICEa(prob, symbol) \ + ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= 0x100; + do + { + price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); + return price; +}; + +static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) +{ + UInt32 price = 0; + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); + return price; +}; + + +static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0 ;) + { + UInt32 bit; + i--; + bit = (symbol >> i) & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + } +}; + +static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = 0; i < numBitLevels; i++) + { + UInt32 bit = symbol & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + symbol >>= 1; + } +} + +static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= (1 << numBitLevels); + while (symbol != 1) + { + price += GET_PRICEa(probs[symbol >> 1], symbol & 1); + symbol >>= 1; + } + return price; +} + +static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += GET_PRICEa(probs[m], bit); + m = (m << 1) | bit; + } + return price; +} + + +static void LenEnc_Init(CLenEnc *p) +{ + unsigned i; + p->choice = p->choice2 = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) + p->low[i] = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) + p->mid[i] = kProbInitValue; + for (i = 0; i < kLenNumHighSymbols; i++) + p->high[i] = kProbInitValue; +} + +static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) +{ + if (symbol < kLenNumLowSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice, 0); + RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice, 1); + if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice2, 0); + RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice2, 1); + RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); + } + } +} + +static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) +{ + UInt32 a0 = GET_PRICE_0a(p->choice); + UInt32 a1 = GET_PRICE_1a(p->choice); + UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); + UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); + UInt32 i = 0; + for (i = 0; i < kLenNumLowSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); + } + for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); + } + for (; i < numSymbols; i++) + prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); +} + +static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) +{ + LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); + p->counters[posState] = p->tableSize; +} + +static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) +{ + UInt32 posState; + for (posState = 0; posState < numPosStates; posState++) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + +static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) +{ + LenEnc_Encode(&p->p, rc, symbol, posState); + if (updatePrice) + if (--p->counters[posState] == 0) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + + + + +static void MovePos(CLzmaEnc *p, UInt32 num) +{ + #ifdef SHOW_STAT + ttt += num; + printf("\n MovePos %d", num); + #endif + if (num != 0) + { + p->additionalOffset += num; + p->matchFinder.Skip(p->matchFinderObj, num); + } +} + +static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) +{ + UInt32 lenRes = 0, numDistancePairs; + numDistancePairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matchDistances); + #ifdef SHOW_STAT + printf("\n i = %d numPairs = %d ", ttt, numDistancePairs / 2); + if (ttt >= 61994) + ttt = ttt; + + ttt++; + { + UInt32 i; + for (i = 0; i < numDistancePairs; i += 2) + printf("%2d %6d | ", p->matchDistances[i], p->matchDistances[i + 1]); + } + #endif + if (numDistancePairs > 0) + { + lenRes = p->matchDistances[numDistancePairs - 2]; + if (lenRes == p->numFastBytes) + { + UInt32 numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) + 1; + const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + UInt32 distance = p->matchDistances[numDistancePairs - 1] + 1; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + + { + const Byte *pby2 = pby - distance; + for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); + } + } + } + p->additionalOffset++; + *numDistancePairsRes = numDistancePairs; + return lenRes; +} + + +#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; +#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; +#define IsShortRep(p) ((p)->backPrev == 0) + +static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) +{ + return + GET_PRICE_0(p->isRepG0[state]) + + GET_PRICE_0(p->isRep0Long[state][posState]); +} + +static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) +{ + UInt32 price; + if (repIndex == 0) + { + price = GET_PRICE_0(p->isRepG0[state]); + price += GET_PRICE_1(p->isRep0Long[state][posState]); + } + else + { + price = GET_PRICE_1(p->isRepG0[state]); + if (repIndex == 1) + price += GET_PRICE_0(p->isRepG1[state]); + else + { + price += GET_PRICE_1(p->isRepG1[state]); + price += GET_PRICE(p->isRepG2[state], repIndex - 2); + } + } + return price; +} + +static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) +{ + return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + + GetPureRepPrice(p, repIndex, state, posState); +} + +static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) +{ + UInt32 posMem = p->opt[cur].posPrev; + UInt32 backMem = p->opt[cur].backPrev; + p->optimumEndIndex = cur; + do + { + if (p->opt[cur].prev1IsChar) + { + MakeAsChar(&p->opt[posMem]) + p->opt[posMem].posPrev = posMem - 1; + if (p->opt[cur].prev2) + { + p->opt[posMem - 1].prev1IsChar = False; + p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; + p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; + } + } + { + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = p->opt[posPrev].backPrev; + posMem = p->opt[posPrev].posPrev; + + p->opt[posPrev].backPrev = backCur; + p->opt[posPrev].posPrev = cur; + cur = posPrev; + } + } + while (cur != 0); + *backRes = p->opt[0].backPrev; + p->optimumCurrentIndex = p->opt[0].posPrev; + return p->optimumCurrentIndex; +} + +#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) + +#pragma GCC diagnostic ignored "-Wshadow" + +static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) +{ + UInt32 numAvailableBytes, lenMain, numDistancePairs; + const Byte *data; + UInt32 reps[LZMA_NUM_REPS]; + UInt32 repLens[LZMA_NUM_REPS]; + UInt32 repMaxIndex, i; + UInt32 *matchDistances; + Byte currentByte, matchByte; + UInt32 posState; + UInt32 matchPrice, repMatchPrice; + UInt32 lenEnd; + UInt32 len; + UInt32 normalMatchPrice; + UInt32 cur; + if (p->optimumEndIndex != p->optimumCurrentIndex) + { + const COptimal *opt = &p->opt[p->optimumCurrentIndex]; + UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; + *backRes = opt->backPrev; + p->optimumCurrentIndex = opt->posPrev; + return lenRes; + } + p->optimumCurrentIndex = p->optimumEndIndex = 0; + + numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + + if (!p->longestMatchWasFound) + { + lenMain = ReadMatchDistances(p, &numDistancePairs); + } + else + { + lenMain = p->longestMatchLength; + numDistancePairs = p->numDistancePairs; + p->longestMatchWasFound = False; + } + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + if (numAvailableBytes < 2) + { + *backRes = (UInt32)(-1); + return 1; + } + if (numAvailableBytes > LZMA_MATCH_LEN_MAX) + numAvailableBytes = LZMA_MATCH_LEN_MAX; + + repMaxIndex = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 lenTest; + const Byte *data2; + reps[i] = p->reps[i]; + data2 = data - (reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + { + repLens[i] = 0; + continue; + } + for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++); + repLens[i] = lenTest; + if (lenTest > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= p->numFastBytes) + { + UInt32 lenRes; + *backRes = repMaxIndex; + lenRes = repLens[repMaxIndex]; + MovePos(p, lenRes - 1); + return lenRes; + } + + matchDistances = p->matchDistances; + if (lenMain >= p->numFastBytes) + { + *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS; + MovePos(p, lenMain - 1); + return lenMain; + } + currentByte = *data; + matchByte = *(data - (reps[0] + 1)); + + if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) + { + *backRes = (UInt32)-1; + return 1; + } + + p->opt[0].state = (CState)p->state; + + posState = (position & p->pbMask); + + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + + (!IsCharState(p->state) ? + LitEnc_GetPriceMatched(probs, currentByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, currentByte, p->ProbPrices)); + } + + MakeAsChar(&p->opt[1]); + + matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); + + if (matchByte == currentByte) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); + if (shortRepPrice < p->opt[1].price) + { + p->opt[1].price = shortRepPrice; + MakeAsShortRep(&p->opt[1]); + } + } + lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); + + if (lenEnd < 2) + { + *backRes = p->opt[1].backPrev; + return 1; + } + + p->opt[1].posPrev = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + p->opt[0].backs[i] = reps[i]; + + len = lenEnd; + do + p->opt[len--].price = kInfinityPrice; + while (len >= 2); + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 repLen = repLens[i]; + UInt32 price; + if (repLen < 2) + continue; + price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; + COptimal *opt = &p->opt[repLen]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = i; + opt->prev1IsChar = False; + } + } + while (--repLen >= 2); + } + + normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= lenMain) + { + UInt32 offs = 0; + while (len > matchDistances[offs]) + offs += 2; + for (; ; len++) + { + COptimal *opt; + UInt32 distance = matchDistances[offs + 1]; + + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(len); + if (distance < kNumFullDistances) + curAndLenPrice += p->distancesPrices[lenToPosState][distance]; + else + { + UInt32 slot; + GetPosSlot2(distance, slot); + curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; + } + opt = &p->opt[len]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = distance + LZMA_NUM_REPS; + opt->prev1IsChar = False; + } + if (len == matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + + cur = 0; + + #ifdef SHOW_STAT2 + if (position >= 0) + { + unsigned i; + printf("\n pos = %4X", position); + for (i = cur; i <= lenEnd; i++) + printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); + } + #endif + + for (;;) + { + UInt32 numAvailableBytesFull, newLen, numDistancePairs; + COptimal *curOpt; + UInt32 posPrev; + UInt32 state; + UInt32 curPrice; + Bool nextIsChar; + const Byte *data; + Byte currentByte, matchByte; + UInt32 posState; + UInt32 curAnd1Price; + COptimal *nextOpt; + UInt32 matchPrice, repMatchPrice; + UInt32 numAvailableBytes; + UInt32 startLen; + + cur++; + if (cur == lenEnd) + return Backward(p, backRes, cur); + + numAvailableBytesFull = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + newLen = ReadMatchDistances(p, &numDistancePairs); + if (newLen >= p->numFastBytes) + { + p->numDistancePairs = numDistancePairs; + p->longestMatchLength = newLen; + p->longestMatchWasFound = True; + return Backward(p, backRes, cur); + } + position++; + curOpt = &p->opt[cur]; + posPrev = curOpt->posPrev; + if (curOpt->prev1IsChar) + { + posPrev--; + if (curOpt->prev2) + { + state = p->opt[curOpt->posPrev2].state; + if (curOpt->backPrev2 < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + else + state = p->opt[posPrev].state; + state = kLiteralNextStates[state]; + } + else + state = p->opt[posPrev].state; + if (posPrev == cur - 1) + { + if (IsShortRep(curOpt)) + state = kShortRepNextStates[state]; + else + state = kLiteralNextStates[state]; + } + else + { + UInt32 pos; + const COptimal *prevOpt; + if (curOpt->prev1IsChar && curOpt->prev2) + { + posPrev = curOpt->posPrev2; + pos = curOpt->backPrev2; + state = kRepNextStates[state]; + } + else + { + pos = curOpt->backPrev; + if (pos < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + prevOpt = &p->opt[posPrev]; + if (pos < LZMA_NUM_REPS) + { + UInt32 i; + reps[0] = prevOpt->backs[pos]; + for (i = 1; i < pos + 1; i++) + reps[i] = prevOpt->backs[i - 1]; + for (; i < LZMA_NUM_REPS; i++) + reps[i] = prevOpt->backs[i]; + } + else + { + UInt32 i; + reps[0] = (pos - LZMA_NUM_REPS); + for (i = 1; i < LZMA_NUM_REPS; i++) + reps[i] = prevOpt->backs[i - 1]; + } + } + curOpt->state = (CState)state; + + curOpt->backs[0] = reps[0]; + curOpt->backs[1] = reps[1]; + curOpt->backs[2] = reps[2]; + curOpt->backs[3] = reps[3]; + + curPrice = curOpt->price; + nextIsChar = False; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + currentByte = *data; + matchByte = *(data - (reps[0] + 1)); + + posState = (position & p->pbMask); + + curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + curAnd1Price += + (!IsCharState(state) ? + LitEnc_GetPriceMatched(probs, currentByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, currentByte, p->ProbPrices)); + } + + nextOpt = &p->opt[cur + 1]; + + if (curAnd1Price < nextOpt->price) + { + nextOpt->price = curAnd1Price; + nextOpt->posPrev = cur; + MakeAsChar(nextOpt); + nextIsChar = True; + } + + matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); + + if (matchByte == currentByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); + if (shortRepPrice <= nextOpt->price) + { + nextOpt->price = shortRepPrice; + nextOpt->posPrev = cur; + MakeAsShortRep(nextOpt); + nextIsChar = True; + } + } + + { + UInt32 temp = kNumOpts - 1 - cur; + if (temp < numAvailableBytesFull) + numAvailableBytesFull = temp; + } + numAvailableBytes = numAvailableBytesFull; + + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > p->numFastBytes) + numAvailableBytes = p->numFastBytes; + if (!nextIsChar && matchByte != currentByte) /* speed optimization */ + { + /* try Literal + rep0 */ + UInt32 temp; + UInt32 lenTest2; + const Byte *data2 = data - (reps[0] + 1); + UInt32 limit = p->numFastBytes + 1; + if (limit > numAvailableBytesFull) + limit = numAvailableBytesFull; + + for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); + lenTest2 = temp - 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kLiteralNextStates[state]; + UInt32 posStateNext = (position + 1) & p->pbMask; + UInt32 nextRepMatchPrice = curAnd1Price + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = False; + } + } + } + } + + startLen = 2; /* speed optimization */ + { + UInt32 repIndex; + for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) + { + UInt32 lenTest; + UInt32 lenTestTemp; + UInt32 price; + const Byte *data2 = data - (reps[repIndex] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++); + while (lenEnd < cur + lenTest) + p->opt[++lenEnd].price = kInfinityPrice; + lenTestTemp = lenTest; + price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; + COptimal *opt = &p->opt[cur + lenTest]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur; + opt->backPrev = repIndex; + opt->prev1IsChar = False; + } + } + while (--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + /* if (_maxMode) */ + { + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailableBytesFull) + limit = numAvailableBytesFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kRepNextStates[state]; + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = + price + p->repLenEnc.prices[posState][lenTest - 2] + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = kLiteralNextStates[state2]; + posStateNext = (position + lenTest + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + lenTest + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = repIndex; + } + } + } + } + } + } + /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ + if (newLen > numAvailableBytes) + { + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2); + matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) + { + UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); + UInt32 offs, curBack, posSlot; + UInt32 lenTest; + while (lenEnd < cur + newLen) + p->opt[++lenEnd].price = kInfinityPrice; + + offs = 0; + while (startLen > matchDistances[offs]) + offs += 2; + curBack = matchDistances[offs + 1]; + GetPosSlot2(curBack, posSlot); + for (lenTest = /*2*/ startLen; ; lenTest++) + { + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(lenTest); + COptimal *opt; + if (curBack < kNumFullDistances) + curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; + else + curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; + + opt = &p->opt[cur + lenTest]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur; + opt->backPrev = curBack + LZMA_NUM_REPS; + opt->prev1IsChar = False; + } + + if (/*_maxMode && */lenTest == matchDistances[offs]) + { + /* Try Match + Literal + Rep0 */ + const Byte *data2 = data - (curBack + 1); + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailableBytesFull) + limit = numAvailableBytesFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kMatchNextStates[state]; + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = kLiteralNextStates[state2]; + posStateNext = (posStateNext + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 offset = cur + lenTest + 1 + lenTest2; + UInt32 curAndLenPrice; + COptimal *opt; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = curBack + LZMA_NUM_REPS; + } + } + } + offs += 2; + if (offs == numDistancePairs) + break; + curBack = matchDistances[offs + 1]; + if (curBack >= kNumFullDistances) + GetPosSlot2(curBack, posSlot); + } + } + } + } +} + +#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) + +static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) +{ + UInt32 numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + UInt32 lenMain, numDistancePairs; + const Byte *data; + UInt32 repLens[LZMA_NUM_REPS]; + UInt32 repMaxIndex, i; + UInt32 *matchDistances; + UInt32 backMain; + + if (!p->longestMatchWasFound) + { + lenMain = ReadMatchDistances(p, &numDistancePairs); + } + else + { + lenMain = p->longestMatchLength; + numDistancePairs = p->numDistancePairs; + p->longestMatchWasFound = False; + } + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + if (numAvailableBytes > LZMA_MATCH_LEN_MAX) + numAvailableBytes = LZMA_MATCH_LEN_MAX; + if (numAvailableBytes < 2) + { + *backRes = (UInt32)(-1); + return 1; + } + + repMaxIndex = 0; + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + const Byte *data2 = data - (p->reps[i] + 1); + UInt32 len; + if (data[0] != data2[0] || data[1] != data2[1]) + { + repLens[i] = 0; + continue; + } + for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++); + if (len >= p->numFastBytes) + { + *backRes = i; + MovePos(p, len - 1); + return len; + } + repLens[i] = len; + if (len > repLens[repMaxIndex]) + repMaxIndex = i; + } + matchDistances = p->matchDistances; + if (lenMain >= p->numFastBytes) + { + *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS; + MovePos(p, lenMain - 1); + return lenMain; + } + + backMain = 0; /* for GCC */ + if (lenMain >= 2) + { + backMain = matchDistances[numDistancePairs - 1]; + while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1) + { + if (!ChangePair(matchDistances[numDistancePairs - 3], backMain)) + break; + numDistancePairs -= 2; + lenMain = matchDistances[numDistancePairs - 2]; + backMain = matchDistances[numDistancePairs - 1]; + } + if (lenMain == 2 && backMain >= 0x80) + lenMain = 1; + } + + if (repLens[repMaxIndex] >= 2) + { + if (repLens[repMaxIndex] + 1 >= lenMain || + (repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9))) || + (repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15)))) + { + UInt32 lenRes; + *backRes = repMaxIndex; + lenRes = repLens[repMaxIndex]; + MovePos(p, lenRes - 1); + return lenRes; + } + } + + if (lenMain >= 2 && numAvailableBytes > 2) + { + UInt32 i; + numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + p->longestMatchLength = ReadMatchDistances(p, &p->numDistancePairs); + if (p->longestMatchLength >= 2) + { + UInt32 newDistance = matchDistances[p->numDistancePairs - 1]; + if ((p->longestMatchLength >= lenMain && newDistance < backMain) || + (p->longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance)) || + (p->longestMatchLength > lenMain + 1) || + (p->longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain))) + { + p->longestMatchWasFound = True; + *backRes = (UInt32)(-1); + return 1; + } + } + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 len; + const Byte *data2 = data - (p->reps[i] + 1); + if (data[1] != data2[1] || data[2] != data2[2]) + { + repLens[i] = 0; + continue; + } + for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++); + if (len + 1 >= lenMain) + { + p->longestMatchWasFound = True; + *backRes = (UInt32)(-1); + return 1; + } + } + *backRes = backMain + LZMA_NUM_REPS; + MovePos(p, lenMain - 2); + return lenMain; + } + *backRes = (UInt32)(-1); + return 1; +} + +static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) +{ + UInt32 len; + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = kMatchNextStates[p->state]; + len = LZMA_MATCH_LEN_MIN; + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); + RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); +} + +static SRes CheckErrors(CLzmaEnc *p) +{ + if (p->result != SZ_OK) + return p->result; + if (p->rc.res != SZ_OK) + p->result = SZ_ERROR_WRITE; + if (p->matchFinderBase.result != SZ_OK) + p->result = SZ_ERROR_READ; + if (p->result != SZ_OK) + p->finished = True; + return p->result; +} + +static SRes Flush(CLzmaEnc *p, UInt32 nowPos) +{ + /* ReleaseMFStream(); */ + p->finished = True; + if (p->writeEndMark) + WriteEndMarker(p, nowPos & p->pbMask); + RangeEnc_FlushData(&p->rc); + RangeEnc_FlushStream(&p->rc); + return CheckErrors(p); +} + +static void FillAlignPrices(CLzmaEnc *p) +{ + UInt32 i; + for (i = 0; i < kAlignTableSize; i++) + p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); + p->alignPriceCount = 0; +} + +static void FillDistancesPrices(CLzmaEnc *p) +{ + UInt32 tempPrices[kNumFullDistances]; + UInt32 i, lenToPosState; + for (i = kStartPosModelIndex; i < kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot1(i); + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); + } + + for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; + UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; + for (posSlot = 0; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); + for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); + + { + UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; + UInt32 i; + for (i = 0; i < kStartPosModelIndex; i++) + distancesPrices[i] = posSlotPrices[i]; + for (; i < kNumFullDistances; i++) + distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; + } + } + p->matchPriceCount = 0; +} + +static void LzmaEnc_Construct(CLzmaEnc *p) +{ + RangeEnc_Construct(&p->rc); + MatchFinder_Construct(&p->matchFinderBase); + #ifdef COMPRESS_MF_MT + MatchFinderMt_Construct(&p->matchFinderMt); + p->matchFinderMt.MatchFinder = &p->matchFinderBase; + #endif + + { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + LzmaEnc_SetProps(p, &props); + } + + #ifndef LZMA_LOG_BSR + LzmaEnc_FastPosInit(p->g_FastPos); + #endif + + LzmaEnc_InitPriceTables(p->ProbPrices); + p->litProbs = 0; + p->saveState.litProbs = 0; +} + +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) +{ + void *p; + p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); + if (p != 0) + LzmaEnc_Construct((CLzmaEnc *)p); + return p; +} + +static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->litProbs); + alloc->Free(alloc, p->saveState.litProbs); + p->litProbs = 0; + p->saveState.litProbs = 0; +} + +static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + #ifdef COMPRESS_MF_MT + MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); + #endif + MatchFinder_Free(&p->matchFinderBase, allocBig); + LzmaEnc_FreeLits(p, alloc); + RangeEnc_Free(&p->rc, alloc); +} + +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); + alloc->Free(alloc, p); +} + +static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) +{ + UInt32 nowPos32, startPos32; + if (p->inStream != 0) + { + p->matchFinderBase.stream = p->inStream; + p->matchFinder.Init(p->matchFinderObj); + p->inStream = 0; + } + + if (p->finished) + return p->result; + RINOK(CheckErrors(p)); + + nowPos32 = (UInt32)p->nowPos64; + startPos32 = nowPos32; + + if (p->nowPos64 == 0) + { + UInt32 numDistancePairs; + Byte curByte; + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + return Flush(p, nowPos32); + ReadMatchDistances(p, &numDistancePairs); + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); + p->state = kLiteralNextStates[p->state]; + curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); + LitEnc_Encode(&p->rc, p->litProbs, curByte); + p->additionalOffset--; + nowPos32++; + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) + for (;;) + { + UInt32 pos, len, posState; + + if (p->fastMode) + len = GetOptimumFast(p, &pos); + else + len = GetOptimum(p, nowPos32, &pos); + + #ifdef SHOW_STAT2 + printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); + #endif + + posState = nowPos32 & p->pbMask; + if (len == 1 && pos == 0xFFFFFFFF) + { + Byte curByte; + CLzmaProb *probs; + const Byte *data; + + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; + curByte = *data; + probs = LIT_PROBS(nowPos32, *(data - 1)); + if (IsCharState(p->state)) + LitEnc_Encode(&p->rc, probs, curByte); + else + LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); + p->state = kLiteralNextStates[p->state]; + } + else + { + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + if (pos < LZMA_NUM_REPS) + { + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); + if (pos == 0) + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); + RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); + } + else + { + UInt32 distance = p->reps[pos]; + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); + if (pos == 1) + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); + else + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); + if (pos == 3) + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + } + p->reps[1] = p->reps[0]; + p->reps[0] = distance; + } + if (len == 1) + p->state = kShortRepNextStates[p->state]; + else + { + LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + p->state = kRepNextStates[p->state]; + } + } + else + { + UInt32 posSlot, lenToPosState; + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = kMatchNextStates[p->state]; + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + pos -= LZMA_NUM_REPS; + GetPosSlot(pos, posSlot); + lenToPosState = GetLenToPosState(len); + if (lenToPosState >= kNumLenToPosStates) + { + p->result = SZ_ERROR_DATA; + return CheckErrors(p); + } + RcTree_Encode(&p->rc, p->posSlotEncoder[lenToPosState], kNumPosSlotBits, posSlot); + + if (posSlot >= kStartPosModelIndex) + { + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - base; + + if (posSlot < kEndPosModelIndex) + RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); + else + { + RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); + p->alignPriceCount++; + } + } + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + p->reps[1] = p->reps[0]; + p->reps[0] = pos; + p->matchPriceCount++; + } + } + p->additionalOffset -= len; + nowPos32 += len; + if (p->additionalOffset == 0) + { + UInt32 processed; + if (!p->fastMode) + { + if (p->matchPriceCount >= (1 << 7)) + FillDistancesPrices(p); + if (p->alignPriceCount >= kAlignTableSize) + FillAlignPrices(p); + } + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + break; + processed = nowPos32 - startPos32; + if (useLimits) + { + if (processed + kNumOpts + 300 >= maxUnpackSize || + RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) + break; + } + else if (processed >= (1 << 15)) + { + p->nowPos64 += nowPos32 - startPos32; + return CheckErrors(p); + } + } + } + p->nowPos64 += nowPos32 - startPos32; + return Flush(p, nowPos32); +} + +#define kBigHashDicLimit ((UInt32)1 << 24) + +static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 beforeSize = kNumOpts; +#ifdef COMPRESS_MF_MT + Bool btMode; +#endif + if (!RangeEnc_Alloc(&p->rc, alloc)) + return SZ_ERROR_MEM; +#ifdef COMPRESS_MF_MT + btMode = (p->matchFinderBase.btMode != 0); + p->mtMode = (p->multiThread && !p->fastMode && btMode); +#endif + + { + unsigned lclp = p->lc + p->lp; + if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) + { + LzmaEnc_FreeLits(p, alloc); + p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); + p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); + if (p->litProbs == 0 || p->saveState.litProbs == 0) + { + LzmaEnc_FreeLits(p, alloc); + return SZ_ERROR_MEM; + } + p->lclp = lclp; + } + } + + p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); + + if (beforeSize + p->dictSize < keepWindowSize) + beforeSize = keepWindowSize - p->dictSize; + + #ifdef COMPRESS_MF_MT + if (p->mtMode) + { + RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); + p->matchFinderObj = &p->matchFinderMt; + MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); + } + else + #endif + { + if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) + return SZ_ERROR_MEM; + p->matchFinderObj = &p->matchFinderBase; + MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); + } + return SZ_OK; +} + +static void LzmaEnc_Init(CLzmaEnc *p) +{ + UInt32 i; + p->state = 0; + for(i = 0 ; i < LZMA_NUM_REPS; i++) + p->reps[i] = 0; + + RangeEnc_Init(&p->rc); + + + for (i = 0; i < kNumStates; i++) + { + UInt32 j; + for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) + { + p->isMatch[i][j] = kProbInitValue; + p->isRep0Long[i][j] = kProbInitValue; + } + p->isRep[i] = kProbInitValue; + p->isRepG0[i] = kProbInitValue; + p->isRepG1[i] = kProbInitValue; + p->isRepG2[i] = kProbInitValue; + } + + { + UInt32 num = 0x300 << (p->lp + p->lc); + for (i = 0; i < num; i++) + p->litProbs[i] = kProbInitValue; + } + + { + for (i = 0; i < kNumLenToPosStates; i++) + { + CLzmaProb *probs = p->posSlotEncoder[i]; + UInt32 j; + for (j = 0; j < (1 << kNumPosSlotBits); j++) + probs[j] = kProbInitValue; + } + } + { + for(i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) + p->posEncoders[i] = kProbInitValue; + } + + LenEnc_Init(&p->lenEnc.p); + LenEnc_Init(&p->repLenEnc.p); + + for (i = 0; i < (1 << kNumAlignBits); i++) + p->posAlignEncoder[i] = kProbInitValue; + + p->longestMatchWasFound = False; + p->optimumEndIndex = 0; + p->optimumCurrentIndex = 0; + p->additionalOffset = 0; + + p->pbMask = (1 << p->pb) - 1; + p->lpMask = (1 << p->lp) - 1; +} + +static void LzmaEnc_InitPrices(CLzmaEnc *p) +{ + if (!p->fastMode) + { + FillDistancesPrices(p); + FillAlignPrices(p); + } + + p->lenEnc.tableSize = + p->repLenEnc.tableSize = + p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; + LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); +} + +static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 i; + for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) + if (p->dictSize <= ((UInt32)1 << i)) + break; + p->distTableSize = i * 2; + + p->finished = False; + p->result = SZ_OK; + RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + p->nowPos64 = 0; + return SZ_OK; +} + +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->inStream = inStream; + p->rc.outStream = outStream; + return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); +} + +static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) +{ + p->seqBufInStream.funcTable.Read = MyRead; + p->seqBufInStream.data = src; + p->seqBufInStream.rem = srcLen; +} + +static void LzmaEnc_Finish(CLzmaEncHandle pp) +{ + #ifdef COMPRESS_MF_MT + CLzmaEnc *p = (CLzmaEnc *)pp; + if (p->mtMode) + MatchFinderMt_ReleaseStream(&p->matchFinderMt); + #else + (void)pp; + #endif +} + +typedef struct _CSeqOutStreamBuf +{ + ISeqOutStream funcTable; + Byte *data; + SizeT rem; + Bool overflow; +} CSeqOutStreamBuf; + +static size_t MyWrite(void *pp, const void *data, size_t size) +{ + CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; + if (p->rem < size) + { + size = p->rem; + p->overflow = True; + } + memcpy(p->data, data, size); + p->rem -= size; + p->data += size; + return size; +} + +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + SRes res = SZ_OK; + + #ifdef COMPRESS_MF_MT + Byte allocaDummy[0x300]; + int i = 0; + for (i = 0; i < 16; i++) + allocaDummy[i] = (Byte)i; + #endif + + RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); + + for (;;) + { + res = LzmaEnc_CodeOneBlock(pp, False, 0, 0); + if (res != SZ_OK || p->finished != 0) + break; + if (progress != 0) + { + res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); + if (res != SZ_OK) + { + res = SZ_ERROR_PROGRESS; + break; + } + } + } + LzmaEnc_Finish(pp); + return res; +} + +SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + int i; + UInt32 dictSize = p->dictSize; + if (*size < LZMA_PROPS_SIZE) + return SZ_ERROR_PARAM; + *size = LZMA_PROPS_SIZE; + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); + + for (i = 11; i <= 30; i++) + { + if (dictSize <= ((UInt32)2 << i)) + { + dictSize = (2 << i); + break; + } + if (dictSize <= ((UInt32)3 << i)) + { + dictSize = (3 << i); + break; + } + } + + for (i = 0; i < 4; i++) + props[1 + i] = (Byte)(dictSize >> (8 * i)); + return SZ_OK; +} + +SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + SRes res; + CLzmaEnc *p = (CLzmaEnc *)pp; + + CSeqOutStreamBuf outStream; + + LzmaEnc_SetInputBuf(p, src, srcLen); + + outStream.funcTable.Write = MyWrite; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = writeEndMark; + res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, + progress, alloc, allocBig); + + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + return res; +} + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); + SRes res; + if (p == 0) + return SZ_ERROR_MEM; + + res = LzmaEnc_SetProps(p, props); + if (res == SZ_OK) + { + res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); + if (res == SZ_OK) + res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, + writeEndMark, progress, alloc, allocBig); + } + + LzmaEnc_Destroy(p, alloc, allocBig); + return res; +} diff --git a/grub-core/lib/adler32.c b/grub-core/lib/adler32.c new file mode 100644 index 0000000..43b68af --- /dev/null +++ b/grub-core/lib/adler32.c @@ -0,0 +1,102 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include <grub/dl.h> +#include <grub/crypto.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct adler32_context +{ + grub_uint16_t a, b; + grub_uint32_t c; +}; + +static void +adler32_init (void *context) +{ + struct adler32_context *ctx = context; + + ctx->a = 1; + ctx->b = 0; +} + +#define MOD 65521 + +static grub_uint16_t +mod_add (grub_uint16_t a, grub_uint16_t b) +{ + if ((grub_uint32_t) a + (grub_uint32_t) b >= MOD) + return a + b - MOD; + return a + b; +} + +static void +adler32_write (void *context, const void *inbuf, grub_size_t inlen) +{ + struct adler32_context *ctx = context; + const grub_uint8_t *ptr = inbuf; + + while (inlen) + { + ctx->a = mod_add (ctx->a, *ptr); + ctx->b = mod_add (ctx->a, ctx->b); + inlen--; + ptr++; + } +} + +static void +adler32_final (void *context __attribute__ ((unused))) +{ +} + +static grub_uint8_t * +adler32_read (void *context) +{ + struct adler32_context *ctx = context; + if (ctx->a > MOD) + ctx->a -= MOD; + if (ctx->b > MOD) + ctx->b -= MOD; + ctx->c = grub_cpu_to_be32 (ctx->a | (ctx->b << 16)); + return (grub_uint8_t *) &ctx->c; +} + +static gcry_md_spec_t spec_adler32 = + { + "ADLER32", 0, 0, 0, 4, + adler32_init, adler32_write, adler32_final, adler32_read, + sizeof (struct adler32_context), +#ifdef GRUB_UTIL + .modname = "adler32", +#endif + .blocksize = 64 + }; + + +GRUB_MOD_INIT(adler32) +{ + grub_md_register (&spec_adler32); +} + +GRUB_MOD_FINI(adler32) +{ + grub_md_unregister (&spec_adler32); +} diff --git a/grub-core/lib/arc/datetime.c b/grub-core/lib/arc/datetime.c new file mode 100644 index 0000000..b8d910e --- /dev/null +++ b/grub-core/lib/arc/datetime.c @@ -0,0 +1,48 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/datetime.h> +#include <grub/dl.h> +#include <grub/misc.h> +#include <grub/arc/arc.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +grub_err_t +grub_get_datetime (struct grub_datetime *datetime) +{ + struct grub_arc_timeinfo *dt; + grub_memset (datetime, 0, sizeof (*datetime)); + + dt = GRUB_ARC_FIRMWARE_VECTOR->gettime (); + + datetime->year = dt->y; + datetime->month = dt->m; + datetime->day = dt->d; + datetime->hour = dt->h; + datetime->minute = dt->min; + datetime->second = dt->s; + + return 0; +} + +grub_err_t +grub_set_datetime (struct grub_datetime *datetime __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_IO, "setting time isn't supported"); +} diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c new file mode 100644 index 0000000..ade82d5 --- /dev/null +++ b/grub-core/lib/arg.c @@ -0,0 +1,492 @@ +/* arg.c - argument parser */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,2007,2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/err.h> +#include <grub/term.h> +#include <grub/extcmd.h> +#include <grub/i18n.h> +#include <grub/safemath.h> + +/* Built-in parser for default options. */ +static const struct grub_arg_option help_options[] = + { + {"help", 0, 0, + N_("Display this help and exit."), 0, ARG_TYPE_NONE}, + {"usage", 0, 0, + N_("Display the usage of this command and exit."), 0, ARG_TYPE_NONE}, + {0, 0, 0, 0, 0, 0} + }; + +/* Helper for find_short. */ +static const struct grub_arg_option * +fnd_short (const struct grub_arg_option *opt, char c) +{ + while (opt->doc) + { + if (opt->shortarg == c) + return opt; + opt++; + } + return 0; +} + +static const struct grub_arg_option * +find_short (const struct grub_arg_option *options, char c) +{ + const struct grub_arg_option *found = 0; + + if (options) + found = fnd_short (options, c); + + if (! found) + { + switch (c) + { + case 'h': + found = help_options; + break; + + case 'u': + found = (help_options + 1); + break; + + default: + break; + } + } + + return found; +} + +/* Helper for find_long. */ +static const struct grub_arg_option * +fnd_long (const struct grub_arg_option *opt, const char *s, int len) +{ + while (opt->doc) + { + if (opt->longarg && ! grub_strncmp (opt->longarg, s, len) && + opt->longarg[len] == '\0') + return opt; + opt++; + } + return 0; +} + +static const struct grub_arg_option * +find_long (const struct grub_arg_option *options, const char *s, int len) +{ + const struct grub_arg_option *found = 0; + + if (options) + found = fnd_long (options, s, len); + + if (! found) + found = fnd_long (help_options, s, len); + + return found; +} + +static void +show_usage (grub_extcmd_t cmd) +{ + grub_printf ("%s %s %s\n", _("Usage:"), cmd->cmd->name, _(cmd->cmd->summary)); +} + +static void +showargs (const struct grub_arg_option *opt, + int h_is_used, int u_is_used) +{ + for (; opt->doc; opt++) + { + int spacing = 20; + + if (opt->shortarg && grub_isgraph (opt->shortarg)) + grub_printf ("-%c%c ", opt->shortarg, opt->longarg ? ',':' '); + else if (opt == help_options && ! h_is_used) + grub_printf ("-h, "); + else if (opt == help_options + 1 && ! u_is_used) + grub_printf ("-u, "); + else + grub_printf (" "); + + if (opt->longarg) + { + grub_printf ("--%s", opt->longarg); + spacing -= grub_strlen (opt->longarg) + 2; + + if (opt->arg) + { + grub_printf ("=%s", opt->arg); + spacing -= grub_strlen (opt->arg) + 1; + } + } + + if (spacing <= 0) + spacing = 3; + + while (spacing--) + grub_xputs (" "); + + grub_printf ("%s\n", _(opt->doc)); + } +} + +void +grub_arg_show_help (grub_extcmd_t cmd) +{ + int h_is_used = 0; + int u_is_used = 0; + const struct grub_arg_option *opt; + + show_usage (cmd); + grub_printf ("%s\n\n", _(cmd->cmd->description)); + + for (opt = cmd->options; opt && opt->doc; opt++) + switch (opt->shortarg) + { + case 'h': + h_is_used = 1; + break; + + case 'u': + u_is_used = 1; + break; + } + + if (cmd->options) + showargs (cmd->options, h_is_used, u_is_used); + showargs (help_options, h_is_used, u_is_used); +#if 0 + grub_printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT); +#endif +} + + +static int +parse_option (grub_extcmd_t cmd, const struct grub_arg_option *opt, + char *arg, struct grub_arg_list *usr) +{ + if (opt == help_options) + { + grub_arg_show_help (cmd); + return -1; + } + + if (opt == help_options + 1) + { + show_usage (cmd); + return -1; + } + { + int found = opt - cmd->options; + + if (opt->flags & GRUB_ARG_OPTION_REPEATABLE) + { + usr[found].args[usr[found].set++] = arg; + usr[found].args[usr[found].set] = NULL; + } + else + { + usr[found].set = 1; + usr[found].arg = arg; + } + } + + return 0; +} + +static inline grub_err_t +add_arg (char ***argl, int *num, char *s) +{ + char **p = *argl; + grub_size_t sz; + + if (grub_add (++(*num), 1, &sz) || + grub_mul (sz, sizeof (char *), &sz)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + + *argl = grub_realloc (*argl, sz); + if (! *argl) + { + grub_free (p); + return grub_errno; + } + (*argl)[(*num) - 1] = s; + (*argl)[(*num)] = NULL; + return 0; +} + + +int +grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, + struct grub_arg_list *usr, char ***args, int *argnum) +{ + int curarg; + int arglen; + char **argl = 0; + int num = 0; + + for (curarg = 0; curarg < argc; curarg++) + { + char *arg = argv[curarg]; + const struct grub_arg_option *opt; + char *option = 0; + + /* No option is used. */ + if ((num && (cmd->cmd->flags & GRUB_COMMAND_OPTIONS_AT_START)) + || arg[0] != '-' || grub_strlen (arg) == 1) + { + if (add_arg (&argl, &num, arg) != 0) + goto fail; + + continue; + } + + /* One or more short options. */ + if (arg[1] != '-') + { + char *curshort; + + if (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH) + { + for (curshort = arg + 1; *curshort; curshort++) + if (!find_short (cmd->options, *curshort)) + break; + + if (*curshort) + { + if (add_arg (&argl, &num, arg) != 0) + goto fail; + continue; + } + } + + curshort = arg + 1; + + while (1) + { + opt = find_short (cmd->options, *curshort); + + if (! opt) + { + char tmp[3] = { '-', *curshort, 0 }; + grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unknown argument `%s'"), tmp); + goto fail; + } + + curshort++; + + /* Parse all arguments here except the last one because + it can have an argument value. */ + if (*curshort) + { + /* + * Only permit further short opts if this one doesn't + * require a value. + */ + if (opt->type != ARG_TYPE_NONE && + !(opt->flags & GRUB_ARG_OPTION_OPTIONAL)) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("missing mandatory option for `%s'"), + opt->longarg); + goto fail; + } + + if (parse_option (cmd, opt, 0, usr) || grub_errno) + goto fail; + } + else + { + if (opt->type != ARG_TYPE_NONE) + { + if (curarg + 1 < argc) + { + char *nextarg = argv[curarg + 1]; + if (!(opt->flags & GRUB_ARG_OPTION_OPTIONAL) + || (grub_strlen (nextarg) < 2 || nextarg[0] != '-')) + option = argv[++curarg]; + } + } + break; + } + } + + } + else /* The argument starts with "--". */ + { + /* If the argument "--" is used just pass the other + arguments. */ + if (grub_strlen (arg) == 2) + { + for (curarg++; curarg < argc; curarg++) + if (add_arg (&argl, &num, argv[curarg]) != 0) + goto fail; + break; + } + + option = grub_strchr (arg, '='); + if (option) + { + arglen = option - arg - 2; + option++; + } + else + arglen = grub_strlen (arg) - 2; + + opt = find_long (cmd->options, arg + 2, arglen); + + if (!option && argv[curarg + 1] && argv[curarg + 1][0] != '-' + && opt && opt->type != ARG_TYPE_NONE) + option = argv[++curarg]; + + if (!opt && (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH)) + { + if (add_arg (&argl, &num, arg) != 0) + goto fail; + continue; + } + + if (! opt) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"), arg); + goto fail; + } + } + + if (! (opt->type == ARG_TYPE_NONE + || (! option && (opt->flags & GRUB_ARG_OPTION_OPTIONAL)))) + { + if (! option) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("missing mandatory option for `%s'"), opt->longarg); + goto fail; + } + + switch (opt->type) + { + case ARG_TYPE_NONE: + /* This will never happen. */ + break; + + case ARG_TYPE_STRING: + /* No need to do anything. */ + break; + + case ARG_TYPE_INT: + { + const char * tail; + + grub_strtoull (option, &tail, 0); + if (tail == 0 || tail == option || *tail != '\0' || grub_errno) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("the argument `%s' requires an integer"), + arg); + + goto fail; + } + break; + } + + case ARG_TYPE_DEVICE: + case ARG_TYPE_DIR: + case ARG_TYPE_FILE: + case ARG_TYPE_PATHNAME: + /* XXX: Not implemented. */ + break; + } + if (parse_option (cmd, opt, option, usr) || grub_errno) + goto fail; + } + else + { + if (option) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("a value was assigned to the argument `%s' while it " + "doesn't require an argument"), arg); + goto fail; + } + + if (parse_option (cmd, opt, 0, usr) || grub_errno) + goto fail; + } + } + + *args = argl; + *argnum = num; + return 1; + + fail: + return 0; +} + +struct grub_arg_list* +grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, + char **argv __attribute__((unused))) +{ + int i; + char **args; + grub_size_t argcnt; + struct grub_arg_list *list; + const struct grub_arg_option *options; + grub_size_t sz0, sz1; + + options = extcmd->options; + if (! options) + return 0; + + argcnt = 0; + for (i = 0; options[i].doc; i++) + { + if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE) + argcnt += ((grub_size_t) argc + 1) / 2 + 1; /* max possible for any option */ + } + + if (grub_mul (sizeof (*list), i, &sz0) || + grub_mul (sizeof (char *), argcnt, &sz1) || + grub_add (sz0, sz1, &sz0)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + return 0; + } + + list = grub_zalloc (sz0); + if (! list) + return 0; + + args = (char**) (list + i); + for (i = 0; options[i].doc; i++) + { + list[i].set = 0; + list[i].arg = 0; + + if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE) + { + list[i].args = args; + args += (grub_size_t) argc / 2 + 1; + } + } + return list; +} diff --git a/grub-core/lib/arm/setjmp.S b/grub-core/lib/arm/setjmp.S new file mode 100644 index 0000000..a5373d3 --- /dev/null +++ b/grub-core/lib/arm/setjmp.S @@ -0,0 +1,53 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> +#include <grub/dl.h> + + .file "setjmp.S" + +GRUB_MOD_LICENSE "GPLv3+" + + .syntax unified +#if !defined (__thumb2__) + .arm +#else + .thumb +#endif + + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + mov r12, sp + stm r0, { r4-r12, lr } + mov r0, #0 + bx lr + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + ldm r0, { r4-r12, lr } + mov sp, r12 + movs r0, r1 + it eq + moveq r0, #1 + bx lr diff --git a/grub-core/lib/arm64/setjmp.S b/grub-core/lib/arm64/setjmp.S new file mode 100644 index 0000000..ffcabf6 --- /dev/null +++ b/grub-core/lib/arm64/setjmp.S @@ -0,0 +1,56 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> +#include <grub/dl.h> + + .file "setjmp.S" +GRUB_MOD_LICENSE "GPLv3+" + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + stp x19, x20, [x0], #16 + stp x21, x22, [x0], #16 + stp x23, x24, [x0], #16 + stp x25, x26, [x0], #16 + stp x27, x28, [x0], #16 + stp x29, x30, [x0], #16 + mov x1, sp + str x1, [x0] + mov x0, #0 + ret + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + ldp x19, x20, [x0], #16 + ldp x21, x22, [x0], #16 + ldp x23, x24, [x0], #16 + ldp x25, x26, [x0], #16 + ldp x27, x28, [x0], #16 + ldp x29, x30, [x0], #16 + ldr x2, [x0] + mov sp, x2 + mov x0, #1 + cmp x1, #0 + csel x0, x1, x0, ne + ret diff --git a/grub-core/lib/backtrace.c b/grub-core/lib/backtrace.c new file mode 100644 index 0000000..825a880 --- /dev/null +++ b/grub-core/lib/backtrace.c @@ -0,0 +1,70 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/misc.h> +#include <grub/command.h> +#include <grub/err.h> +#include <grub/dl.h> +#include <grub/mm.h> +#include <grub/term.h> +#include <grub/backtrace.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +void +grub_backtrace_print_address (void *addr) +{ + grub_dl_t mod; + + FOR_DL_MODULES (mod) + { + grub_dl_segment_t segment; + for (segment = mod->segment; segment; segment = segment->next) + if (segment->addr <= addr && (grub_uint8_t *) segment->addr + + segment->size > (grub_uint8_t *) addr) + { + grub_printf ("%s.%x+%" PRIxGRUB_SIZE, mod->name, segment->section, + (grub_size_t) ((grub_uint8_t *) addr - (grub_uint8_t *) segment->addr)); + return; + } + } + + grub_printf ("%p", addr); +} + +static grub_err_t +grub_cmd_backtrace (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_backtrace (); + return 0; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(backtrace) +{ + cmd = grub_register_command ("backtrace", grub_cmd_backtrace, + 0, N_("Print backtrace.")); +} + +GRUB_MOD_FINI(backtrace) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c new file mode 100644 index 0000000..ed0b149 --- /dev/null +++ b/grub-core/lib/cmdline.c @@ -0,0 +1,109 @@ +/* cmdline.c - linux command line handling */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/lib/cmdline.h> +#include <grub/misc.h> + +static unsigned int check_arg (char *c, int *has_space) +{ + int space = 0; + unsigned int size = 0; + + while (*c) + { + if (*c == '\\' || *c == '\'' || *c == '"') + size++; + else if (*c == ' ') + space = 1; + + size++; + c++; + } + + if (space) + size += 2; + + if (has_space) + *has_space = space; + + return size; +} + +unsigned int grub_loader_cmdline_size (int argc, char *argv[]) +{ + int i; + unsigned int size = 0; + + for (i = 0; i < argc; i++) + { + size += check_arg (argv[i], 0); + size++; /* Separator space or NULL. */ + } + + if (size == 0) + size = 1; + + return size; +} + +grub_err_t +grub_create_loader_cmdline (int argc, char *argv[], char *buf, + grub_size_t size, enum grub_verify_string_type type) +{ + int i, space; + unsigned int arg_size; + char *c, *orig_buf = buf; + + for (i = 0; i < argc; i++) + { + c = argv[i]; + arg_size = check_arg(argv[i], &space); + arg_size++; /* Separator space or NULL. */ + + if (size < arg_size) + break; + + size -= arg_size; + + if (space) + *buf++ = '"'; + + while (*c) + { + if (*c == '\\' || *c == '\'' || *c == '"') + *buf++ = '\\'; + + *buf++ = *c; + c++; + } + + if (space) + *buf++ = '"'; + + *buf++ = ' '; + } + + /* Replace last space with null. */ + if (i) + buf--; + + *buf = 0; + + return grub_verify_string (orig_buf, type); +} diff --git a/grub-core/lib/cmos_datetime.c b/grub-core/lib/cmos_datetime.c new file mode 100644 index 0000000..86cd911 --- /dev/null +++ b/grub-core/lib/cmos_datetime.c @@ -0,0 +1,194 @@ +/* kern/cmos_datetime.c - CMOS datetime function. + * + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/datetime.h> +#include <grub/cmos.h> +#include <grub/dl.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +#if !defined (__powerpc__) && !defined (__sparc__) +#define grub_get_datetime_cmos grub_get_datetime +#define grub_set_datetime_cmos grub_set_datetime +#endif + +grub_err_t +grub_get_datetime_cmos (struct grub_datetime *datetime) +{ + int is_bcd, is_12hour; + grub_uint8_t value, flag; + grub_err_t err; + + err = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B, &flag); + if (err) + return err; + + is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY); + + err = grub_cmos_read (GRUB_CMOS_INDEX_YEAR, &value); + if (err) + return err; + if (is_bcd) + value = grub_bcd_to_num (value); + + datetime->year = value; + datetime->year += (value < 80) ? 2000 : 1900; + + err = grub_cmos_read (GRUB_CMOS_INDEX_MONTH, &value); + if (err) + return err; + if (is_bcd) + value = grub_bcd_to_num (value); + + datetime->month = value; + + err = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH, &value); + if (err) + return err; + if (is_bcd) + value = grub_bcd_to_num (value); + + datetime->day = value; + + is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR); + + err = grub_cmos_read (GRUB_CMOS_INDEX_HOUR, &value); + if (err) + return err; + if (is_12hour) + { + is_12hour = (value & 0x80); + + value &= 0x7F; + value--; + } + + if (is_bcd) + value = grub_bcd_to_num (value); + + if (is_12hour) + value += 12; + + datetime->hour = value; + + err = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE, &value); + if (err) + return err; + + if (is_bcd) + value = grub_bcd_to_num (value); + + datetime->minute = value; + + err = grub_cmos_read (GRUB_CMOS_INDEX_SECOND, &value); + if (err) + return err; + if (is_bcd) + value = grub_bcd_to_num (value); + + datetime->second = value; + + return 0; +} + +grub_err_t +grub_set_datetime_cmos (struct grub_datetime *datetime) +{ + int is_bcd, is_12hour; + grub_uint8_t value, flag; + grub_err_t err; + + err = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B, &flag); + if (err) + return err; + + is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY); + + value = ((datetime->year >= 2000) ? datetime->year - 2000 : + datetime->year - 1900); + + if (is_bcd) + value = grub_num_to_bcd (value); + + err = grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value); + if (err) + return err; + + value = datetime->month; + + if (is_bcd) + value = grub_num_to_bcd (value); + + err = grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value); + if (err) + return err; + + value = datetime->day; + + if (is_bcd) + value = grub_num_to_bcd (value); + + err = grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value); + if (err) + return err; + + value = datetime->hour; + + is_12hour = (! (flag & GRUB_CMOS_STATUS_B_24HOUR)); + + if (is_12hour) + { + value++; + + if (value > 12) + value -= 12; + else + is_12hour = 0; + } + + if (is_bcd) + value = grub_num_to_bcd (value); + + if (is_12hour) + value |= 0x80; + + err = grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value); + if (err) + return err; + + value = datetime->minute; + + if (is_bcd) + value = grub_num_to_bcd (value); + + err = grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value); + if (err) + return err; + + value = datetime->second; + + if (is_bcd) + value = grub_num_to_bcd (value); + + err = grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value); + if (err) + return err; + + return 0; +} diff --git a/grub-core/lib/crc.c b/grub-core/lib/crc.c new file mode 100644 index 0000000..bf97cc6 --- /dev/null +++ b/grub-core/lib/crc.c @@ -0,0 +1,76 @@ +/* crc.c - crc function */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/types.h> +#include <grub/lib/crc.h> + +static grub_uint32_t crc32c_table [256]; + +/* Helper for init_crc32c_table. */ +static grub_uint32_t +reflect (grub_uint32_t ref, int len) +{ + grub_uint32_t result = 0; + int i; + + for (i = 1; i <= len; i++) + { + if (ref & 1) + result |= 1 << (len - i); + ref >>= 1; + } + + return result; +} + +static void +init_crc32c_table (void) +{ + grub_uint32_t polynomial = 0x1edc6f41; + int i, j; + + for(i = 0; i < 256; i++) + { + crc32c_table[i] = reflect(i, 8) << 24; + for (j = 0; j < 8; j++) + crc32c_table[i] = (crc32c_table[i] << 1) ^ + (crc32c_table[i] & (1 << 31) ? polynomial : 0); + crc32c_table[i] = reflect(crc32c_table[i], 32); + } +} + +grub_uint32_t +grub_getcrc32c (grub_uint32_t crc, const void *buf, int size) +{ + int i; + const grub_uint8_t *data = buf; + + if (! crc32c_table[1]) + init_crc32c_table (); + + crc^= 0xffffffff; + + for (i = 0; i < size; i++) + { + crc = (crc >> 8) ^ crc32c_table[(crc & 0xFF) ^ *data]; + data++; + } + + return crc ^ 0xffffffff; +} diff --git a/grub-core/lib/crc64.c b/grub-core/lib/crc64.c new file mode 100644 index 0000000..4960f3f --- /dev/null +++ b/grub-core/lib/crc64.c @@ -0,0 +1,114 @@ +/* crc64.c - crc64 function */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/types.h> +#include <grub/dl.h> +#include <grub/crypto.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_uint64_t crc64_table [256]; + +/* Helper for init_crc64_table. */ +static grub_uint64_t +reflect (grub_uint64_t ref, int len) +{ + grub_uint64_t result = 0; + int i; + + for (i = 1; i <= len; i++) + { + if (ref & 1) + result |= 1ULL << (len - i); + ref >>= 1; + } + + return result; +} + +static void +init_crc64_table (void) +{ + grub_uint64_t polynomial = 0x42f0e1eba9ea3693ULL; + int i, j; + + for(i = 0; i < 256; i++) + { + crc64_table[i] = reflect(i, 8) << 56; + for (j = 0; j < 8; j++) + { + crc64_table[i] = (crc64_table[i] << 1) ^ + (crc64_table[i] & (1ULL << 63) ? polynomial : 0); + } + crc64_table[i] = reflect(crc64_table[i], 64); + } +} + +static void +crc64_init (void *context) +{ + if (! crc64_table[1]) + init_crc64_table (); + *(grub_uint64_t *) context = 0; +} + +static void +crc64_write (void *context, const void *buf, grub_size_t size) +{ + unsigned i; + const grub_uint8_t *data = buf; + grub_uint64_t crc = ~grub_le_to_cpu64 (*(grub_uint64_t *) context); + + for (i = 0; i < size; i++) + { + crc = (crc >> 8) ^ crc64_table[(crc & 0xFF) ^ *data]; + data++; + } + + *(grub_uint64_t *) context = grub_cpu_to_le64 (~crc); +} + +static grub_uint8_t * +crc64_read (void *context) +{ + return context; +} + +static void +crc64_final (void *context __attribute__ ((unused))) +{ +} + +gcry_md_spec_t _gcry_digest_spec_crc64 = + { + "CRC64", 0, 0, 0, 8, + crc64_init, crc64_write, crc64_final, crc64_read, + sizeof (grub_uint64_t), + .blocksize = 64 + }; + +GRUB_MOD_INIT(crc64) +{ + grub_md_register (&_gcry_digest_spec_crc64); +} + +GRUB_MOD_FINI(crc64) +{ + grub_md_unregister (&_gcry_digest_spec_crc64); +} diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c new file mode 100644 index 0000000..ca334d5 --- /dev/null +++ b/grub-core/lib/crypto.c @@ -0,0 +1,493 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 + * 2007, 2008, 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/crypto.h> +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/term.h> +#include <grub/dl.h> +#include <grub/i18n.h> +#include <grub/env.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_crypto_hmac_handle +{ + const struct gcry_md_spec *md; + void *ctx; + void *opad; +}; + +static gcry_cipher_spec_t *grub_ciphers = NULL; +static gcry_md_spec_t *grub_digests = NULL; + +void (*grub_crypto_autoload_hook) (const char *name) = NULL; + +/* Based on libgcrypt-1.4.4/src/misc.c. */ +void +grub_burn_stack (grub_size_t size) +{ + char buf[64]; + + grub_memset (buf, 0, sizeof (buf)); + if (size > sizeof (buf)) + grub_burn_stack (size - sizeof (buf)); +} + +void +_gcry_burn_stack (int size) +{ + grub_burn_stack (size); +} + +void __attribute__ ((noreturn)) +_gcry_assert_failed (const char *expr, const char *file, int line, + const char *func) + +{ + grub_fatal ("assertion %s at %s:%d (%s) failed\n", expr, file, line, func); +} + + +void _gcry_log_error (const char *fmt, ...) +{ + va_list args; + const char *debug = grub_env_get ("debug"); + + if (! debug) + return; + + if (grub_strword (debug, "all") || grub_strword (debug, "gcrypt")) + { + grub_printf ("gcrypt error: "); + va_start (args, fmt); + grub_vprintf (fmt, args); + va_end (args); + grub_refresh (); + } +} + +void +grub_cipher_register (gcry_cipher_spec_t *cipher) +{ + cipher->next = grub_ciphers; + grub_ciphers = cipher; +} + +void +grub_cipher_unregister (gcry_cipher_spec_t *cipher) +{ + gcry_cipher_spec_t **ciph; + for (ciph = &grub_ciphers; *ciph; ciph = &((*ciph)->next)) + if (*ciph == cipher) + { + *ciph = (*ciph)->next; + break; + } +} + +void +grub_md_register (gcry_md_spec_t *digest) +{ + digest->next = grub_digests; + grub_digests = digest; +} + +void +grub_md_unregister (gcry_md_spec_t *cipher) +{ + gcry_md_spec_t **ciph; + for (ciph = &grub_digests; *ciph; ciph = &((*ciph)->next)) + if (*ciph == cipher) + { + *ciph = (*ciph)->next; + break; + } +} + +void +grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in, + grub_size_t inlen) +{ + GRUB_PROPERLY_ALIGNED_ARRAY (ctx, GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + + if (hash->contextsize > sizeof (ctx)) + grub_fatal ("Too large md context"); + hash->init (&ctx); + hash->write (&ctx, in, inlen); + hash->final (&ctx); + grub_memcpy (out, hash->read (&ctx), hash->mdlen); +} + +const gcry_md_spec_t * +grub_crypto_lookup_md_by_name (const char *name) +{ + const gcry_md_spec_t *md; + int first = 1; + while (1) + { + for (md = grub_digests; md; md = md->next) + if (grub_strcasecmp (name, md->name) == 0) + return md; + if (grub_crypto_autoload_hook && first) + grub_crypto_autoload_hook (name); + else + return NULL; + first = 0; + } +} + +const gcry_cipher_spec_t * +grub_crypto_lookup_cipher_by_name (const char *name) +{ + const gcry_cipher_spec_t *ciph; + int first = 1; + while (1) + { + for (ciph = grub_ciphers; ciph; ciph = ciph->next) + { + const char **alias; + if (grub_strcasecmp (name, ciph->name) == 0) + return ciph; + if (!ciph->aliases) + continue; + for (alias = ciph->aliases; *alias; alias++) + if (grub_strcasecmp (name, *alias) == 0) + return ciph; + } + if (grub_crypto_autoload_hook && first) + grub_crypto_autoload_hook (name); + else + return NULL; + first = 0; + } +} + + +grub_crypto_cipher_handle_t +grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher) +{ + grub_crypto_cipher_handle_t ret; + ret = grub_malloc (sizeof (*ret) + cipher->contextsize); + if (!ret) + return NULL; + ret->cipher = cipher; + return ret; +} + +gcry_err_code_t +grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher, + const unsigned char *key, + unsigned keylen) +{ + return cipher->cipher->setkey (cipher->ctx, key, keylen); +} + +gcry_err_code_t +grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher, + void *out, const void *in, grub_size_t size) +{ + const grub_uint8_t *inptr, *end; + grub_uint8_t *outptr; + grub_size_t blocksize; + if (!cipher->cipher->decrypt) + return GPG_ERR_NOT_SUPPORTED; + blocksize = cipher->cipher->blocksize; + if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) + || ((size & (blocksize - 1)) != 0)) + return GPG_ERR_INV_ARG; + end = (const grub_uint8_t *) in + size; + for (inptr = in, outptr = out; inptr < end; + inptr += blocksize, outptr += blocksize) + cipher->cipher->decrypt (cipher->ctx, outptr, inptr); + return GPG_ERR_NO_ERROR; +} + +gcry_err_code_t +grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher, + void *out, const void *in, grub_size_t size) +{ + const grub_uint8_t *inptr, *end; + grub_uint8_t *outptr; + grub_size_t blocksize; + if (!cipher->cipher->encrypt) + return GPG_ERR_NOT_SUPPORTED; + blocksize = cipher->cipher->blocksize; + if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) + || ((size & (blocksize - 1)) != 0)) + return GPG_ERR_INV_ARG; + end = (const grub_uint8_t *) in + size; + for (inptr = in, outptr = out; inptr < end; + inptr += blocksize, outptr += blocksize) + cipher->cipher->encrypt (cipher->ctx, outptr, inptr); + return GPG_ERR_NO_ERROR; +} + +gcry_err_code_t +grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher, + void *out, const void *in, grub_size_t size, + void *iv_in) +{ + grub_uint8_t *outptr; + const grub_uint8_t *inptr, *end; + void *iv; + grub_size_t blocksize; + if (!cipher->cipher->encrypt) + return GPG_ERR_NOT_SUPPORTED; + blocksize = cipher->cipher->blocksize; + if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) + || ((size & (blocksize - 1)) != 0)) + return GPG_ERR_INV_ARG; + end = (const grub_uint8_t *) in + size; + iv = iv_in; + for (inptr = in, outptr = out; inptr < end; + inptr += blocksize, outptr += blocksize) + { + grub_crypto_xor (outptr, inptr, iv, blocksize); + cipher->cipher->encrypt (cipher->ctx, outptr, outptr); + iv = outptr; + } + grub_memcpy (iv_in, iv, blocksize); + return GPG_ERR_NO_ERROR; +} + +gcry_err_code_t +grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher, + void *out, const void *in, grub_size_t size, + void *iv) +{ + const grub_uint8_t *inptr, *end; + grub_uint8_t *outptr; + grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; + grub_size_t blocksize; + if (!cipher->cipher->decrypt) + return GPG_ERR_NOT_SUPPORTED; + blocksize = cipher->cipher->blocksize; + if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) + || ((size & (blocksize - 1)) != 0)) + return GPG_ERR_INV_ARG; + if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) + return GPG_ERR_INV_ARG; + end = (const grub_uint8_t *) in + size; + for (inptr = in, outptr = out; inptr < end; + inptr += blocksize, outptr += blocksize) + { + grub_memcpy (ivt, inptr, blocksize); + cipher->cipher->decrypt (cipher->ctx, outptr, inptr); + grub_crypto_xor (outptr, outptr, iv, blocksize); + grub_memcpy (iv, ivt, blocksize); + } + return GPG_ERR_NO_ERROR; +} + +/* Based on gcry/cipher/md.c. */ +struct grub_crypto_hmac_handle * +grub_crypto_hmac_init (const struct gcry_md_spec *md, + const void *key, grub_size_t keylen) +{ + grub_uint8_t *helpkey = NULL; + grub_uint8_t *ipad = NULL, *opad = NULL; + void *ctx = NULL; + struct grub_crypto_hmac_handle *ret = NULL; + unsigned i; + + if (md->mdlen > md->blocksize) + return NULL; + + ctx = grub_malloc (md->contextsize); + if (!ctx) + goto err; + + if ( keylen > md->blocksize ) + { + helpkey = grub_malloc (md->mdlen); + if (!helpkey) + goto err; + grub_crypto_hash (md, helpkey, key, keylen); + + key = helpkey; + keylen = md->mdlen; + } + + ipad = grub_zalloc (md->blocksize); + if (!ipad) + goto err; + + opad = grub_zalloc (md->blocksize); + if (!opad) + goto err; + + grub_memcpy ( ipad, key, keylen ); + grub_memcpy ( opad, key, keylen ); + for (i=0; i < md->blocksize; i++ ) + { + ipad[i] ^= 0x36; + opad[i] ^= 0x5c; + } + grub_free (helpkey); + helpkey = NULL; + + md->init (ctx); + + md->write (ctx, ipad, md->blocksize); /* inner pad */ + grub_memset (ipad, 0, md->blocksize); + grub_free (ipad); + ipad = NULL; + + ret = grub_malloc (sizeof (*ret)); + if (!ret) + goto err; + + ret->md = md; + ret->ctx = ctx; + ret->opad = opad; + + return ret; + + err: + grub_free (helpkey); + grub_free (ctx); + grub_free (ipad); + grub_free (opad); + return NULL; +} + +void +grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, + const void *data, + grub_size_t datalen) +{ + hnd->md->write (hnd->ctx, data, datalen); +} + +gcry_err_code_t +grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out) +{ + grub_uint8_t *p; + grub_uint8_t *ctx2; + + ctx2 = grub_malloc (hnd->md->contextsize); + if (!ctx2) + return GPG_ERR_OUT_OF_MEMORY; + + hnd->md->final (hnd->ctx); + hnd->md->read (hnd->ctx); + p = hnd->md->read (hnd->ctx); + + hnd->md->init (ctx2); + hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize); + hnd->md->write (ctx2, p, hnd->md->mdlen); + hnd->md->final (ctx2); + grub_memset (hnd->opad, 0, hnd->md->blocksize); + grub_free (hnd->opad); + grub_memset (hnd->ctx, 0, hnd->md->contextsize); + grub_free (hnd->ctx); + + grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen); + grub_memset (ctx2, 0, hnd->md->contextsize); + grub_free (ctx2); + + grub_memset (hnd, 0, sizeof (*hnd)); + grub_free (hnd); + + return GPG_ERR_NO_ERROR; +} + +gcry_err_code_t +grub_crypto_hmac_buffer (const struct gcry_md_spec *md, + const void *key, grub_size_t keylen, + const void *data, grub_size_t datalen, void *out) +{ + struct grub_crypto_hmac_handle *hnd; + + hnd = grub_crypto_hmac_init (md, key, keylen); + if (!hnd) + return GPG_ERR_OUT_OF_MEMORY; + + grub_crypto_hmac_write (hnd, data, datalen); + return grub_crypto_hmac_fini (hnd, out); +} + + +grub_err_t +grub_crypto_gcry_error (gcry_err_code_t in) +{ + if (in == GPG_ERR_NO_ERROR) + return GRUB_ERR_NONE; + return GRUB_ACCESS_DENIED; +} + +int +grub_crypto_memcmp (const void *a, const void *b, grub_size_t n) +{ + register grub_size_t counter = 0; + const grub_uint8_t *pa, *pb; + + for (pa = a, pb = b; n; pa++, pb++, n--) + { + if (*pa != *pb) + counter++; + } + + return !!counter; +} + +#ifndef GRUB_UTIL + +int +grub_password_get (char buf[], unsigned buf_size) +{ + unsigned cur_len = 0; + int key; + + while (1) + { + key = grub_getkey (); + if (key == '\n' || key == '\r') + break; + + if (key == GRUB_TERM_ESC) + { + cur_len = 0; + break; + } + + if (key == '\b') + { + if (cur_len) + cur_len--; + continue; + } + + if (!grub_isprint (key)) + continue; + + if (cur_len + 2 < buf_size) + buf[cur_len++] = key; + } + + grub_memset (buf + cur_len, 0, buf_size - cur_len); + + grub_xputs ("\n"); + grub_refresh (); + + return (key != GRUB_TERM_ESC); +} +#endif + diff --git a/grub-core/lib/datetime.c b/grub-core/lib/datetime.c new file mode 100644 index 0000000..9120128 --- /dev/null +++ b/grub-core/lib/datetime.c @@ -0,0 +1,117 @@ +/* datetime.c - Module for common datetime function. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/datetime.h> +#include <grub/i18n.h> +#include <grub/misc.h> +#include <grub/mm.h> + +static const char *const grub_weekday_names[] = +{ + N_("Sunday"), + N_("Monday"), + N_("Tuesday"), + N_("Wednesday"), + N_("Thursday"), + N_("Friday"), + N_("Saturday"), +}; + +int +grub_get_weekday (struct grub_datetime *datetime) +{ + unsigned a, y, m; + + if (datetime->month <= 2) + a = 1; + else + a = 0; + y = datetime->year - a; + m = datetime->month + 12 * a - 2; + + return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7; +} + +const char * +grub_get_weekday_name (struct grub_datetime *datetime) +{ + return _ (grub_weekday_names[grub_get_weekday (datetime)]); +} + +#define SECPERMIN 60 +#define SECPERHOUR (60*SECPERMIN) +#define SECPERDAY (24*SECPERHOUR) +#define DAYSPERYEAR 365 +#define DAYSPER4YEARS (4*DAYSPERYEAR+1) + + +void +grub_unixtime2datetime (grub_int64_t nix, struct grub_datetime *datetime) +{ + int i; + grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + /* In the period of validity of unixtime all years divisible by 4 + are bissextile*/ + /* Convenience: let's have 3 consecutive non-bissextile years + at the beginning of the counting date. So count from 1901. */ + int days_epoch; + /* Number of days since 1st Januar, 1901. */ + unsigned days; + /* Seconds into current day. */ + unsigned secs_in_day; + + /* Transform C divisions and modulos to mathematical ones */ + if (nix < 0) + /* + * The result of division here shouldn't be larger than GRUB_INT_MAX. + * So, it's safe to store the result back in an int. + */ + days_epoch = -(grub_divmod64 (((grub_int64_t) (SECPERDAY) - nix - 1), SECPERDAY, NULL)); + else + days_epoch = grub_divmod64 (nix, SECPERDAY, NULL); + + secs_in_day = nix - days_epoch * SECPERDAY; + days = days_epoch + 69 * DAYSPERYEAR + 17; + + datetime->year = 1901 + 4 * (days / DAYSPER4YEARS); + days %= DAYSPER4YEARS; + /* On 31st December of bissextile years 365 days from the beginning + of the year elapsed but year isn't finished yet */ + if (days / DAYSPERYEAR == 4) + { + datetime->year += 3; + days -= 3*DAYSPERYEAR; + } + else + { + datetime->year += days / DAYSPERYEAR; + days %= DAYSPERYEAR; + } + for (i = 0; i < 12 + && days >= (i==1 && datetime->year % 4 == 0 + ? 29 : months[i]); i++) + days -= (i==1 && datetime->year % 4 == 0 + ? 29 : months[i]); + datetime->month = i + 1; + datetime->day = 1 + days; + datetime->hour = (secs_in_day / SECPERHOUR); + secs_in_day %= SECPERHOUR; + datetime->minute = secs_in_day / SECPERMIN; + datetime->second = secs_in_day % SECPERMIN; +} diff --git a/grub-core/lib/disk.c b/grub-core/lib/disk.c new file mode 100644 index 0000000..b4eb064 --- /dev/null +++ b/grub-core/lib/disk.c @@ -0,0 +1,161 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2004,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/disk.h> +#include <grub/err.h> +#include <grub/mm.h> +#include <grub/types.h> +#include <grub/partition.h> +#include <grub/misc.h> +#include <grub/time.h> +#include <grub/file.h> +#include <grub/i18n.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +#include "../kern/disk_common.c" + +static void +grub_disk_cache_invalidate (unsigned long dev_id, unsigned long disk_id, + grub_disk_addr_t sector) +{ + unsigned cache_index; + struct grub_disk_cache *cache; + + sector &= ~((grub_disk_addr_t) GRUB_DISK_CACHE_SIZE - 1); + cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); + cache = grub_disk_cache_table + cache_index; + + if (cache->dev_id == dev_id && cache->disk_id == disk_id + && cache->sector == sector && cache->data) + { + cache->lock = 1; + grub_free (cache->data); + cache->data = 0; + cache->lock = 0; + } +} + +grub_err_t +grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, const void *buf) +{ + unsigned real_offset; + grub_disk_addr_t aligned_sector; + + grub_dprintf ("disk", "Writing `%s'...\n", disk->name); + + if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) + return -1; + + aligned_sector = (sector & ~((1ULL << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) - 1)); + real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS); + sector = aligned_sector; + + while (size) + { + if (real_offset != 0 || (size < (1U << disk->log_sector_size) + && size != 0)) + { + char *tmp_buf; + grub_size_t len; + grub_partition_t part; + + tmp_buf = grub_malloc (1U << disk->log_sector_size); + if (!tmp_buf) + return grub_errno; + + part = disk->partition; + disk->partition = 0; + if (grub_disk_read (disk, sector, + 0, (1U << disk->log_sector_size), tmp_buf) + != GRUB_ERR_NONE) + { + disk->partition = part; + grub_free (tmp_buf); + goto finish; + } + disk->partition = part; + + len = (1U << disk->log_sector_size) - real_offset; + if (len > size) + len = size; + + grub_memcpy (tmp_buf + real_offset, buf, len); + + grub_disk_cache_invalidate (disk->dev->id, disk->id, sector); + + if ((disk->dev->disk_write) (disk, transform_sector (disk, sector), + 1, tmp_buf) != GRUB_ERR_NONE) + { + grub_free (tmp_buf); + goto finish; + } + + grub_free (tmp_buf); + + sector += (1U << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); + buf = (const char *) buf + len; + size -= len; + real_offset = 0; + } + else + { + grub_size_t len; + grub_size_t n; + + len = size & ~((1ULL << disk->log_sector_size) - 1); + n = size >> disk->log_sector_size; + + if (n > (disk->max_agglomerate + << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size))) + n = (disk->max_agglomerate + << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size)); + + if ((disk->dev->disk_write) (disk, transform_sector (disk, sector), + n, buf) != GRUB_ERR_NONE) + goto finish; + + while (n--) + { + grub_disk_cache_invalidate (disk->dev->id, disk->id, sector); + sector += (1U << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); + } + + buf = (const char *) buf + len; + size -= len; + } + } + + finish: + + return grub_errno; +} + +GRUB_MOD_INIT(disk) +{ + grub_disk_write_weak = grub_disk_write; +} + +GRUB_MOD_FINI(disk) +{ + grub_disk_write_weak = NULL; +} diff --git a/grub-core/lib/division.c b/grub-core/lib/division.c new file mode 100644 index 0000000..35606fe --- /dev/null +++ b/grub-core/lib/division.c @@ -0,0 +1,74 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2015 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/misc.h> +#include <grub/dl.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_uint64_t +abs64(grub_int64_t a) +{ + return a > 0 ? a : -a; +} + +grub_int64_t +grub_divmod64s (grub_int64_t n, + grub_int64_t d, + grub_int64_t *ro) +{ + grub_uint64_t ru; + grub_int64_t q, r; + q = grub_divmod64 (abs64(n), abs64(d), &ru); + r = ru; + /* Now: |n| = |d| * q + r */ + if (n < 0) + { + /* -|n| = |d| * (-q) + (-r) */ + q = -q; + r = -r; + } + /* Now: n = |d| * q + r */ + if (d < 0) + { + /* n = (-|d|) * (-q) + r */ + q = -q; + } + /* Now: n = d * q + r */ + if (ro) + *ro = r; + return q; +} + +grub_uint32_t +grub_divmod32 (grub_uint32_t n, grub_uint32_t d, grub_uint32_t *ro) +{ + grub_uint64_t q, r; + q = grub_divmod64 (n, d, &r); + *ro = r; + return q; +} + +grub_int32_t +grub_divmod32s (grub_int32_t n, grub_int32_t d, grub_int32_t *ro) +{ + grub_int64_t q, r; + q = grub_divmod64s (n, d, &r); + *ro = r; + return q; +} diff --git a/grub-core/lib/dummy/datetime.c b/grub-core/lib/dummy/datetime.c new file mode 100644 index 0000000..cf693fc --- /dev/null +++ b/grub-core/lib/dummy/datetime.c @@ -0,0 +1,40 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/types.h> +#include <grub/symbol.h> +#include <grub/datetime.h> +#include <grub/dl.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* No simple platform-independent RTC access exists in U-Boot. */ + +grub_err_t +grub_get_datetime (struct grub_datetime *datetime __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_INVALID_COMMAND, + "can\'t get datetime on this machine"); +} + +grub_err_t +grub_set_datetime (struct grub_datetime * datetime __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_INVALID_COMMAND, + "can\'t set datetime on this machine"); +} diff --git a/grub-core/lib/dummy/halt.c b/grub-core/lib/dummy/halt.c new file mode 100644 index 0000000..378d50f --- /dev/null +++ b/grub-core/lib/dummy/halt.c @@ -0,0 +1,32 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/kernel.h> +#include <grub/loader.h> + +void +grub_halt (void) +{ + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); + + /* Just stop here */ + + while (1); +} diff --git a/grub-core/lib/dummy/reboot.c b/grub-core/lib/dummy/reboot.c new file mode 100644 index 0000000..b8cbed8 --- /dev/null +++ b/grub-core/lib/dummy/reboot.c @@ -0,0 +1,32 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/kernel.h> +#include <grub/loader.h> + +void +grub_reboot (void) +{ + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); + + /* Just stop here */ + + while (1); +} diff --git a/grub-core/lib/efi/datetime.c b/grub-core/lib/efi/datetime.c new file mode 100644 index 0000000..0fd1b5f --- /dev/null +++ b/grub-core/lib/efi/datetime.c @@ -0,0 +1,82 @@ +/* kern/efi/datetime.c - efi datetime function. + * + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/types.h> +#include <grub/symbol.h> +#include <grub/efi/api.h> +#include <grub/efi/efi.h> +#include <grub/datetime.h> +#include <grub/dl.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +grub_err_t +grub_get_datetime (struct grub_datetime *datetime) +{ + grub_efi_status_t status; + struct grub_efi_time efi_time; + + status = efi_call_2 (grub_efi_system_table->runtime_services->get_time, + &efi_time, 0); + + if (status) + return grub_error (GRUB_ERR_INVALID_COMMAND, + "can\'t get datetime using efi"); + else + { + datetime->year = efi_time.year; + datetime->month = efi_time.month; + datetime->day = efi_time.day; + datetime->hour = efi_time.hour; + datetime->minute = efi_time.minute; + datetime->second = efi_time.second; + } + + return 0; +} + +grub_err_t +grub_set_datetime (struct grub_datetime *datetime) +{ + grub_efi_status_t status; + struct grub_efi_time efi_time; + + status = efi_call_2 (grub_efi_system_table->runtime_services->get_time, + &efi_time, 0); + + if (status) + return grub_error (GRUB_ERR_INVALID_COMMAND, + "can\'t get datetime using efi"); + + efi_time.year = datetime->year; + efi_time.month = datetime->month; + efi_time.day = datetime->day; + efi_time.hour = datetime->hour; + efi_time.minute = datetime->minute; + efi_time.second = datetime->second; + + status = efi_call_1 (grub_efi_system_table->runtime_services->set_time, + &efi_time); + + if (status) + return grub_error (GRUB_ERR_INVALID_COMMAND, + "can\'t set datetime using efi"); + + return 0; +} diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c new file mode 100644 index 0000000..29d4136 --- /dev/null +++ b/grub-core/lib/efi/halt.c @@ -0,0 +1,41 @@ +/* efi.c - generic EFI support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/efi/api.h> +#include <grub/efi/efi.h> +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/kernel.h> +#include <grub/acpi.h> +#include <grub/loader.h> + +void +grub_halt (void) +{ + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN | + GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY); +#if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) && \ + !defined(__riscv) + grub_acpi_halt (); +#endif + efi_call_4 (grub_efi_system_table->runtime_services->reset_system, + GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); + + while (1); +} diff --git a/grub-core/lib/efi/relocator.c b/grub-core/lib/efi/relocator.c new file mode 100644 index 0000000..319b69e --- /dev/null +++ b/grub-core/lib/efi/relocator.c @@ -0,0 +1,119 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/relocator.h> +#include <grub/relocator_private.h> +#include <grub/memory.h> +#include <grub/efi/efi.h> +#include <grub/efi/api.h> +#include <grub/term.h> + +#define NEXT_MEMORY_DESCRIPTOR(desc, size) \ + ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) + +unsigned +grub_relocator_firmware_get_max_events (void) +{ + grub_efi_uintn_t mmapsize = 0, descriptor_size = 0; + grub_efi_uint32_t descriptor_version = 0; + grub_efi_uintn_t key; + grub_efi_get_memory_map (&mmapsize, NULL, &key, &descriptor_size, + &descriptor_version); + /* Since grub_relocator_firmware_fill_events uses malloc + we need some reserve. Hence +10. */ + return 2 * (mmapsize / descriptor_size + 10); +} + +unsigned +grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) +{ + grub_efi_uintn_t mmapsize = 0, desc_size = 0; + grub_efi_uint32_t descriptor_version = 0; + grub_efi_memory_descriptor_t *descs = NULL; + grub_efi_uintn_t key; + int counter = 0; + grub_efi_memory_descriptor_t *desc; + + grub_efi_get_memory_map (&mmapsize, NULL, &key, &desc_size, + &descriptor_version); + descs = grub_malloc (mmapsize); + if (!descs) + return 0; + + grub_efi_get_memory_map (&mmapsize, descs, &key, &desc_size, + &descriptor_version); + + for (desc = descs; + (char *) desc < ((char *) descs + mmapsize); + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) + { + grub_uint64_t start = desc->physical_start; + grub_uint64_t end = desc->physical_start + (desc->num_pages << 12); + + /* post-4G addresses are never supported on 32-bit EFI. + Moreover it has been reported that some 64-bit EFI contrary to the + spec don't map post-4G pages. So if you enable post-4G allocations, + map pages manually or check that they are mapped. + */ + if (end >= 0x100000000ULL) + end = 0x100000000ULL; + if (end <= start) + continue; + if (desc->type != GRUB_EFI_CONVENTIONAL_MEMORY) + continue; + events[counter].type = REG_FIRMWARE_START; + events[counter].pos = start; + counter++; + events[counter].type = REG_FIRMWARE_END; + events[counter].pos = end; + counter++; + } + + return counter; +} + +int +grub_relocator_firmware_alloc_region (grub_addr_t start, grub_size_t size) +{ + grub_efi_boot_services_t *b; + grub_efi_physical_address_t address = start; + grub_efi_status_t status; + + if (grub_efi_is_finished) + return 1; +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF + grub_dprintf ("relocator", "EFI alloc: %llx, %llx\n", + (unsigned long long) start, (unsigned long long) size); +#endif + b = grub_efi_system_table->boot_services; + status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ADDRESS, + GRUB_EFI_LOADER_DATA, size >> 12, &address); + return (status == GRUB_EFI_SUCCESS); +} + +void +grub_relocator_firmware_free_region (grub_addr_t start, grub_size_t size) +{ + grub_efi_boot_services_t *b; + + if (grub_efi_is_finished) + return; + + b = grub_efi_system_table->boot_services; + efi_call_2 (b->free_pages, start, size >> 12); +} diff --git a/grub-core/lib/emu/halt.c b/grub-core/lib/emu/halt.c new file mode 100644 index 0000000..620935b --- /dev/null +++ b/grub-core/lib/emu/halt.c @@ -0,0 +1,25 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/misc.h> + +void +grub_halt (void) +{ + grub_reboot (); +} diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c new file mode 100644 index 0000000..2e4e78b --- /dev/null +++ b/grub-core/lib/envblk.c @@ -0,0 +1,297 @@ +/* envblk.c - Common functions for environment block. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <grub/types.h> +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/lib/envblk.h> + +grub_envblk_t +grub_envblk_open (char *buf, grub_size_t size) +{ + grub_envblk_t envblk; + + if (size < sizeof (GRUB_ENVBLK_SIGNATURE) + || grub_memcmp (buf, GRUB_ENVBLK_SIGNATURE, + sizeof (GRUB_ENVBLK_SIGNATURE) - 1)) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block"); + return 0; + } + + envblk = grub_malloc (sizeof (*envblk)); + if (envblk) + { + envblk->buf = buf; + envblk->size = size; + } + + return envblk; +} + +void +grub_envblk_close (grub_envblk_t envblk) +{ + grub_free (envblk->buf); + grub_free (envblk); +} + +static int +escaped_value_len (const char *value) +{ + int n = 0; + char *p; + + for (p = (char *) value; *p; p++) + { + if (*p == '\\' || *p == '\n') + n += 2; + else + n++; + } + + return n; +} + +static char * +find_next_line (char *p, const char *pend) +{ + while (p < pend) + { + if (*p == '\\') + p += 2; + else if (*p == '\n') + break; + else + p++; + } + + return p + 1; +} + +int +grub_envblk_set (grub_envblk_t envblk, const char *name, const char *value) +{ + char *p, *pend; + char *space; + int found = 0; + int nl; + int vl; + int i; + + nl = grub_strlen (name); + vl = escaped_value_len (value); + p = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1; + pend = envblk->buf + envblk->size; + + /* First, look at free space. */ + for (space = pend - 1; *space == '#'; space--) + ; + + if (*space != '\n') + /* Broken. */ + return 0; + + space++; + + while (p + nl + 1 < space) + { + if (grub_memcmp (p, name, nl) == 0 && p[nl] == '=') + { + int len; + + /* Found the same name. */ + p += nl + 1; + + /* Check the length of the current value. */ + len = 0; + while (p + len < pend && p[len] != '\n') + { + if (p[len] == '\\') + len += 2; + else + len++; + } + + if (p + len >= pend) + /* Broken. */ + return 0; + + if (pend - space < vl - len) + /* No space. */ + return 0; + + if (vl < len) + { + /* Move the following characters backward, and fill the new + space with harmless characters. */ + grub_memmove (p + vl, p + len, pend - (p + len)); + grub_memset (space - (len - vl), '#', len - vl); + } + else + /* Move the following characters forward. */ + grub_memmove (p + vl, p + len, pend - (p + vl)); + + found = 1; + break; + } + + p = find_next_line (p, pend); + } + + if (! found) + { + /* Append a new variable. */ + + if (pend - space < nl + 1 + vl + 1) + /* No space. */ + return 0; + + grub_memcpy (space, name, nl); + p = space + nl; + *p++ = '='; + } + + /* Write the value. */ + for (i = 0; value[i]; i++) + { + if (value[i] == '\\' || value[i] == '\n') + *p++ = '\\'; + + *p++ = value[i]; + } + + *p = '\n'; + return 1; +} + +void +grub_envblk_delete (grub_envblk_t envblk, const char *name) +{ + char *p, *pend; + int nl; + + nl = grub_strlen (name); + p = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1; + pend = envblk->buf + envblk->size; + + while (p + nl + 1 < pend) + { + if (grub_memcmp (p, name, nl) == 0 && p[nl] == '=') + { + /* Found. */ + int len = nl + 1; + + while (p + len < pend) + { + if (p[len] == '\n') + break; + else if (p[len] == '\\') + len += 2; + else + len++; + } + + if (p + len >= pend) + /* Broken. */ + return; + + len++; + grub_memmove (p, p + len, pend - (p + len)); + grub_memset (pend - len, '#', len); + break; + } + + p = find_next_line (p, pend); + } +} + +void +grub_envblk_iterate (grub_envblk_t envblk, + void *hook_data, + int hook (const char *name, const char *value, void *hook_data)) +{ + char *p, *pend; + + p = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1; + pend = envblk->buf + envblk->size; + + while (p < pend) + { + if (*p != '#') + { + char *name; + char *value; + char *name_start, *name_end, *value_start; + char *q; + int ret; + + name_start = p; + while (p < pend && *p != '=') + p++; + if (p == pend) + /* Broken. */ + return; + name_end = p; + + p++; + value_start = p; + while (p < pend) + { + if (*p == '\n') + break; + else if (*p == '\\') + p += 2; + else + p++; + } + + if (p >= pend) + /* Broken. */ + return; + + name = grub_malloc (p - name_start + 1); + if (! name) + /* out of memory. */ + return; + + value = name + (value_start - name_start); + + grub_memcpy (name, name_start, name_end - name_start); + name[name_end - name_start] = '\0'; + + for (p = value_start, q = value; *p != '\n'; ++p) + { + if (*p == '\\') + *q++ = *++p; + else + *q++ = *p; + } + *q = '\0'; + + ret = hook (name, value, hook_data); + grub_free (name); + if (ret) + return; + } + + p = find_next_line (p, pend); + } +} diff --git a/grub-core/lib/fake_module.c b/grub-core/lib/fake_module.c new file mode 100644 index 0000000..3646ced --- /dev/null +++ b/grub-core/lib/fake_module.c @@ -0,0 +1,4 @@ +/* This file is intentionally empty: it's used to generate modules with no code or data. (purely dependency modules) */ +#include <grub/dl.h> + +GRUB_MOD_LICENSE ("GPLv3+"); diff --git a/grub-core/lib/fdt.c b/grub-core/lib/fdt.c new file mode 100644 index 0000000..0d371c5 --- /dev/null +++ b/grub-core/lib/fdt.c @@ -0,0 +1,531 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/fdt.h> +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/dl.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define FDT_SUPPORTED_VERSION 17 + +#define FDT_BEGIN_NODE 0x00000001 +#define FDT_END_NODE 0x00000002 +#define FDT_PROP 0x00000003 +#define FDT_NOP 0x00000004 +#define FDT_END 0x00000009 + +#define struct_end(fdt) \ + ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt) \ + + grub_fdt_get_size_dt_struct(fdt)) + +/* Size needed by a node entry: 2 tokens (FDT_BEGIN_NODE and FDT_END_NODE), plus + the NULL-terminated string containing the name, plus padding if needed. */ +#define node_entry_size(node_name) \ + (2 * sizeof(grub_uint32_t) \ + + ALIGN_UP (grub_strlen (name) + 1, sizeof(grub_uint32_t))) + +#define SKIP_NODE_NAME(name, token, end) \ + name = (char *) ((token) + 1); \ + while (name < (char *) end) \ + { \ + if (!*name++) \ + break; \ + } \ + token = (grub_uint32_t *) ALIGN_UP((grub_addr_t) (name), sizeof(*token)) + + +static grub_uint32_t *get_next_node (const void *fdt, char *node_name) +{ + grub_uint32_t *end = (void *) struct_end (fdt); + grub_uint32_t *token; + + if (node_name >= (char *) end) + return NULL; + while (*node_name++) + { + if (node_name >= (char *) end) + return NULL; + } + token = (grub_uint32_t *) ALIGN_UP ((grub_addr_t) node_name, 4); + while (token < end) + { + switch (grub_be_to_cpu32(*token)) + { + case FDT_BEGIN_NODE: + token = get_next_node (fdt, (char *) (token + 1)); + if (!token) + return NULL; + break; + case FDT_END_NODE: + token++; + if (token >= end) + return NULL; + return token; + case FDT_PROP: + /* Skip property token and following data (len, nameoff and property + value). */ + token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1))) + / sizeof(*token); + break; + case FDT_NOP: + token++; + break; + default: + return NULL; + } + } + return NULL; +} + +static int get_mem_rsvmap_size (const void *fdt) +{ + int size = 0; + grub_unaligned_uint64_t *ptr = (void *) ((grub_addr_t) fdt + + grub_fdt_get_off_mem_rsvmap (fdt)); + + do + { + size += 2 * sizeof(*ptr); + if (!ptr[0].val && !ptr[1].val) + return size; + ptr += 2; + } while ((grub_addr_t) ptr <= (grub_addr_t) fdt + grub_fdt_get_totalsize (fdt) + - 2 * sizeof(grub_uint64_t)); + return -1; +} + +static grub_uint32_t get_free_space (void *fdt) +{ + int mem_rsvmap_size = get_mem_rsvmap_size (fdt); + + if (mem_rsvmap_size < 0) + /* invalid memory reservation block */ + return 0; + return (grub_fdt_get_totalsize (fdt) - sizeof(grub_fdt_header_t) + - mem_rsvmap_size - grub_fdt_get_size_dt_strings (fdt) + - grub_fdt_get_size_dt_struct (fdt)); +} + +static int add_subnode (void *fdt, int parentoffset, const char *name) +{ + grub_uint32_t *token = (void *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct(fdt) + + parentoffset); + grub_uint32_t *end = (void *) struct_end (fdt); + unsigned int entry_size = node_entry_size (name); + unsigned int struct_size = grub_fdt_get_size_dt_struct(fdt); + char *node_name; + + SKIP_NODE_NAME(node_name, token, end); + + /* Insert the new subnode just after the properties of the parent node (if + any).*/ + while (1) + { + if (token >= end) + return -1; + switch (grub_be_to_cpu32(*token)) + { + case FDT_PROP: + /* Skip len, nameoff and property value. */ + token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1))) + / sizeof(*token); + break; + case FDT_BEGIN_NODE: + case FDT_END_NODE: + goto insert; + case FDT_NOP: + token++; + break; + default: + /* invalid token */ + return -1; + } + } +insert: + grub_memmove (token + entry_size / sizeof(*token), token, + (grub_addr_t) end - (grub_addr_t) token); + *token = grub_cpu_to_be32_compile_time(FDT_BEGIN_NODE); + token[entry_size / sizeof(*token) - 2] = 0; /* padding bytes */ + grub_strcpy((char *) (token + 1), name); + token[entry_size / sizeof(*token) - 1] = grub_cpu_to_be32_compile_time(FDT_END_NODE); + grub_fdt_set_size_dt_struct (fdt, struct_size + entry_size); + return ((grub_addr_t) token - (grub_addr_t) fdt + - grub_fdt_get_off_dt_struct(fdt)); +} + +/* Rearrange FDT blocks in the canonical order: first the memory reservation + block (just after the FDT header), then the structure block and finally the + strings block. No free space is left between the first and the second block, + while the space between the second and the third block is given by the + clearance argument. */ +static int rearrange_blocks (void *fdt, unsigned int clearance) +{ + grub_uint32_t off_mem_rsvmap = ALIGN_UP(sizeof(grub_fdt_header_t), 8); + grub_uint32_t off_dt_struct = off_mem_rsvmap + get_mem_rsvmap_size (fdt); + grub_uint32_t off_dt_strings = off_dt_struct + + grub_fdt_get_size_dt_struct (fdt) + + clearance; + grub_uint8_t *fdt_ptr = fdt; + grub_uint8_t *tmp_fdt; + + if ((grub_fdt_get_off_mem_rsvmap (fdt) == off_mem_rsvmap) + && (grub_fdt_get_off_dt_struct (fdt) == off_dt_struct)) + { + /* No need to allocate memory for a temporary FDT, just move the strings + block if needed. */ + if (grub_fdt_get_off_dt_strings (fdt) != off_dt_strings) + { + grub_memmove(fdt_ptr + off_dt_strings, + fdt_ptr + grub_fdt_get_off_dt_strings (fdt), + grub_fdt_get_size_dt_strings (fdt)); + grub_fdt_set_off_dt_strings (fdt, off_dt_strings); + } + return 0; + } + tmp_fdt = grub_malloc (grub_fdt_get_totalsize (fdt)); + if (!tmp_fdt) + return -1; + grub_memcpy (tmp_fdt + off_mem_rsvmap, + fdt_ptr + grub_fdt_get_off_mem_rsvmap (fdt), + get_mem_rsvmap_size (fdt)); + grub_fdt_set_off_mem_rsvmap (fdt, off_mem_rsvmap); + grub_memcpy (tmp_fdt + off_dt_struct, + fdt_ptr + grub_fdt_get_off_dt_struct (fdt), + grub_fdt_get_size_dt_struct (fdt)); + grub_fdt_set_off_dt_struct (fdt, off_dt_struct); + grub_memcpy (tmp_fdt + off_dt_strings, + fdt_ptr + grub_fdt_get_off_dt_strings (fdt), + grub_fdt_get_size_dt_strings (fdt)); + grub_fdt_set_off_dt_strings (fdt, off_dt_strings); + + /* Copy reordered blocks back to fdt. */ + grub_memcpy (fdt_ptr + off_mem_rsvmap, tmp_fdt + off_mem_rsvmap, + grub_fdt_get_totalsize (fdt) - off_mem_rsvmap); + + grub_free(tmp_fdt); + return 0; +} + +static grub_uint32_t *find_prop (const void *fdt, unsigned int nodeoffset, + const char *name) +{ + grub_uint32_t *prop = (void *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct (fdt) + + nodeoffset); + grub_uint32_t *end = (void *) struct_end(fdt); + grub_uint32_t nameoff; + char *node_name; + + SKIP_NODE_NAME(node_name, prop, end); + while (prop < end - 2) + { + if (grub_be_to_cpu32(*prop) == FDT_PROP) + { + nameoff = grub_be_to_cpu32(*(prop + 2)); + if ((nameoff + grub_strlen (name) < grub_fdt_get_size_dt_strings (fdt)) + && !grub_strcmp (name, (char *) fdt + + grub_fdt_get_off_dt_strings (fdt) + nameoff)) + { + if (prop + grub_fdt_prop_entry_size(grub_be_to_cpu32(*(prop + 1))) + / sizeof (*prop) >= end) + return NULL; + return prop; + } + prop += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(prop + 1))) / sizeof (*prop); + } + else if (grub_be_to_cpu32(*prop) == FDT_NOP) + prop++; + else + return NULL; + } + return NULL; +} + +/* Check the FDT header for consistency and adjust the totalsize field to match + the size allocated for the FDT; if this function is called before the other + functions in this file and returns success, the other functions are + guaranteed not to access memory locations outside the allocated memory. */ +int grub_fdt_check_header_nosize (const void *fdt) +{ + if (((grub_addr_t) fdt & 0x3) || (grub_fdt_get_magic (fdt) != FDT_MAGIC) + || (grub_fdt_get_version (fdt) < FDT_SUPPORTED_VERSION) + || (grub_fdt_get_last_comp_version (fdt) > FDT_SUPPORTED_VERSION) + || (grub_fdt_get_off_dt_struct (fdt) & 0x00000003) + || (grub_fdt_get_size_dt_struct (fdt) & 0x00000003) + || (grub_fdt_get_off_dt_struct (fdt) + grub_fdt_get_size_dt_struct (fdt) + > grub_fdt_get_totalsize (fdt)) + || (grub_fdt_get_off_dt_strings (fdt) + grub_fdt_get_size_dt_strings (fdt) + > grub_fdt_get_totalsize (fdt)) + || (grub_fdt_get_off_mem_rsvmap (fdt) & 0x00000007) + || (grub_fdt_get_off_mem_rsvmap (fdt) + > grub_fdt_get_totalsize (fdt) - 2 * sizeof(grub_uint64_t))) + return -1; + return 0; +} + +int grub_fdt_check_header (const void *fdt, unsigned int size) +{ + if (size < sizeof (grub_fdt_header_t) + || (grub_fdt_get_totalsize (fdt) > size) + || grub_fdt_check_header_nosize (fdt) == -1) + return -1; + return 0; +} + +static const grub_uint32_t * +advance_token (const void *fdt, const grub_uint32_t *token, const grub_uint32_t *end, int skip_current) +{ + for (; token < end; skip_current = 0) + { + switch (grub_be_to_cpu32 (*token)) + { + case FDT_BEGIN_NODE: + if (skip_current) + { + token = get_next_node (fdt, (char *) (token + 1)); + continue; + } + char *ptr; + for (ptr = (char *) (token + 1); *ptr && ptr < (char *) end; ptr++) + ; + if (ptr >= (char *) end) + return 0; + return token; + case FDT_PROP: + /* Skip property token and following data (len, nameoff and property + value). */ + if (token >= end - 1) + return 0; + token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1))) + / sizeof(*token); + break; + case FDT_NOP: + token++; + break; + default: + return 0; + } + } + return 0; +} + +int grub_fdt_next_node (const void *fdt, unsigned int currentoffset) +{ + const grub_uint32_t *token = (const grub_uint32_t *) fdt + (currentoffset + grub_fdt_get_off_dt_struct (fdt)) / 4; + token = advance_token (fdt, token, (const void *) struct_end (fdt), 1); + if (!token) + return -1; + return (int) ((grub_addr_t) token - (grub_addr_t) fdt + - grub_fdt_get_off_dt_struct (fdt)); +} + +int grub_fdt_first_node (const void *fdt, unsigned int parentoffset) +{ + const grub_uint32_t *token, *end; + char *node_name; + + if (parentoffset & 0x3) + return -1; + token = (const void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt) + + parentoffset); + end = (const void *) struct_end (fdt); + if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE)) + return -1; + SKIP_NODE_NAME(node_name, token, end); + token = advance_token (fdt, token, end, 0); + if (!token) + return -1; + return (int) ((grub_addr_t) token - (grub_addr_t) fdt + - grub_fdt_get_off_dt_struct (fdt)); +} + +/* Find a direct sub-node of a given parent node. */ +int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset, + const char *name) +{ + const grub_uint32_t *token, *end; + const char *node_name; + int skip_current = 0; + + if (parentoffset & 0x3) + return -1; + token = (const void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt) + + parentoffset); + end = (const void *) struct_end (fdt); + if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE)) + return -1; + SKIP_NODE_NAME(node_name, token, end); + while (1) { + token = advance_token (fdt, token, end, skip_current); + if (!token) + return -1; + skip_current = 1; + node_name = (const char *) token + 4; + if (grub_strcmp (node_name, name) == 0) + return (int) ((grub_addr_t) token - (grub_addr_t) fdt + - grub_fdt_get_off_dt_struct (fdt)); + } +} + +const char * +grub_fdt_get_nodename (const void *fdt, unsigned int nodeoffset) +{ + return (const char *) fdt + grub_fdt_get_off_dt_struct(fdt) + nodeoffset + 4; +} + +int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset, + const char *name) +{ + unsigned int entry_size = node_entry_size(name); + + if ((parentoffset & 0x3) || (get_free_space (fdt) < entry_size)) + return -1; + + /* The new node entry will increase the size of the structure block: rearrange + blocks such that there is sufficient free space between the structure and + the strings block, then add the new node entry. */ + if (rearrange_blocks (fdt, entry_size) < 0) + return -1; + return add_subnode (fdt, parentoffset, name); +} + +const void * +grub_fdt_get_prop (const void *fdt, unsigned int nodeoffset, const char *name, + grub_uint32_t *len) +{ + grub_uint32_t *prop; + if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3) + || (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct (fdt) + nodeoffset)) + != FDT_BEGIN_NODE)) + return 0; + prop = find_prop (fdt, nodeoffset, name); + if (!prop) + return 0; + if (len) + *len = grub_be_to_cpu32 (*(prop + 1)); + return prop + 3; +} + +int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name, + const void *val, grub_uint32_t len) +{ + grub_uint32_t *prop; + int prop_name_present = 0; + grub_uint32_t nameoff = 0; + + if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3) + || (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct (fdt) + nodeoffset)) + != FDT_BEGIN_NODE)) + return -1; + prop = find_prop (fdt, nodeoffset, name); + if (prop) + { + grub_uint32_t prop_len = ALIGN_UP(grub_be_to_cpu32 (*(prop + 1)), + sizeof(grub_uint32_t)); + grub_uint32_t i; + + prop_name_present = 1; + for (i = 0; i < prop_len / sizeof(grub_uint32_t); i++) + *(prop + 3 + i) = grub_cpu_to_be32_compile_time (FDT_NOP); + if (len > ALIGN_UP(prop_len, sizeof(grub_uint32_t))) + { + /* Length of new property value is greater than the space allocated + for the current value: a new entry needs to be created, so save the + nameoff field of the current entry and replace the current entry + with NOP tokens. */ + nameoff = grub_be_to_cpu32 (*(prop + 2)); + *prop = *(prop + 1) = *(prop + 2) = grub_cpu_to_be32_compile_time (FDT_NOP); + prop = NULL; + } + } + if (!prop || !prop_name_present) { + unsigned int needed_space = 0; + + if (!prop) + needed_space = grub_fdt_prop_entry_size(len); + if (!prop_name_present) + needed_space += grub_strlen (name) + 1; + if (needed_space > get_free_space (fdt)) + return -1; + if (rearrange_blocks (fdt, !prop ? grub_fdt_prop_entry_size(len) : 0) < 0) + return -1; + } + if (!prop_name_present) { + /* Append the property name at the end of the strings block. */ + nameoff = grub_fdt_get_size_dt_strings (fdt); + grub_strcpy ((char *) fdt + grub_fdt_get_off_dt_strings (fdt) + nameoff, + name); + grub_fdt_set_size_dt_strings (fdt, grub_fdt_get_size_dt_strings (fdt) + + grub_strlen (name) + 1); + } + if (!prop) { + char *node_name = (char *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct (fdt) + nodeoffset + + sizeof(grub_uint32_t)); + + prop = (void *) (node_name + ALIGN_UP(grub_strlen(node_name) + 1, 4)); + grub_memmove (prop + grub_fdt_prop_entry_size(len) / sizeof(*prop), prop, + struct_end(fdt) - (grub_addr_t) prop); + grub_fdt_set_size_dt_struct (fdt, grub_fdt_get_size_dt_struct (fdt) + + grub_fdt_prop_entry_size(len)); + *prop = grub_cpu_to_be32_compile_time (FDT_PROP); + *(prop + 2) = grub_cpu_to_be32 (nameoff); + } + *(prop + 1) = grub_cpu_to_be32 (len); + + /* Insert padding bytes at the end of the value; if they are not needed, they + will be overwritten by the following memcpy. */ + *(prop + grub_fdt_prop_entry_size(len) / sizeof(grub_uint32_t) - 1) = 0; + + grub_memcpy (prop + 3, val, len); + return 0; +} + +int +grub_fdt_create_empty_tree (void *fdt, unsigned int size) +{ + struct grub_fdt_empty_tree *et; + + if (size < GRUB_FDT_EMPTY_TREE_SZ) + return -1; + + grub_memset (fdt, 0, size); + et = fdt; + + et->empty_node.tree_end = grub_cpu_to_be32_compile_time (FDT_END); + et->empty_node.node_end = grub_cpu_to_be32_compile_time (FDT_END_NODE); + et->empty_node.node_start = grub_cpu_to_be32_compile_time (FDT_BEGIN_NODE); + ((struct grub_fdt_empty_tree *) fdt)->header.off_mem_rsvmap = + grub_cpu_to_be32_compile_time (ALIGN_UP (sizeof (grub_fdt_header_t), 8)); + + grub_fdt_set_off_dt_strings (fdt, sizeof (*et)); + grub_fdt_set_off_dt_struct (fdt, + sizeof (et->header) + sizeof (et->empty_rsvmap)); + grub_fdt_set_version (fdt, FDT_SUPPORTED_VERSION); + grub_fdt_set_last_comp_version (fdt, FDT_SUPPORTED_VERSION); + grub_fdt_set_size_dt_struct (fdt, sizeof (et->empty_node)); + grub_fdt_set_totalsize (fdt, size); + grub_fdt_set_magic (fdt, FDT_MAGIC); + + return 0; +} diff --git a/grub-core/lib/getline.c b/grub-core/lib/getline.c new file mode 100644 index 0000000..edb8e9f --- /dev/null +++ b/grub-core/lib/getline.c @@ -0,0 +1,92 @@ +/* main.c - the normal mode main routine */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2005,2006,2007,2008,2009,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/kernel.h> +#include <grub/normal.h> +#include <grub/dl.h> +#include <grub/misc.h> +#include <grub/file.h> +#include <grub/mm.h> +#include <grub/term.h> +#include <grub/env.h> +#include <grub/parser.h> +#include <grub/reader.h> +#include <grub/menu_viewer.h> +#include <grub/auth.h> +#include <grub/i18n.h> +#include <grub/charset.h> +#include <grub/script_sh.h> + +/* Read a line from the file FILE. */ +char * +grub_file_getline (grub_file_t file) +{ + char c; + grub_size_t pos = 0; + char *cmdline; + int have_newline = 0; + grub_size_t max_len = 64; + + /* Initially locate some space. */ + cmdline = grub_malloc (max_len); + if (! cmdline) + return 0; + + while (1) + { + if (grub_file_read (file, &c, 1) != 1) + break; + + /* Skip all carriage returns. */ + if (c == '\r') + continue; + + + if (pos + 1 >= max_len) + { + char *old_cmdline = cmdline; + max_len = max_len * 2; + cmdline = grub_realloc (cmdline, max_len); + if (! cmdline) + { + grub_free (old_cmdline); + return 0; + } + } + + if (c == '\n') + { + have_newline = 1; + break; + } + + cmdline[pos++] = c; + } + + cmdline[pos] = '\0'; + + /* If the buffer is empty, don't return anything at all. */ + if (pos == 0 && !have_newline) + { + grub_free (cmdline); + cmdline = 0; + } + + return cmdline; +} diff --git a/grub-core/lib/gnulib-patches/fix-base64.patch b/grub-core/lib/gnulib-patches/fix-base64.patch new file mode 100644 index 0000000..985db12 --- /dev/null +++ b/grub-core/lib/gnulib-patches/fix-base64.patch @@ -0,0 +1,21 @@ +diff --git a/lib/base64.h b/lib/base64.h +index 9cd0183b8..185a2afa1 100644 +--- a/lib/base64.h ++++ b/lib/base64.h +@@ -21,8 +21,14 @@ + /* Get size_t. */ + # include <stddef.h> + +-/* Get bool. */ +-# include <stdbool.h> ++#ifndef GRUB_POSIX_BOOL_DEFINED ++typedef enum { false = 0, true = 1 } bool; ++#define GRUB_POSIX_BOOL_DEFINED 1 ++#endif ++ ++#ifndef _GL_ATTRIBUTE_CONST ++# define _GL_ATTRIBUTE_CONST /* empty */ ++#endif + + # ifdef __cplusplus + extern "C" { diff --git a/grub-core/lib/gnulib-patches/fix-null-deref.patch b/grub-core/lib/gnulib-patches/fix-null-deref.patch new file mode 100644 index 0000000..8fafa15 --- /dev/null +++ b/grub-core/lib/gnulib-patches/fix-null-deref.patch @@ -0,0 +1,13 @@ +diff --git a/lib/argp-parse.c b/lib/argp-parse.c +index 6dec57310..900adad54 100644 +--- a/lib/argp-parse.c ++++ b/lib/argp-parse.c +@@ -940,7 +940,7 @@ weak_alias (__argp_parse, argp_parse) + void * + __argp_input (const struct argp *argp, const struct argp_state *state) + { +- if (state) ++ if (state && state->pstate) + { + struct group *group; + struct parser *parser = state->pstate; diff --git a/grub-core/lib/gnulib-patches/fix-null-state-deref.patch b/grub-core/lib/gnulib-patches/fix-null-state-deref.patch new file mode 100644 index 0000000..813ec09 --- /dev/null +++ b/grub-core/lib/gnulib-patches/fix-null-state-deref.patch @@ -0,0 +1,12 @@ +--- a/lib/argp-help.c 2020-10-28 14:32:19.189215988 +0000 ++++ b/lib/argp-help.c 2020-10-28 14:38:21.204673940 +0000 +@@ -145,7 +145,8 @@ + if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin) + { + __argp_failure (state, 0, 0, +- dgettext (state->root_argp->argp_domain, ++ dgettext (state == NULL ? NULL ++ : state->root_argp->argp_domain, + "\ + ARGP_HELP_FMT: %s value is less than or equal to %s"), + "rmargin", up->name); diff --git a/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch b/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch new file mode 100644 index 0000000..02e0631 --- /dev/null +++ b/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch @@ -0,0 +1,15 @@ +--- a/lib/regcomp.c 2020-11-24 17:06:08.159223858 +0000 ++++ b/lib/regcomp.c 2020-11-24 17:06:15.630253923 +0000 +@@ -3808,11 +3808,7 @@ + create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, + re_token_type_t type) + { +- re_token_t t; +-#if defined GCC_LINT || defined lint +- memset (&t, 0, sizeof t); +-#endif +- t.type = type; ++ re_token_t t = { .type = type }; + return create_token_tree (dfa, left, right, &t); + } + diff --git a/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch b/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch new file mode 100644 index 0000000..db6dac9 --- /dev/null +++ b/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch @@ -0,0 +1,12 @@ +--- a/lib/regexec.c 2020-10-21 14:25:35.310195912 +0000 ++++ b/lib/regexec.c 2020-11-05 10:55:09.621542984 +0000 +@@ -1692,6 +1692,9 @@ + { + Idx top = mctx->state_log_top; + ++ if (mctx->state_log == NULL) ++ return REG_NOERROR; ++ + if ((next_state_log_idx >= mctx->input.bufs_len + && mctx->input.bufs_len < mctx->input.len) + || (next_state_log_idx >= mctx->input.valid_len diff --git a/grub-core/lib/gnulib-patches/fix-uninit-structure.patch b/grub-core/lib/gnulib-patches/fix-uninit-structure.patch new file mode 100644 index 0000000..7b4d9f6 --- /dev/null +++ b/grub-core/lib/gnulib-patches/fix-uninit-structure.patch @@ -0,0 +1,11 @@ +--- a/lib/regcomp.c 2020-10-22 13:49:06.770168928 +0000 ++++ b/lib/regcomp.c 2020-10-22 13:50:37.026528298 +0000 +@@ -3662,7 +3662,7 @@ + Idx alloc = 0; + #endif /* not RE_ENABLE_I18N */ + reg_errcode_t ret; +- re_token_t br_token; ++ re_token_t br_token = {0}; + bin_tree_t *tree; + + sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); diff --git a/grub-core/lib/gnulib-patches/fix-unused-value.patch b/grub-core/lib/gnulib-patches/fix-unused-value.patch new file mode 100644 index 0000000..ba51f1b --- /dev/null +++ b/grub-core/lib/gnulib-patches/fix-unused-value.patch @@ -0,0 +1,14 @@ +--- a/lib/regexec.c 2020-10-21 14:25:35.310195912 +0000 ++++ b/lib/regexec.c 2020-10-21 14:32:07.961765604 +0000 +@@ -828,7 +828,11 @@ + break; + if (__glibc_unlikely (err != REG_NOMATCH)) + goto free_return; ++#ifdef DEBUG ++ /* Only used for assertion below when DEBUG is set, otherwise ++ it will be over-written when we loop around. */ + match_last = -1; ++#endif + } + else + break; /* We found a match. */ diff --git a/grub-core/lib/gnulib-patches/fix-width.patch b/grub-core/lib/gnulib-patches/fix-width.patch new file mode 100644 index 0000000..0a208ad --- /dev/null +++ b/grub-core/lib/gnulib-patches/fix-width.patch @@ -0,0 +1,217 @@ +diff --git a/lib/argp-fmtstream.c b/lib/argp-fmtstream.c +index ba6a407f7..d0685b3d4 100644 +--- a/lib/argp-fmtstream.c ++++ b/lib/argp-fmtstream.c +@@ -28,9 +28,11 @@ + #include <errno.h> + #include <stdarg.h> + #include <ctype.h> ++#include <wchar.h> + + #include "argp-fmtstream.h" + #include "argp-namefrob.h" ++#include "mbswidth.h" + + #ifndef ARGP_FMTSTREAM_USE_LINEWRAP + +@@ -115,6 +117,51 @@ weak_alias (__argp_fmtstream_free, argp_fmtstream_free) + #endif + #endif + ++ ++/* Return the pointer to the first character that doesn't fit in l columns. */ ++static inline const ptrdiff_t ++add_width (const char *ptr, const char *end, size_t l) ++{ ++ mbstate_t ps; ++ const char *ptr0 = ptr; ++ ++ memset (&ps, 0, sizeof (ps)); ++ ++ while (ptr < end) ++ { ++ wchar_t wc; ++ size_t s, k; ++ ++ s = mbrtowc (&wc, ptr, end - ptr, &ps); ++ if (s == (size_t) -1) ++ break; ++ if (s == (size_t) -2) ++ { ++ if (1 >= l) ++ break; ++ l--; ++ ptr++; ++ continue; ++ } ++ ++ if (wc == '\e' && ptr + 3 < end ++ && ptr[1] == '[' && (ptr[2] == '0' || ptr[2] == '1') ++ && ptr[3] == 'm') ++ { ++ ptr += 4; ++ continue; ++ } ++ ++ k = wcwidth (wc); ++ ++ if (k >= l) ++ break; ++ l -= k; ++ ptr += s; ++ } ++ return ptr - ptr0; ++} ++ + /* Process FS's buffer so that line wrapping is done from POINT_OFFS to the + end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ + void +@@ -168,13 +215,15 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + if (!nl) + { + /* The buffer ends in a partial line. */ ++ size_t display_width = mbsnwidth (buf, fs->p - buf, ++ MBSW_STOP_AT_NUL); + +- if (fs->point_col + len < fs->rmargin) ++ if (fs->point_col + display_width < fs->rmargin) + { + /* The remaining buffer text is a partial line and fits + within the maximum line width. Advance point for the + characters to be written and stop scanning. */ +- fs->point_col += len; ++ fs->point_col += display_width; + break; + } + else +@@ -182,14 +231,18 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + the end of the buffer. */ + nl = fs->p; + } +- else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin) +- { +- /* The buffer contains a full line that fits within the maximum +- line width. Reset point and scan the next line. */ +- fs->point_col = 0; +- buf = nl + 1; +- continue; +- } ++ else ++ { ++ size_t display_width = mbsnwidth (buf, nl - buf, MBSW_STOP_AT_NUL); ++ if (display_width < (ssize_t) fs->rmargin) ++ { ++ /* The buffer contains a full line that fits within the maximum ++ line width. Reset point and scan the next line. */ ++ fs->point_col = 0; ++ buf = nl + 1; ++ continue; ++ } ++ } + + /* This line is too long. */ + r = fs->rmargin - 1; +@@ -225,7 +278,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + char *p, *nextline; + int i; + +- p = buf + (r + 1 - fs->point_col); ++ p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); + while (p >= buf && !isblank ((unsigned char) *p)) + --p; + nextline = p + 1; /* This will begin the next line. */ +@@ -243,7 +296,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + { + /* A single word that is greater than the maximum line width. + Oh well. Put it on an overlong line by itself. */ +- p = buf + (r + 1 - fs->point_col); ++ p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); + /* Find the end of the long word. */ + if (p < nl) + do +@@ -277,7 +330,8 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + && fs->p > nextline) + { + /* The margin needs more blanks than we removed. */ +- if (fs->end - fs->p > fs->wmargin + 1) ++ if (mbsnwidth (fs->p, fs->end - fs->p, MBSW_STOP_AT_NUL) ++ > fs->wmargin + 1) + /* Make some space for them. */ + { + size_t mv = fs->p - nextline; +diff --git a/lib/argp-help.c b/lib/argp-help.c +index e5375a0f0..5d8f451ec 100644 +--- a/lib/argp-help.c ++++ b/lib/argp-help.c +@@ -51,6 +51,7 @@ + #include "argp.h" + #include "argp-fmtstream.h" + #include "argp-namefrob.h" ++#include "mbswidth.h" + + #ifndef SIZE_MAX + # define SIZE_MAX ((size_t) -1) +@@ -1432,7 +1433,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, + + /* Manually do line wrapping so that it (probably) won't get wrapped at + any embedded spaces. */ +- space (stream, 1 + nl - cp); ++ space (stream, 1 + mbsnwidth (cp, nl - cp, MBSW_STOP_AT_NUL)); + + __argp_fmtstream_write (stream, cp, nl - cp); + } +diff --git a/lib/mbswidth.c b/lib/mbswidth.c +index 408a15e34..b3fb7f83a 100644 +--- a/lib/mbswidth.c ++++ b/lib/mbswidth.c +@@ -38,6 +38,14 @@ + /* Get INT_MAX. */ + #include <limits.h> + ++#ifndef FALLTHROUGH ++# if __GNUC__ < 7 ++# define FALLTHROUGH ((void) 0) ++# else ++# define FALLTHROUGH __attribute__ ((__fallthrough__)) ++# endif ++#endif ++ + /* Returns the number of columns needed to represent the multibyte + character string pointed to by STRING. If a non-printable character + occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned. +@@ -90,6 +98,10 @@ mbsnwidth (const char *string, size_t nbytes, int flags) + p++; + width++; + break; ++ case '\0': ++ if (flags & MBSW_STOP_AT_NUL) ++ return width; ++ FALLTHROUGH; + default: + /* If we have a multibyte sequence, scan it up to its end. */ + { +@@ -168,6 +180,9 @@ mbsnwidth (const char *string, size_t nbytes, int flags) + { + unsigned char c = (unsigned char) *p++; + ++ if (c == 0 && (flags & MBSW_STOP_AT_NUL)) ++ return width; ++ + if (isprint (c)) + { + if (width == INT_MAX) +diff --git a/lib/mbswidth.h b/lib/mbswidth.h +index 2b5c53c37..45a123e63 100644 +--- a/lib/mbswidth.h ++++ b/lib/mbswidth.h +@@ -45,6 +45,10 @@ extern "C" { + control characters and 1 otherwise. */ + #define MBSW_REJECT_UNPRINTABLE 2 + ++/* If this bit is set \0 is treated as the end of string. ++ Otherwise it's treated as a normal one column width character. */ ++#define MBSW_STOP_AT_NUL 4 ++ + + /* Returns the number of screen columns needed for STRING. */ + #define mbswidth gnu_mbswidth /* avoid clash with UnixWare 7.1.1 function */ diff --git a/grub-core/lib/gnulib-patches/no-abort.patch b/grub-core/lib/gnulib-patches/no-abort.patch new file mode 100644 index 0000000..e469c47 --- /dev/null +++ b/grub-core/lib/gnulib-patches/no-abort.patch @@ -0,0 +1,26 @@ +diff --git a/lib/regcomp.c b/lib/regcomp.c +index cc85f35ac..de45ebb5c 100644 +--- a/lib/regcomp.c ++++ b/lib/regcomp.c +@@ -528,9 +528,9 @@ regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf, + to this routine. If we are given anything else, or if other regex + code generates an invalid error code, then the program has a bug. + Dump core so we can fix it. */ +- abort (); +- +- msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); ++ msg = gettext ("unknown regexp error"); ++ else ++ msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); + + msg_size = strlen (msg) + 1; /* Includes the null. */ + +@@ -1136,7 +1136,7 @@ optimize_utf8 (re_dfa_t *dfa) + } + break; + default: +- abort (); ++ break; + } + + if (mb_chars || has_period) diff --git a/grub-core/lib/gnulib/Makefile.am b/grub-core/lib/gnulib/Makefile.am new file mode 100644 index 0000000..4c0b646 --- /dev/null +++ b/grub-core/lib/gnulib/Makefile.am @@ -0,0 +1,2221 @@ +## DO NOT EDIT! GENERATED AUTOMATICALLY! +## Process this file with automake to produce Makefile.in. +# Copyright (C) 2002-2019 Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this file. If not, see <https://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, +# this file may be distributed as part of a program that +# contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# Generated by gnulib-tool. +# Reproduce by: +# gnulib-tool --import --local-dir=gl \ +# --lib=libgnu \ +# --source-base=grub-core/lib/gnulib \ +# --m4-base=m4 \ +# --doc-base=doc \ +# --tests-base=tests \ +# --aux-dir=build-aux \ +# --no-conditional-dependencies \ +# --no-libtool \ +# --macro-prefix=gl \ +# --no-vc-files \ +# argp \ +# base64 \ +# error \ +# fnmatch \ +# getdelim \ +# getline \ +# gettext-h \ +# gitlog-to-changelog \ +# mbswidth \ +# progname \ +# realloc-gnu \ +# regex \ +# save-cwd + +AUTOMAKE_OPTIONS = 1.11 gnits subdir-objects + +SUBDIRS = +noinst_HEADERS = +noinst_LIBRARIES = +noinst_LTLIBRARIES = +EXTRA_DIST = +BUILT_SOURCES = +SUFFIXES = +MOSTLYCLEANFILES = core *.stackdump +MOSTLYCLEANDIRS = +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = +# No GNU Make output. + +AM_CPPFLAGS = +AM_CFLAGS = + +noinst_LIBRARIES += libgnu.a + +libgnu_a_SOURCES = +libgnu_a_LIBADD = $(gl_LIBOBJS) +libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) +EXTRA_libgnu_a_SOURCES = + +## begin gnulib module absolute-header + +# Use this preprocessor expression to decide whether #include_next works. +# Do not rely on a 'configure'-time test for this, since the expression +# might appear in an installed header, which is used by some other compiler. +HAVE_INCLUDE_NEXT = (__GNUC__ || 60000000 <= __DECC_VER) + +## end gnulib module absolute-header + +## begin gnulib module alloca + + +libgnu_a_LIBADD += @ALLOCA@ +libgnu_a_DEPENDENCIES += @ALLOCA@ +EXTRA_DIST += alloca.c + +EXTRA_libgnu_a_SOURCES += alloca.c + +## end gnulib module alloca + +## begin gnulib module alloca-opt + +BUILT_SOURCES += $(ALLOCA_H) + +# We need the following in order to create <alloca.h> when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_ALLOCA_H +alloca.h: alloca.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/alloca.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +else +alloca.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += alloca.h alloca.h-t + +EXTRA_DIST += alloca.in.h + +## end gnulib module alloca-opt + +## begin gnulib module argp + +libgnu_a_SOURCES += argp.h argp-ba.c argp-eexst.c argp-fmtstream.c argp-fmtstream.h argp-fs-xinl.c argp-help.c argp-namefrob.h argp-parse.c argp-pin.c argp-pv.c argp-pvh.c argp-xinl.c + +## end gnulib module argp + +## begin gnulib module assure + + +EXTRA_DIST += assure.h + +## end gnulib module assure + +## begin gnulib module at-internal + + +EXTRA_DIST += openat-priv.h openat-proc.c + +EXTRA_libgnu_a_SOURCES += openat-proc.c + +## end gnulib module at-internal + +## begin gnulib module base64 + +libgnu_a_SOURCES += base64.h base64.c + +## end gnulib module base64 + +## begin gnulib module btowc + + +EXTRA_DIST += btowc.c + +EXTRA_libgnu_a_SOURCES += btowc.c + +## end gnulib module btowc + +## begin gnulib module chdir-long + + +EXTRA_DIST += chdir-long.c chdir-long.h + +EXTRA_libgnu_a_SOURCES += chdir-long.c + +## end gnulib module chdir-long + +## begin gnulib module cloexec + +libgnu_a_SOURCES += cloexec.c + +EXTRA_DIST += cloexec.h + +## end gnulib module cloexec + +## begin gnulib module close + + +EXTRA_DIST += close.c + +EXTRA_libgnu_a_SOURCES += close.c + +## end gnulib module close + +## begin gnulib module dirent + +BUILT_SOURCES += dirent.h + +# We need the following in order to create <dirent.h> when the system +# doesn't have one that works with the given compiler. +dirent.h: dirent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_DIRENT_H''@|$(HAVE_DIRENT_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_DIRENT_H''@|$(NEXT_DIRENT_H)|g' \ + -e 's/@''GNULIB_OPENDIR''@/$(GNULIB_OPENDIR)/g' \ + -e 's/@''GNULIB_READDIR''@/$(GNULIB_READDIR)/g' \ + -e 's/@''GNULIB_REWINDDIR''@/$(GNULIB_REWINDDIR)/g' \ + -e 's/@''GNULIB_CLOSEDIR''@/$(GNULIB_CLOSEDIR)/g' \ + -e 's/@''GNULIB_DIRFD''@/$(GNULIB_DIRFD)/g' \ + -e 's/@''GNULIB_FDOPENDIR''@/$(GNULIB_FDOPENDIR)/g' \ + -e 's/@''GNULIB_SCANDIR''@/$(GNULIB_SCANDIR)/g' \ + -e 's/@''GNULIB_ALPHASORT''@/$(GNULIB_ALPHASORT)/g' \ + -e 's/@''HAVE_OPENDIR''@/$(HAVE_OPENDIR)/g' \ + -e 's/@''HAVE_READDIR''@/$(HAVE_READDIR)/g' \ + -e 's/@''HAVE_REWINDDIR''@/$(HAVE_REWINDDIR)/g' \ + -e 's/@''HAVE_CLOSEDIR''@/$(HAVE_CLOSEDIR)/g' \ + -e 's|@''HAVE_DECL_DIRFD''@|$(HAVE_DECL_DIRFD)|g' \ + -e 's|@''HAVE_DECL_FDOPENDIR''@|$(HAVE_DECL_FDOPENDIR)|g' \ + -e 's|@''HAVE_FDOPENDIR''@|$(HAVE_FDOPENDIR)|g' \ + -e 's|@''HAVE_SCANDIR''@|$(HAVE_SCANDIR)|g' \ + -e 's|@''HAVE_ALPHASORT''@|$(HAVE_ALPHASORT)|g' \ + -e 's|@''REPLACE_OPENDIR''@|$(REPLACE_OPENDIR)|g' \ + -e 's|@''REPLACE_CLOSEDIR''@|$(REPLACE_CLOSEDIR)|g' \ + -e 's|@''REPLACE_DIRFD''@|$(REPLACE_DIRFD)|g' \ + -e 's|@''REPLACE_FDOPENDIR''@|$(REPLACE_FDOPENDIR)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/dirent.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += dirent.h dirent.h-t + +EXTRA_DIST += dirent.in.h + +## end gnulib module dirent + +## begin gnulib module dirfd + + +EXTRA_DIST += dirfd.c + +EXTRA_libgnu_a_SOURCES += dirfd.c + +## end gnulib module dirfd + +## begin gnulib module dirname-lgpl + +libgnu_a_SOURCES += dirname-lgpl.c basename-lgpl.c stripslash.c + +EXTRA_DIST += dirname.h + +## end gnulib module dirname-lgpl + +## begin gnulib module dosname + + +EXTRA_DIST += dosname.h + +## end gnulib module dosname + +## begin gnulib module dup2 + + +EXTRA_DIST += dup2.c + +EXTRA_libgnu_a_SOURCES += dup2.c + +## end gnulib module dup2 + +## begin gnulib module errno + +BUILT_SOURCES += $(ERRNO_H) + +# We need the following in order to create <errno.h> when the system +# doesn't have one that is POSIX compliant. +if GL_GENERATE_ERRNO_H +errno.h: errno.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_ERRNO_H''@|$(NEXT_ERRNO_H)|g' \ + -e 's|@''EMULTIHOP_HIDDEN''@|$(EMULTIHOP_HIDDEN)|g' \ + -e 's|@''EMULTIHOP_VALUE''@|$(EMULTIHOP_VALUE)|g' \ + -e 's|@''ENOLINK_HIDDEN''@|$(ENOLINK_HIDDEN)|g' \ + -e 's|@''ENOLINK_VALUE''@|$(ENOLINK_VALUE)|g' \ + -e 's|@''EOVERFLOW_HIDDEN''@|$(EOVERFLOW_HIDDEN)|g' \ + -e 's|@''EOVERFLOW_VALUE''@|$(EOVERFLOW_VALUE)|g' \ + < $(srcdir)/errno.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +errno.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += errno.h errno.h-t + +EXTRA_DIST += errno.in.h + +## end gnulib module errno + +## begin gnulib module error + + +EXTRA_DIST += error.c error.h + +EXTRA_libgnu_a_SOURCES += error.c + +## end gnulib module error + +## begin gnulib module exitfail + +libgnu_a_SOURCES += exitfail.c + +EXTRA_DIST += exitfail.h + +## end gnulib module exitfail + +## begin gnulib module fchdir + + +EXTRA_DIST += fchdir.c + +EXTRA_libgnu_a_SOURCES += fchdir.c + +## end gnulib module fchdir + +## begin gnulib module fcntl + + +EXTRA_DIST += fcntl.c + +EXTRA_libgnu_a_SOURCES += fcntl.c + +## end gnulib module fcntl + +## begin gnulib module fcntl-h + +BUILT_SOURCES += fcntl.h + +# We need the following in order to create <fcntl.h> when the system +# doesn't have one that works with the given compiler. +fcntl.h: fcntl.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_FCNTL_H''@|$(NEXT_FCNTL_H)|g' \ + -e 's/@''GNULIB_FCNTL''@/$(GNULIB_FCNTL)/g' \ + -e 's/@''GNULIB_NONBLOCKING''@/$(GNULIB_NONBLOCKING)/g' \ + -e 's/@''GNULIB_OPEN''@/$(GNULIB_OPEN)/g' \ + -e 's/@''GNULIB_OPENAT''@/$(GNULIB_OPENAT)/g' \ + -e 's|@''HAVE_FCNTL''@|$(HAVE_FCNTL)|g' \ + -e 's|@''HAVE_OPENAT''@|$(HAVE_OPENAT)|g' \ + -e 's|@''REPLACE_FCNTL''@|$(REPLACE_FCNTL)|g' \ + -e 's|@''REPLACE_OPEN''@|$(REPLACE_OPEN)|g' \ + -e 's|@''REPLACE_OPENAT''@|$(REPLACE_OPENAT)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/fcntl.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += fcntl.h fcntl.h-t + +EXTRA_DIST += fcntl.in.h + +## end gnulib module fcntl-h + +## begin gnulib module fd-hook + +libgnu_a_SOURCES += fd-hook.c + +EXTRA_DIST += fd-hook.h + +## end gnulib module fd-hook + +## begin gnulib module fd-safer-flag + +libgnu_a_SOURCES += fd-safer-flag.c dup-safer-flag.c + +## end gnulib module fd-safer-flag + +## begin gnulib module filename + + +EXTRA_DIST += filename.h + +## end gnulib module filename + +## begin gnulib module filenamecat-lgpl + +libgnu_a_SOURCES += filenamecat-lgpl.c + +EXTRA_DIST += filenamecat.h + +## end gnulib module filenamecat-lgpl + +## begin gnulib module flexmember + + +EXTRA_DIST += flexmember.h + +## end gnulib module flexmember + +## begin gnulib module float + +BUILT_SOURCES += $(FLOAT_H) + +# We need the following in order to create <float.h> when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_FLOAT_H +float.h: float.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_FLOAT_H''@|$(NEXT_FLOAT_H)|g' \ + -e 's|@''REPLACE_ITOLD''@|$(REPLACE_ITOLD)|g' \ + < $(srcdir)/float.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +float.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += float.h float.h-t + +EXTRA_DIST += float.c float.in.h itold.c + +EXTRA_libgnu_a_SOURCES += float.c itold.c + +## end gnulib module float + +## begin gnulib module fnmatch + + +EXTRA_DIST += fnmatch.c fnmatch_loop.c + +EXTRA_libgnu_a_SOURCES += fnmatch.c fnmatch_loop.c + +## end gnulib module fnmatch + +## begin gnulib module fnmatch-h + +BUILT_SOURCES += $(FNMATCH_H) + +# We need the following in order to create <fnmatch.h>. +if GL_GENERATE_FNMATCH_H +fnmatch.h: fnmatch.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_FNMATCH_H''@|$(HAVE_FNMATCH_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_FNMATCH_H''@|$(NEXT_FNMATCH_H)|g' \ + -e 's/@''GNULIB_FNMATCH''@/$(GNULIB_FNMATCH)/g' \ + -e 's|@''HAVE_FNMATCH''@|$(HAVE_FNMATCH)|g' \ + -e 's|@''REPLACE_FNMATCH''@|$(REPLACE_FNMATCH)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/fnmatch.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +fnmatch.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += fnmatch.h fnmatch.h-t + +EXTRA_DIST += fnmatch.in.h + +## end gnulib module fnmatch-h + +## begin gnulib module fstat + + +EXTRA_DIST += fstat.c stat-w32.c stat-w32.h + +EXTRA_libgnu_a_SOURCES += fstat.c stat-w32.c + +## end gnulib module fstat + +## begin gnulib module getcwd-lgpl + + +EXTRA_DIST += getcwd-lgpl.c + +EXTRA_libgnu_a_SOURCES += getcwd-lgpl.c + +## end gnulib module getcwd-lgpl + +## begin gnulib module getdelim + + +EXTRA_DIST += getdelim.c + +EXTRA_libgnu_a_SOURCES += getdelim.c + +## end gnulib module getdelim + +## begin gnulib module getdtablesize + + +EXTRA_DIST += getdtablesize.c + +EXTRA_libgnu_a_SOURCES += getdtablesize.c + +## end gnulib module getdtablesize + +## begin gnulib module getline + + +EXTRA_DIST += getline.c + +EXTRA_libgnu_a_SOURCES += getline.c + +## end gnulib module getline + +## begin gnulib module getopt-posix + +BUILT_SOURCES += $(GETOPT_H) $(GETOPT_CDEFS_H) + +# We need the following in order to create <getopt.h> when the system +# doesn't have one that works with the given compiler. +getopt.h: getopt.in.h $(top_builddir)/config.status $(ARG_NONNULL_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_GETOPT_H''@|$(HAVE_GETOPT_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_GETOPT_H''@|$(NEXT_GETOPT_H)|g' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + < $(srcdir)/getopt.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +getopt-cdefs.h: getopt-cdefs.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''HAVE_SYS_CDEFS_H''@|$(HAVE_SYS_CDEFS_H)|g' \ + < $(srcdir)/getopt-cdefs.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +MOSTLYCLEANFILES += getopt.h getopt.h-t getopt-cdefs.h getopt-cdefs.h-t + +EXTRA_DIST += getopt-cdefs.in.h getopt-core.h getopt-ext.h getopt-pfx-core.h getopt-pfx-ext.h getopt.c getopt.in.h getopt1.c getopt_int.h + +EXTRA_libgnu_a_SOURCES += getopt.c getopt1.c + +## end gnulib module getopt-posix + +## begin gnulib module getprogname + +libgnu_a_SOURCES += getprogname.h getprogname.c + +## end gnulib module getprogname + +## begin gnulib module gettext-h + +libgnu_a_SOURCES += gettext.h + +## end gnulib module gettext-h + +## begin gnulib module gitlog-to-changelog + + +EXTRA_DIST += $(top_srcdir)/build-aux/gitlog-to-changelog + +## end gnulib module gitlog-to-changelog + +## begin gnulib module hard-locale + +libgnu_a_SOURCES += hard-locale.c + +EXTRA_DIST += hard-locale.h + +## end gnulib module hard-locale + +## begin gnulib module havelib + + +EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath + +## end gnulib module havelib + +## begin gnulib module intprops + + +EXTRA_DIST += intprops.h + +## end gnulib module intprops + +## begin gnulib module langinfo + +BUILT_SOURCES += langinfo.h + +# We need the following in order to create an empty placeholder for +# <langinfo.h> when the system doesn't have one. +langinfo.h: langinfo.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_LANGINFO_H''@|$(HAVE_LANGINFO_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_LANGINFO_H''@|$(NEXT_LANGINFO_H)|g' \ + -e 's/@''GNULIB_NL_LANGINFO''@/$(GNULIB_NL_LANGINFO)/g' \ + -e 's|@''HAVE_LANGINFO_CODESET''@|$(HAVE_LANGINFO_CODESET)|g' \ + -e 's|@''HAVE_LANGINFO_T_FMT_AMPM''@|$(HAVE_LANGINFO_T_FMT_AMPM)|g' \ + -e 's|@''HAVE_LANGINFO_ALTMON''@|$(HAVE_LANGINFO_ALTMON)|g' \ + -e 's|@''HAVE_LANGINFO_ERA''@|$(HAVE_LANGINFO_ERA)|g' \ + -e 's|@''HAVE_LANGINFO_YESEXPR''@|$(HAVE_LANGINFO_YESEXPR)|g' \ + -e 's|@''HAVE_NL_LANGINFO''@|$(HAVE_NL_LANGINFO)|g' \ + -e 's|@''REPLACE_NL_LANGINFO''@|$(REPLACE_NL_LANGINFO)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/langinfo.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += langinfo.h langinfo.h-t + +EXTRA_DIST += langinfo.in.h + +## end gnulib module langinfo + +## begin gnulib module libc-config + + +EXTRA_DIST += cdefs.h libc-config.h + +## end gnulib module libc-config + +## begin gnulib module limits-h + +BUILT_SOURCES += $(LIMITS_H) + +# We need the following in order to create <limits.h> when the system +# doesn't have one that is compatible with GNU. +if GL_GENERATE_LIMITS_H +limits.h: limits.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_LIMITS_H''@|$(NEXT_LIMITS_H)|g' \ + < $(srcdir)/limits.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +limits.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += limits.h limits.h-t + +EXTRA_DIST += limits.in.h + +## end gnulib module limits-h + +## begin gnulib module localcharset + +libgnu_a_SOURCES += localcharset.c + +EXTRA_DIST += localcharset.h + +## end gnulib module localcharset + +## begin gnulib module locale + +BUILT_SOURCES += locale.h + +# We need the following in order to create <locale.h> when the system +# doesn't have one that provides all definitions. +locale.h: locale.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_LOCALE_H''@|$(NEXT_LOCALE_H)|g' \ + -e 's/@''GNULIB_LOCALECONV''@/$(GNULIB_LOCALECONV)/g' \ + -e 's/@''GNULIB_SETLOCALE''@/$(GNULIB_SETLOCALE)/g' \ + -e 's/@''GNULIB_DUPLOCALE''@/$(GNULIB_DUPLOCALE)/g' \ + -e 's/@''GNULIB_LOCALENAME''@/$(GNULIB_LOCALENAME)/g' \ + -e 's|@''HAVE_NEWLOCALE''@|$(HAVE_NEWLOCALE)|g' \ + -e 's|@''HAVE_DUPLOCALE''@|$(HAVE_DUPLOCALE)|g' \ + -e 's|@''HAVE_FREELOCALE''@|$(HAVE_FREELOCALE)|g' \ + -e 's|@''HAVE_XLOCALE_H''@|$(HAVE_XLOCALE_H)|g' \ + -e 's|@''REPLACE_LOCALECONV''@|$(REPLACE_LOCALECONV)|g' \ + -e 's|@''REPLACE_SETLOCALE''@|$(REPLACE_SETLOCALE)|g' \ + -e 's|@''REPLACE_NEWLOCALE''@|$(REPLACE_NEWLOCALE)|g' \ + -e 's|@''REPLACE_DUPLOCALE''@|$(REPLACE_DUPLOCALE)|g' \ + -e 's|@''REPLACE_FREELOCALE''@|$(REPLACE_FREELOCALE)|g' \ + -e 's|@''REPLACE_STRUCT_LCONV''@|$(REPLACE_STRUCT_LCONV)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/locale.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += locale.h locale.h-t + +EXTRA_DIST += locale.in.h + +## end gnulib module locale + +## begin gnulib module localeconv + + +EXTRA_DIST += localeconv.c + +EXTRA_libgnu_a_SOURCES += localeconv.c + +## end gnulib module localeconv + +## begin gnulib module lock + +libgnu_a_SOURCES += glthread/lock.h glthread/lock.c + +## end gnulib module lock + +## begin gnulib module malloc-gnu + + +EXTRA_DIST += malloc.c + +EXTRA_libgnu_a_SOURCES += malloc.c + +## end gnulib module malloc-gnu + +## begin gnulib module malloc-posix + + +EXTRA_DIST += malloc.c + +EXTRA_libgnu_a_SOURCES += malloc.c + +## end gnulib module malloc-posix + +## begin gnulib module malloca + +libgnu_a_SOURCES += malloca.c + +EXTRA_DIST += malloca.h + +## end gnulib module malloca + +## begin gnulib module mbrtowc + + +EXTRA_DIST += mbrtowc.c + +EXTRA_libgnu_a_SOURCES += mbrtowc.c + +## end gnulib module mbrtowc + +## begin gnulib module mbsinit + + +EXTRA_DIST += mbsinit.c + +EXTRA_libgnu_a_SOURCES += mbsinit.c + +## end gnulib module mbsinit + +## begin gnulib module mbsrtowcs + + +EXTRA_DIST += mbsrtowcs-impl.h mbsrtowcs-state.c mbsrtowcs.c + +EXTRA_libgnu_a_SOURCES += mbsrtowcs-state.c mbsrtowcs.c + +## end gnulib module mbsrtowcs + +## begin gnulib module mbswidth + +libgnu_a_SOURCES += mbswidth.h mbswidth.c + +## end gnulib module mbswidth + +## begin gnulib module mbtowc + + +EXTRA_DIST += mbtowc-impl.h mbtowc.c + +EXTRA_libgnu_a_SOURCES += mbtowc.c + +## end gnulib module mbtowc + +## begin gnulib module memchr + + +EXTRA_DIST += memchr.c memchr.valgrind + +EXTRA_libgnu_a_SOURCES += memchr.c + +## end gnulib module memchr + +## begin gnulib module mempcpy + + +EXTRA_DIST += mempcpy.c + +EXTRA_libgnu_a_SOURCES += mempcpy.c + +## end gnulib module mempcpy + +## begin gnulib module memrchr + + +EXTRA_DIST += memrchr.c + +EXTRA_libgnu_a_SOURCES += memrchr.c + +## end gnulib module memrchr + +## begin gnulib module msvc-inval + + +EXTRA_DIST += msvc-inval.c msvc-inval.h + +EXTRA_libgnu_a_SOURCES += msvc-inval.c + +## end gnulib module msvc-inval + +## begin gnulib module msvc-nothrow + + +EXTRA_DIST += msvc-nothrow.c msvc-nothrow.h + +EXTRA_libgnu_a_SOURCES += msvc-nothrow.c + +## end gnulib module msvc-nothrow + +## begin gnulib module nl_langinfo + + +EXTRA_DIST += nl_langinfo.c + +EXTRA_libgnu_a_SOURCES += nl_langinfo.c + +## end gnulib module nl_langinfo + +## begin gnulib module open + + +EXTRA_DIST += open.c + +EXTRA_libgnu_a_SOURCES += open.c + +## end gnulib module open + +## begin gnulib module openat + + +EXTRA_DIST += openat.c + +EXTRA_libgnu_a_SOURCES += openat.c + +## end gnulib module openat + +## begin gnulib module openat-die + +libgnu_a_SOURCES += openat-die.c + +## end gnulib module openat-die + +## begin gnulib module openat-h + + +EXTRA_DIST += openat.h + +## end gnulib module openat-h + +## begin gnulib module pathmax + + +EXTRA_DIST += pathmax.h + +## end gnulib module pathmax + +## begin gnulib module progname + +libgnu_a_SOURCES += progname.h progname.c + +## end gnulib module progname + +## begin gnulib module rawmemchr + + +EXTRA_DIST += rawmemchr.c rawmemchr.valgrind + +EXTRA_libgnu_a_SOURCES += rawmemchr.c + +## end gnulib module rawmemchr + +## begin gnulib module realloc-gnu + + +EXTRA_DIST += realloc.c + +EXTRA_libgnu_a_SOURCES += realloc.c + +## end gnulib module realloc-gnu + +## begin gnulib module realloc-posix + + +EXTRA_DIST += realloc.c + +EXTRA_libgnu_a_SOURCES += realloc.c + +## end gnulib module realloc-posix + +## begin gnulib module regex + + +EXTRA_DIST += regcomp.c regex.c regex.h regex_internal.c regex_internal.h regexec.c + +EXTRA_libgnu_a_SOURCES += regcomp.c regex.c regex_internal.c regexec.c + +## end gnulib module regex + +## begin gnulib module save-cwd + +libgnu_a_SOURCES += save-cwd.c + +EXTRA_DIST += save-cwd.h + +## end gnulib module save-cwd + +## begin gnulib module size_max + +libgnu_a_SOURCES += size_max.h + +## end gnulib module size_max + +## begin gnulib module sleep + + +EXTRA_DIST += sleep.c + +EXTRA_libgnu_a_SOURCES += sleep.c + +## end gnulib module sleep + +## begin gnulib module snippet/_Noreturn + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all makefiles that +# need it. This is ensured by the applicability 'all' defined above. + +_NORETURN_H=$(srcdir)/_Noreturn.h + +EXTRA_DIST += _Noreturn.h + +## end gnulib module snippet/_Noreturn + +## begin gnulib module snippet/arg-nonnull + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all makefiles that +# need it. This is ensured by the applicability 'all' defined above. + +ARG_NONNULL_H=$(srcdir)/arg-nonnull.h + +EXTRA_DIST += arg-nonnull.h + +## end gnulib module snippet/arg-nonnull + +## begin gnulib module snippet/c++defs + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all makefiles that +# need it. This is ensured by the applicability 'all' defined above. + +CXXDEFS_H=$(srcdir)/c++defs.h + +EXTRA_DIST += c++defs.h + +## end gnulib module snippet/c++defs + +## begin gnulib module snippet/warn-on-use + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all makefiles that +# need it. This is ensured by the applicability 'all' defined above. + +WARN_ON_USE_H=$(srcdir)/warn-on-use.h + +EXTRA_DIST += warn-on-use.h + +## end gnulib module snippet/warn-on-use + +## begin gnulib module stat + + +EXTRA_DIST += stat-w32.c stat-w32.h stat.c + +EXTRA_libgnu_a_SOURCES += stat-w32.c stat.c + +## end gnulib module stat + +## begin gnulib module stat-time + +libgnu_a_SOURCES += stat-time.c + +EXTRA_DIST += stat-time.h + +## end gnulib module stat-time + +## begin gnulib module stdalign + +BUILT_SOURCES += $(STDALIGN_H) + +# We need the following in order to create <stdalign.h> when the system +# doesn't have one that works. +if GL_GENERATE_STDALIGN_H +stdalign.h: stdalign.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/stdalign.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +stdalign.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stdalign.h stdalign.h-t + +EXTRA_DIST += stdalign.in.h + +## end gnulib module stdalign + +## begin gnulib module stdbool + +BUILT_SOURCES += $(STDBOOL_H) + +# We need the following in order to create <stdbool.h> when the system +# doesn't have one that works. +if GL_GENERATE_STDBOOL_H +stdbool.h: stdbool.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +stdbool.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stdbool.h stdbool.h-t + +EXTRA_DIST += stdbool.in.h + +## end gnulib module stdbool + +## begin gnulib module stddef + +BUILT_SOURCES += $(STDDEF_H) + +# We need the following in order to create <stddef.h> when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_STDDEF_H +stddef.h: stddef.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDDEF_H''@|$(NEXT_STDDEF_H)|g' \ + -e 's|@''HAVE_MAX_ALIGN_T''@|$(HAVE_MAX_ALIGN_T)|g' \ + -e 's|@''HAVE_WCHAR_T''@|$(HAVE_WCHAR_T)|g' \ + -e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \ + < $(srcdir)/stddef.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +stddef.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stddef.h stddef.h-t + +EXTRA_DIST += stddef.in.h + +## end gnulib module stddef + +## begin gnulib module stdint + +BUILT_SOURCES += $(STDINT_H) + +# We need the following in order to create <stdint.h> when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_STDINT_H +stdint.h: stdint.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDINT_H''@|$(NEXT_STDINT_H)|g' \ + -e 's/@''HAVE_C99_STDINT_H''@/$(HAVE_C99_STDINT_H)/g' \ + -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \ + -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \ + -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \ + -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \ + -e 's/@''HAVE_WCHAR_H''@/$(HAVE_WCHAR_H)/g' \ + -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \ + -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \ + -e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \ + -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \ + -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \ + -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \ + -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \ + -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \ + -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \ + -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \ + -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \ + -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \ + -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \ + -e 's/@''GNULIB_OVERRIDES_WINT_T''@/$(GNULIB_OVERRIDES_WINT_T)/g' \ + < $(srcdir)/stdint.in.h; \ + } > $@-t && \ + mv $@-t $@ +else +stdint.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += stdint.h stdint.h-t + +EXTRA_DIST += stdint.in.h + +## end gnulib module stdint + +## begin gnulib module stdio + +BUILT_SOURCES += stdio.h + +# We need the following in order to create <stdio.h> when the system +# doesn't have one that works with the given compiler. +stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDIO_H''@|$(NEXT_STDIO_H)|g' \ + -e 's/@''GNULIB_DPRINTF''@/$(GNULIB_DPRINTF)/g' \ + -e 's/@''GNULIB_FCLOSE''@/$(GNULIB_FCLOSE)/g' \ + -e 's/@''GNULIB_FDOPEN''@/$(GNULIB_FDOPEN)/g' \ + -e 's/@''GNULIB_FFLUSH''@/$(GNULIB_FFLUSH)/g' \ + -e 's/@''GNULIB_FGETC''@/$(GNULIB_FGETC)/g' \ + -e 's/@''GNULIB_FGETS''@/$(GNULIB_FGETS)/g' \ + -e 's/@''GNULIB_FOPEN''@/$(GNULIB_FOPEN)/g' \ + -e 's/@''GNULIB_FPRINTF''@/$(GNULIB_FPRINTF)/g' \ + -e 's/@''GNULIB_FPRINTF_POSIX''@/$(GNULIB_FPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_FPURGE''@/$(GNULIB_FPURGE)/g' \ + -e 's/@''GNULIB_FPUTC''@/$(GNULIB_FPUTC)/g' \ + -e 's/@''GNULIB_FPUTS''@/$(GNULIB_FPUTS)/g' \ + -e 's/@''GNULIB_FREAD''@/$(GNULIB_FREAD)/g' \ + -e 's/@''GNULIB_FREOPEN''@/$(GNULIB_FREOPEN)/g' \ + -e 's/@''GNULIB_FSCANF''@/$(GNULIB_FSCANF)/g' \ + -e 's/@''GNULIB_FSEEK''@/$(GNULIB_FSEEK)/g' \ + -e 's/@''GNULIB_FSEEKO''@/$(GNULIB_FSEEKO)/g' \ + -e 's/@''GNULIB_FTELL''@/$(GNULIB_FTELL)/g' \ + -e 's/@''GNULIB_FTELLO''@/$(GNULIB_FTELLO)/g' \ + -e 's/@''GNULIB_FWRITE''@/$(GNULIB_FWRITE)/g' \ + -e 's/@''GNULIB_GETC''@/$(GNULIB_GETC)/g' \ + -e 's/@''GNULIB_GETCHAR''@/$(GNULIB_GETCHAR)/g' \ + -e 's/@''GNULIB_GETDELIM''@/$(GNULIB_GETDELIM)/g' \ + -e 's/@''GNULIB_GETLINE''@/$(GNULIB_GETLINE)/g' \ + -e 's/@''GNULIB_OBSTACK_PRINTF''@/$(GNULIB_OBSTACK_PRINTF)/g' \ + -e 's/@''GNULIB_OBSTACK_PRINTF_POSIX''@/$(GNULIB_OBSTACK_PRINTF_POSIX)/g' \ + -e 's/@''GNULIB_PCLOSE''@/$(GNULIB_PCLOSE)/g' \ + -e 's/@''GNULIB_PERROR''@/$(GNULIB_PERROR)/g' \ + -e 's/@''GNULIB_POPEN''@/$(GNULIB_POPEN)/g' \ + -e 's/@''GNULIB_PRINTF''@/$(GNULIB_PRINTF)/g' \ + -e 's/@''GNULIB_PRINTF_POSIX''@/$(GNULIB_PRINTF_POSIX)/g' \ + -e 's/@''GNULIB_PUTC''@/$(GNULIB_PUTC)/g' \ + -e 's/@''GNULIB_PUTCHAR''@/$(GNULIB_PUTCHAR)/g' \ + -e 's/@''GNULIB_PUTS''@/$(GNULIB_PUTS)/g' \ + -e 's/@''GNULIB_REMOVE''@/$(GNULIB_REMOVE)/g' \ + -e 's/@''GNULIB_RENAME''@/$(GNULIB_RENAME)/g' \ + -e 's/@''GNULIB_RENAMEAT''@/$(GNULIB_RENAMEAT)/g' \ + -e 's/@''GNULIB_SCANF''@/$(GNULIB_SCANF)/g' \ + -e 's/@''GNULIB_SNPRINTF''@/$(GNULIB_SNPRINTF)/g' \ + -e 's/@''GNULIB_SPRINTF_POSIX''@/$(GNULIB_SPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_STDIO_H_NONBLOCKING''@/$(GNULIB_STDIO_H_NONBLOCKING)/g' \ + -e 's/@''GNULIB_STDIO_H_SIGPIPE''@/$(GNULIB_STDIO_H_SIGPIPE)/g' \ + -e 's/@''GNULIB_TMPFILE''@/$(GNULIB_TMPFILE)/g' \ + -e 's/@''GNULIB_VASPRINTF''@/$(GNULIB_VASPRINTF)/g' \ + -e 's/@''GNULIB_VDPRINTF''@/$(GNULIB_VDPRINTF)/g' \ + -e 's/@''GNULIB_VFPRINTF''@/$(GNULIB_VFPRINTF)/g' \ + -e 's/@''GNULIB_VFPRINTF_POSIX''@/$(GNULIB_VFPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_VFSCANF''@/$(GNULIB_VFSCANF)/g' \ + -e 's/@''GNULIB_VSCANF''@/$(GNULIB_VSCANF)/g' \ + -e 's/@''GNULIB_VPRINTF''@/$(GNULIB_VPRINTF)/g' \ + -e 's/@''GNULIB_VPRINTF_POSIX''@/$(GNULIB_VPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_VSNPRINTF''@/$(GNULIB_VSNPRINTF)/g' \ + -e 's/@''GNULIB_VSPRINTF_POSIX''@/$(GNULIB_VSPRINTF_POSIX)/g' \ + < $(srcdir)/stdio.in.h | \ + sed -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \ + -e 's|@''HAVE_DECL_FSEEKO''@|$(HAVE_DECL_FSEEKO)|g' \ + -e 's|@''HAVE_DECL_FTELLO''@|$(HAVE_DECL_FTELLO)|g' \ + -e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \ + -e 's|@''HAVE_DECL_GETLINE''@|$(HAVE_DECL_GETLINE)|g' \ + -e 's|@''HAVE_DECL_OBSTACK_PRINTF''@|$(HAVE_DECL_OBSTACK_PRINTF)|g' \ + -e 's|@''HAVE_DECL_SNPRINTF''@|$(HAVE_DECL_SNPRINTF)|g' \ + -e 's|@''HAVE_DECL_VSNPRINTF''@|$(HAVE_DECL_VSNPRINTF)|g' \ + -e 's|@''HAVE_DPRINTF''@|$(HAVE_DPRINTF)|g' \ + -e 's|@''HAVE_FSEEKO''@|$(HAVE_FSEEKO)|g' \ + -e 's|@''HAVE_FTELLO''@|$(HAVE_FTELLO)|g' \ + -e 's|@''HAVE_PCLOSE''@|$(HAVE_PCLOSE)|g' \ + -e 's|@''HAVE_POPEN''@|$(HAVE_POPEN)|g' \ + -e 's|@''HAVE_RENAMEAT''@|$(HAVE_RENAMEAT)|g' \ + -e 's|@''HAVE_VASPRINTF''@|$(HAVE_VASPRINTF)|g' \ + -e 's|@''HAVE_VDPRINTF''@|$(HAVE_VDPRINTF)|g' \ + -e 's|@''REPLACE_DPRINTF''@|$(REPLACE_DPRINTF)|g' \ + -e 's|@''REPLACE_FCLOSE''@|$(REPLACE_FCLOSE)|g' \ + -e 's|@''REPLACE_FDOPEN''@|$(REPLACE_FDOPEN)|g' \ + -e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \ + -e 's|@''REPLACE_FOPEN''@|$(REPLACE_FOPEN)|g' \ + -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \ + -e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \ + -e 's|@''REPLACE_FREOPEN''@|$(REPLACE_FREOPEN)|g' \ + -e 's|@''REPLACE_FSEEK''@|$(REPLACE_FSEEK)|g' \ + -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \ + -e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \ + -e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \ + -e 's|@''REPLACE_GETDELIM''@|$(REPLACE_GETDELIM)|g' \ + -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \ + -e 's|@''REPLACE_OBSTACK_PRINTF''@|$(REPLACE_OBSTACK_PRINTF)|g' \ + -e 's|@''REPLACE_PERROR''@|$(REPLACE_PERROR)|g' \ + -e 's|@''REPLACE_POPEN''@|$(REPLACE_POPEN)|g' \ + -e 's|@''REPLACE_PRINTF''@|$(REPLACE_PRINTF)|g' \ + -e 's|@''REPLACE_REMOVE''@|$(REPLACE_REMOVE)|g' \ + -e 's|@''REPLACE_RENAME''@|$(REPLACE_RENAME)|g' \ + -e 's|@''REPLACE_RENAMEAT''@|$(REPLACE_RENAMEAT)|g' \ + -e 's|@''REPLACE_SNPRINTF''@|$(REPLACE_SNPRINTF)|g' \ + -e 's|@''REPLACE_SPRINTF''@|$(REPLACE_SPRINTF)|g' \ + -e 's|@''REPLACE_STDIO_READ_FUNCS''@|$(REPLACE_STDIO_READ_FUNCS)|g' \ + -e 's|@''REPLACE_STDIO_WRITE_FUNCS''@|$(REPLACE_STDIO_WRITE_FUNCS)|g' \ + -e 's|@''REPLACE_TMPFILE''@|$(REPLACE_TMPFILE)|g' \ + -e 's|@''REPLACE_VASPRINTF''@|$(REPLACE_VASPRINTF)|g' \ + -e 's|@''REPLACE_VDPRINTF''@|$(REPLACE_VDPRINTF)|g' \ + -e 's|@''REPLACE_VFPRINTF''@|$(REPLACE_VFPRINTF)|g' \ + -e 's|@''REPLACE_VPRINTF''@|$(REPLACE_VPRINTF)|g' \ + -e 's|@''REPLACE_VSNPRINTF''@|$(REPLACE_VSNPRINTF)|g' \ + -e 's|@''REPLACE_VSPRINTF''@|$(REPLACE_VSPRINTF)|g' \ + -e 's|@''ASM_SYMBOL_PREFIX''@|$(ASM_SYMBOL_PREFIX)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += stdio.h stdio.h-t + +EXTRA_DIST += stdio.in.h + +## end gnulib module stdio + +## begin gnulib module stdlib + +BUILT_SOURCES += stdlib.h + +# We need the following in order to create <stdlib.h> when the system +# doesn't have one that works with the given compiler. +stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ + $(_NORETURN_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDLIB_H''@|$(NEXT_STDLIB_H)|g' \ + -e 's/@''GNULIB__EXIT''@/$(GNULIB__EXIT)/g' \ + -e 's/@''GNULIB_ATOLL''@/$(GNULIB_ATOLL)/g' \ + -e 's/@''GNULIB_CALLOC_POSIX''@/$(GNULIB_CALLOC_POSIX)/g' \ + -e 's/@''GNULIB_CANONICALIZE_FILE_NAME''@/$(GNULIB_CANONICALIZE_FILE_NAME)/g' \ + -e 's/@''GNULIB_GETLOADAVG''@/$(GNULIB_GETLOADAVG)/g' \ + -e 's/@''GNULIB_GETSUBOPT''@/$(GNULIB_GETSUBOPT)/g' \ + -e 's/@''GNULIB_GRANTPT''@/$(GNULIB_GRANTPT)/g' \ + -e 's/@''GNULIB_MALLOC_POSIX''@/$(GNULIB_MALLOC_POSIX)/g' \ + -e 's/@''GNULIB_MBTOWC''@/$(GNULIB_MBTOWC)/g' \ + -e 's/@''GNULIB_MKDTEMP''@/$(GNULIB_MKDTEMP)/g' \ + -e 's/@''GNULIB_MKOSTEMP''@/$(GNULIB_MKOSTEMP)/g' \ + -e 's/@''GNULIB_MKOSTEMPS''@/$(GNULIB_MKOSTEMPS)/g' \ + -e 's/@''GNULIB_MKSTEMP''@/$(GNULIB_MKSTEMP)/g' \ + -e 's/@''GNULIB_MKSTEMPS''@/$(GNULIB_MKSTEMPS)/g' \ + -e 's/@''GNULIB_POSIX_OPENPT''@/$(GNULIB_POSIX_OPENPT)/g' \ + -e 's/@''GNULIB_PTSNAME''@/$(GNULIB_PTSNAME)/g' \ + -e 's/@''GNULIB_PTSNAME_R''@/$(GNULIB_PTSNAME_R)/g' \ + -e 's/@''GNULIB_PUTENV''@/$(GNULIB_PUTENV)/g' \ + -e 's/@''GNULIB_QSORT_R''@/$(GNULIB_QSORT_R)/g' \ + -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/g' \ + -e 's/@''GNULIB_RANDOM_R''@/$(GNULIB_RANDOM_R)/g' \ + -e 's/@''GNULIB_REALLOC_POSIX''@/$(GNULIB_REALLOC_POSIX)/g' \ + -e 's/@''GNULIB_REALLOCARRAY''@/$(GNULIB_REALLOCARRAY)/g' \ + -e 's/@''GNULIB_REALPATH''@/$(GNULIB_REALPATH)/g' \ + -e 's/@''GNULIB_RPMATCH''@/$(GNULIB_RPMATCH)/g' \ + -e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \ + -e 's/@''GNULIB_SETENV''@/$(GNULIB_SETENV)/g' \ + -e 's/@''GNULIB_STRTOD''@/$(GNULIB_STRTOD)/g' \ + -e 's/@''GNULIB_STRTOLL''@/$(GNULIB_STRTOLL)/g' \ + -e 's/@''GNULIB_STRTOULL''@/$(GNULIB_STRTOULL)/g' \ + -e 's/@''GNULIB_SYSTEM_POSIX''@/$(GNULIB_SYSTEM_POSIX)/g' \ + -e 's/@''GNULIB_UNLOCKPT''@/$(GNULIB_UNLOCKPT)/g' \ + -e 's/@''GNULIB_UNSETENV''@/$(GNULIB_UNSETENV)/g' \ + -e 's/@''GNULIB_WCTOMB''@/$(GNULIB_WCTOMB)/g' \ + < $(srcdir)/stdlib.in.h | \ + sed -e 's|@''HAVE__EXIT''@|$(HAVE__EXIT)|g' \ + -e 's|@''HAVE_ATOLL''@|$(HAVE_ATOLL)|g' \ + -e 's|@''HAVE_CANONICALIZE_FILE_NAME''@|$(HAVE_CANONICALIZE_FILE_NAME)|g' \ + -e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \ + -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \ + -e 's|@''HAVE_GRANTPT''@|$(HAVE_GRANTPT)|g' \ + -e 's|@''HAVE_DECL_INITSTATE''@|$(HAVE_DECL_INITSTATE)|g' \ + -e 's|@''HAVE_MKDTEMP''@|$(HAVE_MKDTEMP)|g' \ + -e 's|@''HAVE_MKOSTEMP''@|$(HAVE_MKOSTEMP)|g' \ + -e 's|@''HAVE_MKOSTEMPS''@|$(HAVE_MKOSTEMPS)|g' \ + -e 's|@''HAVE_MKSTEMP''@|$(HAVE_MKSTEMP)|g' \ + -e 's|@''HAVE_MKSTEMPS''@|$(HAVE_MKSTEMPS)|g' \ + -e 's|@''HAVE_POSIX_OPENPT''@|$(HAVE_POSIX_OPENPT)|g' \ + -e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \ + -e 's|@''HAVE_PTSNAME_R''@|$(HAVE_PTSNAME_R)|g' \ + -e 's|@''HAVE_QSORT_R''@|$(HAVE_QSORT_R)|g' \ + -e 's|@''HAVE_RANDOM''@|$(HAVE_RANDOM)|g' \ + -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \ + -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \ + -e 's|@''HAVE_REALLOCARRAY''@|$(HAVE_REALLOCARRAY)|g' \ + -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \ + -e 's|@''HAVE_RPMATCH''@|$(HAVE_RPMATCH)|g' \ + -e 's|@''HAVE_SECURE_GETENV''@|$(HAVE_SECURE_GETENV)|g' \ + -e 's|@''HAVE_DECL_SETENV''@|$(HAVE_DECL_SETENV)|g' \ + -e 's|@''HAVE_DECL_SETSTATE''@|$(HAVE_DECL_SETSTATE)|g' \ + -e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \ + -e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \ + -e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \ + -e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \ + -e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \ + -e 's|@''HAVE_UNLOCKPT''@|$(HAVE_UNLOCKPT)|g' \ + -e 's|@''HAVE_DECL_UNSETENV''@|$(HAVE_DECL_UNSETENV)|g' \ + -e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \ + -e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \ + -e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \ + -e 's|@''REPLACE_MBTOWC''@|$(REPLACE_MBTOWC)|g' \ + -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \ + -e 's|@''REPLACE_PTSNAME''@|$(REPLACE_PTSNAME)|g' \ + -e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \ + -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \ + -e 's|@''REPLACE_QSORT_R''@|$(REPLACE_QSORT_R)|g' \ + -e 's|@''REPLACE_RANDOM_R''@|$(REPLACE_RANDOM_R)|g' \ + -e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \ + -e 's|@''REPLACE_REALPATH''@|$(REPLACE_REALPATH)|g' \ + -e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \ + -e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \ + -e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \ + -e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _Noreturn/r $(_NORETURN_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += stdlib.h stdlib.h-t + +EXTRA_DIST += stdlib.in.h + +## end gnulib module stdlib + +## begin gnulib module strcase + + +EXTRA_DIST += strcasecmp.c strncasecmp.c + +EXTRA_libgnu_a_SOURCES += strcasecmp.c strncasecmp.c + +## end gnulib module strcase + +## begin gnulib module strchrnul + + +EXTRA_DIST += strchrnul.c strchrnul.valgrind + +EXTRA_libgnu_a_SOURCES += strchrnul.c + +## end gnulib module strchrnul + +## begin gnulib module strdup-posix + + +EXTRA_DIST += strdup.c + +EXTRA_libgnu_a_SOURCES += strdup.c + +## end gnulib module strdup-posix + +## begin gnulib module streq + + +EXTRA_DIST += streq.h + +## end gnulib module streq + +## begin gnulib module strerror + + +EXTRA_DIST += strerror.c + +EXTRA_libgnu_a_SOURCES += strerror.c + +## end gnulib module strerror + +## begin gnulib module strerror-override + + +EXTRA_DIST += strerror-override.c strerror-override.h + +EXTRA_libgnu_a_SOURCES += strerror-override.c + +## end gnulib module strerror-override + +## begin gnulib module string + +BUILT_SOURCES += string.h + +# We need the following in order to create <string.h> when the system +# doesn't have one that works with the given compiler. +string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STRING_H''@|$(NEXT_STRING_H)|g' \ + -e 's/@''GNULIB_EXPLICIT_BZERO''@/$(GNULIB_EXPLICIT_BZERO)/g' \ + -e 's/@''GNULIB_FFSL''@/$(GNULIB_FFSL)/g' \ + -e 's/@''GNULIB_FFSLL''@/$(GNULIB_FFSLL)/g' \ + -e 's/@''GNULIB_MBSLEN''@/$(GNULIB_MBSLEN)/g' \ + -e 's/@''GNULIB_MBSNLEN''@/$(GNULIB_MBSNLEN)/g' \ + -e 's/@''GNULIB_MBSCHR''@/$(GNULIB_MBSCHR)/g' \ + -e 's/@''GNULIB_MBSRCHR''@/$(GNULIB_MBSRCHR)/g' \ + -e 's/@''GNULIB_MBSSTR''@/$(GNULIB_MBSSTR)/g' \ + -e 's/@''GNULIB_MBSCASECMP''@/$(GNULIB_MBSCASECMP)/g' \ + -e 's/@''GNULIB_MBSNCASECMP''@/$(GNULIB_MBSNCASECMP)/g' \ + -e 's/@''GNULIB_MBSPCASECMP''@/$(GNULIB_MBSPCASECMP)/g' \ + -e 's/@''GNULIB_MBSCASESTR''@/$(GNULIB_MBSCASESTR)/g' \ + -e 's/@''GNULIB_MBSCSPN''@/$(GNULIB_MBSCSPN)/g' \ + -e 's/@''GNULIB_MBSPBRK''@/$(GNULIB_MBSPBRK)/g' \ + -e 's/@''GNULIB_MBSSPN''@/$(GNULIB_MBSSPN)/g' \ + -e 's/@''GNULIB_MBSSEP''@/$(GNULIB_MBSSEP)/g' \ + -e 's/@''GNULIB_MBSTOK_R''@/$(GNULIB_MBSTOK_R)/g' \ + -e 's/@''GNULIB_MEMCHR''@/$(GNULIB_MEMCHR)/g' \ + -e 's/@''GNULIB_MEMMEM''@/$(GNULIB_MEMMEM)/g' \ + -e 's/@''GNULIB_MEMPCPY''@/$(GNULIB_MEMPCPY)/g' \ + -e 's/@''GNULIB_MEMRCHR''@/$(GNULIB_MEMRCHR)/g' \ + -e 's/@''GNULIB_RAWMEMCHR''@/$(GNULIB_RAWMEMCHR)/g' \ + -e 's/@''GNULIB_STPCPY''@/$(GNULIB_STPCPY)/g' \ + -e 's/@''GNULIB_STPNCPY''@/$(GNULIB_STPNCPY)/g' \ + -e 's/@''GNULIB_STRCHRNUL''@/$(GNULIB_STRCHRNUL)/g' \ + -e 's/@''GNULIB_STRDUP''@/$(GNULIB_STRDUP)/g' \ + -e 's/@''GNULIB_STRNCAT''@/$(GNULIB_STRNCAT)/g' \ + -e 's/@''GNULIB_STRNDUP''@/$(GNULIB_STRNDUP)/g' \ + -e 's/@''GNULIB_STRNLEN''@/$(GNULIB_STRNLEN)/g' \ + -e 's/@''GNULIB_STRPBRK''@/$(GNULIB_STRPBRK)/g' \ + -e 's/@''GNULIB_STRSEP''@/$(GNULIB_STRSEP)/g' \ + -e 's/@''GNULIB_STRSTR''@/$(GNULIB_STRSTR)/g' \ + -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \ + -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \ + -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \ + -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \ + -e 's/@''GNULIB_STRSIGNAL''@/$(GNULIB_STRSIGNAL)/g' \ + -e 's/@''GNULIB_STRVERSCMP''@/$(GNULIB_STRVERSCMP)/g' \ + < $(srcdir)/string.in.h | \ + sed -e 's|@''HAVE_EXPLICIT_BZERO''@|$(HAVE_EXPLICIT_BZERO)|g' \ + -e 's|@''HAVE_FFSL''@|$(HAVE_FFSL)|g' \ + -e 's|@''HAVE_FFSLL''@|$(HAVE_FFSLL)|g' \ + -e 's|@''HAVE_MBSLEN''@|$(HAVE_MBSLEN)|g' \ + -e 's|@''HAVE_MEMCHR''@|$(HAVE_MEMCHR)|g' \ + -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \ + -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \ + -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \ + -e 's|@''HAVE_RAWMEMCHR''@|$(HAVE_RAWMEMCHR)|g' \ + -e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \ + -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \ + -e 's|@''HAVE_STRCHRNUL''@|$(HAVE_STRCHRNUL)|g' \ + -e 's|@''HAVE_DECL_STRDUP''@|$(HAVE_DECL_STRDUP)|g' \ + -e 's|@''HAVE_DECL_STRNDUP''@|$(HAVE_DECL_STRNDUP)|g' \ + -e 's|@''HAVE_DECL_STRNLEN''@|$(HAVE_DECL_STRNLEN)|g' \ + -e 's|@''HAVE_STRPBRK''@|$(HAVE_STRPBRK)|g' \ + -e 's|@''HAVE_STRSEP''@|$(HAVE_STRSEP)|g' \ + -e 's|@''HAVE_STRCASESTR''@|$(HAVE_STRCASESTR)|g' \ + -e 's|@''HAVE_DECL_STRTOK_R''@|$(HAVE_DECL_STRTOK_R)|g' \ + -e 's|@''HAVE_DECL_STRERROR_R''@|$(HAVE_DECL_STRERROR_R)|g' \ + -e 's|@''HAVE_DECL_STRSIGNAL''@|$(HAVE_DECL_STRSIGNAL)|g' \ + -e 's|@''HAVE_STRVERSCMP''@|$(HAVE_STRVERSCMP)|g' \ + -e 's|@''REPLACE_MEMCHR''@|$(REPLACE_MEMCHR)|g' \ + -e 's|@''REPLACE_MEMMEM''@|$(REPLACE_MEMMEM)|g' \ + -e 's|@''REPLACE_STPNCPY''@|$(REPLACE_STPNCPY)|g' \ + -e 's|@''REPLACE_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|g' \ + -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \ + -e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \ + -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \ + -e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \ + -e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \ + -e 's|@''REPLACE_STRCASESTR''@|$(REPLACE_STRCASESTR)|g' \ + -e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \ + -e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \ + -e 's|@''REPLACE_STRERROR_R''@|$(REPLACE_STRERROR_R)|g' \ + -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \ + -e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + < $(srcdir)/string.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += string.h string.h-t + +EXTRA_DIST += string.in.h + +## end gnulib module string + +## begin gnulib module strings + +BUILT_SOURCES += strings.h + +# We need the following in order to create <strings.h> when the system +# doesn't have one that works with the given compiler. +strings.h: strings.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(ARG_NONNULL_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_STRINGS_H''@|$(HAVE_STRINGS_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STRINGS_H''@|$(NEXT_STRINGS_H)|g' \ + -e 's/@''GNULIB_FFS''@/$(GNULIB_FFS)/g' \ + -e 's|@''HAVE_FFS''@|$(HAVE_FFS)|g' \ + -e 's|@''HAVE_STRCASECMP''@|$(HAVE_STRCASECMP)|g' \ + -e 's|@''HAVE_DECL_STRNCASECMP''@|$(HAVE_DECL_STRNCASECMP)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/strings.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += strings.h strings.h-t + +EXTRA_DIST += strings.in.h + +## end gnulib module strings + +## begin gnulib module strndup + + +EXTRA_DIST += strndup.c + +EXTRA_libgnu_a_SOURCES += strndup.c + +## end gnulib module strndup + +## begin gnulib module strnlen + + +EXTRA_DIST += strnlen.c + +EXTRA_libgnu_a_SOURCES += strnlen.c + +## end gnulib module strnlen + +## begin gnulib module strnlen1 + +libgnu_a_SOURCES += strnlen1.h strnlen1.c + +## end gnulib module strnlen1 + +## begin gnulib module sys_stat + +BUILT_SOURCES += sys/stat.h + +# We need the following in order to create <sys/stat.h> when the system +# has one that is incomplete. +sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \ + -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \ + -e 's|@''WINDOWS_STAT_TIMESPEC''@|$(WINDOWS_STAT_TIMESPEC)|g' \ + -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \ + -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \ + -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \ + -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \ + -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \ + -e 's/@''GNULIB_LSTAT''@/$(GNULIB_LSTAT)/g' \ + -e 's/@''GNULIB_MKDIRAT''@/$(GNULIB_MKDIRAT)/g' \ + -e 's/@''GNULIB_MKFIFO''@/$(GNULIB_MKFIFO)/g' \ + -e 's/@''GNULIB_MKFIFOAT''@/$(GNULIB_MKFIFOAT)/g' \ + -e 's/@''GNULIB_MKNOD''@/$(GNULIB_MKNOD)/g' \ + -e 's/@''GNULIB_MKNODAT''@/$(GNULIB_MKNODAT)/g' \ + -e 's/@''GNULIB_STAT''@/$(GNULIB_STAT)/g' \ + -e 's/@''GNULIB_UTIMENSAT''@/$(GNULIB_UTIMENSAT)/g' \ + -e 's/@''GNULIB_OVERRIDES_STRUCT_STAT''@/$(GNULIB_OVERRIDES_STRUCT_STAT)/g' \ + -e 's|@''HAVE_FCHMODAT''@|$(HAVE_FCHMODAT)|g' \ + -e 's|@''HAVE_FSTATAT''@|$(HAVE_FSTATAT)|g' \ + -e 's|@''HAVE_FUTIMENS''@|$(HAVE_FUTIMENS)|g' \ + -e 's|@''HAVE_LCHMOD''@|$(HAVE_LCHMOD)|g' \ + -e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \ + -e 's|@''HAVE_MKDIRAT''@|$(HAVE_MKDIRAT)|g' \ + -e 's|@''HAVE_MKFIFO''@|$(HAVE_MKFIFO)|g' \ + -e 's|@''HAVE_MKFIFOAT''@|$(HAVE_MKFIFOAT)|g' \ + -e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \ + -e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \ + -e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \ + -e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \ + -e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \ + -e 's|@''REPLACE_FUTIMENS''@|$(REPLACE_FUTIMENS)|g' \ + -e 's|@''REPLACE_LSTAT''@|$(REPLACE_LSTAT)|g' \ + -e 's|@''REPLACE_MKDIR''@|$(REPLACE_MKDIR)|g' \ + -e 's|@''REPLACE_MKFIFO''@|$(REPLACE_MKFIFO)|g' \ + -e 's|@''REPLACE_MKNOD''@|$(REPLACE_MKNOD)|g' \ + -e 's|@''REPLACE_STAT''@|$(REPLACE_STAT)|g' \ + -e 's|@''REPLACE_UTIMENSAT''@|$(REPLACE_UTIMENSAT)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/sys_stat.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += sys/stat.h sys/stat.h-t +MOSTLYCLEANDIRS += sys + +EXTRA_DIST += sys_stat.in.h + +## end gnulib module sys_stat + +## begin gnulib module sys_types + +BUILT_SOURCES += sys/types.h + +# We need the following in order to create <sys/types.h> when the system +# doesn't have one that works with the given compiler. +sys/types.h: sys_types.in.h $(top_builddir)/config.status + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + -e 's|@''WINDOWS_STAT_INODES''@|$(WINDOWS_STAT_INODES)|g' \ + < $(srcdir)/sys_types.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += sys/types.h sys/types.h-t + +EXTRA_DIST += sys_types.in.h + +## end gnulib module sys_types + +## begin gnulib module sysexits + +BUILT_SOURCES += $(SYSEXITS_H) + +# We need the following in order to create <sysexits.h> when the system +# doesn't have one that works with the given compiler. +if GL_GENERATE_SYSEXITS_H +sysexits.h: sysexits.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_SYSEXITS_H''@|$(HAVE_SYSEXITS_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYSEXITS_H''@|$(NEXT_SYSEXITS_H)|g' \ + < $(srcdir)/sysexits.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +else +sysexits.h: $(top_builddir)/config.status + rm -f $@ +endif +MOSTLYCLEANFILES += sysexits.h sysexits.h-t + +EXTRA_DIST += sysexits.in.h + +## end gnulib module sysexits + +## begin gnulib module threadlib + +libgnu_a_SOURCES += glthread/threadlib.c + +EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath + +## end gnulib module threadlib + +## begin gnulib module time + +BUILT_SOURCES += time.h + +# We need the following in order to create <time.h> when the system +# doesn't have one that works with the given compiler. +time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_TIME_H''@|$(NEXT_TIME_H)|g' \ + -e 's/@''GNULIB_CTIME''@/$(GNULIB_CTIME)/g' \ + -e 's/@''GNULIB_LOCALTIME''@/$(GNULIB_LOCALTIME)/g' \ + -e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \ + -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \ + -e 's/@''GNULIB_STRFTIME''@/$(GNULIB_STRFTIME)/g' \ + -e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \ + -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \ + -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \ + -e 's/@''GNULIB_TIME_RZ''@/$(GNULIB_TIME_RZ)/g' \ + -e 's/@''GNULIB_TZSET''@/$(GNULIB_TZSET)/g' \ + -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \ + -e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \ + -e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \ + -e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \ + -e 's|@''HAVE_TIMEZONE_T''@|$(HAVE_TIMEZONE_T)|g' \ + -e 's|@''HAVE_TZSET''@|$(HAVE_TZSET)|g' \ + -e 's|@''REPLACE_CTIME''@|$(REPLACE_CTIME)|g' \ + -e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \ + -e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \ + -e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \ + -e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \ + -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \ + -e 's|@''REPLACE_STRFTIME''@|$(REPLACE_STRFTIME)|g' \ + -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \ + -e 's|@''REPLACE_TZSET''@|$(REPLACE_TZSET)|g' \ + -e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e 's|@''UNISTD_H_DEFINES_STRUCT_TIMESPEC''@|$(UNISTD_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/time.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += time.h time.h-t + +EXTRA_DIST += time.in.h + +## end gnulib module time + +## begin gnulib module unistd + +BUILT_SOURCES += unistd.h +libgnu_a_SOURCES += unistd.c + +# We need the following in order to create an empty placeholder for +# <unistd.h> when the system doesn't have one. +unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_UNISTD_H''@|$(HAVE_UNISTD_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_UNISTD_H''@|$(NEXT_UNISTD_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + -e 's/@''GNULIB_CHDIR''@/$(GNULIB_CHDIR)/g' \ + -e 's/@''GNULIB_CHOWN''@/$(GNULIB_CHOWN)/g' \ + -e 's/@''GNULIB_CLOSE''@/$(GNULIB_CLOSE)/g' \ + -e 's/@''GNULIB_DUP''@/$(GNULIB_DUP)/g' \ + -e 's/@''GNULIB_DUP2''@/$(GNULIB_DUP2)/g' \ + -e 's/@''GNULIB_DUP3''@/$(GNULIB_DUP3)/g' \ + -e 's/@''GNULIB_ENVIRON''@/$(GNULIB_ENVIRON)/g' \ + -e 's/@''GNULIB_EUIDACCESS''@/$(GNULIB_EUIDACCESS)/g' \ + -e 's/@''GNULIB_FACCESSAT''@/$(GNULIB_FACCESSAT)/g' \ + -e 's/@''GNULIB_FCHDIR''@/$(GNULIB_FCHDIR)/g' \ + -e 's/@''GNULIB_FCHOWNAT''@/$(GNULIB_FCHOWNAT)/g' \ + -e 's/@''GNULIB_FDATASYNC''@/$(GNULIB_FDATASYNC)/g' \ + -e 's/@''GNULIB_FSYNC''@/$(GNULIB_FSYNC)/g' \ + -e 's/@''GNULIB_FTRUNCATE''@/$(GNULIB_FTRUNCATE)/g' \ + -e 's/@''GNULIB_GETCWD''@/$(GNULIB_GETCWD)/g' \ + -e 's/@''GNULIB_GETDOMAINNAME''@/$(GNULIB_GETDOMAINNAME)/g' \ + -e 's/@''GNULIB_GETDTABLESIZE''@/$(GNULIB_GETDTABLESIZE)/g' \ + -e 's/@''GNULIB_GETGROUPS''@/$(GNULIB_GETGROUPS)/g' \ + -e 's/@''GNULIB_GETHOSTNAME''@/$(GNULIB_GETHOSTNAME)/g' \ + -e 's/@''GNULIB_GETLOGIN''@/$(GNULIB_GETLOGIN)/g' \ + -e 's/@''GNULIB_GETLOGIN_R''@/$(GNULIB_GETLOGIN_R)/g' \ + -e 's/@''GNULIB_GETPAGESIZE''@/$(GNULIB_GETPAGESIZE)/g' \ + -e 's/@''GNULIB_GETPASS''@/$(GNULIB_GETPASS)/g' \ + -e 's/@''GNULIB_GETUSERSHELL''@/$(GNULIB_GETUSERSHELL)/g' \ + -e 's/@''GNULIB_GROUP_MEMBER''@/$(GNULIB_GROUP_MEMBER)/g' \ + -e 's/@''GNULIB_ISATTY''@/$(GNULIB_ISATTY)/g' \ + -e 's/@''GNULIB_LCHOWN''@/$(GNULIB_LCHOWN)/g' \ + -e 's/@''GNULIB_LINK''@/$(GNULIB_LINK)/g' \ + -e 's/@''GNULIB_LINKAT''@/$(GNULIB_LINKAT)/g' \ + -e 's/@''GNULIB_LSEEK''@/$(GNULIB_LSEEK)/g' \ + -e 's/@''GNULIB_PIPE''@/$(GNULIB_PIPE)/g' \ + -e 's/@''GNULIB_PIPE2''@/$(GNULIB_PIPE2)/g' \ + -e 's/@''GNULIB_PREAD''@/$(GNULIB_PREAD)/g' \ + -e 's/@''GNULIB_PWRITE''@/$(GNULIB_PWRITE)/g' \ + -e 's/@''GNULIB_READ''@/$(GNULIB_READ)/g' \ + -e 's/@''GNULIB_READLINK''@/$(GNULIB_READLINK)/g' \ + -e 's/@''GNULIB_READLINKAT''@/$(GNULIB_READLINKAT)/g' \ + -e 's/@''GNULIB_RMDIR''@/$(GNULIB_RMDIR)/g' \ + -e 's/@''GNULIB_SETHOSTNAME''@/$(GNULIB_SETHOSTNAME)/g' \ + -e 's/@''GNULIB_SLEEP''@/$(GNULIB_SLEEP)/g' \ + -e 's/@''GNULIB_SYMLINK''@/$(GNULIB_SYMLINK)/g' \ + -e 's/@''GNULIB_SYMLINKAT''@/$(GNULIB_SYMLINKAT)/g' \ + -e 's/@''GNULIB_TRUNCATE''@/$(GNULIB_TRUNCATE)/g' \ + -e 's/@''GNULIB_TTYNAME_R''@/$(GNULIB_TTYNAME_R)/g' \ + -e 's/@''GNULIB_UNISTD_H_GETOPT''@/0$(GNULIB_GL_UNISTD_H_GETOPT)/g' \ + -e 's/@''GNULIB_UNISTD_H_NONBLOCKING''@/$(GNULIB_UNISTD_H_NONBLOCKING)/g' \ + -e 's/@''GNULIB_UNISTD_H_SIGPIPE''@/$(GNULIB_UNISTD_H_SIGPIPE)/g' \ + -e 's/@''GNULIB_UNLINK''@/$(GNULIB_UNLINK)/g' \ + -e 's/@''GNULIB_UNLINKAT''@/$(GNULIB_UNLINKAT)/g' \ + -e 's/@''GNULIB_USLEEP''@/$(GNULIB_USLEEP)/g' \ + -e 's/@''GNULIB_WRITE''@/$(GNULIB_WRITE)/g' \ + < $(srcdir)/unistd.in.h | \ + sed -e 's|@''HAVE_CHOWN''@|$(HAVE_CHOWN)|g' \ + -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \ + -e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \ + -e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \ + -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \ + -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \ + -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \ + -e 's|@''HAVE_FDATASYNC''@|$(HAVE_FDATASYNC)|g' \ + -e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \ + -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \ + -e 's|@''HAVE_GETDTABLESIZE''@|$(HAVE_GETDTABLESIZE)|g' \ + -e 's|@''HAVE_GETGROUPS''@|$(HAVE_GETGROUPS)|g' \ + -e 's|@''HAVE_GETHOSTNAME''@|$(HAVE_GETHOSTNAME)|g' \ + -e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \ + -e 's|@''HAVE_GETPASS''@|$(HAVE_GETPASS)|g' \ + -e 's|@''HAVE_GROUP_MEMBER''@|$(HAVE_GROUP_MEMBER)|g' \ + -e 's|@''HAVE_LCHOWN''@|$(HAVE_LCHOWN)|g' \ + -e 's|@''HAVE_LINK''@|$(HAVE_LINK)|g' \ + -e 's|@''HAVE_LINKAT''@|$(HAVE_LINKAT)|g' \ + -e 's|@''HAVE_PIPE''@|$(HAVE_PIPE)|g' \ + -e 's|@''HAVE_PIPE2''@|$(HAVE_PIPE2)|g' \ + -e 's|@''HAVE_PREAD''@|$(HAVE_PREAD)|g' \ + -e 's|@''HAVE_PWRITE''@|$(HAVE_PWRITE)|g' \ + -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \ + -e 's|@''HAVE_READLINKAT''@|$(HAVE_READLINKAT)|g' \ + -e 's|@''HAVE_SETHOSTNAME''@|$(HAVE_SETHOSTNAME)|g' \ + -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \ + -e 's|@''HAVE_SYMLINK''@|$(HAVE_SYMLINK)|g' \ + -e 's|@''HAVE_SYMLINKAT''@|$(HAVE_SYMLINKAT)|g' \ + -e 's|@''HAVE_UNLINKAT''@|$(HAVE_UNLINKAT)|g' \ + -e 's|@''HAVE_USLEEP''@|$(HAVE_USLEEP)|g' \ + -e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \ + -e 's|@''HAVE_DECL_FCHDIR''@|$(HAVE_DECL_FCHDIR)|g' \ + -e 's|@''HAVE_DECL_FDATASYNC''@|$(HAVE_DECL_FDATASYNC)|g' \ + -e 's|@''HAVE_DECL_GETDOMAINNAME''@|$(HAVE_DECL_GETDOMAINNAME)|g' \ + -e 's|@''HAVE_DECL_GETLOGIN''@|$(HAVE_DECL_GETLOGIN)|g' \ + -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \ + -e 's|@''HAVE_DECL_GETPAGESIZE''@|$(HAVE_DECL_GETPAGESIZE)|g' \ + -e 's|@''HAVE_DECL_GETUSERSHELL''@|$(HAVE_DECL_GETUSERSHELL)|g' \ + -e 's|@''HAVE_DECL_SETHOSTNAME''@|$(HAVE_DECL_SETHOSTNAME)|g' \ + -e 's|@''HAVE_DECL_TRUNCATE''@|$(HAVE_DECL_TRUNCATE)|g' \ + -e 's|@''HAVE_DECL_TTYNAME_R''@|$(HAVE_DECL_TTYNAME_R)|g' \ + -e 's|@''HAVE_OS_H''@|$(HAVE_OS_H)|g' \ + -e 's|@''HAVE_SYS_PARAM_H''@|$(HAVE_SYS_PARAM_H)|g' \ + | \ + sed -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \ + -e 's|@''REPLACE_CLOSE''@|$(REPLACE_CLOSE)|g' \ + -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \ + -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \ + -e 's|@''REPLACE_FACCESSAT''@|$(REPLACE_FACCESSAT)|g' \ + -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \ + -e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \ + -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \ + -e 's|@''REPLACE_GETDOMAINNAME''@|$(REPLACE_GETDOMAINNAME)|g' \ + -e 's|@''REPLACE_GETDTABLESIZE''@|$(REPLACE_GETDTABLESIZE)|g' \ + -e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \ + -e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \ + -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \ + -e 's|@''REPLACE_GETPASS''@|$(REPLACE_GETPASS)|g' \ + -e 's|@''REPLACE_ISATTY''@|$(REPLACE_ISATTY)|g' \ + -e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \ + -e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \ + -e 's|@''REPLACE_LINKAT''@|$(REPLACE_LINKAT)|g' \ + -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \ + -e 's|@''REPLACE_PREAD''@|$(REPLACE_PREAD)|g' \ + -e 's|@''REPLACE_PWRITE''@|$(REPLACE_PWRITE)|g' \ + -e 's|@''REPLACE_READ''@|$(REPLACE_READ)|g' \ + -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \ + -e 's|@''REPLACE_READLINKAT''@|$(REPLACE_READLINKAT)|g' \ + -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \ + -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \ + -e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \ + -e 's|@''REPLACE_SYMLINKAT''@|$(REPLACE_SYMLINKAT)|g' \ + -e 's|@''REPLACE_TRUNCATE''@|$(REPLACE_TRUNCATE)|g' \ + -e 's|@''REPLACE_TTYNAME_R''@|$(REPLACE_TTYNAME_R)|g' \ + -e 's|@''REPLACE_UNLINK''@|$(REPLACE_UNLINK)|g' \ + -e 's|@''REPLACE_UNLINKAT''@|$(REPLACE_UNLINKAT)|g' \ + -e 's|@''REPLACE_USLEEP''@|$(REPLACE_USLEEP)|g' \ + -e 's|@''REPLACE_WRITE''@|$(REPLACE_WRITE)|g' \ + -e 's|@''UNISTD_H_HAVE_WINSOCK2_H''@|$(UNISTD_H_HAVE_WINSOCK2_H)|g' \ + -e 's|@''UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS''@|$(UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += unistd.h unistd.h-t + +EXTRA_DIST += unistd.in.h + +## end gnulib module unistd + +## begin gnulib module unistd-safer + +libgnu_a_SOURCES += dup-safer.c fd-safer.c pipe-safer.c + +EXTRA_DIST += unistd--.h unistd-safer.h + +## end gnulib module unistd-safer + +## begin gnulib module unitypes + +BUILT_SOURCES += $(LIBUNISTRING_UNITYPES_H) + +unitypes.h: unitypes.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/unitypes.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += unitypes.h unitypes.h-t + +EXTRA_DIST += unitypes.in.h + +## end gnulib module unitypes + +## begin gnulib module uniwidth/base + +BUILT_SOURCES += $(LIBUNISTRING_UNIWIDTH_H) + +uniwidth.h: uniwidth.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/uniwidth.in.h; \ + } > $@-t && \ + mv -f $@-t $@ +MOSTLYCLEANFILES += uniwidth.h uniwidth.h-t + +EXTRA_DIST += localcharset.h uniwidth.in.h + +## end gnulib module uniwidth/base + +## begin gnulib module uniwidth/width + +if LIBUNISTRING_COMPILE_UNIWIDTH_WIDTH +libgnu_a_SOURCES += uniwidth/width.c +endif + +EXTRA_DIST += uniwidth/cjk.h + +## end gnulib module uniwidth/width + +## begin gnulib module vasnprintf + + +EXTRA_DIST += asnprintf.c float+.h printf-args.c printf-args.h printf-parse.c printf-parse.h vasnprintf.c vasnprintf.h + +EXTRA_libgnu_a_SOURCES += asnprintf.c printf-args.c printf-parse.c vasnprintf.c + +## end gnulib module vasnprintf + +## begin gnulib module verify + + +EXTRA_DIST += verify.h + +## end gnulib module verify + +## begin gnulib module vsnprintf + + +EXTRA_DIST += vsnprintf.c + +EXTRA_libgnu_a_SOURCES += vsnprintf.c + +## end gnulib module vsnprintf + +## begin gnulib module wchar + +BUILT_SOURCES += wchar.h + +# We need the following in order to create <wchar.h> when the system +# version does not work standalone. +wchar.h: wchar.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''HAVE_FEATURES_H''@|$(HAVE_FEATURES_H)|g' \ + -e 's|@''NEXT_WCHAR_H''@|$(NEXT_WCHAR_H)|g' \ + -e 's|@''HAVE_WCHAR_H''@|$(HAVE_WCHAR_H)|g' \ + -e 's/@''HAVE_CRTDEFS_H''@/$(HAVE_CRTDEFS_H)/g' \ + -e 's/@''GNULIB_OVERRIDES_WINT_T''@/$(GNULIB_OVERRIDES_WINT_T)/g' \ + -e 's/@''GNULIB_BTOWC''@/$(GNULIB_BTOWC)/g' \ + -e 's/@''GNULIB_WCTOB''@/$(GNULIB_WCTOB)/g' \ + -e 's/@''GNULIB_MBSINIT''@/$(GNULIB_MBSINIT)/g' \ + -e 's/@''GNULIB_MBRTOWC''@/$(GNULIB_MBRTOWC)/g' \ + -e 's/@''GNULIB_MBRLEN''@/$(GNULIB_MBRLEN)/g' \ + -e 's/@''GNULIB_MBSRTOWCS''@/$(GNULIB_MBSRTOWCS)/g' \ + -e 's/@''GNULIB_MBSNRTOWCS''@/$(GNULIB_MBSNRTOWCS)/g' \ + -e 's/@''GNULIB_WCRTOMB''@/$(GNULIB_WCRTOMB)/g' \ + -e 's/@''GNULIB_WCSRTOMBS''@/$(GNULIB_WCSRTOMBS)/g' \ + -e 's/@''GNULIB_WCSNRTOMBS''@/$(GNULIB_WCSNRTOMBS)/g' \ + -e 's/@''GNULIB_WCWIDTH''@/$(GNULIB_WCWIDTH)/g' \ + -e 's/@''GNULIB_WMEMCHR''@/$(GNULIB_WMEMCHR)/g' \ + -e 's/@''GNULIB_WMEMCMP''@/$(GNULIB_WMEMCMP)/g' \ + -e 's/@''GNULIB_WMEMCPY''@/$(GNULIB_WMEMCPY)/g' \ + -e 's/@''GNULIB_WMEMMOVE''@/$(GNULIB_WMEMMOVE)/g' \ + -e 's/@''GNULIB_WMEMSET''@/$(GNULIB_WMEMSET)/g' \ + -e 's/@''GNULIB_WCSLEN''@/$(GNULIB_WCSLEN)/g' \ + -e 's/@''GNULIB_WCSNLEN''@/$(GNULIB_WCSNLEN)/g' \ + -e 's/@''GNULIB_WCSCPY''@/$(GNULIB_WCSCPY)/g' \ + -e 's/@''GNULIB_WCPCPY''@/$(GNULIB_WCPCPY)/g' \ + -e 's/@''GNULIB_WCSNCPY''@/$(GNULIB_WCSNCPY)/g' \ + -e 's/@''GNULIB_WCPNCPY''@/$(GNULIB_WCPNCPY)/g' \ + -e 's/@''GNULIB_WCSCAT''@/$(GNULIB_WCSCAT)/g' \ + -e 's/@''GNULIB_WCSNCAT''@/$(GNULIB_WCSNCAT)/g' \ + -e 's/@''GNULIB_WCSCMP''@/$(GNULIB_WCSCMP)/g' \ + -e 's/@''GNULIB_WCSNCMP''@/$(GNULIB_WCSNCMP)/g' \ + -e 's/@''GNULIB_WCSCASECMP''@/$(GNULIB_WCSCASECMP)/g' \ + -e 's/@''GNULIB_WCSNCASECMP''@/$(GNULIB_WCSNCASECMP)/g' \ + -e 's/@''GNULIB_WCSCOLL''@/$(GNULIB_WCSCOLL)/g' \ + -e 's/@''GNULIB_WCSXFRM''@/$(GNULIB_WCSXFRM)/g' \ + -e 's/@''GNULIB_WCSDUP''@/$(GNULIB_WCSDUP)/g' \ + -e 's/@''GNULIB_WCSCHR''@/$(GNULIB_WCSCHR)/g' \ + -e 's/@''GNULIB_WCSRCHR''@/$(GNULIB_WCSRCHR)/g' \ + -e 's/@''GNULIB_WCSCSPN''@/$(GNULIB_WCSCSPN)/g' \ + -e 's/@''GNULIB_WCSSPN''@/$(GNULIB_WCSSPN)/g' \ + -e 's/@''GNULIB_WCSPBRK''@/$(GNULIB_WCSPBRK)/g' \ + -e 's/@''GNULIB_WCSSTR''@/$(GNULIB_WCSSTR)/g' \ + -e 's/@''GNULIB_WCSTOK''@/$(GNULIB_WCSTOK)/g' \ + -e 's/@''GNULIB_WCSWIDTH''@/$(GNULIB_WCSWIDTH)/g' \ + -e 's/@''GNULIB_WCSFTIME''@/$(GNULIB_WCSFTIME)/g' \ + < $(srcdir)/wchar.in.h | \ + sed -e 's|@''HAVE_WINT_T''@|$(HAVE_WINT_T)|g' \ + -e 's|@''HAVE_BTOWC''@|$(HAVE_BTOWC)|g' \ + -e 's|@''HAVE_MBSINIT''@|$(HAVE_MBSINIT)|g' \ + -e 's|@''HAVE_MBRTOWC''@|$(HAVE_MBRTOWC)|g' \ + -e 's|@''HAVE_MBRLEN''@|$(HAVE_MBRLEN)|g' \ + -e 's|@''HAVE_MBSRTOWCS''@|$(HAVE_MBSRTOWCS)|g' \ + -e 's|@''HAVE_MBSNRTOWCS''@|$(HAVE_MBSNRTOWCS)|g' \ + -e 's|@''HAVE_WCRTOMB''@|$(HAVE_WCRTOMB)|g' \ + -e 's|@''HAVE_WCSRTOMBS''@|$(HAVE_WCSRTOMBS)|g' \ + -e 's|@''HAVE_WCSNRTOMBS''@|$(HAVE_WCSNRTOMBS)|g' \ + -e 's|@''HAVE_WMEMCHR''@|$(HAVE_WMEMCHR)|g' \ + -e 's|@''HAVE_WMEMCMP''@|$(HAVE_WMEMCMP)|g' \ + -e 's|@''HAVE_WMEMCPY''@|$(HAVE_WMEMCPY)|g' \ + -e 's|@''HAVE_WMEMMOVE''@|$(HAVE_WMEMMOVE)|g' \ + -e 's|@''HAVE_WMEMSET''@|$(HAVE_WMEMSET)|g' \ + -e 's|@''HAVE_WCSLEN''@|$(HAVE_WCSLEN)|g' \ + -e 's|@''HAVE_WCSNLEN''@|$(HAVE_WCSNLEN)|g' \ + -e 's|@''HAVE_WCSCPY''@|$(HAVE_WCSCPY)|g' \ + -e 's|@''HAVE_WCPCPY''@|$(HAVE_WCPCPY)|g' \ + -e 's|@''HAVE_WCSNCPY''@|$(HAVE_WCSNCPY)|g' \ + -e 's|@''HAVE_WCPNCPY''@|$(HAVE_WCPNCPY)|g' \ + -e 's|@''HAVE_WCSCAT''@|$(HAVE_WCSCAT)|g' \ + -e 's|@''HAVE_WCSNCAT''@|$(HAVE_WCSNCAT)|g' \ + -e 's|@''HAVE_WCSCMP''@|$(HAVE_WCSCMP)|g' \ + -e 's|@''HAVE_WCSNCMP''@|$(HAVE_WCSNCMP)|g' \ + -e 's|@''HAVE_WCSCASECMP''@|$(HAVE_WCSCASECMP)|g' \ + -e 's|@''HAVE_WCSNCASECMP''@|$(HAVE_WCSNCASECMP)|g' \ + -e 's|@''HAVE_WCSCOLL''@|$(HAVE_WCSCOLL)|g' \ + -e 's|@''HAVE_WCSXFRM''@|$(HAVE_WCSXFRM)|g' \ + -e 's|@''HAVE_WCSDUP''@|$(HAVE_WCSDUP)|g' \ + -e 's|@''HAVE_WCSCHR''@|$(HAVE_WCSCHR)|g' \ + -e 's|@''HAVE_WCSRCHR''@|$(HAVE_WCSRCHR)|g' \ + -e 's|@''HAVE_WCSCSPN''@|$(HAVE_WCSCSPN)|g' \ + -e 's|@''HAVE_WCSSPN''@|$(HAVE_WCSSPN)|g' \ + -e 's|@''HAVE_WCSPBRK''@|$(HAVE_WCSPBRK)|g' \ + -e 's|@''HAVE_WCSSTR''@|$(HAVE_WCSSTR)|g' \ + -e 's|@''HAVE_WCSTOK''@|$(HAVE_WCSTOK)|g' \ + -e 's|@''HAVE_WCSWIDTH''@|$(HAVE_WCSWIDTH)|g' \ + -e 's|@''HAVE_WCSFTIME''@|$(HAVE_WCSFTIME)|g' \ + -e 's|@''HAVE_DECL_WCTOB''@|$(HAVE_DECL_WCTOB)|g' \ + -e 's|@''HAVE_DECL_WCWIDTH''@|$(HAVE_DECL_WCWIDTH)|g' \ + | \ + sed -e 's|@''REPLACE_MBSTATE_T''@|$(REPLACE_MBSTATE_T)|g' \ + -e 's|@''REPLACE_BTOWC''@|$(REPLACE_BTOWC)|g' \ + -e 's|@''REPLACE_WCTOB''@|$(REPLACE_WCTOB)|g' \ + -e 's|@''REPLACE_MBSINIT''@|$(REPLACE_MBSINIT)|g' \ + -e 's|@''REPLACE_MBRTOWC''@|$(REPLACE_MBRTOWC)|g' \ + -e 's|@''REPLACE_MBRLEN''@|$(REPLACE_MBRLEN)|g' \ + -e 's|@''REPLACE_MBSRTOWCS''@|$(REPLACE_MBSRTOWCS)|g' \ + -e 's|@''REPLACE_MBSNRTOWCS''@|$(REPLACE_MBSNRTOWCS)|g' \ + -e 's|@''REPLACE_WCRTOMB''@|$(REPLACE_WCRTOMB)|g' \ + -e 's|@''REPLACE_WCSRTOMBS''@|$(REPLACE_WCSRTOMBS)|g' \ + -e 's|@''REPLACE_WCSNRTOMBS''@|$(REPLACE_WCSNRTOMBS)|g' \ + -e 's|@''REPLACE_WCWIDTH''@|$(REPLACE_WCWIDTH)|g' \ + -e 's|@''REPLACE_WCSWIDTH''@|$(REPLACE_WCSWIDTH)|g' \ + -e 's|@''REPLACE_WCSFTIME''@|$(REPLACE_WCSFTIME)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += wchar.h wchar.h-t + +EXTRA_DIST += wchar.in.h + +## end gnulib module wchar + +## begin gnulib module wcrtomb + + +EXTRA_DIST += wcrtomb.c + +EXTRA_libgnu_a_SOURCES += wcrtomb.c + +## end gnulib module wcrtomb + +## begin gnulib module wctype-h + +BUILT_SOURCES += wctype.h +libgnu_a_SOURCES += wctype-h.c + +# We need the following in order to create <wctype.h> when the system +# doesn't have one that works with the given compiler. +wctype.h: wctype.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's/@''HAVE_WCTYPE_H''@/$(HAVE_WCTYPE_H)/g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_WCTYPE_H''@|$(NEXT_WCTYPE_H)|g' \ + -e 's/@''HAVE_CRTDEFS_H''@/$(HAVE_CRTDEFS_H)/g' \ + -e 's/@''GNULIB_OVERRIDES_WINT_T''@/$(GNULIB_OVERRIDES_WINT_T)/g' \ + -e 's/@''GNULIB_ISWBLANK''@/$(GNULIB_ISWBLANK)/g' \ + -e 's/@''GNULIB_WCTYPE''@/$(GNULIB_WCTYPE)/g' \ + -e 's/@''GNULIB_ISWCTYPE''@/$(GNULIB_ISWCTYPE)/g' \ + -e 's/@''GNULIB_WCTRANS''@/$(GNULIB_WCTRANS)/g' \ + -e 's/@''GNULIB_TOWCTRANS''@/$(GNULIB_TOWCTRANS)/g' \ + -e 's/@''HAVE_ISWBLANK''@/$(HAVE_ISWBLANK)/g' \ + -e 's/@''HAVE_ISWCNTRL''@/$(HAVE_ISWCNTRL)/g' \ + -e 's/@''HAVE_WCTYPE_T''@/$(HAVE_WCTYPE_T)/g' \ + -e 's/@''HAVE_WCTRANS_T''@/$(HAVE_WCTRANS_T)/g' \ + -e 's/@''HAVE_WINT_T''@/$(HAVE_WINT_T)/g' \ + -e 's/@''REPLACE_ISWBLANK''@/$(REPLACE_ISWBLANK)/g' \ + -e 's/@''REPLACE_ISWCNTRL''@/$(REPLACE_ISWCNTRL)/g' \ + -e 's/@''REPLACE_TOWLOWER''@/$(REPLACE_TOWLOWER)/g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/wctype.in.h; \ + } > $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += wctype.h wctype.h-t + +EXTRA_DIST += wctype.in.h + +## end gnulib module wctype-h + +## begin gnulib module wcwidth + + +EXTRA_DIST += wcwidth.c + +EXTRA_libgnu_a_SOURCES += wcwidth.c + +## end gnulib module wcwidth + +## begin gnulib module xalloc-oversized + + +EXTRA_DIST += xalloc-oversized.h + +## end gnulib module xalloc-oversized + +## begin gnulib module xsize + +libgnu_a_SOURCES += xsize.h xsize.c + +## end gnulib module xsize + + +mostlyclean-local: mostlyclean-generic + @for dir in '' $(MOSTLYCLEANDIRS); do \ + if test -n "$$dir" && test -d $$dir; then \ + echo "rmdir $$dir"; rmdir $$dir; \ + fi; \ + done; \ + : diff --git a/grub-core/lib/gnulib/Makefile.in b/grub-core/lib/gnulib/Makefile.in new file mode 100644 index 0000000..839c259 --- /dev/null +++ b/grub-core/lib/gnulib/Makefile.in @@ -0,0 +1,3071 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (C) 2002-2019 Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this file. If not, see <https://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, +# this file may be distributed as part of a program that +# contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# Generated by gnulib-tool. +# Reproduce by: +# gnulib-tool --import --local-dir=gl \ +# --lib=libgnu \ +# --source-base=grub-core/lib/gnulib \ +# --m4-base=m4 \ +# --doc-base=doc \ +# --tests-base=tests \ +# --aux-dir=build-aux \ +# --no-conditional-dependencies \ +# --no-libtool \ +# --macro-prefix=gl \ +# --no-vc-files \ +# argp \ +# base64 \ +# error \ +# fnmatch \ +# getdelim \ +# getline \ +# gettext-h \ +# gitlog-to-changelog \ +# mbswidth \ +# progname \ +# realloc-gnu \ +# regex \ +# save-cwd + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@LIBUNISTRING_COMPILE_UNIWIDTH_WIDTH_TRUE@am__append_1 = uniwidth/width.c +subdir = grub-core/lib/gnulib +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \ + $(top_srcdir)/m4/__inline.m4 \ + $(top_srcdir)/m4/absolute-header.m4 $(top_srcdir)/m4/alloca.m4 \ + $(top_srcdir)/m4/argp.m4 $(top_srcdir)/m4/base64.m4 \ + $(top_srcdir)/m4/btowc.m4 $(top_srcdir)/m4/builtin-expect.m4 \ + $(top_srcdir)/m4/chdir-long.m4 $(top_srcdir)/m4/close.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/dirent_h.m4 \ + $(top_srcdir)/m4/dirfd.m4 $(top_srcdir)/m4/dirname.m4 \ + $(top_srcdir)/m4/double-slash-root.m4 $(top_srcdir)/m4/dup2.m4 \ + $(top_srcdir)/m4/eealloc.m4 $(top_srcdir)/m4/errno_h.m4 \ + $(top_srcdir)/m4/error.m4 $(top_srcdir)/m4/exponentd.m4 \ + $(top_srcdir)/m4/extensions.m4 \ + $(top_srcdir)/m4/extern-inline.m4 $(top_srcdir)/m4/fchdir.m4 \ + $(top_srcdir)/m4/fcntl-o.m4 $(top_srcdir)/m4/fcntl.m4 \ + $(top_srcdir)/m4/fcntl_h.m4 $(top_srcdir)/m4/filenamecat.m4 \ + $(top_srcdir)/m4/flexmember.m4 $(top_srcdir)/m4/float_h.m4 \ + $(top_srcdir)/m4/fnmatch.m4 $(top_srcdir)/m4/fnmatch_h.m4 \ + $(top_srcdir)/m4/fstat.m4 $(top_srcdir)/m4/getcwd.m4 \ + $(top_srcdir)/m4/getdelim.m4 $(top_srcdir)/m4/getdtablesize.m4 \ + $(top_srcdir)/m4/getline.m4 $(top_srcdir)/m4/getopt.m4 \ + $(top_srcdir)/m4/getprogname.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnulib-common.m4 \ + $(top_srcdir)/m4/gnulib-comp.m4 \ + $(top_srcdir)/m4/host-cpu-c-abi.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/include_next.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax_t.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/langinfo_h.m4 \ + $(top_srcdir)/m4/largefile.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libunistring-base.m4 \ + $(top_srcdir)/m4/limits-h.m4 $(top_srcdir)/m4/localcharset.m4 \ + $(top_srcdir)/m4/locale-fr.m4 $(top_srcdir)/m4/locale-ja.m4 \ + $(top_srcdir)/m4/locale-zh.m4 $(top_srcdir)/m4/locale_h.m4 \ + $(top_srcdir)/m4/localeconv.m4 $(top_srcdir)/m4/lock.m4 \ + $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/lstat.m4 \ + $(top_srcdir)/m4/malloc.m4 $(top_srcdir)/m4/malloca.m4 \ + $(top_srcdir)/m4/mbrtowc.m4 $(top_srcdir)/m4/mbsinit.m4 \ + $(top_srcdir)/m4/mbsrtowcs.m4 $(top_srcdir)/m4/mbstate_t.m4 \ + $(top_srcdir)/m4/mbswidth.m4 $(top_srcdir)/m4/mbtowc.m4 \ + $(top_srcdir)/m4/memchr.m4 $(top_srcdir)/m4/mempcpy.m4 \ + $(top_srcdir)/m4/memrchr.m4 $(top_srcdir)/m4/mmap-anon.m4 \ + $(top_srcdir)/m4/mode_t.m4 $(top_srcdir)/m4/msvc-inval.m4 \ + $(top_srcdir)/m4/msvc-nothrow.m4 $(top_srcdir)/m4/multiarch.m4 \ + $(top_srcdir)/m4/nl_langinfo.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/nocrash.m4 $(top_srcdir)/m4/off_t.m4 \ + $(top_srcdir)/m4/open-cloexec.m4 $(top_srcdir)/m4/open.m4 \ + $(top_srcdir)/m4/openat.m4 $(top_srcdir)/m4/pathmax.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf.m4 \ + $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/pthread_rwlock_rdlock.m4 \ + $(top_srcdir)/m4/rawmemchr.m4 $(top_srcdir)/m4/realloc.m4 \ + $(top_srcdir)/m4/regex.m4 $(top_srcdir)/m4/save-cwd.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/sleep.m4 \ + $(top_srcdir)/m4/ssize_t.m4 $(top_srcdir)/m4/stat-time.m4 \ + $(top_srcdir)/m4/stat.m4 $(top_srcdir)/m4/stdalign.m4 \ + $(top_srcdir)/m4/stdbool.m4 $(top_srcdir)/m4/stddef_h.m4 \ + $(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/stdio_h.m4 $(top_srcdir)/m4/stdlib_h.m4 \ + $(top_srcdir)/m4/strcase.m4 $(top_srcdir)/m4/strchrnul.m4 \ + $(top_srcdir)/m4/strdup.m4 $(top_srcdir)/m4/strerror.m4 \ + $(top_srcdir)/m4/string_h.m4 $(top_srcdir)/m4/strings_h.m4 \ + $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/strnlen.m4 \ + $(top_srcdir)/m4/sys_socket_h.m4 \ + $(top_srcdir)/m4/sys_stat_h.m4 $(top_srcdir)/m4/sys_types_h.m4 \ + $(top_srcdir)/m4/sysexits.m4 $(top_srcdir)/m4/threadlib.m4 \ + $(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/unistd-safer.m4 \ + $(top_srcdir)/m4/unistd_h.m4 $(top_srcdir)/m4/vasnprintf.m4 \ + $(top_srcdir)/m4/vsnprintf.m4 $(top_srcdir)/m4/warn-on-use.m4 \ + $(top_srcdir)/m4/wchar_h.m4 $(top_srcdir)/m4/wchar_t.m4 \ + $(top_srcdir)/m4/wcrtomb.m4 $(top_srcdir)/m4/wctype_h.m4 \ + $(top_srcdir)/m4/wcwidth.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config-util.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = +libgnu_a_AR = $(AR) $(ARFLAGS) +am__DEPENDENCIES_1 = +am__libgnu_a_SOURCES_DIST = argp.h argp-ba.c argp-eexst.c \ + argp-fmtstream.c argp-fmtstream.h argp-fs-xinl.c argp-help.c \ + argp-namefrob.h argp-parse.c argp-pin.c argp-pv.c argp-pvh.c \ + argp-xinl.c base64.h base64.c cloexec.c dirname-lgpl.c \ + basename-lgpl.c stripslash.c exitfail.c fd-hook.c \ + fd-safer-flag.c dup-safer-flag.c filenamecat-lgpl.c \ + getprogname.h getprogname.c gettext.h hard-locale.c \ + localcharset.c glthread/lock.h glthread/lock.c malloca.c \ + mbswidth.h mbswidth.c openat-die.c progname.h progname.c \ + save-cwd.c size_max.h stat-time.c strnlen1.h strnlen1.c \ + glthread/threadlib.c unistd.c dup-safer.c fd-safer.c \ + pipe-safer.c uniwidth/width.c wctype-h.c xsize.h xsize.c +am__dirstamp = $(am__leading_dot)dirstamp +@LIBUNISTRING_COMPILE_UNIWIDTH_WIDTH_TRUE@am__objects_1 = uniwidth/width.$(OBJEXT) +am_libgnu_a_OBJECTS = argp-ba.$(OBJEXT) argp-eexst.$(OBJEXT) \ + argp-fmtstream.$(OBJEXT) argp-fs-xinl.$(OBJEXT) \ + argp-help.$(OBJEXT) argp-parse.$(OBJEXT) argp-pin.$(OBJEXT) \ + argp-pv.$(OBJEXT) argp-pvh.$(OBJEXT) argp-xinl.$(OBJEXT) \ + base64.$(OBJEXT) cloexec.$(OBJEXT) dirname-lgpl.$(OBJEXT) \ + basename-lgpl.$(OBJEXT) stripslash.$(OBJEXT) \ + exitfail.$(OBJEXT) fd-hook.$(OBJEXT) fd-safer-flag.$(OBJEXT) \ + dup-safer-flag.$(OBJEXT) filenamecat-lgpl.$(OBJEXT) \ + getprogname.$(OBJEXT) hard-locale.$(OBJEXT) \ + localcharset.$(OBJEXT) glthread/lock.$(OBJEXT) \ + malloca.$(OBJEXT) mbswidth.$(OBJEXT) openat-die.$(OBJEXT) \ + progname.$(OBJEXT) save-cwd.$(OBJEXT) stat-time.$(OBJEXT) \ + strnlen1.$(OBJEXT) glthread/threadlib.$(OBJEXT) \ + unistd.$(OBJEXT) dup-safer.$(OBJEXT) fd-safer.$(OBJEXT) \ + pipe-safer.$(OBJEXT) $(am__objects_1) wctype-h.$(OBJEXT) \ + xsize.$(OBJEXT) +libgnu_a_OBJECTS = $(am_libgnu_a_OBJECTS) +LTLIBRARIES = $(noinst_LTLIBRARIES) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgnu_a_SOURCES) $(EXTRA_libgnu_a_SOURCES) +DIST_SOURCES = $(am__libgnu_a_SOURCES_DIST) $(EXTRA_libgnu_a_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp alloca.c +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +BOOT_TIME_STATS = @BOOT_TIME_STATS@ +BSS_START_SYMBOL = @BSS_START_SYMBOL@ +BUILD_CC = @BUILD_CC@ +BUILD_CFLAGS = @BUILD_CFLAGS@ +BUILD_CPPFLAGS = @BUILD_CPPFLAGS@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_FREETYPE_CFLAGS = @BUILD_FREETYPE_CFLAGS@ +BUILD_FREETYPE_LIBS = @BUILD_FREETYPE_LIBS@ +BUILD_LDFLAGS = @BUILD_LDFLAGS@ +BUILD_LIBM = @BUILD_LIBM@ +BUILD_SHEBANG = @BUILD_SHEBANG@ +BUILD_SIZEOF_LONG = @BUILD_SIZEOF_LONG@ +BUILD_SIZEOF_VOID_P = @BUILD_SIZEOF_VOID_P@ +BUILD_WORDS_BIGENDIAN = @BUILD_WORDS_BIGENDIAN@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CMP = @CMP@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISK_CACHE_STATS = @DISK_CACHE_STATS@ +DJVU_FONT_SOURCE = @DJVU_FONT_SOURCE@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EFIEMU64_LINK_FORMAT = @EFIEMU64_LINK_FORMAT@ +EGREP = @EGREP@ +EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@ +EMULTIHOP_VALUE = @EMULTIHOP_VALUE@ +END_SYMBOL = @END_SYMBOL@ +ENOLINK_HIDDEN = @ENOLINK_HIDDEN@ +ENOLINK_VALUE = @ENOLINK_VALUE@ +EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@ +EOVERFLOW_VALUE = @EOVERFLOW_VALUE@ +ERRNO_H = @ERRNO_H@ +EXEEXT = @EXEEXT@ +FLOAT_H = @FLOAT_H@ +FNMATCH_H = @FNMATCH_H@ +FONT_SOURCE = @FONT_SOURCE@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GETOPT_CDEFS_H = @GETOPT_CDEFS_H@ +GETOPT_H = @GETOPT_H@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIBC21 = @GLIBC21@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIB_ALPHASORT = @GNULIB_ALPHASORT@ +GNULIB_ATOLL = @GNULIB_ATOLL@ +GNULIB_BTOWC = @GNULIB_BTOWC@ +GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@ +GNULIB_CANONICALIZE_FILE_NAME = @GNULIB_CANONICALIZE_FILE_NAME@ +GNULIB_CHDIR = @GNULIB_CHDIR@ +GNULIB_CHOWN = @GNULIB_CHOWN@ +GNULIB_CLOSE = @GNULIB_CLOSE@ +GNULIB_CLOSEDIR = @GNULIB_CLOSEDIR@ +GNULIB_CTIME = @GNULIB_CTIME@ +GNULIB_DIRFD = @GNULIB_DIRFD@ +GNULIB_DPRINTF = @GNULIB_DPRINTF@ +GNULIB_DUP = @GNULIB_DUP@ +GNULIB_DUP2 = @GNULIB_DUP2@ +GNULIB_DUP3 = @GNULIB_DUP3@ +GNULIB_DUPLOCALE = @GNULIB_DUPLOCALE@ +GNULIB_ENVIRON = @GNULIB_ENVIRON@ +GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@ +GNULIB_EXPLICIT_BZERO = @GNULIB_EXPLICIT_BZERO@ +GNULIB_FACCESSAT = @GNULIB_FACCESSAT@ +GNULIB_FCHDIR = @GNULIB_FCHDIR@ +GNULIB_FCHMODAT = @GNULIB_FCHMODAT@ +GNULIB_FCHOWNAT = @GNULIB_FCHOWNAT@ +GNULIB_FCLOSE = @GNULIB_FCLOSE@ +GNULIB_FCNTL = @GNULIB_FCNTL@ +GNULIB_FDATASYNC = @GNULIB_FDATASYNC@ +GNULIB_FDOPEN = @GNULIB_FDOPEN@ +GNULIB_FDOPENDIR = @GNULIB_FDOPENDIR@ +GNULIB_FFLUSH = @GNULIB_FFLUSH@ +GNULIB_FFS = @GNULIB_FFS@ +GNULIB_FFSL = @GNULIB_FFSL@ +GNULIB_FFSLL = @GNULIB_FFSLL@ +GNULIB_FGETC = @GNULIB_FGETC@ +GNULIB_FGETS = @GNULIB_FGETS@ +GNULIB_FNMATCH = @GNULIB_FNMATCH@ +GNULIB_FOPEN = @GNULIB_FOPEN@ +GNULIB_FPRINTF = @GNULIB_FPRINTF@ +GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@ +GNULIB_FPURGE = @GNULIB_FPURGE@ +GNULIB_FPUTC = @GNULIB_FPUTC@ +GNULIB_FPUTS = @GNULIB_FPUTS@ +GNULIB_FREAD = @GNULIB_FREAD@ +GNULIB_FREOPEN = @GNULIB_FREOPEN@ +GNULIB_FSCANF = @GNULIB_FSCANF@ +GNULIB_FSEEK = @GNULIB_FSEEK@ +GNULIB_FSEEKO = @GNULIB_FSEEKO@ +GNULIB_FSTAT = @GNULIB_FSTAT@ +GNULIB_FSTATAT = @GNULIB_FSTATAT@ +GNULIB_FSYNC = @GNULIB_FSYNC@ +GNULIB_FTELL = @GNULIB_FTELL@ +GNULIB_FTELLO = @GNULIB_FTELLO@ +GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@ +GNULIB_FUTIMENS = @GNULIB_FUTIMENS@ +GNULIB_FWRITE = @GNULIB_FWRITE@ +GNULIB_GETC = @GNULIB_GETC@ +GNULIB_GETCHAR = @GNULIB_GETCHAR@ +GNULIB_GETCWD = @GNULIB_GETCWD@ +GNULIB_GETDELIM = @GNULIB_GETDELIM@ +GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@ +GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@ +GNULIB_GETGROUPS = @GNULIB_GETGROUPS@ +GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@ +GNULIB_GETLINE = @GNULIB_GETLINE@ +GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@ +GNULIB_GETLOGIN = @GNULIB_GETLOGIN@ +GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@ +GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@ +GNULIB_GETPASS = @GNULIB_GETPASS@ +GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ +GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@ +GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@ +GNULIB_GL_UNISTD_H_GETOPT = @GNULIB_GL_UNISTD_H_GETOPT@ +GNULIB_GRANTPT = @GNULIB_GRANTPT@ +GNULIB_GROUP_MEMBER = @GNULIB_GROUP_MEMBER@ +GNULIB_ISATTY = @GNULIB_ISATTY@ +GNULIB_ISWBLANK = @GNULIB_ISWBLANK@ +GNULIB_ISWCTYPE = @GNULIB_ISWCTYPE@ +GNULIB_LCHMOD = @GNULIB_LCHMOD@ +GNULIB_LCHOWN = @GNULIB_LCHOWN@ +GNULIB_LINK = @GNULIB_LINK@ +GNULIB_LINKAT = @GNULIB_LINKAT@ +GNULIB_LOCALECONV = @GNULIB_LOCALECONV@ +GNULIB_LOCALENAME = @GNULIB_LOCALENAME@ +GNULIB_LOCALTIME = @GNULIB_LOCALTIME@ +GNULIB_LSEEK = @GNULIB_LSEEK@ +GNULIB_LSTAT = @GNULIB_LSTAT@ +GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@ +GNULIB_MBRLEN = @GNULIB_MBRLEN@ +GNULIB_MBRTOWC = @GNULIB_MBRTOWC@ +GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@ +GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@ +GNULIB_MBSCHR = @GNULIB_MBSCHR@ +GNULIB_MBSCSPN = @GNULIB_MBSCSPN@ +GNULIB_MBSINIT = @GNULIB_MBSINIT@ +GNULIB_MBSLEN = @GNULIB_MBSLEN@ +GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@ +GNULIB_MBSNLEN = @GNULIB_MBSNLEN@ +GNULIB_MBSNRTOWCS = @GNULIB_MBSNRTOWCS@ +GNULIB_MBSPBRK = @GNULIB_MBSPBRK@ +GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@ +GNULIB_MBSRCHR = @GNULIB_MBSRCHR@ +GNULIB_MBSRTOWCS = @GNULIB_MBSRTOWCS@ +GNULIB_MBSSEP = @GNULIB_MBSSEP@ +GNULIB_MBSSPN = @GNULIB_MBSSPN@ +GNULIB_MBSSTR = @GNULIB_MBSSTR@ +GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@ +GNULIB_MBTOWC = @GNULIB_MBTOWC@ +GNULIB_MEMCHR = @GNULIB_MEMCHR@ +GNULIB_MEMMEM = @GNULIB_MEMMEM@ +GNULIB_MEMPCPY = @GNULIB_MEMPCPY@ +GNULIB_MEMRCHR = @GNULIB_MEMRCHR@ +GNULIB_MKDIRAT = @GNULIB_MKDIRAT@ +GNULIB_MKDTEMP = @GNULIB_MKDTEMP@ +GNULIB_MKFIFO = @GNULIB_MKFIFO@ +GNULIB_MKFIFOAT = @GNULIB_MKFIFOAT@ +GNULIB_MKNOD = @GNULIB_MKNOD@ +GNULIB_MKNODAT = @GNULIB_MKNODAT@ +GNULIB_MKOSTEMP = @GNULIB_MKOSTEMP@ +GNULIB_MKOSTEMPS = @GNULIB_MKOSTEMPS@ +GNULIB_MKSTEMP = @GNULIB_MKSTEMP@ +GNULIB_MKSTEMPS = @GNULIB_MKSTEMPS@ +GNULIB_MKTIME = @GNULIB_MKTIME@ +GNULIB_NANOSLEEP = @GNULIB_NANOSLEEP@ +GNULIB_NL_LANGINFO = @GNULIB_NL_LANGINFO@ +GNULIB_NONBLOCKING = @GNULIB_NONBLOCKING@ +GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@ +GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@ +GNULIB_OPEN = @GNULIB_OPEN@ +GNULIB_OPENAT = @GNULIB_OPENAT@ +GNULIB_OPENDIR = @GNULIB_OPENDIR@ +GNULIB_OVERRIDES_STRUCT_STAT = @GNULIB_OVERRIDES_STRUCT_STAT@ +GNULIB_OVERRIDES_WINT_T = @GNULIB_OVERRIDES_WINT_T@ +GNULIB_PCLOSE = @GNULIB_PCLOSE@ +GNULIB_PERROR = @GNULIB_PERROR@ +GNULIB_PIPE = @GNULIB_PIPE@ +GNULIB_PIPE2 = @GNULIB_PIPE2@ +GNULIB_POPEN = @GNULIB_POPEN@ +GNULIB_POSIX_OPENPT = @GNULIB_POSIX_OPENPT@ +GNULIB_PREAD = @GNULIB_PREAD@ +GNULIB_PRINTF = @GNULIB_PRINTF@ +GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@ +GNULIB_PTSNAME = @GNULIB_PTSNAME@ +GNULIB_PTSNAME_R = @GNULIB_PTSNAME_R@ +GNULIB_PUTC = @GNULIB_PUTC@ +GNULIB_PUTCHAR = @GNULIB_PUTCHAR@ +GNULIB_PUTENV = @GNULIB_PUTENV@ +GNULIB_PUTS = @GNULIB_PUTS@ +GNULIB_PWRITE = @GNULIB_PWRITE@ +GNULIB_QSORT_R = @GNULIB_QSORT_R@ +GNULIB_RANDOM = @GNULIB_RANDOM@ +GNULIB_RANDOM_R = @GNULIB_RANDOM_R@ +GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@ +GNULIB_READ = @GNULIB_READ@ +GNULIB_READDIR = @GNULIB_READDIR@ +GNULIB_READLINK = @GNULIB_READLINK@ +GNULIB_READLINKAT = @GNULIB_READLINKAT@ +GNULIB_REALLOCARRAY = @GNULIB_REALLOCARRAY@ +GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ +GNULIB_REALPATH = @GNULIB_REALPATH@ +GNULIB_REMOVE = @GNULIB_REMOVE@ +GNULIB_RENAME = @GNULIB_RENAME@ +GNULIB_RENAMEAT = @GNULIB_RENAMEAT@ +GNULIB_REWINDDIR = @GNULIB_REWINDDIR@ +GNULIB_RMDIR = @GNULIB_RMDIR@ +GNULIB_RPMATCH = @GNULIB_RPMATCH@ +GNULIB_SCANDIR = @GNULIB_SCANDIR@ +GNULIB_SCANF = @GNULIB_SCANF@ +GNULIB_SECURE_GETENV = @GNULIB_SECURE_GETENV@ +GNULIB_SETENV = @GNULIB_SETENV@ +GNULIB_SETHOSTNAME = @GNULIB_SETHOSTNAME@ +GNULIB_SETLOCALE = @GNULIB_SETLOCALE@ +GNULIB_SLEEP = @GNULIB_SLEEP@ +GNULIB_SNPRINTF = @GNULIB_SNPRINTF@ +GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@ +GNULIB_STAT = @GNULIB_STAT@ +GNULIB_STDIO_H_NONBLOCKING = @GNULIB_STDIO_H_NONBLOCKING@ +GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@ +GNULIB_STPCPY = @GNULIB_STPCPY@ +GNULIB_STPNCPY = @GNULIB_STPNCPY@ +GNULIB_STRCASESTR = @GNULIB_STRCASESTR@ +GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@ +GNULIB_STRDUP = @GNULIB_STRDUP@ +GNULIB_STRERROR = @GNULIB_STRERROR@ +GNULIB_STRERROR_R = @GNULIB_STRERROR_R@ +GNULIB_STRFTIME = @GNULIB_STRFTIME@ +GNULIB_STRNCAT = @GNULIB_STRNCAT@ +GNULIB_STRNDUP = @GNULIB_STRNDUP@ +GNULIB_STRNLEN = @GNULIB_STRNLEN@ +GNULIB_STRPBRK = @GNULIB_STRPBRK@ +GNULIB_STRPTIME = @GNULIB_STRPTIME@ +GNULIB_STRSEP = @GNULIB_STRSEP@ +GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@ +GNULIB_STRSTR = @GNULIB_STRSTR@ +GNULIB_STRTOD = @GNULIB_STRTOD@ +GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_STRTOLL = @GNULIB_STRTOLL@ +GNULIB_STRTOULL = @GNULIB_STRTOULL@ +GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@ +GNULIB_SYMLINK = @GNULIB_SYMLINK@ +GNULIB_SYMLINKAT = @GNULIB_SYMLINKAT@ +GNULIB_SYSTEM_POSIX = @GNULIB_SYSTEM_POSIX@ +GNULIB_TIMEGM = @GNULIB_TIMEGM@ +GNULIB_TIME_R = @GNULIB_TIME_R@ +GNULIB_TIME_RZ = @GNULIB_TIME_RZ@ +GNULIB_TMPFILE = @GNULIB_TMPFILE@ +GNULIB_TOWCTRANS = @GNULIB_TOWCTRANS@ +GNULIB_TRUNCATE = @GNULIB_TRUNCATE@ +GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@ +GNULIB_TZSET = @GNULIB_TZSET@ +GNULIB_UNISTD_H_NONBLOCKING = @GNULIB_UNISTD_H_NONBLOCKING@ +GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@ +GNULIB_UNLINK = @GNULIB_UNLINK@ +GNULIB_UNLINKAT = @GNULIB_UNLINKAT@ +GNULIB_UNLOCKPT = @GNULIB_UNLOCKPT@ +GNULIB_UNSETENV = @GNULIB_UNSETENV@ +GNULIB_USLEEP = @GNULIB_USLEEP@ +GNULIB_UTIMENSAT = @GNULIB_UTIMENSAT@ +GNULIB_VASPRINTF = @GNULIB_VASPRINTF@ +GNULIB_VDPRINTF = @GNULIB_VDPRINTF@ +GNULIB_VFPRINTF = @GNULIB_VFPRINTF@ +GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@ +GNULIB_VFSCANF = @GNULIB_VFSCANF@ +GNULIB_VPRINTF = @GNULIB_VPRINTF@ +GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@ +GNULIB_VSCANF = @GNULIB_VSCANF@ +GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@ +GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@ +GNULIB_WCPCPY = @GNULIB_WCPCPY@ +GNULIB_WCPNCPY = @GNULIB_WCPNCPY@ +GNULIB_WCRTOMB = @GNULIB_WCRTOMB@ +GNULIB_WCSCASECMP = @GNULIB_WCSCASECMP@ +GNULIB_WCSCAT = @GNULIB_WCSCAT@ +GNULIB_WCSCHR = @GNULIB_WCSCHR@ +GNULIB_WCSCMP = @GNULIB_WCSCMP@ +GNULIB_WCSCOLL = @GNULIB_WCSCOLL@ +GNULIB_WCSCPY = @GNULIB_WCSCPY@ +GNULIB_WCSCSPN = @GNULIB_WCSCSPN@ +GNULIB_WCSDUP = @GNULIB_WCSDUP@ +GNULIB_WCSFTIME = @GNULIB_WCSFTIME@ +GNULIB_WCSLEN = @GNULIB_WCSLEN@ +GNULIB_WCSNCASECMP = @GNULIB_WCSNCASECMP@ +GNULIB_WCSNCAT = @GNULIB_WCSNCAT@ +GNULIB_WCSNCMP = @GNULIB_WCSNCMP@ +GNULIB_WCSNCPY = @GNULIB_WCSNCPY@ +GNULIB_WCSNLEN = @GNULIB_WCSNLEN@ +GNULIB_WCSNRTOMBS = @GNULIB_WCSNRTOMBS@ +GNULIB_WCSPBRK = @GNULIB_WCSPBRK@ +GNULIB_WCSRCHR = @GNULIB_WCSRCHR@ +GNULIB_WCSRTOMBS = @GNULIB_WCSRTOMBS@ +GNULIB_WCSSPN = @GNULIB_WCSSPN@ +GNULIB_WCSSTR = @GNULIB_WCSSTR@ +GNULIB_WCSTOK = @GNULIB_WCSTOK@ +GNULIB_WCSWIDTH = @GNULIB_WCSWIDTH@ +GNULIB_WCSXFRM = @GNULIB_WCSXFRM@ +GNULIB_WCTOB = @GNULIB_WCTOB@ +GNULIB_WCTOMB = @GNULIB_WCTOMB@ +GNULIB_WCTRANS = @GNULIB_WCTRANS@ +GNULIB_WCTYPE = @GNULIB_WCTYPE@ +GNULIB_WCWIDTH = @GNULIB_WCWIDTH@ +GNULIB_WMEMCHR = @GNULIB_WMEMCHR@ +GNULIB_WMEMCMP = @GNULIB_WMEMCMP@ +GNULIB_WMEMCPY = @GNULIB_WMEMCPY@ +GNULIB_WMEMMOVE = @GNULIB_WMEMMOVE@ +GNULIB_WMEMSET = @GNULIB_WMEMSET@ +GNULIB_WRITE = @GNULIB_WRITE@ +GNULIB__EXIT = @GNULIB__EXIT@ +GREP = @GREP@ +GRUB_BOOT_MACHINE_LINK_ADDR = @GRUB_BOOT_MACHINE_LINK_ADDR@ +GRUB_PLATFORM = @GRUB_PLATFORM@ +GRUB_TARGET_CPU = @GRUB_TARGET_CPU@ +HAVE_ALPHASORT = @HAVE_ALPHASORT@ +HAVE_ASM_USCORE = @HAVE_ASM_USCORE@ +HAVE_ATOLL = @HAVE_ATOLL@ +HAVE_BTOWC = @HAVE_BTOWC@ +HAVE_C99_STDINT_H = @HAVE_C99_STDINT_H@ +HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ +HAVE_CHOWN = @HAVE_CHOWN@ +HAVE_CLOSEDIR = @HAVE_CLOSEDIR@ +HAVE_CRTDEFS_H = @HAVE_CRTDEFS_H@ +HAVE_CXX = @HAVE_CXX@ +HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@ +HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@ +HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@ +HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@ +HAVE_DECL_FDOPENDIR = @HAVE_DECL_FDOPENDIR@ +HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@ +HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@ +HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETDOMAINNAME = @HAVE_DECL_GETDOMAINNAME@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@ +HAVE_DECL_GETLOGIN = @HAVE_DECL_GETLOGIN@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_GETPAGESIZE = @HAVE_DECL_GETPAGESIZE@ +HAVE_DECL_GETUSERSHELL = @HAVE_DECL_GETUSERSHELL@ +HAVE_DECL_INITSTATE = @HAVE_DECL_INITSTATE@ +HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@ +HAVE_DECL_SETENV = @HAVE_DECL_SETENV@ +HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@ +HAVE_DECL_SETSTATE = @HAVE_DECL_SETSTATE@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRERROR_R = @HAVE_DECL_STRERROR_R@ +HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_TRUNCATE = @HAVE_DECL_TRUNCATE@ +HAVE_DECL_TTYNAME_R = @HAVE_DECL_TTYNAME_R@ +HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@ +HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@ +HAVE_DIRENT_H = @HAVE_DIRENT_H@ +HAVE_DPRINTF = @HAVE_DPRINTF@ +HAVE_DUP2 = @HAVE_DUP2@ +HAVE_DUP3 = @HAVE_DUP3@ +HAVE_DUPLOCALE = @HAVE_DUPLOCALE@ +HAVE_EUIDACCESS = @HAVE_EUIDACCESS@ +HAVE_EXPLICIT_BZERO = @HAVE_EXPLICIT_BZERO@ +HAVE_FACCESSAT = @HAVE_FACCESSAT@ +HAVE_FCHDIR = @HAVE_FCHDIR@ +HAVE_FCHMODAT = @HAVE_FCHMODAT@ +HAVE_FCHOWNAT = @HAVE_FCHOWNAT@ +HAVE_FCNTL = @HAVE_FCNTL@ +HAVE_FDATASYNC = @HAVE_FDATASYNC@ +HAVE_FDOPENDIR = @HAVE_FDOPENDIR@ +HAVE_FEATURES_H = @HAVE_FEATURES_H@ +HAVE_FFS = @HAVE_FFS@ +HAVE_FFSL = @HAVE_FFSL@ +HAVE_FFSLL = @HAVE_FFSLL@ +HAVE_FNMATCH = @HAVE_FNMATCH@ +HAVE_FNMATCH_H = @HAVE_FNMATCH_H@ +HAVE_FONT_SOURCE = @HAVE_FONT_SOURCE@ +HAVE_FREELOCALE = @HAVE_FREELOCALE@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FSTATAT = @HAVE_FSTATAT@ +HAVE_FSYNC = @HAVE_FSYNC@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_FUTIMENS = @HAVE_FUTIMENS@ +HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@ +HAVE_GETGROUPS = @HAVE_GETGROUPS@ +HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@ +HAVE_GETLOGIN = @HAVE_GETLOGIN@ +HAVE_GETOPT_H = @HAVE_GETOPT_H@ +HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@ +HAVE_GETPASS = @HAVE_GETPASS@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_GRANTPT = @HAVE_GRANTPT@ +HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_ISWBLANK = @HAVE_ISWBLANK@ +HAVE_ISWCNTRL = @HAVE_ISWCNTRL@ +HAVE_LANGINFO_ALTMON = @HAVE_LANGINFO_ALTMON@ +HAVE_LANGINFO_CODESET = @HAVE_LANGINFO_CODESET@ +HAVE_LANGINFO_ERA = @HAVE_LANGINFO_ERA@ +HAVE_LANGINFO_H = @HAVE_LANGINFO_H@ +HAVE_LANGINFO_T_FMT_AMPM = @HAVE_LANGINFO_T_FMT_AMPM@ +HAVE_LANGINFO_YESEXPR = @HAVE_LANGINFO_YESEXPR@ +HAVE_LCHMOD = @HAVE_LCHMOD@ +HAVE_LCHOWN = @HAVE_LCHOWN@ +HAVE_LINK = @HAVE_LINK@ +HAVE_LINKAT = @HAVE_LINKAT@ +HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@ +HAVE_MBRLEN = @HAVE_MBRLEN@ +HAVE_MBRTOWC = @HAVE_MBRTOWC@ +HAVE_MBSINIT = @HAVE_MBSINIT@ +HAVE_MBSLEN = @HAVE_MBSLEN@ +HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@ +HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@ +HAVE_MEMCHR = @HAVE_MEMCHR@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDIRAT = @HAVE_MKDIRAT@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_MKFIFO = @HAVE_MKFIFO@ +HAVE_MKFIFOAT = @HAVE_MKFIFOAT@ +HAVE_MKNOD = @HAVE_MKNOD@ +HAVE_MKNODAT = @HAVE_MKNODAT@ +HAVE_MKOSTEMP = @HAVE_MKOSTEMP@ +HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@ +HAVE_MKSTEMP = @HAVE_MKSTEMP@ +HAVE_MKSTEMPS = @HAVE_MKSTEMPS@ +HAVE_MSVC_INVALID_PARAMETER_HANDLER = @HAVE_MSVC_INVALID_PARAMETER_HANDLER@ +HAVE_NANOSLEEP = @HAVE_NANOSLEEP@ +HAVE_NEWLOCALE = @HAVE_NEWLOCALE@ +HAVE_NL_LANGINFO = @HAVE_NL_LANGINFO@ +HAVE_OPENAT = @HAVE_OPENAT@ +HAVE_OPENDIR = @HAVE_OPENDIR@ +HAVE_OS_H = @HAVE_OS_H@ +HAVE_PCLOSE = @HAVE_PCLOSE@ +HAVE_PIPE = @HAVE_PIPE@ +HAVE_PIPE2 = @HAVE_PIPE2@ +HAVE_POPEN = @HAVE_POPEN@ +HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@ +HAVE_PREAD = @HAVE_PREAD@ +HAVE_PTSNAME = @HAVE_PTSNAME@ +HAVE_PTSNAME_R = @HAVE_PTSNAME_R@ +HAVE_PWRITE = @HAVE_PWRITE@ +HAVE_QSORT_R = @HAVE_QSORT_R@ +HAVE_RANDOM = @HAVE_RANDOM@ +HAVE_RANDOM_H = @HAVE_RANDOM_H@ +HAVE_RANDOM_R = @HAVE_RANDOM_R@ +HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@ +HAVE_READDIR = @HAVE_READDIR@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_READLINKAT = @HAVE_READLINKAT@ +HAVE_REALLOCARRAY = @HAVE_REALLOCARRAY@ +HAVE_REALPATH = @HAVE_REALPATH@ +HAVE_RENAMEAT = @HAVE_RENAMEAT@ +HAVE_REWINDDIR = @HAVE_REWINDDIR@ +HAVE_RPMATCH = @HAVE_RPMATCH@ +HAVE_SCANDIR = @HAVE_SCANDIR@ +HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@ +HAVE_SETENV = @HAVE_SETENV@ +HAVE_SETHOSTNAME = @HAVE_SETHOSTNAME@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASECMP = @HAVE_STRCASECMP@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRINGS_H = @HAVE_STRINGS_H@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRPTIME = @HAVE_STRPTIME@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRTOD = @HAVE_STRTOD@ +HAVE_STRTOLL = @HAVE_STRTOLL@ +HAVE_STRTOULL = @HAVE_STRTOULL@ +HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@ +HAVE_STRVERSCMP = @HAVE_STRVERSCMP@ +HAVE_SYMLINK = @HAVE_SYMLINK@ +HAVE_SYMLINKAT = @HAVE_SYMLINKAT@ +HAVE_SYSEXITS_H = @HAVE_SYSEXITS_H@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_CDEFS_H = @HAVE_SYS_CDEFS_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@ +HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_TIMEGM = @HAVE_TIMEGM@ +HAVE_TIMEZONE_T = @HAVE_TIMEZONE_T@ +HAVE_TZSET = @HAVE_TZSET@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNLINKAT = @HAVE_UNLINKAT@ +HAVE_UNLOCKPT = @HAVE_UNLOCKPT@ +HAVE_UNSIGNED_LONG_LONG_INT = @HAVE_UNSIGNED_LONG_LONG_INT@ +HAVE_USLEEP = @HAVE_USLEEP@ +HAVE_UTIMENSAT = @HAVE_UTIMENSAT@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VDPRINTF = @HAVE_VDPRINTF@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WCHAR_T = @HAVE_WCHAR_T@ +HAVE_WCPCPY = @HAVE_WCPCPY@ +HAVE_WCPNCPY = @HAVE_WCPNCPY@ +HAVE_WCRTOMB = @HAVE_WCRTOMB@ +HAVE_WCSCASECMP = @HAVE_WCSCASECMP@ +HAVE_WCSCAT = @HAVE_WCSCAT@ +HAVE_WCSCHR = @HAVE_WCSCHR@ +HAVE_WCSCMP = @HAVE_WCSCMP@ +HAVE_WCSCOLL = @HAVE_WCSCOLL@ +HAVE_WCSCPY = @HAVE_WCSCPY@ +HAVE_WCSCSPN = @HAVE_WCSCSPN@ +HAVE_WCSDUP = @HAVE_WCSDUP@ +HAVE_WCSFTIME = @HAVE_WCSFTIME@ +HAVE_WCSLEN = @HAVE_WCSLEN@ +HAVE_WCSNCASECMP = @HAVE_WCSNCASECMP@ +HAVE_WCSNCAT = @HAVE_WCSNCAT@ +HAVE_WCSNCMP = @HAVE_WCSNCMP@ +HAVE_WCSNCPY = @HAVE_WCSNCPY@ +HAVE_WCSNLEN = @HAVE_WCSNLEN@ +HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@ +HAVE_WCSPBRK = @HAVE_WCSPBRK@ +HAVE_WCSRCHR = @HAVE_WCSRCHR@ +HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@ +HAVE_WCSSPN = @HAVE_WCSSPN@ +HAVE_WCSSTR = @HAVE_WCSSTR@ +HAVE_WCSTOK = @HAVE_WCSTOK@ +HAVE_WCSWIDTH = @HAVE_WCSWIDTH@ +HAVE_WCSXFRM = @HAVE_WCSXFRM@ +HAVE_WCTRANS_T = @HAVE_WCTRANS_T@ +HAVE_WCTYPE_H = @HAVE_WCTYPE_H@ +HAVE_WCTYPE_T = @HAVE_WCTYPE_T@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WINT_T = @HAVE_WINT_T@ +HAVE_WMEMCHR = @HAVE_WMEMCHR@ +HAVE_WMEMCMP = @HAVE_WMEMCMP@ +HAVE_WMEMCPY = @HAVE_WMEMCPY@ +HAVE_WMEMMOVE = @HAVE_WMEMMOVE@ +HAVE_WMEMSET = @HAVE_WMEMSET@ +HAVE_XLOCALE_H = @HAVE_XLOCALE_H@ +HAVE__BOOL = @HAVE__BOOL@ +HAVE__EXIT = @HAVE__EXIT@ +HELP2MAN = @HELP2MAN@ +HOST_CC = @HOST_CC@ +HOST_CCASFLAGS = @HOST_CCASFLAGS@ +HOST_CFLAGS = @HOST_CFLAGS@ +HOST_CPPFLAGS = @HOST_CPPFLAGS@ +HOST_LDFLAGS = @HOST_LDFLAGS@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBDEVMAPPER = @LIBDEVMAPPER@ +LIBGEOM = @LIBGEOM@ +LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@ +LIBGNU_LTLIBDEPS = @LIBGNU_LTLIBDEPS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBLZMA = @LIBLZMA@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBNVPAIR = @LIBNVPAIR@ +LIBOBJS = @LIBOBJS@ +LIBPCIACCESS = @LIBPCIACCESS@ +LIBPTH = @LIBPTH@ +LIBPTH_PREFIX = @LIBPTH_PREFIX@ +LIBS = @LIBS@ +LIBSDL = @LIBSDL@ +LIBTHREAD = @LIBTHREAD@ +LIBUNISTRING_UNITYPES_H = @LIBUNISTRING_UNITYPES_H@ +LIBUNISTRING_UNIWIDTH_H = @LIBUNISTRING_UNIWIDTH_H@ +LIBUTIL = @LIBUTIL@ +LIBZFS = @LIBZFS@ +LIMITS_H = @LIMITS_H@ +LN_S = @LN_S@ +LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@ +LOCALE_FR = @LOCALE_FR@ +LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@ +LOCALE_JA = @LOCALE_JA@ +LOCALE_ZH_CN = @LOCALE_ZH_CN@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTHREAD = @LTLIBTHREAD@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEXT_AS_FIRST_DIRECTIVE_DIRENT_H = @NEXT_AS_FIRST_DIRECTIVE_DIRENT_H@ +NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@ +NEXT_AS_FIRST_DIRECTIVE_FCNTL_H = @NEXT_AS_FIRST_DIRECTIVE_FCNTL_H@ +NEXT_AS_FIRST_DIRECTIVE_FLOAT_H = @NEXT_AS_FIRST_DIRECTIVE_FLOAT_H@ +NEXT_AS_FIRST_DIRECTIVE_FNMATCH_H = @NEXT_AS_FIRST_DIRECTIVE_FNMATCH_H@ +NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@ +NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H = @NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H@ +NEXT_AS_FIRST_DIRECTIVE_LIMITS_H = @NEXT_AS_FIRST_DIRECTIVE_LIMITS_H@ +NEXT_AS_FIRST_DIRECTIVE_LOCALE_H = @NEXT_AS_FIRST_DIRECTIVE_LOCALE_H@ +NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@ +NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@ +NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ +NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@ +NEXT_AS_FIRST_DIRECTIVE_STRINGS_H = @NEXT_AS_FIRST_DIRECTIVE_STRINGS_H@ +NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@ +NEXT_AS_FIRST_DIRECTIVE_SYSEXITS_H = @NEXT_AS_FIRST_DIRECTIVE_SYSEXITS_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@ +NEXT_AS_FIRST_DIRECTIVE_WCHAR_H = @NEXT_AS_FIRST_DIRECTIVE_WCHAR_H@ +NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H@ +NEXT_DIRENT_H = @NEXT_DIRENT_H@ +NEXT_ERRNO_H = @NEXT_ERRNO_H@ +NEXT_FCNTL_H = @NEXT_FCNTL_H@ +NEXT_FLOAT_H = @NEXT_FLOAT_H@ +NEXT_FNMATCH_H = @NEXT_FNMATCH_H@ +NEXT_GETOPT_H = @NEXT_GETOPT_H@ +NEXT_LANGINFO_H = @NEXT_LANGINFO_H@ +NEXT_LIMITS_H = @NEXT_LIMITS_H@ +NEXT_LOCALE_H = @NEXT_LOCALE_H@ +NEXT_STDDEF_H = @NEXT_STDDEF_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRINGS_H = @NEXT_STRINGS_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYSEXITS_H = @NEXT_SYSEXITS_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TYPES_H = @NEXT_SYS_TYPES_H@ +NEXT_TIME_H = @NEXT_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NEXT_WCHAR_H = @NEXT_WCHAR_H@ +NEXT_WCTYPE_H = @NEXT_WCTYPE_H@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +PRAGMA_COLUMNS = @PRAGMA_COLUMNS@ +PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@ +PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +REPLACE_BTOWC = @REPLACE_BTOWC@ +REPLACE_CALLOC = @REPLACE_CALLOC@ +REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_CLOSE = @REPLACE_CLOSE@ +REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@ +REPLACE_CTIME = @REPLACE_CTIME@ +REPLACE_DIRFD = @REPLACE_DIRFD@ +REPLACE_DPRINTF = @REPLACE_DPRINTF@ +REPLACE_DUP = @REPLACE_DUP@ +REPLACE_DUP2 = @REPLACE_DUP2@ +REPLACE_DUPLOCALE = @REPLACE_DUPLOCALE@ +REPLACE_FACCESSAT = @REPLACE_FACCESSAT@ +REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@ +REPLACE_FCLOSE = @REPLACE_FCLOSE@ +REPLACE_FCNTL = @REPLACE_FCNTL@ +REPLACE_FDOPEN = @REPLACE_FDOPEN@ +REPLACE_FDOPENDIR = @REPLACE_FDOPENDIR@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FNMATCH = @REPLACE_FNMATCH@ +REPLACE_FOPEN = @REPLACE_FOPEN@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FPURGE = @REPLACE_FPURGE@ +REPLACE_FREELOCALE = @REPLACE_FREELOCALE@ +REPLACE_FREOPEN = @REPLACE_FREOPEN@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FSTAT = @REPLACE_FSTAT@ +REPLACE_FSTATAT = @REPLACE_FSTATAT@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_FTRUNCATE = @REPLACE_FTRUNCATE@ +REPLACE_FUTIMENS = @REPLACE_FUTIMENS@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETDELIM = @REPLACE_GETDELIM@ +REPLACE_GETDOMAINNAME = @REPLACE_GETDOMAINNAME@ +REPLACE_GETDTABLESIZE = @REPLACE_GETDTABLESIZE@ +REPLACE_GETGROUPS = @REPLACE_GETGROUPS@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@ +REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@ +REPLACE_GETPASS = @REPLACE_GETPASS@ +REPLACE_GMTIME = @REPLACE_GMTIME@ +REPLACE_ISATTY = @REPLACE_ISATTY@ +REPLACE_ISWBLANK = @REPLACE_ISWBLANK@ +REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@ +REPLACE_ITOLD = @REPLACE_ITOLD@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LINK = @REPLACE_LINK@ +REPLACE_LINKAT = @REPLACE_LINKAT@ +REPLACE_LOCALECONV = @REPLACE_LOCALECONV@ +REPLACE_LOCALTIME = @REPLACE_LOCALTIME@ +REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_LSTAT = @REPLACE_LSTAT@ +REPLACE_MALLOC = @REPLACE_MALLOC@ +REPLACE_MBRLEN = @REPLACE_MBRLEN@ +REPLACE_MBRTOWC = @REPLACE_MBRTOWC@ +REPLACE_MBSINIT = @REPLACE_MBSINIT@ +REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@ +REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@ +REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@ +REPLACE_MBTOWC = @REPLACE_MBTOWC@ +REPLACE_MEMCHR = @REPLACE_MEMCHR@ +REPLACE_MEMMEM = @REPLACE_MEMMEM@ +REPLACE_MKDIR = @REPLACE_MKDIR@ +REPLACE_MKFIFO = @REPLACE_MKFIFO@ +REPLACE_MKNOD = @REPLACE_MKNOD@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_MKTIME = @REPLACE_MKTIME@ +REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@ +REPLACE_NEWLOCALE = @REPLACE_NEWLOCALE@ +REPLACE_NL_LANGINFO = @REPLACE_NL_LANGINFO@ +REPLACE_NULL = @REPLACE_NULL@ +REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@ +REPLACE_OPEN = @REPLACE_OPEN@ +REPLACE_OPENAT = @REPLACE_OPENAT@ +REPLACE_OPENDIR = @REPLACE_OPENDIR@ +REPLACE_PERROR = @REPLACE_PERROR@ +REPLACE_POPEN = @REPLACE_POPEN@ +REPLACE_PREAD = @REPLACE_PREAD@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_PTSNAME = @REPLACE_PTSNAME@ +REPLACE_PTSNAME_R = @REPLACE_PTSNAME_R@ +REPLACE_PUTENV = @REPLACE_PUTENV@ +REPLACE_PWRITE = @REPLACE_PWRITE@ +REPLACE_QSORT_R = @REPLACE_QSORT_R@ +REPLACE_RANDOM_R = @REPLACE_RANDOM_R@ +REPLACE_READ = @REPLACE_READ@ +REPLACE_READLINK = @REPLACE_READLINK@ +REPLACE_READLINKAT = @REPLACE_READLINKAT@ +REPLACE_REALLOC = @REPLACE_REALLOC@ +REPLACE_REALPATH = @REPLACE_REALPATH@ +REPLACE_REMOVE = @REPLACE_REMOVE@ +REPLACE_RENAME = @REPLACE_RENAME@ +REPLACE_RENAMEAT = @REPLACE_RENAMEAT@ +REPLACE_RMDIR = @REPLACE_RMDIR@ +REPLACE_SETENV = @REPLACE_SETENV@ +REPLACE_SETLOCALE = @REPLACE_SETLOCALE@ +REPLACE_SLEEP = @REPLACE_SLEEP@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_STAT = @REPLACE_STAT@ +REPLACE_STDIO_READ_FUNCS = @REPLACE_STDIO_READ_FUNCS@ +REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@ +REPLACE_STPNCPY = @REPLACE_STPNCPY@ +REPLACE_STRCASESTR = @REPLACE_STRCASESTR@ +REPLACE_STRCHRNUL = @REPLACE_STRCHRNUL@ +REPLACE_STRDUP = @REPLACE_STRDUP@ +REPLACE_STRERROR = @REPLACE_STRERROR@ +REPLACE_STRERROR_R = @REPLACE_STRERROR_R@ +REPLACE_STRFTIME = @REPLACE_STRFTIME@ +REPLACE_STRNCAT = @REPLACE_STRNCAT@ +REPLACE_STRNDUP = @REPLACE_STRNDUP@ +REPLACE_STRNLEN = @REPLACE_STRNLEN@ +REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@ +REPLACE_STRSTR = @REPLACE_STRSTR@ +REPLACE_STRTOD = @REPLACE_STRTOD@ +REPLACE_STRTOK_R = @REPLACE_STRTOK_R@ +REPLACE_STRUCT_LCONV = @REPLACE_STRUCT_LCONV@ +REPLACE_SYMLINK = @REPLACE_SYMLINK@ +REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@ +REPLACE_TIMEGM = @REPLACE_TIMEGM@ +REPLACE_TMPFILE = @REPLACE_TMPFILE@ +REPLACE_TOWLOWER = @REPLACE_TOWLOWER@ +REPLACE_TRUNCATE = @REPLACE_TRUNCATE@ +REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@ +REPLACE_TZSET = @REPLACE_TZSET@ +REPLACE_UNLINK = @REPLACE_UNLINK@ +REPLACE_UNLINKAT = @REPLACE_UNLINKAT@ +REPLACE_UNSETENV = @REPLACE_UNSETENV@ +REPLACE_USLEEP = @REPLACE_USLEEP@ +REPLACE_UTIMENSAT = @REPLACE_UTIMENSAT@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VDPRINTF = @REPLACE_VDPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCRTOMB = @REPLACE_WCRTOMB@ +REPLACE_WCSFTIME = @REPLACE_WCSFTIME@ +REPLACE_WCSNRTOMBS = @REPLACE_WCSNRTOMBS@ +REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@ +REPLACE_WCSWIDTH = @REPLACE_WCSWIDTH@ +REPLACE_WCTOB = @REPLACE_WCTOB@ +REPLACE_WCTOMB = @REPLACE_WCTOMB@ +REPLACE_WCWIDTH = @REPLACE_WCWIDTH@ +REPLACE_WRITE = @REPLACE_WRITE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +STDALIGN_H = @STDALIGN_H@ +STDBOOL_H = @STDBOOL_H@ +STDDEF_H = @STDDEF_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SYSEXITS_H = @SYSEXITS_H@ +SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +TARGET_APPLE_LINKER = @TARGET_APPLE_LINKER@ +TARGET_CC = @TARGET_CC@ +TARGET_CCAS = @TARGET_CCAS@ +TARGET_CCASFLAGS = @TARGET_CCASFLAGS@ +TARGET_CC_VERSION = @TARGET_CC_VERSION@ +TARGET_CFLAGS = @TARGET_CFLAGS@ +TARGET_CPP = @TARGET_CPP@ +TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ +TARGET_DECOMPRESSOR_LINK_ADDR = @TARGET_DECOMPRESSOR_LINK_ADDR@ +TARGET_IMG_BASE_LDOPT = @TARGET_IMG_BASE_LDOPT@ +TARGET_IMG_CFLAGS = @TARGET_IMG_CFLAGS@ +TARGET_IMG_LDFLAGS = @TARGET_IMG_LDFLAGS@ +TARGET_LDFLAGS = @TARGET_LDFLAGS@ +TARGET_LDFLAGS_OLDMAGIC = @TARGET_LDFLAGS_OLDMAGIC@ +TARGET_LINK_ADDR = @TARGET_LINK_ADDR@ +TARGET_MODULE_FORMAT = @TARGET_MODULE_FORMAT@ +TARGET_NM = @TARGET_NM@ +TARGET_NMFLAGS_DEFINED_ONLY = @TARGET_NMFLAGS_DEFINED_ONLY@ +TARGET_NMFLAGS_MINUS_P = @TARGET_NMFLAGS_MINUS_P@ +TARGET_OBJ2ELF = @TARGET_OBJ2ELF@ +TARGET_OBJCONV = @TARGET_OBJCONV@ +TARGET_OBJCOPY = @TARGET_OBJCOPY@ +TARGET_RANLIB = @TARGET_RANLIB@ +TARGET_STRIP = @TARGET_STRIP@ +TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@ +UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@ +UNISTD_H_DEFINES_STRUCT_TIMESPEC = @UNISTD_H_DEFINES_STRUCT_TIMESPEC@ +UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@ +UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@ +WINDOWS_64_BIT_ST_SIZE = @WINDOWS_64_BIT_ST_SIZE@ +WINDOWS_STAT_INODES = @WINDOWS_STAT_INODES@ +WINDOWS_STAT_TIMESPEC = @WINDOWS_STAT_TIMESPEC@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_TARGET_CC = @ac_ct_TARGET_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +bootdirname = @bootdirname@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +enable_efiemu = @enable_efiemu@ +enable_grub_emu_pci = @enable_grub_emu_pci@ +enable_grub_emu_sdl = @enable_grub_emu_sdl@ +enable_grub_mkfont = @enable_grub_mkfont@ +enable_grub_mount = @enable_grub_mount@ +exec_prefix = @exec_prefix@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +gltests_LIBOBJS = @gltests_LIBOBJS@ +gltests_LTLIBOBJS = @gltests_LTLIBOBJS@ +gltests_WITNESS = @gltests_WITNESS@ +grub_bios_setup = @grub_bios_setup@ +grub_editenv = @grub_editenv@ +grub_file = @grub_file@ +grub_glue_efi = @grub_glue_efi@ +grub_install = @grub_install@ +grub_mkconfig = @grub_mkconfig@ +grub_mkfont = @grub_mkfont@ +grub_mkimage = @grub_mkimage@ +grub_mklayout = @grub_mklayout@ +grub_mkpasswd_pbkdf2 = @grub_mkpasswd_pbkdf2@ +grub_mkrelpath = @grub_mkrelpath@ +grub_mkrescue = @grub_mkrescue@ +grub_probe = @grub_probe@ +grub_reboot = @grub_reboot@ +grub_render_label = @grub_render_label@ +grub_script_check = @grub_script_check@ +grub_set_default = @grub_set_default@ +grub_sparc64_setup = @grub_sparc64_setup@ +grubdirname = @grubdirname@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_kernel = @host_kernel@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +platform = @platform@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = 1.11 gnits subdir-objects +SUBDIRS = +noinst_HEADERS = +noinst_LIBRARIES = libgnu.a +noinst_LTLIBRARIES = +EXTRA_DIST = alloca.c alloca.in.h assure.h openat-priv.h openat-proc.c \ + btowc.c chdir-long.c chdir-long.h cloexec.h close.c \ + dirent.in.h dirfd.c dirname.h dosname.h dup2.c errno.in.h \ + error.c error.h exitfail.h fchdir.c fcntl.c fcntl.in.h \ + fd-hook.h filename.h filenamecat.h flexmember.h float.c \ + float.in.h itold.c fnmatch.c fnmatch_loop.c fnmatch.in.h \ + fstat.c stat-w32.c stat-w32.h getcwd-lgpl.c getdelim.c \ + getdtablesize.c getline.c getopt-cdefs.in.h getopt-core.h \ + getopt-ext.h getopt-pfx-core.h getopt-pfx-ext.h getopt.c \ + getopt.in.h getopt1.c getopt_int.h \ + $(top_srcdir)/build-aux/gitlog-to-changelog hard-locale.h \ + $(top_srcdir)/build-aux/config.rpath intprops.h langinfo.in.h \ + cdefs.h libc-config.h limits.in.h localcharset.h locale.in.h \ + localeconv.c malloc.c malloc.c malloca.h mbrtowc.c mbsinit.c \ + mbsrtowcs-impl.h mbsrtowcs-state.c mbsrtowcs.c mbtowc-impl.h \ + mbtowc.c memchr.c memchr.valgrind mempcpy.c memrchr.c \ + msvc-inval.c msvc-inval.h msvc-nothrow.c msvc-nothrow.h \ + nl_langinfo.c open.c openat.c openat.h pathmax.h rawmemchr.c \ + rawmemchr.valgrind realloc.c realloc.c regcomp.c regex.c \ + regex.h regex_internal.c regex_internal.h regexec.c save-cwd.h \ + sleep.c _Noreturn.h arg-nonnull.h c++defs.h warn-on-use.h \ + stat-w32.c stat-w32.h stat.c stat-time.h stdalign.in.h \ + stdbool.in.h stddef.in.h stdint.in.h stdio.in.h stdlib.in.h \ + strcasecmp.c strncasecmp.c strchrnul.c strchrnul.valgrind \ + strdup.c streq.h strerror.c strerror-override.c \ + strerror-override.h string.in.h strings.in.h strndup.c \ + strnlen.c sys_stat.in.h sys_types.in.h sysexits.in.h \ + $(top_srcdir)/build-aux/config.rpath time.in.h unistd.in.h \ + unistd--.h unistd-safer.h unitypes.in.h localcharset.h \ + uniwidth.in.h uniwidth/cjk.h asnprintf.c float+.h \ + printf-args.c printf-args.h printf-parse.c printf-parse.h \ + vasnprintf.c vasnprintf.h verify.h vsnprintf.c wchar.in.h \ + wcrtomb.c wctype.in.h wcwidth.c xalloc-oversized.h +BUILT_SOURCES = $(ALLOCA_H) dirent.h $(ERRNO_H) fcntl.h $(FLOAT_H) \ + $(FNMATCH_H) $(GETOPT_H) $(GETOPT_CDEFS_H) langinfo.h \ + $(LIMITS_H) locale.h $(STDALIGN_H) $(STDBOOL_H) $(STDDEF_H) \ + $(STDINT_H) stdio.h stdlib.h string.h strings.h sys/stat.h \ + sys/types.h $(SYSEXITS_H) time.h unistd.h \ + $(LIBUNISTRING_UNITYPES_H) $(LIBUNISTRING_UNIWIDTH_H) wchar.h \ + wctype.h +SUFFIXES = +MOSTLYCLEANFILES = core *.stackdump alloca.h alloca.h-t dirent.h \ + dirent.h-t errno.h errno.h-t fcntl.h fcntl.h-t float.h \ + float.h-t fnmatch.h fnmatch.h-t getopt.h getopt.h-t \ + getopt-cdefs.h getopt-cdefs.h-t langinfo.h langinfo.h-t \ + limits.h limits.h-t locale.h locale.h-t stdalign.h \ + stdalign.h-t stdbool.h stdbool.h-t stddef.h stddef.h-t \ + stdint.h stdint.h-t stdio.h stdio.h-t stdlib.h stdlib.h-t \ + string.h string.h-t strings.h strings.h-t sys/stat.h \ + sys/stat.h-t sys/types.h sys/types.h-t sysexits.h sysexits.h-t \ + time.h time.h-t unistd.h unistd.h-t unitypes.h unitypes.h-t \ + uniwidth.h uniwidth.h-t wchar.h wchar.h-t wctype.h wctype.h-t +MOSTLYCLEANDIRS = sys +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = +# No GNU Make output. +AM_CPPFLAGS = +AM_CFLAGS = +libgnu_a_SOURCES = argp.h argp-ba.c argp-eexst.c argp-fmtstream.c \ + argp-fmtstream.h argp-fs-xinl.c argp-help.c argp-namefrob.h \ + argp-parse.c argp-pin.c argp-pv.c argp-pvh.c argp-xinl.c \ + base64.h base64.c cloexec.c dirname-lgpl.c basename-lgpl.c \ + stripslash.c exitfail.c fd-hook.c fd-safer-flag.c \ + dup-safer-flag.c filenamecat-lgpl.c getprogname.h \ + getprogname.c gettext.h hard-locale.c localcharset.c \ + glthread/lock.h glthread/lock.c malloca.c mbswidth.h \ + mbswidth.c openat-die.c progname.h progname.c save-cwd.c \ + size_max.h stat-time.c strnlen1.h strnlen1.c \ + glthread/threadlib.c unistd.c dup-safer.c fd-safer.c \ + pipe-safer.c $(am__append_1) wctype-h.c xsize.h xsize.c +libgnu_a_LIBADD = $(gl_LIBOBJS) @ALLOCA@ +libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) @ALLOCA@ +EXTRA_libgnu_a_SOURCES = alloca.c openat-proc.c btowc.c chdir-long.c \ + close.c dirfd.c dup2.c error.c fchdir.c fcntl.c float.c \ + itold.c fnmatch.c fnmatch_loop.c fstat.c stat-w32.c \ + getcwd-lgpl.c getdelim.c getdtablesize.c getline.c getopt.c \ + getopt1.c localeconv.c malloc.c malloc.c mbrtowc.c mbsinit.c \ + mbsrtowcs-state.c mbsrtowcs.c mbtowc.c memchr.c mempcpy.c \ + memrchr.c msvc-inval.c msvc-nothrow.c nl_langinfo.c open.c \ + openat.c rawmemchr.c realloc.c realloc.c regcomp.c regex.c \ + regex_internal.c regexec.c sleep.c stat-w32.c stat.c \ + strcasecmp.c strncasecmp.c strchrnul.c strdup.c strerror.c \ + strerror-override.c strndup.c strnlen.c asnprintf.c \ + printf-args.c printf-parse.c vasnprintf.c vsnprintf.c \ + wcrtomb.c wcwidth.c + +# Use this preprocessor expression to decide whether #include_next works. +# Do not rely on a 'configure'-time test for this, since the expression +# might appear in an installed header, which is used by some other compiler. +HAVE_INCLUDE_NEXT = (__GNUC__ || 60000000 <= __DECC_VER) + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all makefiles that +# need it. This is ensured by the applicability 'all' defined above. +_NORETURN_H = $(srcdir)/_Noreturn.h + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all makefiles that +# need it. This is ensured by the applicability 'all' defined above. +ARG_NONNULL_H = $(srcdir)/arg-nonnull.h + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all makefiles that +# need it. This is ensured by the applicability 'all' defined above. +CXXDEFS_H = $(srcdir)/c++defs.h + +# Because this Makefile snippet defines a variable used by other +# gnulib Makefile snippets, it must be present in all makefiles that +# need it. This is ensured by the applicability 'all' defined above. +WARN_ON_USE_H = $(srcdir)/warn-on-use.h +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits grub-core/lib/gnulib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnits grub-core/lib/gnulib/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +glthread/$(am__dirstamp): + @$(MKDIR_P) glthread + @: > glthread/$(am__dirstamp) +glthread/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) glthread/$(DEPDIR) + @: > glthread/$(DEPDIR)/$(am__dirstamp) +glthread/lock.$(OBJEXT): glthread/$(am__dirstamp) \ + glthread/$(DEPDIR)/$(am__dirstamp) +glthread/threadlib.$(OBJEXT): glthread/$(am__dirstamp) \ + glthread/$(DEPDIR)/$(am__dirstamp) +uniwidth/$(am__dirstamp): + @$(MKDIR_P) uniwidth + @: > uniwidth/$(am__dirstamp) +uniwidth/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) uniwidth/$(DEPDIR) + @: > uniwidth/$(DEPDIR)/$(am__dirstamp) +uniwidth/width.$(OBJEXT): uniwidth/$(am__dirstamp) \ + uniwidth/$(DEPDIR)/$(am__dirstamp) + +libgnu.a: $(libgnu_a_OBJECTS) $(libgnu_a_DEPENDENCIES) $(EXTRA_libgnu_a_DEPENDENCIES) + $(AM_V_at)-rm -f libgnu.a + $(AM_V_AR)$(libgnu_a_AR) libgnu.a $(libgnu_a_OBJECTS) $(libgnu_a_LIBADD) + $(AM_V_at)$(RANLIB) libgnu.a + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f glthread/*.$(OBJEXT) + -rm -f uniwidth/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/alloca.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloca.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-ba.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-eexst.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-fmtstream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-fs-xinl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-help.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-parse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-pin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-pv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-pvh.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-xinl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asnprintf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basename-lgpl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/btowc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chdir-long.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cloexec.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/close.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirfd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirname-lgpl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dup-safer-flag.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dup-safer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dup2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exitfail.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fchdir.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcntl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fd-hook.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fd-safer-flag.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fd-safer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filenamecat-lgpl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/float.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fnmatch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fnmatch_loop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fstat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getcwd-lgpl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getdelim.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getdtablesize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getprogname.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hard-locale.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/itold.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localcharset.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localeconv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloca.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbrtowc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbsinit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbsrtowcs-state.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbsrtowcs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbswidth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbtowc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memchr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mempcpy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memrchr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msvc-inval.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msvc-nothrow.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nl_langinfo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/open.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openat-die.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openat-proc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipe-safer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printf-args.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printf-parse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/progname.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rawmemchr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/realloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regcomp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_internal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regexec.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/save-cwd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sleep.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stat-time.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stat-w32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strcasecmp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strchrnul.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strdup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strerror-override.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strerror.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stripslash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strncasecmp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strndup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strnlen.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strnlen1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unistd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vasnprintf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vsnprintf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wcrtomb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wctype-h.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wcwidth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xsize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@glthread/$(DEPDIR)/lock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@glthread/$(DEPDIR)/threadlib.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@uniwidth/$(DEPDIR)/width.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f glthread/$(DEPDIR)/$(am__dirstamp) + -rm -f glthread/$(am__dirstamp) + -rm -f uniwidth/$(DEPDIR)/$(am__dirstamp) + -rm -f uniwidth/$(am__dirstamp) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-recursive + +clean-am: clean-generic clean-noinstLIBRARIES clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf $(DEPDIR) ./$(DEPDIR) glthread/$(DEPDIR) uniwidth/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf $(DEPDIR) ./$(DEPDIR) glthread/$(DEPDIR) uniwidth/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-local + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) all check install install-am \ + install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-noinstLIBRARIES \ + clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-local pdf \ + pdf-am ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# We need the following in order to create <alloca.h> when the system +# doesn't have one that works with the given compiler. +@GL_GENERATE_ALLOCA_H_TRUE@alloca.h: alloca.in.h $(top_builddir)/config.status +@GL_GENERATE_ALLOCA_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_ALLOCA_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ +@GL_GENERATE_ALLOCA_H_TRUE@ cat $(srcdir)/alloca.in.h; \ +@GL_GENERATE_ALLOCA_H_TRUE@ } > $@-t && \ +@GL_GENERATE_ALLOCA_H_TRUE@ mv -f $@-t $@ +@GL_GENERATE_ALLOCA_H_FALSE@alloca.h: $(top_builddir)/config.status +@GL_GENERATE_ALLOCA_H_FALSE@ rm -f $@ + +# We need the following in order to create <dirent.h> when the system +# doesn't have one that works with the given compiler. +dirent.h: dirent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_DIRENT_H''@|$(HAVE_DIRENT_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_DIRENT_H''@|$(NEXT_DIRENT_H)|g' \ + -e 's/@''GNULIB_OPENDIR''@/$(GNULIB_OPENDIR)/g' \ + -e 's/@''GNULIB_READDIR''@/$(GNULIB_READDIR)/g' \ + -e 's/@''GNULIB_REWINDDIR''@/$(GNULIB_REWINDDIR)/g' \ + -e 's/@''GNULIB_CLOSEDIR''@/$(GNULIB_CLOSEDIR)/g' \ + -e 's/@''GNULIB_DIRFD''@/$(GNULIB_DIRFD)/g' \ + -e 's/@''GNULIB_FDOPENDIR''@/$(GNULIB_FDOPENDIR)/g' \ + -e 's/@''GNULIB_SCANDIR''@/$(GNULIB_SCANDIR)/g' \ + -e 's/@''GNULIB_ALPHASORT''@/$(GNULIB_ALPHASORT)/g' \ + -e 's/@''HAVE_OPENDIR''@/$(HAVE_OPENDIR)/g' \ + -e 's/@''HAVE_READDIR''@/$(HAVE_READDIR)/g' \ + -e 's/@''HAVE_REWINDDIR''@/$(HAVE_REWINDDIR)/g' \ + -e 's/@''HAVE_CLOSEDIR''@/$(HAVE_CLOSEDIR)/g' \ + -e 's|@''HAVE_DECL_DIRFD''@|$(HAVE_DECL_DIRFD)|g' \ + -e 's|@''HAVE_DECL_FDOPENDIR''@|$(HAVE_DECL_FDOPENDIR)|g' \ + -e 's|@''HAVE_FDOPENDIR''@|$(HAVE_FDOPENDIR)|g' \ + -e 's|@''HAVE_SCANDIR''@|$(HAVE_SCANDIR)|g' \ + -e 's|@''HAVE_ALPHASORT''@|$(HAVE_ALPHASORT)|g' \ + -e 's|@''REPLACE_OPENDIR''@|$(REPLACE_OPENDIR)|g' \ + -e 's|@''REPLACE_CLOSEDIR''@|$(REPLACE_CLOSEDIR)|g' \ + -e 's|@''REPLACE_DIRFD''@|$(REPLACE_DIRFD)|g' \ + -e 's|@''REPLACE_FDOPENDIR''@|$(REPLACE_FDOPENDIR)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/dirent.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create <errno.h> when the system +# doesn't have one that is POSIX compliant. +@GL_GENERATE_ERRNO_H_TRUE@errno.h: errno.in.h $(top_builddir)/config.status +@GL_GENERATE_ERRNO_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_ERRNO_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ +@GL_GENERATE_ERRNO_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''NEXT_ERRNO_H''@|$(NEXT_ERRNO_H)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''EMULTIHOP_HIDDEN''@|$(EMULTIHOP_HIDDEN)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''EMULTIHOP_VALUE''@|$(EMULTIHOP_VALUE)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''ENOLINK_HIDDEN''@|$(ENOLINK_HIDDEN)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''ENOLINK_VALUE''@|$(ENOLINK_VALUE)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''EOVERFLOW_HIDDEN''@|$(EOVERFLOW_HIDDEN)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ -e 's|@''EOVERFLOW_VALUE''@|$(EOVERFLOW_VALUE)|g' \ +@GL_GENERATE_ERRNO_H_TRUE@ < $(srcdir)/errno.in.h; \ +@GL_GENERATE_ERRNO_H_TRUE@ } > $@-t && \ +@GL_GENERATE_ERRNO_H_TRUE@ mv $@-t $@ +@GL_GENERATE_ERRNO_H_FALSE@errno.h: $(top_builddir)/config.status +@GL_GENERATE_ERRNO_H_FALSE@ rm -f $@ + +# We need the following in order to create <fcntl.h> when the system +# doesn't have one that works with the given compiler. +fcntl.h: fcntl.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_FCNTL_H''@|$(NEXT_FCNTL_H)|g' \ + -e 's/@''GNULIB_FCNTL''@/$(GNULIB_FCNTL)/g' \ + -e 's/@''GNULIB_NONBLOCKING''@/$(GNULIB_NONBLOCKING)/g' \ + -e 's/@''GNULIB_OPEN''@/$(GNULIB_OPEN)/g' \ + -e 's/@''GNULIB_OPENAT''@/$(GNULIB_OPENAT)/g' \ + -e 's|@''HAVE_FCNTL''@|$(HAVE_FCNTL)|g' \ + -e 's|@''HAVE_OPENAT''@|$(HAVE_OPENAT)|g' \ + -e 's|@''REPLACE_FCNTL''@|$(REPLACE_FCNTL)|g' \ + -e 's|@''REPLACE_OPEN''@|$(REPLACE_OPEN)|g' \ + -e 's|@''REPLACE_OPENAT''@|$(REPLACE_OPENAT)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/fcntl.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create <float.h> when the system +# doesn't have one that works with the given compiler. +@GL_GENERATE_FLOAT_H_TRUE@float.h: float.in.h $(top_builddir)/config.status +@GL_GENERATE_FLOAT_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_FLOAT_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ +@GL_GENERATE_FLOAT_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ -e 's|@''NEXT_FLOAT_H''@|$(NEXT_FLOAT_H)|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ -e 's|@''REPLACE_ITOLD''@|$(REPLACE_ITOLD)|g' \ +@GL_GENERATE_FLOAT_H_TRUE@ < $(srcdir)/float.in.h; \ +@GL_GENERATE_FLOAT_H_TRUE@ } > $@-t && \ +@GL_GENERATE_FLOAT_H_TRUE@ mv $@-t $@ +@GL_GENERATE_FLOAT_H_FALSE@float.h: $(top_builddir)/config.status +@GL_GENERATE_FLOAT_H_FALSE@ rm -f $@ + +# We need the following in order to create <fnmatch.h>. +@GL_GENERATE_FNMATCH_H_TRUE@fnmatch.h: fnmatch.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) +@GL_GENERATE_FNMATCH_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_FNMATCH_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ +@GL_GENERATE_FNMATCH_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_FNMATCH_H_TRUE@ -e 's|@''HAVE_FNMATCH_H''@|$(HAVE_FNMATCH_H)|g' \ +@GL_GENERATE_FNMATCH_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_FNMATCH_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_FNMATCH_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_FNMATCH_H_TRUE@ -e 's|@''NEXT_FNMATCH_H''@|$(NEXT_FNMATCH_H)|g' \ +@GL_GENERATE_FNMATCH_H_TRUE@ -e 's/@''GNULIB_FNMATCH''@/$(GNULIB_FNMATCH)/g' \ +@GL_GENERATE_FNMATCH_H_TRUE@ -e 's|@''HAVE_FNMATCH''@|$(HAVE_FNMATCH)|g' \ +@GL_GENERATE_FNMATCH_H_TRUE@ -e 's|@''REPLACE_FNMATCH''@|$(REPLACE_FNMATCH)|g' \ +@GL_GENERATE_FNMATCH_H_TRUE@ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ +@GL_GENERATE_FNMATCH_H_TRUE@ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ +@GL_GENERATE_FNMATCH_H_TRUE@ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ +@GL_GENERATE_FNMATCH_H_TRUE@ < $(srcdir)/fnmatch.in.h; \ +@GL_GENERATE_FNMATCH_H_TRUE@ } > $@-t && \ +@GL_GENERATE_FNMATCH_H_TRUE@ mv $@-t $@ +@GL_GENERATE_FNMATCH_H_FALSE@fnmatch.h: $(top_builddir)/config.status +@GL_GENERATE_FNMATCH_H_FALSE@ rm -f $@ + +# We need the following in order to create <getopt.h> when the system +# doesn't have one that works with the given compiler. +getopt.h: getopt.in.h $(top_builddir)/config.status $(ARG_NONNULL_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_GETOPT_H''@|$(HAVE_GETOPT_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_GETOPT_H''@|$(NEXT_GETOPT_H)|g' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + < $(srcdir)/getopt.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +getopt-cdefs.h: getopt-cdefs.in.h $(top_builddir)/config.status + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''HAVE_SYS_CDEFS_H''@|$(HAVE_SYS_CDEFS_H)|g' \ + < $(srcdir)/getopt-cdefs.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +# We need the following in order to create an empty placeholder for +# <langinfo.h> when the system doesn't have one. +langinfo.h: langinfo.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_LANGINFO_H''@|$(HAVE_LANGINFO_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_LANGINFO_H''@|$(NEXT_LANGINFO_H)|g' \ + -e 's/@''GNULIB_NL_LANGINFO''@/$(GNULIB_NL_LANGINFO)/g' \ + -e 's|@''HAVE_LANGINFO_CODESET''@|$(HAVE_LANGINFO_CODESET)|g' \ + -e 's|@''HAVE_LANGINFO_T_FMT_AMPM''@|$(HAVE_LANGINFO_T_FMT_AMPM)|g' \ + -e 's|@''HAVE_LANGINFO_ALTMON''@|$(HAVE_LANGINFO_ALTMON)|g' \ + -e 's|@''HAVE_LANGINFO_ERA''@|$(HAVE_LANGINFO_ERA)|g' \ + -e 's|@''HAVE_LANGINFO_YESEXPR''@|$(HAVE_LANGINFO_YESEXPR)|g' \ + -e 's|@''HAVE_NL_LANGINFO''@|$(HAVE_NL_LANGINFO)|g' \ + -e 's|@''REPLACE_NL_LANGINFO''@|$(REPLACE_NL_LANGINFO)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/langinfo.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create <limits.h> when the system +# doesn't have one that is compatible with GNU. +@GL_GENERATE_LIMITS_H_TRUE@limits.h: limits.in.h $(top_builddir)/config.status +@GL_GENERATE_LIMITS_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_LIMITS_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ +@GL_GENERATE_LIMITS_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_LIMITS_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_LIMITS_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_LIMITS_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_LIMITS_H_TRUE@ -e 's|@''NEXT_LIMITS_H''@|$(NEXT_LIMITS_H)|g' \ +@GL_GENERATE_LIMITS_H_TRUE@ < $(srcdir)/limits.in.h; \ +@GL_GENERATE_LIMITS_H_TRUE@ } > $@-t && \ +@GL_GENERATE_LIMITS_H_TRUE@ mv $@-t $@ +@GL_GENERATE_LIMITS_H_FALSE@limits.h: $(top_builddir)/config.status +@GL_GENERATE_LIMITS_H_FALSE@ rm -f $@ + +# We need the following in order to create <locale.h> when the system +# doesn't have one that provides all definitions. +locale.h: locale.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_LOCALE_H''@|$(NEXT_LOCALE_H)|g' \ + -e 's/@''GNULIB_LOCALECONV''@/$(GNULIB_LOCALECONV)/g' \ + -e 's/@''GNULIB_SETLOCALE''@/$(GNULIB_SETLOCALE)/g' \ + -e 's/@''GNULIB_DUPLOCALE''@/$(GNULIB_DUPLOCALE)/g' \ + -e 's/@''GNULIB_LOCALENAME''@/$(GNULIB_LOCALENAME)/g' \ + -e 's|@''HAVE_NEWLOCALE''@|$(HAVE_NEWLOCALE)|g' \ + -e 's|@''HAVE_DUPLOCALE''@|$(HAVE_DUPLOCALE)|g' \ + -e 's|@''HAVE_FREELOCALE''@|$(HAVE_FREELOCALE)|g' \ + -e 's|@''HAVE_XLOCALE_H''@|$(HAVE_XLOCALE_H)|g' \ + -e 's|@''REPLACE_LOCALECONV''@|$(REPLACE_LOCALECONV)|g' \ + -e 's|@''REPLACE_SETLOCALE''@|$(REPLACE_SETLOCALE)|g' \ + -e 's|@''REPLACE_NEWLOCALE''@|$(REPLACE_NEWLOCALE)|g' \ + -e 's|@''REPLACE_DUPLOCALE''@|$(REPLACE_DUPLOCALE)|g' \ + -e 's|@''REPLACE_FREELOCALE''@|$(REPLACE_FREELOCALE)|g' \ + -e 's|@''REPLACE_STRUCT_LCONV''@|$(REPLACE_STRUCT_LCONV)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/locale.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create <stdalign.h> when the system +# doesn't have one that works. +@GL_GENERATE_STDALIGN_H_TRUE@stdalign.h: stdalign.in.h $(top_builddir)/config.status +@GL_GENERATE_STDALIGN_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_STDALIGN_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ +@GL_GENERATE_STDALIGN_H_TRUE@ cat $(srcdir)/stdalign.in.h; \ +@GL_GENERATE_STDALIGN_H_TRUE@ } > $@-t && \ +@GL_GENERATE_STDALIGN_H_TRUE@ mv $@-t $@ +@GL_GENERATE_STDALIGN_H_FALSE@stdalign.h: $(top_builddir)/config.status +@GL_GENERATE_STDALIGN_H_FALSE@ rm -f $@ + +# We need the following in order to create <stdbool.h> when the system +# doesn't have one that works. +@GL_GENERATE_STDBOOL_H_TRUE@stdbool.h: stdbool.in.h $(top_builddir)/config.status +@GL_GENERATE_STDBOOL_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_STDBOOL_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ +@GL_GENERATE_STDBOOL_H_TRUE@ sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool.in.h; \ +@GL_GENERATE_STDBOOL_H_TRUE@ } > $@-t && \ +@GL_GENERATE_STDBOOL_H_TRUE@ mv $@-t $@ +@GL_GENERATE_STDBOOL_H_FALSE@stdbool.h: $(top_builddir)/config.status +@GL_GENERATE_STDBOOL_H_FALSE@ rm -f $@ + +# We need the following in order to create <stddef.h> when the system +# doesn't have one that works with the given compiler. +@GL_GENERATE_STDDEF_H_TRUE@stddef.h: stddef.in.h $(top_builddir)/config.status +@GL_GENERATE_STDDEF_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_STDDEF_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ +@GL_GENERATE_STDDEF_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''NEXT_STDDEF_H''@|$(NEXT_STDDEF_H)|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''HAVE_MAX_ALIGN_T''@|$(HAVE_MAX_ALIGN_T)|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''HAVE_WCHAR_T''@|$(HAVE_WCHAR_T)|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ -e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \ +@GL_GENERATE_STDDEF_H_TRUE@ < $(srcdir)/stddef.in.h; \ +@GL_GENERATE_STDDEF_H_TRUE@ } > $@-t && \ +@GL_GENERATE_STDDEF_H_TRUE@ mv $@-t $@ +@GL_GENERATE_STDDEF_H_FALSE@stddef.h: $(top_builddir)/config.status +@GL_GENERATE_STDDEF_H_FALSE@ rm -f $@ + +# We need the following in order to create <stdint.h> when the system +# doesn't have one that works with the given compiler. +@GL_GENERATE_STDINT_H_TRUE@stdint.h: stdint.in.h $(top_builddir)/config.status +@GL_GENERATE_STDINT_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_STDINT_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ +@GL_GENERATE_STDINT_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's|@''NEXT_STDINT_H''@|$(NEXT_STDINT_H)|g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_C99_STDINT_H''@/$(HAVE_C99_STDINT_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_WCHAR_H''@/$(HAVE_WCHAR_H)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ -e 's/@''GNULIB_OVERRIDES_WINT_T''@/$(GNULIB_OVERRIDES_WINT_T)/g' \ +@GL_GENERATE_STDINT_H_TRUE@ < $(srcdir)/stdint.in.h; \ +@GL_GENERATE_STDINT_H_TRUE@ } > $@-t && \ +@GL_GENERATE_STDINT_H_TRUE@ mv $@-t $@ +@GL_GENERATE_STDINT_H_FALSE@stdint.h: $(top_builddir)/config.status +@GL_GENERATE_STDINT_H_FALSE@ rm -f $@ + +# We need the following in order to create <stdio.h> when the system +# doesn't have one that works with the given compiler. +stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDIO_H''@|$(NEXT_STDIO_H)|g' \ + -e 's/@''GNULIB_DPRINTF''@/$(GNULIB_DPRINTF)/g' \ + -e 's/@''GNULIB_FCLOSE''@/$(GNULIB_FCLOSE)/g' \ + -e 's/@''GNULIB_FDOPEN''@/$(GNULIB_FDOPEN)/g' \ + -e 's/@''GNULIB_FFLUSH''@/$(GNULIB_FFLUSH)/g' \ + -e 's/@''GNULIB_FGETC''@/$(GNULIB_FGETC)/g' \ + -e 's/@''GNULIB_FGETS''@/$(GNULIB_FGETS)/g' \ + -e 's/@''GNULIB_FOPEN''@/$(GNULIB_FOPEN)/g' \ + -e 's/@''GNULIB_FPRINTF''@/$(GNULIB_FPRINTF)/g' \ + -e 's/@''GNULIB_FPRINTF_POSIX''@/$(GNULIB_FPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_FPURGE''@/$(GNULIB_FPURGE)/g' \ + -e 's/@''GNULIB_FPUTC''@/$(GNULIB_FPUTC)/g' \ + -e 's/@''GNULIB_FPUTS''@/$(GNULIB_FPUTS)/g' \ + -e 's/@''GNULIB_FREAD''@/$(GNULIB_FREAD)/g' \ + -e 's/@''GNULIB_FREOPEN''@/$(GNULIB_FREOPEN)/g' \ + -e 's/@''GNULIB_FSCANF''@/$(GNULIB_FSCANF)/g' \ + -e 's/@''GNULIB_FSEEK''@/$(GNULIB_FSEEK)/g' \ + -e 's/@''GNULIB_FSEEKO''@/$(GNULIB_FSEEKO)/g' \ + -e 's/@''GNULIB_FTELL''@/$(GNULIB_FTELL)/g' \ + -e 's/@''GNULIB_FTELLO''@/$(GNULIB_FTELLO)/g' \ + -e 's/@''GNULIB_FWRITE''@/$(GNULIB_FWRITE)/g' \ + -e 's/@''GNULIB_GETC''@/$(GNULIB_GETC)/g' \ + -e 's/@''GNULIB_GETCHAR''@/$(GNULIB_GETCHAR)/g' \ + -e 's/@''GNULIB_GETDELIM''@/$(GNULIB_GETDELIM)/g' \ + -e 's/@''GNULIB_GETLINE''@/$(GNULIB_GETLINE)/g' \ + -e 's/@''GNULIB_OBSTACK_PRINTF''@/$(GNULIB_OBSTACK_PRINTF)/g' \ + -e 's/@''GNULIB_OBSTACK_PRINTF_POSIX''@/$(GNULIB_OBSTACK_PRINTF_POSIX)/g' \ + -e 's/@''GNULIB_PCLOSE''@/$(GNULIB_PCLOSE)/g' \ + -e 's/@''GNULIB_PERROR''@/$(GNULIB_PERROR)/g' \ + -e 's/@''GNULIB_POPEN''@/$(GNULIB_POPEN)/g' \ + -e 's/@''GNULIB_PRINTF''@/$(GNULIB_PRINTF)/g' \ + -e 's/@''GNULIB_PRINTF_POSIX''@/$(GNULIB_PRINTF_POSIX)/g' \ + -e 's/@''GNULIB_PUTC''@/$(GNULIB_PUTC)/g' \ + -e 's/@''GNULIB_PUTCHAR''@/$(GNULIB_PUTCHAR)/g' \ + -e 's/@''GNULIB_PUTS''@/$(GNULIB_PUTS)/g' \ + -e 's/@''GNULIB_REMOVE''@/$(GNULIB_REMOVE)/g' \ + -e 's/@''GNULIB_RENAME''@/$(GNULIB_RENAME)/g' \ + -e 's/@''GNULIB_RENAMEAT''@/$(GNULIB_RENAMEAT)/g' \ + -e 's/@''GNULIB_SCANF''@/$(GNULIB_SCANF)/g' \ + -e 's/@''GNULIB_SNPRINTF''@/$(GNULIB_SNPRINTF)/g' \ + -e 's/@''GNULIB_SPRINTF_POSIX''@/$(GNULIB_SPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_STDIO_H_NONBLOCKING''@/$(GNULIB_STDIO_H_NONBLOCKING)/g' \ + -e 's/@''GNULIB_STDIO_H_SIGPIPE''@/$(GNULIB_STDIO_H_SIGPIPE)/g' \ + -e 's/@''GNULIB_TMPFILE''@/$(GNULIB_TMPFILE)/g' \ + -e 's/@''GNULIB_VASPRINTF''@/$(GNULIB_VASPRINTF)/g' \ + -e 's/@''GNULIB_VDPRINTF''@/$(GNULIB_VDPRINTF)/g' \ + -e 's/@''GNULIB_VFPRINTF''@/$(GNULIB_VFPRINTF)/g' \ + -e 's/@''GNULIB_VFPRINTF_POSIX''@/$(GNULIB_VFPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_VFSCANF''@/$(GNULIB_VFSCANF)/g' \ + -e 's/@''GNULIB_VSCANF''@/$(GNULIB_VSCANF)/g' \ + -e 's/@''GNULIB_VPRINTF''@/$(GNULIB_VPRINTF)/g' \ + -e 's/@''GNULIB_VPRINTF_POSIX''@/$(GNULIB_VPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_VSNPRINTF''@/$(GNULIB_VSNPRINTF)/g' \ + -e 's/@''GNULIB_VSPRINTF_POSIX''@/$(GNULIB_VSPRINTF_POSIX)/g' \ + < $(srcdir)/stdio.in.h | \ + sed -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \ + -e 's|@''HAVE_DECL_FSEEKO''@|$(HAVE_DECL_FSEEKO)|g' \ + -e 's|@''HAVE_DECL_FTELLO''@|$(HAVE_DECL_FTELLO)|g' \ + -e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \ + -e 's|@''HAVE_DECL_GETLINE''@|$(HAVE_DECL_GETLINE)|g' \ + -e 's|@''HAVE_DECL_OBSTACK_PRINTF''@|$(HAVE_DECL_OBSTACK_PRINTF)|g' \ + -e 's|@''HAVE_DECL_SNPRINTF''@|$(HAVE_DECL_SNPRINTF)|g' \ + -e 's|@''HAVE_DECL_VSNPRINTF''@|$(HAVE_DECL_VSNPRINTF)|g' \ + -e 's|@''HAVE_DPRINTF''@|$(HAVE_DPRINTF)|g' \ + -e 's|@''HAVE_FSEEKO''@|$(HAVE_FSEEKO)|g' \ + -e 's|@''HAVE_FTELLO''@|$(HAVE_FTELLO)|g' \ + -e 's|@''HAVE_PCLOSE''@|$(HAVE_PCLOSE)|g' \ + -e 's|@''HAVE_POPEN''@|$(HAVE_POPEN)|g' \ + -e 's|@''HAVE_RENAMEAT''@|$(HAVE_RENAMEAT)|g' \ + -e 's|@''HAVE_VASPRINTF''@|$(HAVE_VASPRINTF)|g' \ + -e 's|@''HAVE_VDPRINTF''@|$(HAVE_VDPRINTF)|g' \ + -e 's|@''REPLACE_DPRINTF''@|$(REPLACE_DPRINTF)|g' \ + -e 's|@''REPLACE_FCLOSE''@|$(REPLACE_FCLOSE)|g' \ + -e 's|@''REPLACE_FDOPEN''@|$(REPLACE_FDOPEN)|g' \ + -e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \ + -e 's|@''REPLACE_FOPEN''@|$(REPLACE_FOPEN)|g' \ + -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \ + -e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \ + -e 's|@''REPLACE_FREOPEN''@|$(REPLACE_FREOPEN)|g' \ + -e 's|@''REPLACE_FSEEK''@|$(REPLACE_FSEEK)|g' \ + -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \ + -e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \ + -e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \ + -e 's|@''REPLACE_GETDELIM''@|$(REPLACE_GETDELIM)|g' \ + -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \ + -e 's|@''REPLACE_OBSTACK_PRINTF''@|$(REPLACE_OBSTACK_PRINTF)|g' \ + -e 's|@''REPLACE_PERROR''@|$(REPLACE_PERROR)|g' \ + -e 's|@''REPLACE_POPEN''@|$(REPLACE_POPEN)|g' \ + -e 's|@''REPLACE_PRINTF''@|$(REPLACE_PRINTF)|g' \ + -e 's|@''REPLACE_REMOVE''@|$(REPLACE_REMOVE)|g' \ + -e 's|@''REPLACE_RENAME''@|$(REPLACE_RENAME)|g' \ + -e 's|@''REPLACE_RENAMEAT''@|$(REPLACE_RENAMEAT)|g' \ + -e 's|@''REPLACE_SNPRINTF''@|$(REPLACE_SNPRINTF)|g' \ + -e 's|@''REPLACE_SPRINTF''@|$(REPLACE_SPRINTF)|g' \ + -e 's|@''REPLACE_STDIO_READ_FUNCS''@|$(REPLACE_STDIO_READ_FUNCS)|g' \ + -e 's|@''REPLACE_STDIO_WRITE_FUNCS''@|$(REPLACE_STDIO_WRITE_FUNCS)|g' \ + -e 's|@''REPLACE_TMPFILE''@|$(REPLACE_TMPFILE)|g' \ + -e 's|@''REPLACE_VASPRINTF''@|$(REPLACE_VASPRINTF)|g' \ + -e 's|@''REPLACE_VDPRINTF''@|$(REPLACE_VDPRINTF)|g' \ + -e 's|@''REPLACE_VFPRINTF''@|$(REPLACE_VFPRINTF)|g' \ + -e 's|@''REPLACE_VPRINTF''@|$(REPLACE_VPRINTF)|g' \ + -e 's|@''REPLACE_VSNPRINTF''@|$(REPLACE_VSNPRINTF)|g' \ + -e 's|@''REPLACE_VSPRINTF''@|$(REPLACE_VSPRINTF)|g' \ + -e 's|@''ASM_SYMBOL_PREFIX''@|$(ASM_SYMBOL_PREFIX)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create <stdlib.h> when the system +# doesn't have one that works with the given compiler. +stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ + $(_NORETURN_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STDLIB_H''@|$(NEXT_STDLIB_H)|g' \ + -e 's/@''GNULIB__EXIT''@/$(GNULIB__EXIT)/g' \ + -e 's/@''GNULIB_ATOLL''@/$(GNULIB_ATOLL)/g' \ + -e 's/@''GNULIB_CALLOC_POSIX''@/$(GNULIB_CALLOC_POSIX)/g' \ + -e 's/@''GNULIB_CANONICALIZE_FILE_NAME''@/$(GNULIB_CANONICALIZE_FILE_NAME)/g' \ + -e 's/@''GNULIB_GETLOADAVG''@/$(GNULIB_GETLOADAVG)/g' \ + -e 's/@''GNULIB_GETSUBOPT''@/$(GNULIB_GETSUBOPT)/g' \ + -e 's/@''GNULIB_GRANTPT''@/$(GNULIB_GRANTPT)/g' \ + -e 's/@''GNULIB_MALLOC_POSIX''@/$(GNULIB_MALLOC_POSIX)/g' \ + -e 's/@''GNULIB_MBTOWC''@/$(GNULIB_MBTOWC)/g' \ + -e 's/@''GNULIB_MKDTEMP''@/$(GNULIB_MKDTEMP)/g' \ + -e 's/@''GNULIB_MKOSTEMP''@/$(GNULIB_MKOSTEMP)/g' \ + -e 's/@''GNULIB_MKOSTEMPS''@/$(GNULIB_MKOSTEMPS)/g' \ + -e 's/@''GNULIB_MKSTEMP''@/$(GNULIB_MKSTEMP)/g' \ + -e 's/@''GNULIB_MKSTEMPS''@/$(GNULIB_MKSTEMPS)/g' \ + -e 's/@''GNULIB_POSIX_OPENPT''@/$(GNULIB_POSIX_OPENPT)/g' \ + -e 's/@''GNULIB_PTSNAME''@/$(GNULIB_PTSNAME)/g' \ + -e 's/@''GNULIB_PTSNAME_R''@/$(GNULIB_PTSNAME_R)/g' \ + -e 's/@''GNULIB_PUTENV''@/$(GNULIB_PUTENV)/g' \ + -e 's/@''GNULIB_QSORT_R''@/$(GNULIB_QSORT_R)/g' \ + -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/g' \ + -e 's/@''GNULIB_RANDOM_R''@/$(GNULIB_RANDOM_R)/g' \ + -e 's/@''GNULIB_REALLOC_POSIX''@/$(GNULIB_REALLOC_POSIX)/g' \ + -e 's/@''GNULIB_REALLOCARRAY''@/$(GNULIB_REALLOCARRAY)/g' \ + -e 's/@''GNULIB_REALPATH''@/$(GNULIB_REALPATH)/g' \ + -e 's/@''GNULIB_RPMATCH''@/$(GNULIB_RPMATCH)/g' \ + -e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \ + -e 's/@''GNULIB_SETENV''@/$(GNULIB_SETENV)/g' \ + -e 's/@''GNULIB_STRTOD''@/$(GNULIB_STRTOD)/g' \ + -e 's/@''GNULIB_STRTOLL''@/$(GNULIB_STRTOLL)/g' \ + -e 's/@''GNULIB_STRTOULL''@/$(GNULIB_STRTOULL)/g' \ + -e 's/@''GNULIB_SYSTEM_POSIX''@/$(GNULIB_SYSTEM_POSIX)/g' \ + -e 's/@''GNULIB_UNLOCKPT''@/$(GNULIB_UNLOCKPT)/g' \ + -e 's/@''GNULIB_UNSETENV''@/$(GNULIB_UNSETENV)/g' \ + -e 's/@''GNULIB_WCTOMB''@/$(GNULIB_WCTOMB)/g' \ + < $(srcdir)/stdlib.in.h | \ + sed -e 's|@''HAVE__EXIT''@|$(HAVE__EXIT)|g' \ + -e 's|@''HAVE_ATOLL''@|$(HAVE_ATOLL)|g' \ + -e 's|@''HAVE_CANONICALIZE_FILE_NAME''@|$(HAVE_CANONICALIZE_FILE_NAME)|g' \ + -e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \ + -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \ + -e 's|@''HAVE_GRANTPT''@|$(HAVE_GRANTPT)|g' \ + -e 's|@''HAVE_DECL_INITSTATE''@|$(HAVE_DECL_INITSTATE)|g' \ + -e 's|@''HAVE_MKDTEMP''@|$(HAVE_MKDTEMP)|g' \ + -e 's|@''HAVE_MKOSTEMP''@|$(HAVE_MKOSTEMP)|g' \ + -e 's|@''HAVE_MKOSTEMPS''@|$(HAVE_MKOSTEMPS)|g' \ + -e 's|@''HAVE_MKSTEMP''@|$(HAVE_MKSTEMP)|g' \ + -e 's|@''HAVE_MKSTEMPS''@|$(HAVE_MKSTEMPS)|g' \ + -e 's|@''HAVE_POSIX_OPENPT''@|$(HAVE_POSIX_OPENPT)|g' \ + -e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \ + -e 's|@''HAVE_PTSNAME_R''@|$(HAVE_PTSNAME_R)|g' \ + -e 's|@''HAVE_QSORT_R''@|$(HAVE_QSORT_R)|g' \ + -e 's|@''HAVE_RANDOM''@|$(HAVE_RANDOM)|g' \ + -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \ + -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \ + -e 's|@''HAVE_REALLOCARRAY''@|$(HAVE_REALLOCARRAY)|g' \ + -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \ + -e 's|@''HAVE_RPMATCH''@|$(HAVE_RPMATCH)|g' \ + -e 's|@''HAVE_SECURE_GETENV''@|$(HAVE_SECURE_GETENV)|g' \ + -e 's|@''HAVE_DECL_SETENV''@|$(HAVE_DECL_SETENV)|g' \ + -e 's|@''HAVE_DECL_SETSTATE''@|$(HAVE_DECL_SETSTATE)|g' \ + -e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \ + -e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \ + -e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \ + -e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \ + -e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \ + -e 's|@''HAVE_UNLOCKPT''@|$(HAVE_UNLOCKPT)|g' \ + -e 's|@''HAVE_DECL_UNSETENV''@|$(HAVE_DECL_UNSETENV)|g' \ + -e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \ + -e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \ + -e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \ + -e 's|@''REPLACE_MBTOWC''@|$(REPLACE_MBTOWC)|g' \ + -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \ + -e 's|@''REPLACE_PTSNAME''@|$(REPLACE_PTSNAME)|g' \ + -e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \ + -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \ + -e 's|@''REPLACE_QSORT_R''@|$(REPLACE_QSORT_R)|g' \ + -e 's|@''REPLACE_RANDOM_R''@|$(REPLACE_RANDOM_R)|g' \ + -e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \ + -e 's|@''REPLACE_REALPATH''@|$(REPLACE_REALPATH)|g' \ + -e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \ + -e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \ + -e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \ + -e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _Noreturn/r $(_NORETURN_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create <string.h> when the system +# doesn't have one that works with the given compiler. +string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STRING_H''@|$(NEXT_STRING_H)|g' \ + -e 's/@''GNULIB_EXPLICIT_BZERO''@/$(GNULIB_EXPLICIT_BZERO)/g' \ + -e 's/@''GNULIB_FFSL''@/$(GNULIB_FFSL)/g' \ + -e 's/@''GNULIB_FFSLL''@/$(GNULIB_FFSLL)/g' \ + -e 's/@''GNULIB_MBSLEN''@/$(GNULIB_MBSLEN)/g' \ + -e 's/@''GNULIB_MBSNLEN''@/$(GNULIB_MBSNLEN)/g' \ + -e 's/@''GNULIB_MBSCHR''@/$(GNULIB_MBSCHR)/g' \ + -e 's/@''GNULIB_MBSRCHR''@/$(GNULIB_MBSRCHR)/g' \ + -e 's/@''GNULIB_MBSSTR''@/$(GNULIB_MBSSTR)/g' \ + -e 's/@''GNULIB_MBSCASECMP''@/$(GNULIB_MBSCASECMP)/g' \ + -e 's/@''GNULIB_MBSNCASECMP''@/$(GNULIB_MBSNCASECMP)/g' \ + -e 's/@''GNULIB_MBSPCASECMP''@/$(GNULIB_MBSPCASECMP)/g' \ + -e 's/@''GNULIB_MBSCASESTR''@/$(GNULIB_MBSCASESTR)/g' \ + -e 's/@''GNULIB_MBSCSPN''@/$(GNULIB_MBSCSPN)/g' \ + -e 's/@''GNULIB_MBSPBRK''@/$(GNULIB_MBSPBRK)/g' \ + -e 's/@''GNULIB_MBSSPN''@/$(GNULIB_MBSSPN)/g' \ + -e 's/@''GNULIB_MBSSEP''@/$(GNULIB_MBSSEP)/g' \ + -e 's/@''GNULIB_MBSTOK_R''@/$(GNULIB_MBSTOK_R)/g' \ + -e 's/@''GNULIB_MEMCHR''@/$(GNULIB_MEMCHR)/g' \ + -e 's/@''GNULIB_MEMMEM''@/$(GNULIB_MEMMEM)/g' \ + -e 's/@''GNULIB_MEMPCPY''@/$(GNULIB_MEMPCPY)/g' \ + -e 's/@''GNULIB_MEMRCHR''@/$(GNULIB_MEMRCHR)/g' \ + -e 's/@''GNULIB_RAWMEMCHR''@/$(GNULIB_RAWMEMCHR)/g' \ + -e 's/@''GNULIB_STPCPY''@/$(GNULIB_STPCPY)/g' \ + -e 's/@''GNULIB_STPNCPY''@/$(GNULIB_STPNCPY)/g' \ + -e 's/@''GNULIB_STRCHRNUL''@/$(GNULIB_STRCHRNUL)/g' \ + -e 's/@''GNULIB_STRDUP''@/$(GNULIB_STRDUP)/g' \ + -e 's/@''GNULIB_STRNCAT''@/$(GNULIB_STRNCAT)/g' \ + -e 's/@''GNULIB_STRNDUP''@/$(GNULIB_STRNDUP)/g' \ + -e 's/@''GNULIB_STRNLEN''@/$(GNULIB_STRNLEN)/g' \ + -e 's/@''GNULIB_STRPBRK''@/$(GNULIB_STRPBRK)/g' \ + -e 's/@''GNULIB_STRSEP''@/$(GNULIB_STRSEP)/g' \ + -e 's/@''GNULIB_STRSTR''@/$(GNULIB_STRSTR)/g' \ + -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \ + -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \ + -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \ + -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \ + -e 's/@''GNULIB_STRSIGNAL''@/$(GNULIB_STRSIGNAL)/g' \ + -e 's/@''GNULIB_STRVERSCMP''@/$(GNULIB_STRVERSCMP)/g' \ + < $(srcdir)/string.in.h | \ + sed -e 's|@''HAVE_EXPLICIT_BZERO''@|$(HAVE_EXPLICIT_BZERO)|g' \ + -e 's|@''HAVE_FFSL''@|$(HAVE_FFSL)|g' \ + -e 's|@''HAVE_FFSLL''@|$(HAVE_FFSLL)|g' \ + -e 's|@''HAVE_MBSLEN''@|$(HAVE_MBSLEN)|g' \ + -e 's|@''HAVE_MEMCHR''@|$(HAVE_MEMCHR)|g' \ + -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \ + -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \ + -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \ + -e 's|@''HAVE_RAWMEMCHR''@|$(HAVE_RAWMEMCHR)|g' \ + -e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \ + -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \ + -e 's|@''HAVE_STRCHRNUL''@|$(HAVE_STRCHRNUL)|g' \ + -e 's|@''HAVE_DECL_STRDUP''@|$(HAVE_DECL_STRDUP)|g' \ + -e 's|@''HAVE_DECL_STRNDUP''@|$(HAVE_DECL_STRNDUP)|g' \ + -e 's|@''HAVE_DECL_STRNLEN''@|$(HAVE_DECL_STRNLEN)|g' \ + -e 's|@''HAVE_STRPBRK''@|$(HAVE_STRPBRK)|g' \ + -e 's|@''HAVE_STRSEP''@|$(HAVE_STRSEP)|g' \ + -e 's|@''HAVE_STRCASESTR''@|$(HAVE_STRCASESTR)|g' \ + -e 's|@''HAVE_DECL_STRTOK_R''@|$(HAVE_DECL_STRTOK_R)|g' \ + -e 's|@''HAVE_DECL_STRERROR_R''@|$(HAVE_DECL_STRERROR_R)|g' \ + -e 's|@''HAVE_DECL_STRSIGNAL''@|$(HAVE_DECL_STRSIGNAL)|g' \ + -e 's|@''HAVE_STRVERSCMP''@|$(HAVE_STRVERSCMP)|g' \ + -e 's|@''REPLACE_MEMCHR''@|$(REPLACE_MEMCHR)|g' \ + -e 's|@''REPLACE_MEMMEM''@|$(REPLACE_MEMMEM)|g' \ + -e 's|@''REPLACE_STPNCPY''@|$(REPLACE_STPNCPY)|g' \ + -e 's|@''REPLACE_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|g' \ + -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \ + -e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \ + -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \ + -e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \ + -e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \ + -e 's|@''REPLACE_STRCASESTR''@|$(REPLACE_STRCASESTR)|g' \ + -e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \ + -e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \ + -e 's|@''REPLACE_STRERROR_R''@|$(REPLACE_STRERROR_R)|g' \ + -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \ + -e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + < $(srcdir)/string.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create <strings.h> when the system +# doesn't have one that works with the given compiler. +strings.h: strings.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(ARG_NONNULL_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_STRINGS_H''@|$(HAVE_STRINGS_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_STRINGS_H''@|$(NEXT_STRINGS_H)|g' \ + -e 's/@''GNULIB_FFS''@/$(GNULIB_FFS)/g' \ + -e 's|@''HAVE_FFS''@|$(HAVE_FFS)|g' \ + -e 's|@''HAVE_STRCASECMP''@|$(HAVE_STRCASECMP)|g' \ + -e 's|@''HAVE_DECL_STRNCASECMP''@|$(HAVE_DECL_STRNCASECMP)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/strings.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create <sys/stat.h> when the system +# has one that is incomplete. +sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \ + -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \ + -e 's|@''WINDOWS_STAT_TIMESPEC''@|$(WINDOWS_STAT_TIMESPEC)|g' \ + -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \ + -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \ + -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \ + -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \ + -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \ + -e 's/@''GNULIB_LSTAT''@/$(GNULIB_LSTAT)/g' \ + -e 's/@''GNULIB_MKDIRAT''@/$(GNULIB_MKDIRAT)/g' \ + -e 's/@''GNULIB_MKFIFO''@/$(GNULIB_MKFIFO)/g' \ + -e 's/@''GNULIB_MKFIFOAT''@/$(GNULIB_MKFIFOAT)/g' \ + -e 's/@''GNULIB_MKNOD''@/$(GNULIB_MKNOD)/g' \ + -e 's/@''GNULIB_MKNODAT''@/$(GNULIB_MKNODAT)/g' \ + -e 's/@''GNULIB_STAT''@/$(GNULIB_STAT)/g' \ + -e 's/@''GNULIB_UTIMENSAT''@/$(GNULIB_UTIMENSAT)/g' \ + -e 's/@''GNULIB_OVERRIDES_STRUCT_STAT''@/$(GNULIB_OVERRIDES_STRUCT_STAT)/g' \ + -e 's|@''HAVE_FCHMODAT''@|$(HAVE_FCHMODAT)|g' \ + -e 's|@''HAVE_FSTATAT''@|$(HAVE_FSTATAT)|g' \ + -e 's|@''HAVE_FUTIMENS''@|$(HAVE_FUTIMENS)|g' \ + -e 's|@''HAVE_LCHMOD''@|$(HAVE_LCHMOD)|g' \ + -e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \ + -e 's|@''HAVE_MKDIRAT''@|$(HAVE_MKDIRAT)|g' \ + -e 's|@''HAVE_MKFIFO''@|$(HAVE_MKFIFO)|g' \ + -e 's|@''HAVE_MKFIFOAT''@|$(HAVE_MKFIFOAT)|g' \ + -e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \ + -e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \ + -e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \ + -e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \ + -e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \ + -e 's|@''REPLACE_FUTIMENS''@|$(REPLACE_FUTIMENS)|g' \ + -e 's|@''REPLACE_LSTAT''@|$(REPLACE_LSTAT)|g' \ + -e 's|@''REPLACE_MKDIR''@|$(REPLACE_MKDIR)|g' \ + -e 's|@''REPLACE_MKFIFO''@|$(REPLACE_MKFIFO)|g' \ + -e 's|@''REPLACE_MKNOD''@|$(REPLACE_MKNOD)|g' \ + -e 's|@''REPLACE_STAT''@|$(REPLACE_STAT)|g' \ + -e 's|@''REPLACE_UTIMENSAT''@|$(REPLACE_UTIMENSAT)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/sys_stat.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create <sys/types.h> when the system +# doesn't have one that works with the given compiler. +sys/types.h: sys_types.in.h $(top_builddir)/config.status + $(AM_V_at)$(MKDIR_P) sys + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + -e 's|@''WINDOWS_STAT_INODES''@|$(WINDOWS_STAT_INODES)|g' \ + < $(srcdir)/sys_types.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create <sysexits.h> when the system +# doesn't have one that works with the given compiler. +@GL_GENERATE_SYSEXITS_H_TRUE@sysexits.h: sysexits.in.h $(top_builddir)/config.status +@GL_GENERATE_SYSEXITS_H_TRUE@ $(AM_V_GEN)rm -f $@-t $@ && \ +@GL_GENERATE_SYSEXITS_H_TRUE@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ +@GL_GENERATE_SYSEXITS_H_TRUE@ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ +@GL_GENERATE_SYSEXITS_H_TRUE@ -e 's|@''HAVE_SYSEXITS_H''@|$(HAVE_SYSEXITS_H)|g' \ +@GL_GENERATE_SYSEXITS_H_TRUE@ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ +@GL_GENERATE_SYSEXITS_H_TRUE@ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ +@GL_GENERATE_SYSEXITS_H_TRUE@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ +@GL_GENERATE_SYSEXITS_H_TRUE@ -e 's|@''NEXT_SYSEXITS_H''@|$(NEXT_SYSEXITS_H)|g' \ +@GL_GENERATE_SYSEXITS_H_TRUE@ < $(srcdir)/sysexits.in.h; \ +@GL_GENERATE_SYSEXITS_H_TRUE@ } > $@-t && \ +@GL_GENERATE_SYSEXITS_H_TRUE@ mv -f $@-t $@ +@GL_GENERATE_SYSEXITS_H_FALSE@sysexits.h: $(top_builddir)/config.status +@GL_GENERATE_SYSEXITS_H_FALSE@ rm -f $@ + +# We need the following in order to create <time.h> when the system +# doesn't have one that works with the given compiler. +time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_TIME_H''@|$(NEXT_TIME_H)|g' \ + -e 's/@''GNULIB_CTIME''@/$(GNULIB_CTIME)/g' \ + -e 's/@''GNULIB_LOCALTIME''@/$(GNULIB_LOCALTIME)/g' \ + -e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \ + -e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \ + -e 's/@''GNULIB_STRFTIME''@/$(GNULIB_STRFTIME)/g' \ + -e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \ + -e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \ + -e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \ + -e 's/@''GNULIB_TIME_RZ''@/$(GNULIB_TIME_RZ)/g' \ + -e 's/@''GNULIB_TZSET''@/$(GNULIB_TZSET)/g' \ + -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \ + -e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \ + -e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \ + -e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \ + -e 's|@''HAVE_TIMEZONE_T''@|$(HAVE_TIMEZONE_T)|g' \ + -e 's|@''HAVE_TZSET''@|$(HAVE_TZSET)|g' \ + -e 's|@''REPLACE_CTIME''@|$(REPLACE_CTIME)|g' \ + -e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \ + -e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \ + -e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \ + -e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \ + -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \ + -e 's|@''REPLACE_STRFTIME''@|$(REPLACE_STRFTIME)|g' \ + -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \ + -e 's|@''REPLACE_TZSET''@|$(REPLACE_TZSET)|g' \ + -e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e 's|@''UNISTD_H_DEFINES_STRUCT_TIMESPEC''@|$(UNISTD_H_DEFINES_STRUCT_TIMESPEC)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/time.in.h; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create an empty placeholder for +# <unistd.h> when the system doesn't have one. +unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''HAVE_UNISTD_H''@|$(HAVE_UNISTD_H)|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_UNISTD_H''@|$(NEXT_UNISTD_H)|g' \ + -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \ + -e 's/@''GNULIB_CHDIR''@/$(GNULIB_CHDIR)/g' \ + -e 's/@''GNULIB_CHOWN''@/$(GNULIB_CHOWN)/g' \ + -e 's/@''GNULIB_CLOSE''@/$(GNULIB_CLOSE)/g' \ + -e 's/@''GNULIB_DUP''@/$(GNULIB_DUP)/g' \ + -e 's/@''GNULIB_DUP2''@/$(GNULIB_DUP2)/g' \ + -e 's/@''GNULIB_DUP3''@/$(GNULIB_DUP3)/g' \ + -e 's/@''GNULIB_ENVIRON''@/$(GNULIB_ENVIRON)/g' \ + -e 's/@''GNULIB_EUIDACCESS''@/$(GNULIB_EUIDACCESS)/g' \ + -e 's/@''GNULIB_FACCESSAT''@/$(GNULIB_FACCESSAT)/g' \ + -e 's/@''GNULIB_FCHDIR''@/$(GNULIB_FCHDIR)/g' \ + -e 's/@''GNULIB_FCHOWNAT''@/$(GNULIB_FCHOWNAT)/g' \ + -e 's/@''GNULIB_FDATASYNC''@/$(GNULIB_FDATASYNC)/g' \ + -e 's/@''GNULIB_FSYNC''@/$(GNULIB_FSYNC)/g' \ + -e 's/@''GNULIB_FTRUNCATE''@/$(GNULIB_FTRUNCATE)/g' \ + -e 's/@''GNULIB_GETCWD''@/$(GNULIB_GETCWD)/g' \ + -e 's/@''GNULIB_GETDOMAINNAME''@/$(GNULIB_GETDOMAINNAME)/g' \ + -e 's/@''GNULIB_GETDTABLESIZE''@/$(GNULIB_GETDTABLESIZE)/g' \ + -e 's/@''GNULIB_GETGROUPS''@/$(GNULIB_GETGROUPS)/g' \ + -e 's/@''GNULIB_GETHOSTNAME''@/$(GNULIB_GETHOSTNAME)/g' \ + -e 's/@''GNULIB_GETLOGIN''@/$(GNULIB_GETLOGIN)/g' \ + -e 's/@''GNULIB_GETLOGIN_R''@/$(GNULIB_GETLOGIN_R)/g' \ + -e 's/@''GNULIB_GETPAGESIZE''@/$(GNULIB_GETPAGESIZE)/g' \ + -e 's/@''GNULIB_GETPASS''@/$(GNULIB_GETPASS)/g' \ + -e 's/@''GNULIB_GETUSERSHELL''@/$(GNULIB_GETUSERSHELL)/g' \ + -e 's/@''GNULIB_GROUP_MEMBER''@/$(GNULIB_GROUP_MEMBER)/g' \ + -e 's/@''GNULIB_ISATTY''@/$(GNULIB_ISATTY)/g' \ + -e 's/@''GNULIB_LCHOWN''@/$(GNULIB_LCHOWN)/g' \ + -e 's/@''GNULIB_LINK''@/$(GNULIB_LINK)/g' \ + -e 's/@''GNULIB_LINKAT''@/$(GNULIB_LINKAT)/g' \ + -e 's/@''GNULIB_LSEEK''@/$(GNULIB_LSEEK)/g' \ + -e 's/@''GNULIB_PIPE''@/$(GNULIB_PIPE)/g' \ + -e 's/@''GNULIB_PIPE2''@/$(GNULIB_PIPE2)/g' \ + -e 's/@''GNULIB_PREAD''@/$(GNULIB_PREAD)/g' \ + -e 's/@''GNULIB_PWRITE''@/$(GNULIB_PWRITE)/g' \ + -e 's/@''GNULIB_READ''@/$(GNULIB_READ)/g' \ + -e 's/@''GNULIB_READLINK''@/$(GNULIB_READLINK)/g' \ + -e 's/@''GNULIB_READLINKAT''@/$(GNULIB_READLINKAT)/g' \ + -e 's/@''GNULIB_RMDIR''@/$(GNULIB_RMDIR)/g' \ + -e 's/@''GNULIB_SETHOSTNAME''@/$(GNULIB_SETHOSTNAME)/g' \ + -e 's/@''GNULIB_SLEEP''@/$(GNULIB_SLEEP)/g' \ + -e 's/@''GNULIB_SYMLINK''@/$(GNULIB_SYMLINK)/g' \ + -e 's/@''GNULIB_SYMLINKAT''@/$(GNULIB_SYMLINKAT)/g' \ + -e 's/@''GNULIB_TRUNCATE''@/$(GNULIB_TRUNCATE)/g' \ + -e 's/@''GNULIB_TTYNAME_R''@/$(GNULIB_TTYNAME_R)/g' \ + -e 's/@''GNULIB_UNISTD_H_GETOPT''@/0$(GNULIB_GL_UNISTD_H_GETOPT)/g' \ + -e 's/@''GNULIB_UNISTD_H_NONBLOCKING''@/$(GNULIB_UNISTD_H_NONBLOCKING)/g' \ + -e 's/@''GNULIB_UNISTD_H_SIGPIPE''@/$(GNULIB_UNISTD_H_SIGPIPE)/g' \ + -e 's/@''GNULIB_UNLINK''@/$(GNULIB_UNLINK)/g' \ + -e 's/@''GNULIB_UNLINKAT''@/$(GNULIB_UNLINKAT)/g' \ + -e 's/@''GNULIB_USLEEP''@/$(GNULIB_USLEEP)/g' \ + -e 's/@''GNULIB_WRITE''@/$(GNULIB_WRITE)/g' \ + < $(srcdir)/unistd.in.h | \ + sed -e 's|@''HAVE_CHOWN''@|$(HAVE_CHOWN)|g' \ + -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \ + -e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \ + -e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \ + -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \ + -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \ + -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \ + -e 's|@''HAVE_FDATASYNC''@|$(HAVE_FDATASYNC)|g' \ + -e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \ + -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \ + -e 's|@''HAVE_GETDTABLESIZE''@|$(HAVE_GETDTABLESIZE)|g' \ + -e 's|@''HAVE_GETGROUPS''@|$(HAVE_GETGROUPS)|g' \ + -e 's|@''HAVE_GETHOSTNAME''@|$(HAVE_GETHOSTNAME)|g' \ + -e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \ + -e 's|@''HAVE_GETPASS''@|$(HAVE_GETPASS)|g' \ + -e 's|@''HAVE_GROUP_MEMBER''@|$(HAVE_GROUP_MEMBER)|g' \ + -e 's|@''HAVE_LCHOWN''@|$(HAVE_LCHOWN)|g' \ + -e 's|@''HAVE_LINK''@|$(HAVE_LINK)|g' \ + -e 's|@''HAVE_LINKAT''@|$(HAVE_LINKAT)|g' \ + -e 's|@''HAVE_PIPE''@|$(HAVE_PIPE)|g' \ + -e 's|@''HAVE_PIPE2''@|$(HAVE_PIPE2)|g' \ + -e 's|@''HAVE_PREAD''@|$(HAVE_PREAD)|g' \ + -e 's|@''HAVE_PWRITE''@|$(HAVE_PWRITE)|g' \ + -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \ + -e 's|@''HAVE_READLINKAT''@|$(HAVE_READLINKAT)|g' \ + -e 's|@''HAVE_SETHOSTNAME''@|$(HAVE_SETHOSTNAME)|g' \ + -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \ + -e 's|@''HAVE_SYMLINK''@|$(HAVE_SYMLINK)|g' \ + -e 's|@''HAVE_SYMLINKAT''@|$(HAVE_SYMLINKAT)|g' \ + -e 's|@''HAVE_UNLINKAT''@|$(HAVE_UNLINKAT)|g' \ + -e 's|@''HAVE_USLEEP''@|$(HAVE_USLEEP)|g' \ + -e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \ + -e 's|@''HAVE_DECL_FCHDIR''@|$(HAVE_DECL_FCHDIR)|g' \ + -e 's|@''HAVE_DECL_FDATASYNC''@|$(HAVE_DECL_FDATASYNC)|g' \ + -e 's|@''HAVE_DECL_GETDOMAINNAME''@|$(HAVE_DECL_GETDOMAINNAME)|g' \ + -e 's|@''HAVE_DECL_GETLOGIN''@|$(HAVE_DECL_GETLOGIN)|g' \ + -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \ + -e 's|@''HAVE_DECL_GETPAGESIZE''@|$(HAVE_DECL_GETPAGESIZE)|g' \ + -e 's|@''HAVE_DECL_GETUSERSHELL''@|$(HAVE_DECL_GETUSERSHELL)|g' \ + -e 's|@''HAVE_DECL_SETHOSTNAME''@|$(HAVE_DECL_SETHOSTNAME)|g' \ + -e 's|@''HAVE_DECL_TRUNCATE''@|$(HAVE_DECL_TRUNCATE)|g' \ + -e 's|@''HAVE_DECL_TTYNAME_R''@|$(HAVE_DECL_TTYNAME_R)|g' \ + -e 's|@''HAVE_OS_H''@|$(HAVE_OS_H)|g' \ + -e 's|@''HAVE_SYS_PARAM_H''@|$(HAVE_SYS_PARAM_H)|g' \ + | \ + sed -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \ + -e 's|@''REPLACE_CLOSE''@|$(REPLACE_CLOSE)|g' \ + -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \ + -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \ + -e 's|@''REPLACE_FACCESSAT''@|$(REPLACE_FACCESSAT)|g' \ + -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \ + -e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \ + -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \ + -e 's|@''REPLACE_GETDOMAINNAME''@|$(REPLACE_GETDOMAINNAME)|g' \ + -e 's|@''REPLACE_GETDTABLESIZE''@|$(REPLACE_GETDTABLESIZE)|g' \ + -e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \ + -e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \ + -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \ + -e 's|@''REPLACE_GETPASS''@|$(REPLACE_GETPASS)|g' \ + -e 's|@''REPLACE_ISATTY''@|$(REPLACE_ISATTY)|g' \ + -e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \ + -e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \ + -e 's|@''REPLACE_LINKAT''@|$(REPLACE_LINKAT)|g' \ + -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \ + -e 's|@''REPLACE_PREAD''@|$(REPLACE_PREAD)|g' \ + -e 's|@''REPLACE_PWRITE''@|$(REPLACE_PWRITE)|g' \ + -e 's|@''REPLACE_READ''@|$(REPLACE_READ)|g' \ + -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \ + -e 's|@''REPLACE_READLINKAT''@|$(REPLACE_READLINKAT)|g' \ + -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \ + -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \ + -e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \ + -e 's|@''REPLACE_SYMLINKAT''@|$(REPLACE_SYMLINKAT)|g' \ + -e 's|@''REPLACE_TRUNCATE''@|$(REPLACE_TRUNCATE)|g' \ + -e 's|@''REPLACE_TTYNAME_R''@|$(REPLACE_TTYNAME_R)|g' \ + -e 's|@''REPLACE_UNLINK''@|$(REPLACE_UNLINK)|g' \ + -e 's|@''REPLACE_UNLINKAT''@|$(REPLACE_UNLINKAT)|g' \ + -e 's|@''REPLACE_USLEEP''@|$(REPLACE_USLEEP)|g' \ + -e 's|@''REPLACE_WRITE''@|$(REPLACE_WRITE)|g' \ + -e 's|@''UNISTD_H_HAVE_WINSOCK2_H''@|$(UNISTD_H_HAVE_WINSOCK2_H)|g' \ + -e 's|@''UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS''@|$(UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ + +unitypes.h: unitypes.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/unitypes.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +uniwidth.h: uniwidth.in.h + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + cat $(srcdir)/uniwidth.in.h; \ + } > $@-t && \ + mv -f $@-t $@ + +# We need the following in order to create <wchar.h> when the system +# version does not work standalone. +wchar.h: wchar.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''HAVE_FEATURES_H''@|$(HAVE_FEATURES_H)|g' \ + -e 's|@''NEXT_WCHAR_H''@|$(NEXT_WCHAR_H)|g' \ + -e 's|@''HAVE_WCHAR_H''@|$(HAVE_WCHAR_H)|g' \ + -e 's/@''HAVE_CRTDEFS_H''@/$(HAVE_CRTDEFS_H)/g' \ + -e 's/@''GNULIB_OVERRIDES_WINT_T''@/$(GNULIB_OVERRIDES_WINT_T)/g' \ + -e 's/@''GNULIB_BTOWC''@/$(GNULIB_BTOWC)/g' \ + -e 's/@''GNULIB_WCTOB''@/$(GNULIB_WCTOB)/g' \ + -e 's/@''GNULIB_MBSINIT''@/$(GNULIB_MBSINIT)/g' \ + -e 's/@''GNULIB_MBRTOWC''@/$(GNULIB_MBRTOWC)/g' \ + -e 's/@''GNULIB_MBRLEN''@/$(GNULIB_MBRLEN)/g' \ + -e 's/@''GNULIB_MBSRTOWCS''@/$(GNULIB_MBSRTOWCS)/g' \ + -e 's/@''GNULIB_MBSNRTOWCS''@/$(GNULIB_MBSNRTOWCS)/g' \ + -e 's/@''GNULIB_WCRTOMB''@/$(GNULIB_WCRTOMB)/g' \ + -e 's/@''GNULIB_WCSRTOMBS''@/$(GNULIB_WCSRTOMBS)/g' \ + -e 's/@''GNULIB_WCSNRTOMBS''@/$(GNULIB_WCSNRTOMBS)/g' \ + -e 's/@''GNULIB_WCWIDTH''@/$(GNULIB_WCWIDTH)/g' \ + -e 's/@''GNULIB_WMEMCHR''@/$(GNULIB_WMEMCHR)/g' \ + -e 's/@''GNULIB_WMEMCMP''@/$(GNULIB_WMEMCMP)/g' \ + -e 's/@''GNULIB_WMEMCPY''@/$(GNULIB_WMEMCPY)/g' \ + -e 's/@''GNULIB_WMEMMOVE''@/$(GNULIB_WMEMMOVE)/g' \ + -e 's/@''GNULIB_WMEMSET''@/$(GNULIB_WMEMSET)/g' \ + -e 's/@''GNULIB_WCSLEN''@/$(GNULIB_WCSLEN)/g' \ + -e 's/@''GNULIB_WCSNLEN''@/$(GNULIB_WCSNLEN)/g' \ + -e 's/@''GNULIB_WCSCPY''@/$(GNULIB_WCSCPY)/g' \ + -e 's/@''GNULIB_WCPCPY''@/$(GNULIB_WCPCPY)/g' \ + -e 's/@''GNULIB_WCSNCPY''@/$(GNULIB_WCSNCPY)/g' \ + -e 's/@''GNULIB_WCPNCPY''@/$(GNULIB_WCPNCPY)/g' \ + -e 's/@''GNULIB_WCSCAT''@/$(GNULIB_WCSCAT)/g' \ + -e 's/@''GNULIB_WCSNCAT''@/$(GNULIB_WCSNCAT)/g' \ + -e 's/@''GNULIB_WCSCMP''@/$(GNULIB_WCSCMP)/g' \ + -e 's/@''GNULIB_WCSNCMP''@/$(GNULIB_WCSNCMP)/g' \ + -e 's/@''GNULIB_WCSCASECMP''@/$(GNULIB_WCSCASECMP)/g' \ + -e 's/@''GNULIB_WCSNCASECMP''@/$(GNULIB_WCSNCASECMP)/g' \ + -e 's/@''GNULIB_WCSCOLL''@/$(GNULIB_WCSCOLL)/g' \ + -e 's/@''GNULIB_WCSXFRM''@/$(GNULIB_WCSXFRM)/g' \ + -e 's/@''GNULIB_WCSDUP''@/$(GNULIB_WCSDUP)/g' \ + -e 's/@''GNULIB_WCSCHR''@/$(GNULIB_WCSCHR)/g' \ + -e 's/@''GNULIB_WCSRCHR''@/$(GNULIB_WCSRCHR)/g' \ + -e 's/@''GNULIB_WCSCSPN''@/$(GNULIB_WCSCSPN)/g' \ + -e 's/@''GNULIB_WCSSPN''@/$(GNULIB_WCSSPN)/g' \ + -e 's/@''GNULIB_WCSPBRK''@/$(GNULIB_WCSPBRK)/g' \ + -e 's/@''GNULIB_WCSSTR''@/$(GNULIB_WCSSTR)/g' \ + -e 's/@''GNULIB_WCSTOK''@/$(GNULIB_WCSTOK)/g' \ + -e 's/@''GNULIB_WCSWIDTH''@/$(GNULIB_WCSWIDTH)/g' \ + -e 's/@''GNULIB_WCSFTIME''@/$(GNULIB_WCSFTIME)/g' \ + < $(srcdir)/wchar.in.h | \ + sed -e 's|@''HAVE_WINT_T''@|$(HAVE_WINT_T)|g' \ + -e 's|@''HAVE_BTOWC''@|$(HAVE_BTOWC)|g' \ + -e 's|@''HAVE_MBSINIT''@|$(HAVE_MBSINIT)|g' \ + -e 's|@''HAVE_MBRTOWC''@|$(HAVE_MBRTOWC)|g' \ + -e 's|@''HAVE_MBRLEN''@|$(HAVE_MBRLEN)|g' \ + -e 's|@''HAVE_MBSRTOWCS''@|$(HAVE_MBSRTOWCS)|g' \ + -e 's|@''HAVE_MBSNRTOWCS''@|$(HAVE_MBSNRTOWCS)|g' \ + -e 's|@''HAVE_WCRTOMB''@|$(HAVE_WCRTOMB)|g' \ + -e 's|@''HAVE_WCSRTOMBS''@|$(HAVE_WCSRTOMBS)|g' \ + -e 's|@''HAVE_WCSNRTOMBS''@|$(HAVE_WCSNRTOMBS)|g' \ + -e 's|@''HAVE_WMEMCHR''@|$(HAVE_WMEMCHR)|g' \ + -e 's|@''HAVE_WMEMCMP''@|$(HAVE_WMEMCMP)|g' \ + -e 's|@''HAVE_WMEMCPY''@|$(HAVE_WMEMCPY)|g' \ + -e 's|@''HAVE_WMEMMOVE''@|$(HAVE_WMEMMOVE)|g' \ + -e 's|@''HAVE_WMEMSET''@|$(HAVE_WMEMSET)|g' \ + -e 's|@''HAVE_WCSLEN''@|$(HAVE_WCSLEN)|g' \ + -e 's|@''HAVE_WCSNLEN''@|$(HAVE_WCSNLEN)|g' \ + -e 's|@''HAVE_WCSCPY''@|$(HAVE_WCSCPY)|g' \ + -e 's|@''HAVE_WCPCPY''@|$(HAVE_WCPCPY)|g' \ + -e 's|@''HAVE_WCSNCPY''@|$(HAVE_WCSNCPY)|g' \ + -e 's|@''HAVE_WCPNCPY''@|$(HAVE_WCPNCPY)|g' \ + -e 's|@''HAVE_WCSCAT''@|$(HAVE_WCSCAT)|g' \ + -e 's|@''HAVE_WCSNCAT''@|$(HAVE_WCSNCAT)|g' \ + -e 's|@''HAVE_WCSCMP''@|$(HAVE_WCSCMP)|g' \ + -e 's|@''HAVE_WCSNCMP''@|$(HAVE_WCSNCMP)|g' \ + -e 's|@''HAVE_WCSCASECMP''@|$(HAVE_WCSCASECMP)|g' \ + -e 's|@''HAVE_WCSNCASECMP''@|$(HAVE_WCSNCASECMP)|g' \ + -e 's|@''HAVE_WCSCOLL''@|$(HAVE_WCSCOLL)|g' \ + -e 's|@''HAVE_WCSXFRM''@|$(HAVE_WCSXFRM)|g' \ + -e 's|@''HAVE_WCSDUP''@|$(HAVE_WCSDUP)|g' \ + -e 's|@''HAVE_WCSCHR''@|$(HAVE_WCSCHR)|g' \ + -e 's|@''HAVE_WCSRCHR''@|$(HAVE_WCSRCHR)|g' \ + -e 's|@''HAVE_WCSCSPN''@|$(HAVE_WCSCSPN)|g' \ + -e 's|@''HAVE_WCSSPN''@|$(HAVE_WCSSPN)|g' \ + -e 's|@''HAVE_WCSPBRK''@|$(HAVE_WCSPBRK)|g' \ + -e 's|@''HAVE_WCSSTR''@|$(HAVE_WCSSTR)|g' \ + -e 's|@''HAVE_WCSTOK''@|$(HAVE_WCSTOK)|g' \ + -e 's|@''HAVE_WCSWIDTH''@|$(HAVE_WCSWIDTH)|g' \ + -e 's|@''HAVE_WCSFTIME''@|$(HAVE_WCSFTIME)|g' \ + -e 's|@''HAVE_DECL_WCTOB''@|$(HAVE_DECL_WCTOB)|g' \ + -e 's|@''HAVE_DECL_WCWIDTH''@|$(HAVE_DECL_WCWIDTH)|g' \ + | \ + sed -e 's|@''REPLACE_MBSTATE_T''@|$(REPLACE_MBSTATE_T)|g' \ + -e 's|@''REPLACE_BTOWC''@|$(REPLACE_BTOWC)|g' \ + -e 's|@''REPLACE_WCTOB''@|$(REPLACE_WCTOB)|g' \ + -e 's|@''REPLACE_MBSINIT''@|$(REPLACE_MBSINIT)|g' \ + -e 's|@''REPLACE_MBRTOWC''@|$(REPLACE_MBRTOWC)|g' \ + -e 's|@''REPLACE_MBRLEN''@|$(REPLACE_MBRLEN)|g' \ + -e 's|@''REPLACE_MBSRTOWCS''@|$(REPLACE_MBSRTOWCS)|g' \ + -e 's|@''REPLACE_MBSNRTOWCS''@|$(REPLACE_MBSNRTOWCS)|g' \ + -e 's|@''REPLACE_WCRTOMB''@|$(REPLACE_WCRTOMB)|g' \ + -e 's|@''REPLACE_WCSRTOMBS''@|$(REPLACE_WCSRTOMBS)|g' \ + -e 's|@''REPLACE_WCSNRTOMBS''@|$(REPLACE_WCSNRTOMBS)|g' \ + -e 's|@''REPLACE_WCWIDTH''@|$(REPLACE_WCWIDTH)|g' \ + -e 's|@''REPLACE_WCSWIDTH''@|$(REPLACE_WCSWIDTH)|g' \ + -e 's|@''REPLACE_WCSFTIME''@|$(REPLACE_WCSFTIME)|g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ + } > $@-t && \ + mv $@-t $@ + +# We need the following in order to create <wctype.h> when the system +# doesn't have one that works with the given compiler. +wctype.h: wctype.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ + sed -e 's|@''GUARD_PREFIX''@|GL|g' \ + -e 's/@''HAVE_WCTYPE_H''@/$(HAVE_WCTYPE_H)/g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''NEXT_WCTYPE_H''@|$(NEXT_WCTYPE_H)|g' \ + -e 's/@''HAVE_CRTDEFS_H''@/$(HAVE_CRTDEFS_H)/g' \ + -e 's/@''GNULIB_OVERRIDES_WINT_T''@/$(GNULIB_OVERRIDES_WINT_T)/g' \ + -e 's/@''GNULIB_ISWBLANK''@/$(GNULIB_ISWBLANK)/g' \ + -e 's/@''GNULIB_WCTYPE''@/$(GNULIB_WCTYPE)/g' \ + -e 's/@''GNULIB_ISWCTYPE''@/$(GNULIB_ISWCTYPE)/g' \ + -e 's/@''GNULIB_WCTRANS''@/$(GNULIB_WCTRANS)/g' \ + -e 's/@''GNULIB_TOWCTRANS''@/$(GNULIB_TOWCTRANS)/g' \ + -e 's/@''HAVE_ISWBLANK''@/$(HAVE_ISWBLANK)/g' \ + -e 's/@''HAVE_ISWCNTRL''@/$(HAVE_ISWCNTRL)/g' \ + -e 's/@''HAVE_WCTYPE_T''@/$(HAVE_WCTYPE_T)/g' \ + -e 's/@''HAVE_WCTRANS_T''@/$(HAVE_WCTRANS_T)/g' \ + -e 's/@''HAVE_WINT_T''@/$(HAVE_WINT_T)/g' \ + -e 's/@''REPLACE_ISWBLANK''@/$(REPLACE_ISWBLANK)/g' \ + -e 's/@''REPLACE_ISWCNTRL''@/$(REPLACE_ISWCNTRL)/g' \ + -e 's/@''REPLACE_TOWLOWER''@/$(REPLACE_TOWLOWER)/g' \ + -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ + -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ + < $(srcdir)/wctype.in.h; \ + } > $@-t && \ + mv $@-t $@ + +mostlyclean-local: mostlyclean-generic + @for dir in '' $(MOSTLYCLEANDIRS); do \ + if test -n "$$dir" && test -d $$dir; then \ + echo "rmdir $$dir"; rmdir $$dir; \ + fi; \ + done; \ + : + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/grub-core/lib/gnulib/_Noreturn.h b/grub-core/lib/gnulib/_Noreturn.h new file mode 100644 index 0000000..94fdfaf --- /dev/null +++ b/grub-core/lib/gnulib/_Noreturn.h @@ -0,0 +1,14 @@ +#ifndef _Noreturn +# if 201103 <= (defined __cplusplus ? __cplusplus : 0) +# define _Noreturn [[noreturn]] +# elif (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \ + || 4 < __GNUC__ + (7 <= __GNUC_MINOR__)) + /* _Noreturn works as-is. */ +# elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C +# define _Noreturn __attribute__ ((__noreturn__)) +# elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0) +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn +# endif +#endif diff --git a/grub-core/lib/gnulib/alloca.c b/grub-core/lib/gnulib/alloca.c new file mode 100644 index 0000000..ee0f018 --- /dev/null +++ b/grub-core/lib/gnulib/alloca.c @@ -0,0 +1,478 @@ +/* alloca.c -- allocate automatically reclaimed memory + (Mostly) portable public-domain implementation -- D A Gwyn + + This implementation of the PWB library alloca function, + which is used to allocate space off the run-time stack so + that it is automatically reclaimed upon procedure exit, + was inspired by discussions with J. Q. Johnson of Cornell. + J.Otto Tennant <jot@cray.com> contributed the Cray support. + + There are some preprocessor constants that can + be defined when compiling for your specific system, for + improved efficiency; however, the defaults should be okay. + + The general concept of this implementation is to keep + track of all alloca-allocated blocks, and reclaim any + that are found to be deeper in the stack than the current + invocation. This heuristic does not reclaim storage as + soon as it becomes invalid, but it will do so eventually. + + As a special case, alloca(0) reclaims storage without + allocating any. It is a good idea to use alloca(0) in + your main control loop, etc. to force garbage collection. */ + +#include <config.h> + +#include <alloca.h> + +#include <string.h> +#include <stdlib.h> + +#ifdef emacs +# include "lisp.h" +# include "blockinput.h" +# ifdef EMACS_FREE +# undef free +# define free EMACS_FREE +# endif +#else +# define memory_full() abort () +#endif + +/* If compiling with GCC 2, this file's not needed. */ +#if !defined (__GNUC__) || __GNUC__ < 2 + +/* If someone has defined alloca as a macro, + there must be some other way alloca is supposed to work. */ +# ifndef alloca + +# ifdef emacs +# ifdef static +/* actually, only want this if static is defined as "" + -- this is for usg, in which emacs must undefine static + in order to make unexec workable + */ +# ifndef STACK_DIRECTION +you +lose +-- must know STACK_DIRECTION at compile-time +/* Using #error here is not wise since this file should work for + old and obscure compilers. */ +# endif /* STACK_DIRECTION undefined */ +# endif /* static */ +# endif /* emacs */ + +/* If your stack is a linked list of frames, you have to + provide an "address metric" ADDRESS_FUNCTION macro. */ + +# if defined (CRAY) && defined (CRAY_STACKSEG_END) +long i00afunc (); +# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) +# else +# define ADDRESS_FUNCTION(arg) &(arg) +# endif + +/* Define STACK_DIRECTION if you know the direction of stack + growth for your system; otherwise it will be automatically + deduced at run-time. + + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ + +# ifndef STACK_DIRECTION +# define STACK_DIRECTION 0 /* Direction unknown. */ +# endif + +# if STACK_DIRECTION != 0 + +# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ + +# else /* STACK_DIRECTION == 0; need run-time code. */ + +static int stack_dir; /* 1 or -1 once known. */ +# define STACK_DIR stack_dir + +static int +find_stack_direction (int *addr, int depth) +{ + int dir, dummy = 0; + if (! addr) + addr = &dummy; + *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; + dir = depth ? find_stack_direction (addr, depth - 1) : 0; + return dir + dummy; +} + +# endif /* STACK_DIRECTION == 0 */ + +/* An "alloca header" is used to: + (a) chain together all alloca'ed blocks; + (b) keep track of stack depth. + + It is very important that sizeof(header) agree with malloc + alignment chunk size. The following default should work okay. */ + +# ifndef ALIGN_SIZE +# define ALIGN_SIZE sizeof(double) +# endif + +typedef union hdr +{ + char align[ALIGN_SIZE]; /* To force sizeof(header). */ + struct + { + union hdr *next; /* For chaining headers. */ + char *deep; /* For stack depth measure. */ + } h; +} header; + +static header *last_alloca_header = NULL; /* -> last alloca header. */ + +/* Return a pointer to at least SIZE bytes of storage, + which will be automatically reclaimed upon exit from + the procedure that called alloca. Originally, this space + was supposed to be taken from the current stack frame of the + caller, but that method cannot be made to work for some + implementations of C, for example under Gould's UTX/32. */ + +void * +alloca (size_t size) +{ + auto char probe; /* Probes stack depth: */ + register char *depth = ADDRESS_FUNCTION (probe); + +# if STACK_DIRECTION == 0 + if (STACK_DIR == 0) /* Unknown growth direction. */ + STACK_DIR = find_stack_direction (NULL, (size & 1) + 20); +# endif + + /* Reclaim garbage, defined as all alloca'd storage that + was allocated from deeper in the stack than currently. */ + + { + register header *hp; /* Traverses linked list. */ + +# ifdef emacs + BLOCK_INPUT; +# endif + + for (hp = last_alloca_header; hp != NULL;) + if ((STACK_DIR > 0 && hp->h.deep > depth) + || (STACK_DIR < 0 && hp->h.deep < depth)) + { + register header *np = hp->h.next; + + free (hp); /* Collect garbage. */ + + hp = np; /* -> next header. */ + } + else + break; /* Rest are not deeper. */ + + last_alloca_header = hp; /* -> last valid storage. */ + +# ifdef emacs + UNBLOCK_INPUT; +# endif + } + + if (size == 0) + return NULL; /* No allocation required. */ + + /* Allocate combined header + user data storage. */ + + { + /* Address of header. */ + register header *new; + + size_t combined_size = sizeof (header) + size; + if (combined_size < sizeof (header)) + memory_full (); + + new = malloc (combined_size); + + if (! new) + memory_full (); + + new->h.next = last_alloca_header; + new->h.deep = depth; + + last_alloca_header = new; + + /* User storage begins just after header. */ + + return (void *) (new + 1); + } +} + +# if defined (CRAY) && defined (CRAY_STACKSEG_END) + +# ifdef DEBUG_I00AFUNC +# include <stdio.h> +# endif + +# ifndef CRAY_STACK +# define CRAY_STACK +# ifndef CRAY2 +/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ +struct stack_control_header + { + long shgrow:32; /* Number of times stack has grown. */ + long shaseg:32; /* Size of increments to stack. */ + long shhwm:32; /* High water mark of stack. */ + long shsize:32; /* Current size of stack (all segments). */ + }; + +/* The stack segment linkage control information occurs at + the high-address end of a stack segment. (The stack + grows from low addresses to high addresses.) The initial + part of the stack segment linkage control information is + 0200 (octal) words. This provides for register storage + for the routine which overflows the stack. */ + +struct stack_segment_linkage + { + long ss[0200]; /* 0200 overflow words. */ + long sssize:32; /* Number of words in this segment. */ + long ssbase:32; /* Offset to stack base. */ + long:32; + long sspseg:32; /* Offset to linkage control of previous + segment of stack. */ + long:32; + long sstcpt:32; /* Pointer to task common address block. */ + long sscsnm; /* Private control structure number for + microtasking. */ + long ssusr1; /* Reserved for user. */ + long ssusr2; /* Reserved for user. */ + long sstpid; /* Process ID for pid based multi-tasking. */ + long ssgvup; /* Pointer to multitasking thread giveup. */ + long sscray[7]; /* Reserved for Cray Research. */ + long ssa0; + long ssa1; + long ssa2; + long ssa3; + long ssa4; + long ssa5; + long ssa6; + long ssa7; + long sss0; + long sss1; + long sss2; + long sss3; + long sss4; + long sss5; + long sss6; + long sss7; + }; + +# else /* CRAY2 */ +/* The following structure defines the vector of words + returned by the STKSTAT library routine. */ +struct stk_stat + { + long now; /* Current total stack size. */ + long maxc; /* Amount of contiguous space which would + be required to satisfy the maximum + stack demand to date. */ + long high_water; /* Stack high-water mark. */ + long overflows; /* Number of stack overflow ($STKOFEN) calls. */ + long hits; /* Number of internal buffer hits. */ + long extends; /* Number of block extensions. */ + long stko_mallocs; /* Block allocations by $STKOFEN. */ + long underflows; /* Number of stack underflow calls ($STKRETN). */ + long stko_free; /* Number of deallocations by $STKRETN. */ + long stkm_free; /* Number of deallocations by $STKMRET. */ + long segments; /* Current number of stack segments. */ + long maxs; /* Maximum number of stack segments so far. */ + long pad_size; /* Stack pad size. */ + long current_address; /* Current stack segment address. */ + long current_size; /* Current stack segment size. This + number is actually corrupted by STKSTAT to + include the fifteen word trailer area. */ + long initial_address; /* Address of initial segment. */ + long initial_size; /* Size of initial segment. */ + }; + +/* The following structure describes the data structure which trails + any stack segment. I think that the description in 'asdef' is + out of date. I only describe the parts that I am sure about. */ + +struct stk_trailer + { + long this_address; /* Address of this block. */ + long this_size; /* Size of this block (does not include + this trailer). */ + long unknown2; + long unknown3; + long link; /* Address of trailer block of previous + segment. */ + long unknown5; + long unknown6; + long unknown7; + long unknown8; + long unknown9; + long unknown10; + long unknown11; + long unknown12; + long unknown13; + long unknown14; + }; + +# endif /* CRAY2 */ +# endif /* not CRAY_STACK */ + +# ifdef CRAY2 +/* Determine a "stack measure" for an arbitrary ADDRESS. + I doubt that "lint" will like this much. */ + +static long +i00afunc (long *address) +{ + struct stk_stat status; + struct stk_trailer *trailer; + long *block, size; + long result = 0; + + /* We want to iterate through all of the segments. The first + step is to get the stack status structure. We could do this + more quickly and more directly, perhaps, by referencing the + $LM00 common block, but I know that this works. */ + + STKSTAT (&status); + + /* Set up the iteration. */ + + trailer = (struct stk_trailer *) (status.current_address + + status.current_size + - 15); + + /* There must be at least one stack segment. Therefore it is + a fatal error if "trailer" is null. */ + + if (trailer == 0) + abort (); + + /* Discard segments that do not contain our argument address. */ + + while (trailer != 0) + { + block = (long *) trailer->this_address; + size = trailer->this_size; + if (block == 0 || size == 0) + abort (); + trailer = (struct stk_trailer *) trailer->link; + if ((block <= address) && (address < (block + size))) + break; + } + + /* Set the result to the offset in this segment and add the sizes + of all predecessor segments. */ + + result = address - block; + + if (trailer == 0) + { + return result; + } + + do + { + if (trailer->this_size <= 0) + abort (); + result += trailer->this_size; + trailer = (struct stk_trailer *) trailer->link; + } + while (trailer != 0); + + /* We are done. Note that if you present a bogus address (one + not in any segment), you will get a different number back, formed + from subtracting the address of the first block. This is probably + not what you want. */ + + return (result); +} + +# else /* not CRAY2 */ +/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. + Determine the number of the cell within the stack, + given the address of the cell. The purpose of this + routine is to linearize, in some sense, stack addresses + for alloca. */ + +static long +i00afunc (long address) +{ + long stkl = 0; + + long size, pseg, this_segment, stack; + long result = 0; + + struct stack_segment_linkage *ssptr; + + /* Register B67 contains the address of the end of the + current stack segment. If you (as a subprogram) store + your registers on the stack and find that you are past + the contents of B67, you have overflowed the segment. + + B67 also points to the stack segment linkage control + area, which is what we are really interested in. */ + + stkl = CRAY_STACKSEG_END (); + ssptr = (struct stack_segment_linkage *) stkl; + + /* If one subtracts 'size' from the end of the segment, + one has the address of the first word of the segment. + + If this is not the first segment, 'pseg' will be + nonzero. */ + + pseg = ssptr->sspseg; + size = ssptr->sssize; + + this_segment = stkl - size; + + /* It is possible that calling this routine itself caused + a stack overflow. Discard stack segments which do not + contain the target address. */ + + while (!(this_segment <= address && address <= stkl)) + { +# ifdef DEBUG_I00AFUNC + fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); +# endif + if (pseg == 0) + break; + stkl = stkl - pseg; + ssptr = (struct stack_segment_linkage *) stkl; + size = ssptr->sssize; + pseg = ssptr->sspseg; + this_segment = stkl - size; + } + + result = address - this_segment; + + /* If you subtract pseg from the current end of the stack, + you get the address of the previous stack segment's end. + This seems a little convoluted to me, but I'll bet you save + a cycle somewhere. */ + + while (pseg != 0) + { +# ifdef DEBUG_I00AFUNC + fprintf (stderr, "%011o %011o\n", pseg, size); +# endif + stkl = stkl - pseg; + ssptr = (struct stack_segment_linkage *) stkl; + size = ssptr->sssize; + pseg = ssptr->sspseg; + result += size; + } + return (result); +} + +# endif /* not CRAY2 */ +# endif /* CRAY */ + +# endif /* no alloca */ +#endif /* not GCC 2 */ diff --git a/grub-core/lib/gnulib/alloca.in.h b/grub-core/lib/gnulib/alloca.in.h new file mode 100644 index 0000000..ec81e11 --- /dev/null +++ b/grub-core/lib/gnulib/alloca.in.h @@ -0,0 +1,65 @@ +/* Memory allocation on the stack. + + Copyright (C) 1995, 1999, 2001-2004, 2006-2019 Free Software Foundation, + Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, see + <https://www.gnu.org/licenses/>. + */ + +/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H + means there is a real alloca function. */ +#ifndef _GL_ALLOCA_H +#define _GL_ALLOCA_H + +/* alloca (N) returns a pointer to N bytes of memory + allocated on the stack, which will last until the function returns. + Use of alloca should be avoided: + - inside arguments of function calls - undefined behaviour, + - in inline functions - the allocation may actually last until the + calling function returns, + - for huge N (say, N >= 65536) - you never know how large (or small) + the stack is, and when the stack cannot fulfill the memory allocation + request, the program just crashes. + */ + +#ifndef alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include <malloc.h> +# define alloca _alloca +# elif defined __DECC && defined __VMS +# define alloca __ALLOCA +# elif defined __TANDEM && defined _TNS_E_TARGET +# ifdef __cplusplus +extern "C" +# endif +void *_alloca (unsigned short); +# pragma intrinsic (_alloca) +# define alloca _alloca +# elif defined __MVS__ +# include <stdlib.h> +# else +# include <stddef.h> +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +#endif /* _GL_ALLOCA_H */ diff --git a/grub-core/lib/gnulib/arg-nonnull.h b/grub-core/lib/gnulib/arg-nonnull.h new file mode 100644 index 0000000..ad8c26c --- /dev/null +++ b/grub-core/lib/gnulib/arg-nonnull.h @@ -0,0 +1,26 @@ +/* A C macro for declaring that specific arguments must not be NULL. + Copyright (C) 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools + that the values passed as arguments n, ..., m must be non-NULL pointers. + n = 1 stands for the first argument, n = 2 for the second argument etc. */ +#ifndef _GL_ARG_NONNULL +# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3 +# define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params)) +# else +# define _GL_ARG_NONNULL(params) +# endif +#endif diff --git a/grub-core/lib/gnulib/argp-ba.c b/grub-core/lib/gnulib/argp-ba.c new file mode 100644 index 0000000..fcf60c8 --- /dev/null +++ b/grub-core/lib/gnulib/argp-ba.c @@ -0,0 +1,34 @@ +/* Default definition for ARGP_PROGRAM_BUG_ADDRESS. + Copyright (C) 1996-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* If set by the user program, it should point to string that is the + bug-reporting address for the program. It will be printed by argp_help if + the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help + messages), embedded in a sentence that says something like "Report bugs to + ADDR." */ +const char *argp_program_bug_address +/* This variable should be zero-initialized. On most systems, putting it into + BSS is sufficient. Not so on Mac OS X 10.3 and 10.4, see + <https://lists.gnu.org/r/bug-gnulib/2009-01/msg00329.html> + <https://lists.gnu.org/r/bug-gnulib/2009-08/msg00096.html>. */ +#if defined __ELF__ + /* On ELF systems, variables in BSS behave well. */ +#else + = (const char *) 0 +#endif + ; diff --git a/grub-core/lib/gnulib/argp-eexst.c b/grub-core/lib/gnulib/argp-eexst.c new file mode 100644 index 0000000..06b025d --- /dev/null +++ b/grub-core/lib/gnulib/argp-eexst.c @@ -0,0 +1,30 @@ +/* Default definition for ARGP_ERR_EXIT_STATUS + Copyright (C) 1997, 2009-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sysexits.h> + +#include "argp.h" + +/* The exit status that argp will use when exiting due to a parsing error. + If not defined or set by the user program, this defaults to EX_USAGE from + <sysexits.h>. */ +error_t argp_err_exit_status = EX_USAGE; diff --git a/grub-core/lib/gnulib/argp-fmtstream.c b/grub-core/lib/gnulib/argp-fmtstream.c new file mode 100644 index 0000000..d0685b3 --- /dev/null +++ b/grub-core/lib/gnulib/argp-fmtstream.c @@ -0,0 +1,488 @@ +/* Word-wrapping and line-truncating streams + Copyright (C) 1997-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* This package emulates glibc 'line_wrap_stream' semantics for systems that + don't have that. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <stdarg.h> +#include <ctype.h> +#include <wchar.h> + +#include "argp-fmtstream.h" +#include "argp-namefrob.h" +#include "mbswidth.h" + +#ifndef ARGP_FMTSTREAM_USE_LINEWRAP + +#ifndef isblank +#define isblank(ch) ((ch)==' ' || (ch)=='\t') +#endif + +#ifdef _LIBC +# include <wchar.h> +# include <libio/libioP.h> +# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) +#endif + +#define INIT_BUF_SIZE 200 +#define PRINTF_SIZE_GUESS 150 + +/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines + written on it with LMARGIN spaces and limits them to RMARGIN columns + total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by + replacing the whitespace before them with a newline and WMARGIN spaces. + Otherwise, chars beyond RMARGIN are simply dropped until a newline. + Returns NULL if there was an error. */ +argp_fmtstream_t +__argp_make_fmtstream (FILE *stream, + size_t lmargin, size_t rmargin, ssize_t wmargin) +{ + argp_fmtstream_t fs; + + fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream)); + if (fs != NULL) + { + fs->stream = stream; + + fs->lmargin = lmargin; + fs->rmargin = rmargin; + fs->wmargin = wmargin; + fs->point_col = 0; + fs->point_offs = 0; + + fs->buf = (char *) malloc (INIT_BUF_SIZE); + if (! fs->buf) + { + free (fs); + fs = 0; + } + else + { + fs->p = fs->buf; + fs->end = fs->buf + INIT_BUF_SIZE; + } + } + + return fs; +} +#if 0 +/* Not exported. */ +#ifdef weak_alias +weak_alias (__argp_make_fmtstream, argp_make_fmtstream) +#endif +#endif + +/* Flush FS to its stream, and free it (but don't close the stream). */ +void +__argp_fmtstream_free (argp_fmtstream_t fs) +{ + __argp_fmtstream_update (fs); + if (fs->p > fs->buf) + { +#ifdef _LIBC + __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf); +#else + fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); +#endif + } + free (fs->buf); + free (fs); +} +#if 0 +/* Not exported. */ +#ifdef weak_alias +weak_alias (__argp_fmtstream_free, argp_fmtstream_free) +#endif +#endif + + +/* Return the pointer to the first character that doesn't fit in l columns. */ +static inline const ptrdiff_t +add_width (const char *ptr, const char *end, size_t l) +{ + mbstate_t ps; + const char *ptr0 = ptr; + + memset (&ps, 0, sizeof (ps)); + + while (ptr < end) + { + wchar_t wc; + size_t s, k; + + s = mbrtowc (&wc, ptr, end - ptr, &ps); + if (s == (size_t) -1) + break; + if (s == (size_t) -2) + { + if (1 >= l) + break; + l--; + ptr++; + continue; + } + + if (wc == '\e' && ptr + 3 < end + && ptr[1] == '[' && (ptr[2] == '0' || ptr[2] == '1') + && ptr[3] == 'm') + { + ptr += 4; + continue; + } + + k = wcwidth (wc); + + if (k >= l) + break; + l -= k; + ptr += s; + } + return ptr - ptr0; +} + +/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the + end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ +void +__argp_fmtstream_update (argp_fmtstream_t fs) +{ + char *buf, *nl; + size_t len; + + /* Scan the buffer for newlines. */ + buf = fs->buf + fs->point_offs; + while (buf < fs->p) + { + size_t r; + + if (fs->point_col == 0 && fs->lmargin != 0) + { + /* We are starting a new line. Print spaces to the left margin. */ + const size_t pad = fs->lmargin; + if (fs->p + pad < fs->end) + { + /* We can fit in them in the buffer by moving the + buffer text up and filling in the beginning. */ + memmove (buf + pad, buf, fs->p - buf); + fs->p += pad; /* Compensate for bigger buffer. */ + memset (buf, ' ', pad); /* Fill in the spaces. */ + buf += pad; /* Don't bother searching them. */ + } + else + { + /* No buffer space for spaces. Must flush. */ + size_t i; + for (i = 0; i < pad; i++) + { +#ifdef _LIBC + if (_IO_fwide (fs->stream, 0) > 0) + putwc_unlocked (L' ', fs->stream); + else +#endif + putc_unlocked (' ', fs->stream); + } + } + fs->point_col = pad; + } + + len = fs->p - buf; + nl = memchr (buf, '\n', len); + + if (fs->point_col < 0) + fs->point_col = 0; + + if (!nl) + { + /* The buffer ends in a partial line. */ + size_t display_width = mbsnwidth (buf, fs->p - buf, + MBSW_STOP_AT_NUL); + + if (fs->point_col + display_width < fs->rmargin) + { + /* The remaining buffer text is a partial line and fits + within the maximum line width. Advance point for the + characters to be written and stop scanning. */ + fs->point_col += display_width; + break; + } + else + /* Set the end-of-line pointer for the code below to + the end of the buffer. */ + nl = fs->p; + } + else + { + size_t display_width = mbsnwidth (buf, nl - buf, MBSW_STOP_AT_NUL); + if (display_width < (ssize_t) fs->rmargin) + { + /* The buffer contains a full line that fits within the maximum + line width. Reset point and scan the next line. */ + fs->point_col = 0; + buf = nl + 1; + continue; + } + } + + /* This line is too long. */ + r = fs->rmargin - 1; + + if (fs->wmargin < 0) + { + /* Truncate the line by overwriting the excess with the + newline and anything after it in the buffer. */ + if (nl < fs->p) + { + memmove (buf + (r - fs->point_col), nl, fs->p - nl); + fs->p -= buf + (r - fs->point_col) - nl; + /* Reset point for the next line and start scanning it. */ + fs->point_col = 0; + buf += r + 1; /* Skip full line plus \n. */ + } + else + { + /* The buffer ends with a partial line that is beyond the + maximum line width. Advance point for the characters + written, and discard those past the max from the buffer. */ + fs->point_col += len; + fs->p -= fs->point_col - r; + break; + } + } + else + { + /* Do word wrap. Go to the column just past the maximum line + width and scan back for the beginning of the word there. + Then insert a line break. */ + + char *p, *nextline; + int i; + + p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); + while (p >= buf && !isblank ((unsigned char) *p)) + --p; + nextline = p + 1; /* This will begin the next line. */ + + if (nextline > buf) + { + /* Swallow separating blanks. */ + if (p >= buf) + do + --p; + while (p >= buf && isblank ((unsigned char) *p)); + nl = p + 1; /* The newline will replace the first blank. */ + } + else + { + /* A single word that is greater than the maximum line width. + Oh well. Put it on an overlong line by itself. */ + p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); + /* Find the end of the long word. */ + if (p < nl) + do + ++p; + while (p < nl && !isblank ((unsigned char) *p)); + if (p == nl) + { + /* It already ends a line. No fussing required. */ + fs->point_col = 0; + buf = nl + 1; + continue; + } + /* We will move the newline to replace the first blank. */ + nl = p; + /* Swallow separating blanks. */ + do + ++p; + while (isblank ((unsigned char) *p)); + /* The next line will start here. */ + nextline = p; + } + + /* Note: There are a bunch of tests below for + NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall + at the end of the buffer, and NEXTLINE is in fact empty (and so + we need not be careful to maintain its contents). */ + + if ((nextline == buf + len + 1 + ? fs->end - nl < fs->wmargin + 1 + : nextline - (nl + 1) < fs->wmargin) + && fs->p > nextline) + { + /* The margin needs more blanks than we removed. */ + if (mbsnwidth (fs->p, fs->end - fs->p, MBSW_STOP_AT_NUL) + > fs->wmargin + 1) + /* Make some space for them. */ + { + size_t mv = fs->p - nextline; + memmove (nl + 1 + fs->wmargin, nextline, mv); + nextline = nl + 1 + fs->wmargin; + len = nextline + mv - buf; + *nl++ = '\n'; + } + else + /* Output the first line so we can use the space. */ + { +#ifdef _LIBC + __fxprintf (fs->stream, "%.*s\n", + (int) (nl - fs->buf), fs->buf); +#else + if (nl > fs->buf) + fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream); + putc_unlocked ('\n', fs->stream); +#endif + + len += buf - fs->buf; + nl = buf = fs->buf; + } + } + else + /* We can fit the newline and blanks in before + the next word. */ + *nl++ = '\n'; + + if (nextline - nl >= fs->wmargin + || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin)) + /* Add blanks up to the wrap margin column. */ + for (i = 0; i < fs->wmargin; ++i) + *nl++ = ' '; + else + for (i = 0; i < fs->wmargin; ++i) +#ifdef _LIBC + if (_IO_fwide (fs->stream, 0) > 0) + putwc_unlocked (L' ', fs->stream); + else +#endif + putc_unlocked (' ', fs->stream); + + /* Copy the tail of the original buffer into the current buffer + position. */ + if (nl < nextline) + memmove (nl, nextline, buf + len - nextline); + len -= nextline - buf; + + /* Continue the scan on the remaining lines in the buffer. */ + buf = nl; + + /* Restore bufp to include all the remaining text. */ + fs->p = nl + len; + + /* Reset the counter of what has been output this line. If wmargin + is 0, we want to avoid the lmargin getting added, so we set + point_col to a magic value of -1 in that case. */ + fs->point_col = fs->wmargin ? fs->wmargin : -1; + } + } + + /* Remember that we've scanned as far as the end of the buffer. */ + fs->point_offs = fs->p - fs->buf; +} + +/* Ensure that FS has space for AMOUNT more bytes in its buffer, either by + growing the buffer, or by flushing it. True is returned iff we succeed. */ +int +__argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) +{ + if ((size_t) (fs->end - fs->p) < amount) + { + ssize_t wrote; + + /* Flush FS's buffer. */ + __argp_fmtstream_update (fs); + +#ifdef _LIBC + __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf); + wrote = fs->p - fs->buf; +#else + wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); +#endif + if (wrote == fs->p - fs->buf) + { + fs->p = fs->buf; + fs->point_offs = 0; + } + else + { + fs->p -= wrote; + fs->point_offs -= wrote; + memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf); + return 0; + } + + if ((size_t) (fs->end - fs->buf) < amount) + /* Gotta grow the buffer. */ + { + size_t old_size = fs->end - fs->buf; + size_t new_size = old_size + amount; + char *new_buf; + + if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size))) + { + __set_errno (ENOMEM); + return 0; + } + + fs->buf = new_buf; + fs->end = new_buf + new_size; + fs->p = fs->buf; + } + } + + return 1; +} + +ssize_t +__argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...) +{ + int out; + size_t avail; + size_t size_guess = PRINTF_SIZE_GUESS; /* How much space to reserve. */ + + do + { + va_list args; + + if (! __argp_fmtstream_ensure (fs, size_guess)) + return -1; + + va_start (args, fmt); + avail = fs->end - fs->p; + out = __vsnprintf (fs->p, avail, fmt, args); + va_end (args); + if ((size_t) out >= avail) + size_guess = out + 1; + } + while ((size_t) out >= avail); + + fs->p += out; + + return out; +} +#if 0 +/* Not exported. */ +#ifdef weak_alias +weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf) +#endif +#endif + +#endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */ diff --git a/grub-core/lib/gnulib/argp-fmtstream.h b/grub-core/lib/gnulib/argp-fmtstream.h new file mode 100644 index 0000000..0cc8852 --- /dev/null +++ b/grub-core/lib/gnulib/argp-fmtstream.h @@ -0,0 +1,310 @@ +/* Word-wrapping and line-truncating streams. + Copyright (C) 1997-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* This package emulates glibc 'line_wrap_stream' semantics for systems that + don't have that. If the system does have it, it is just a wrapper for + that. This header file is only used internally while compiling argp, and + shouldn't be installed. */ + +#ifndef _ARGP_FMTSTREAM_H +#define _ARGP_FMTSTREAM_H + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The __-protected variants of the attributes 'format' and 'printf' are + accepted by gcc versions 2.6.4 (effectively 2.7) and later. + We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because + gnulib and libintl do '#define printf __printf__' when they override + the 'printf' function. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +#endif + +#if defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H) +/* line_wrap_stream is available, so use that. */ +#define ARGP_FMTSTREAM_USE_LINEWRAP +#endif + +#ifdef ARGP_FMTSTREAM_USE_LINEWRAP +/* Just be a simple wrapper for line_wrap_stream; the semantics are + *slightly* different, as line_wrap_stream doesn't actually make a new + object, it just modifies the given stream (reversibly) to do + line-wrapping. Since we control who uses this code, it doesn't matter. */ + +#include <linewrap.h> + +typedef FILE *argp_fmtstream_t; + +#define argp_make_fmtstream line_wrap_stream +#define __argp_make_fmtstream line_wrap_stream +#define argp_fmtstream_free line_unwrap_stream +#define __argp_fmtstream_free line_unwrap_stream + +#define __argp_fmtstream_putc(fs,ch) putc(ch,fs) +#define argp_fmtstream_putc(fs,ch) putc(ch,fs) +#define __argp_fmtstream_puts(fs,str) fputs(str,fs) +#define argp_fmtstream_puts(fs,str) fputs(str,fs) +#define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) +#define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) +#define __argp_fmtstream_printf fprintf +#define argp_fmtstream_printf fprintf + +#define __argp_fmtstream_lmargin line_wrap_lmargin +#define argp_fmtstream_lmargin line_wrap_lmargin +#define __argp_fmtstream_set_lmargin line_wrap_set_lmargin +#define argp_fmtstream_set_lmargin line_wrap_set_lmargin +#define __argp_fmtstream_rmargin line_wrap_rmargin +#define argp_fmtstream_rmargin line_wrap_rmargin +#define __argp_fmtstream_set_rmargin line_wrap_set_rmargin +#define argp_fmtstream_set_rmargin line_wrap_set_rmargin +#define __argp_fmtstream_wmargin line_wrap_wmargin +#define argp_fmtstream_wmargin line_wrap_wmargin +#define __argp_fmtstream_set_wmargin line_wrap_set_wmargin +#define argp_fmtstream_set_wmargin line_wrap_set_wmargin +#define __argp_fmtstream_point line_wrap_point +#define argp_fmtstream_point line_wrap_point + +#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */ +/* Guess we have to define our own version. */ + + +struct argp_fmtstream +{ + FILE *stream; /* The stream we're outputting to. */ + + size_t lmargin, rmargin; /* Left and right margins. */ + ssize_t wmargin; /* Margin to wrap to, or -1 to truncate. */ + + /* Point in buffer to which we've processed for wrapping, but not output. */ + size_t point_offs; + /* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin. */ + ssize_t point_col; + + char *buf; /* Output buffer. */ + char *p; /* Current end of text in BUF. */ + char *end; /* Absolute end of BUF. */ +}; + +typedef struct argp_fmtstream *argp_fmtstream_t; + +/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines + written on it with LMARGIN spaces and limits them to RMARGIN columns + total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by + replacing the whitespace before them with a newline and WMARGIN spaces. + Otherwise, chars beyond RMARGIN are simply dropped until a newline. + Returns NULL if there was an error. */ +extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream, + size_t __lmargin, + size_t __rmargin, + ssize_t __wmargin); +extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream, + size_t __lmargin, + size_t __rmargin, + ssize_t __wmargin); + +/* Flush __FS to its stream, and free it (but don't close the stream). */ +extern void __argp_fmtstream_free (argp_fmtstream_t __fs); +extern void argp_fmtstream_free (argp_fmtstream_t __fs); + +extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs, + const char *__fmt, ...) + _GL_ATTRIBUTE_FORMAT ((printf, 2, 3)); +extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs, + const char *__fmt, ...) + _GL_ATTRIBUTE_FORMAT ((printf, 2, 3)); + +#if _LIBC +extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); +extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); + +extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); +extern int argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); + +extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs, + const char *__str, size_t __len); +extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, + const char *__str, size_t __len); +#endif + +/* Access macros for various bits of state. */ +#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin) +#define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin) +#define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin) +#define __argp_fmtstream_lmargin argp_fmtstream_lmargin +#define __argp_fmtstream_rmargin argp_fmtstream_rmargin +#define __argp_fmtstream_wmargin argp_fmtstream_wmargin + +#if _LIBC +/* Set __FS's left margin to LMARGIN and return the old value. */ +extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, + size_t __lmargin); +extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, + size_t __lmargin); + +/* Set __FS's right margin to __RMARGIN and return the old value. */ +extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, + size_t __rmargin); +extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, + size_t __rmargin); + +/* Set __FS's wrap margin to __WMARGIN and return the old value. */ +extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, + size_t __wmargin); +extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, + size_t __wmargin); + +/* Return the column number of the current output point in __FS. */ +extern size_t argp_fmtstream_point (argp_fmtstream_t __fs); +extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs); +#endif + +/* Internal routines. */ +extern void _argp_fmtstream_update (argp_fmtstream_t __fs); +extern void __argp_fmtstream_update (argp_fmtstream_t __fs); +extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); +extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); + +#if !_LIBC || defined __OPTIMIZE__ +/* Inline versions of above routines. */ + +#if !_LIBC +#define __argp_fmtstream_putc argp_fmtstream_putc +#define __argp_fmtstream_puts argp_fmtstream_puts +#define __argp_fmtstream_write argp_fmtstream_write +#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin +#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin +#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin +#define __argp_fmtstream_point argp_fmtstream_point +#define __argp_fmtstream_update _argp_fmtstream_update +#define __argp_fmtstream_ensure _argp_fmtstream_ensure +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef ARGP_FS_EI +# define ARGP_FS_EI _GL_INLINE +#endif +#endif + +#ifndef ARGP_FS_EI +#define ARGP_FS_EI extern inline +#endif + +ARGP_FS_EI size_t +__argp_fmtstream_write (argp_fmtstream_t __fs, const char *__str, size_t __len) +{ + if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len)) + { + memcpy (__fs->p, __str, __len); + __fs->p += __len; + return __len; + } + else + return 0; +} + +ARGP_FS_EI int +__argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str) +{ + size_t __len = strlen (__str); + if (__len) + { + size_t __wrote = __argp_fmtstream_write (__fs, __str, __len); + return __wrote == __len ? 0 : -1; + } + else + return 0; +} + +ARGP_FS_EI int +__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch) +{ + if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1)) + return *__fs->p++ = __ch; + else + return EOF; +} + +/* Set __FS's left margin to __LMARGIN and return the old value. */ +ARGP_FS_EI size_t +__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin) +{ + size_t __old; + if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) + __argp_fmtstream_update (__fs); + __old = __fs->lmargin; + __fs->lmargin = __lmargin; + return __old; +} + +/* Set __FS's right margin to __RMARGIN and return the old value. */ +ARGP_FS_EI size_t +__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin) +{ + size_t __old; + if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) + __argp_fmtstream_update (__fs); + __old = __fs->rmargin; + __fs->rmargin = __rmargin; + return __old; +} + +/* Set FS's wrap margin to __WMARGIN and return the old value. */ +ARGP_FS_EI size_t +__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin) +{ + size_t __old; + if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) + __argp_fmtstream_update (__fs); + __old = __fs->wmargin; + __fs->wmargin = __wmargin; + return __old; +} + +/* Return the column number of the current output point in __FS. */ +ARGP_FS_EI size_t +__argp_fmtstream_point (argp_fmtstream_t __fs) +{ + if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) + __argp_fmtstream_update (__fs); + return __fs->point_col >= 0 ? __fs->point_col : 0; +} + +#if !_LIBC +#undef __argp_fmtstream_putc +#undef __argp_fmtstream_puts +#undef __argp_fmtstream_write +#undef __argp_fmtstream_set_lmargin +#undef __argp_fmtstream_set_rmargin +#undef __argp_fmtstream_set_wmargin +#undef __argp_fmtstream_point +#undef __argp_fmtstream_update +#undef __argp_fmtstream_ensure +_GL_INLINE_HEADER_END +#endif + +#endif /* !_LIBC || __OPTIMIZE__ */ + +#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */ + +#endif /* argp-fmtstream.h */ diff --git a/grub-core/lib/gnulib/argp-fs-xinl.c b/grub-core/lib/gnulib/argp-fs-xinl.c new file mode 100644 index 0000000..a2e843c --- /dev/null +++ b/grub-core/lib/gnulib/argp-fs-xinl.c @@ -0,0 +1,46 @@ +/* Real definitions for extern inline functions in argp-fmtstream.h + Copyright (C) 1997-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef _LIBC +# define ARGP_FS_EI +#else +# define ARGP_FS_EI _GL_EXTERN_INLINE +#endif +#undef __OPTIMIZE__ +#define __OPTIMIZE__ 1 +#include "argp-fmtstream.h" + +#if 0 +/* Not exported. */ +/* Add weak aliases. */ +#if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias) + +weak_alias (__argp_fmtstream_putc, argp_fmtstream_putc) +weak_alias (__argp_fmtstream_puts, argp_fmtstream_puts) +weak_alias (__argp_fmtstream_write, argp_fmtstream_write) +weak_alias (__argp_fmtstream_set_lmargin, argp_fmtstream_set_lmargin) +weak_alias (__argp_fmtstream_set_rmargin, argp_fmtstream_set_rmargin) +weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin) +weak_alias (__argp_fmtstream_point, argp_fmtstream_point) + +#endif +#endif diff --git a/grub-core/lib/gnulib/argp-help.c b/grub-core/lib/gnulib/argp-help.c new file mode 100644 index 0000000..c75568c --- /dev/null +++ b/grub-core/lib/gnulib/argp-help.c @@ -0,0 +1,1912 @@ +/* Hierarchical argument parsing help output + Copyright (C) 1995-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <alloca.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <stdarg.h> +#include <ctype.h> +#include <limits.h> +#ifdef _LIBC +# include <../libio/libioP.h> +# include <wchar.h> +#endif + +#ifdef _LIBC +# include <libintl.h> +# undef dgettext +# define dgettext(domain, msgid) \ + __dcgettext (domain, msgid, LC_MESSAGES) +#else +# include "gettext.h" +#endif + +#include "argp.h" +#include "argp-fmtstream.h" +#include "argp-namefrob.h" +#include "mbswidth.h" + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +/* User-selectable (using an environment variable) formatting parameters. + + These may be specified in an environment variable called 'ARGP_HELP_FMT', + with a contents like: VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2 + Where VALn must be a positive integer. The list of variables is in the + UPARAM_NAMES vector, below. */ + +/* Default parameters. */ +#define DUP_ARGS 0 /* True if option argument can be duplicated. */ +#define DUP_ARGS_NOTE 1 /* True to print a note about duplicate args. */ +#define SHORT_OPT_COL 2 /* column in which short options start */ +#define LONG_OPT_COL 6 /* column in which long options start */ +#define DOC_OPT_COL 2 /* column in which doc options start */ +#define OPT_DOC_COL 29 /* column in which option text starts */ +#define HEADER_COL 1 /* column in which group headers are printed */ +#define USAGE_INDENT 12 /* indentation of wrapped usage lines */ +#define RMARGIN 79 /* right margin used for wrapping */ + +/* User-selectable (using an environment variable) formatting parameters. + They must all be of type 'int' for the parsing code to work. */ +struct uparams +{ + /* If true, arguments for an option are shown with both short and long + options, even when a given option has both, e.g. '-x ARG, --longx=ARG'. + If false, then if an option has both, the argument is only shown with + the long one, e.g., '-x, --longx=ARG', and a message indicating that + this really means both is printed below the options. */ + int dup_args; + + /* This is true if when DUP_ARGS is false, and some duplicate arguments have + been suppressed, an explanatory message should be printed. */ + int dup_args_note; + + /* Various output columns. */ + int short_opt_col; /* column in which short options start */ + int long_opt_col; /* column in which long options start */ + int doc_opt_col; /* column in which doc options start */ + int opt_doc_col; /* column in which option text starts */ + int header_col; /* column in which group headers are printed */ + int usage_indent; /* indentation of wrapped usage lines */ + int rmargin; /* right margin used for wrapping */ + + int valid; /* True when the values in here are valid. */ +}; + +/* This is a global variable, as user options are only ever read once. */ +static struct uparams uparams = { + DUP_ARGS, DUP_ARGS_NOTE, + SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL, + USAGE_INDENT, RMARGIN +}; + +/* A particular uparam, and what the user name is. */ +struct uparam_name +{ + const char name[14]; /* User name. */ + bool is_bool; /* Whether it's 'boolean'. */ + unsigned char uparams_offs; /* Location of the (int) field in UPARAMS. */ +}; + +/* The name-field mappings we know about. */ +static const struct uparam_name uparam_names[] = +{ + { "dup-args", true, offsetof (struct uparams, dup_args) }, + { "dup-args-note", true, offsetof (struct uparams, dup_args_note) }, + { "short-opt-col", false, offsetof (struct uparams, short_opt_col) }, + { "long-opt-col", false, offsetof (struct uparams, long_opt_col) }, + { "doc-opt-col", false, offsetof (struct uparams, doc_opt_col) }, + { "opt-doc-col", false, offsetof (struct uparams, opt_doc_col) }, + { "header-col", false, offsetof (struct uparams, header_col) }, + { "usage-indent", false, offsetof (struct uparams, usage_indent) }, + { "rmargin", false, offsetof (struct uparams, rmargin) } +}; +#define nuparam_names (sizeof (uparam_names) / sizeof (uparam_names[0])) + +static void +validate_uparams (const struct argp_state *state, struct uparams *upptr) +{ + const struct uparam_name *up; + + for (up = uparam_names; up < uparam_names + nuparam_names; up++) + { + if (up->is_bool + || up->uparams_offs == offsetof (struct uparams, rmargin)) + continue; + if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin) + { + __argp_failure (state, 0, 0, + dgettext (state == NULL ? NULL + : state->root_argp->argp_domain, + "\ +ARGP_HELP_FMT: %s value is less than or equal to %s"), + "rmargin", up->name); + return; + } + } + uparams = *upptr; + uparams.valid = 1; +} + +/* Read user options from the environment, and fill in UPARAMS appropriately. */ +static void +fill_in_uparams (const struct argp_state *state) +{ + const char *var = getenv ("ARGP_HELP_FMT"); + struct uparams new_params = uparams; + +#define SKIPWS(p) do { while (isspace ((unsigned char) *p)) p++; } while (0); + + if (var) + { + /* Parse var. */ + while (*var) + { + SKIPWS (var); + + if (isalpha ((unsigned char) *var)) + { + size_t var_len; + const struct uparam_name *un; + int unspec = 0, val = 0; + const char *arg = var; + + while (isalnum ((unsigned char) *arg) || *arg == '-' || *arg == '_') + arg++; + var_len = arg - var; + + SKIPWS (arg); + + if (*arg == '\0' || *arg == ',') + unspec = 1; + else if (*arg == '=') + { + arg++; + SKIPWS (arg); + } + + if (unspec) + { + if (var[0] == 'n' && var[1] == 'o' && var[2] == '-') + { + val = 0; + var += 3; + var_len -= 3; + } + else + val = 1; + } + else if (isdigit ((unsigned char) *arg)) + { + val = atoi (arg); + while (isdigit ((unsigned char) *arg)) + arg++; + SKIPWS (arg); + } + + for (un = uparam_names; + un < uparam_names + nuparam_names; + un++) + if (strlen (un->name) == var_len + && strncmp (var, un->name, var_len) == 0) + { + if (unspec && !un->is_bool) + __argp_failure (state, 0, 0, + dgettext (state == NULL ? NULL + : state->root_argp->argp_domain, + "\ +%.*s: ARGP_HELP_FMT parameter requires a value"), + (int) var_len, var); + else + *(int *)((char *)&new_params + un->uparams_offs) = val; + break; + } + if (un == uparam_names + nuparam_names) + __argp_failure (state, 0, 0, + dgettext (state == NULL ? NULL + : state->root_argp->argp_domain, "\ +%.*s: Unknown ARGP_HELP_FMT parameter"), + (int) var_len, var); + + var = arg; + if (*var == ',') + var++; + } + else if (*var) + { + __argp_failure (state, 0, 0, + dgettext (state == NULL ? NULL + : state->root_argp->argp_domain, + "Garbage in ARGP_HELP_FMT: %s"), var); + break; + } + } + validate_uparams (state, &new_params); + } +} + +/* Returns true if OPT hasn't been marked invisible. Visibility only affects + whether OPT is displayed or used in sorting, not option shadowing. */ +#define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN)) + +/* Returns true if OPT is an alias for an earlier option. */ +#define oalias(opt) ((opt)->flags & OPTION_ALIAS) + +/* Returns true if OPT is a documentation-only entry. */ +#define odoc(opt) ((opt)->flags & OPTION_DOC) + +/* Returns true if OPT should not be translated */ +#define onotrans(opt) ((opt)->flags & OPTION_NO_TRANS) + +/* Returns true if OPT is the end-of-list marker for a list of options. */ +#define oend(opt) __option_is_end (opt) + +/* Returns true if OPT has a short option. */ +#define oshort(opt) __option_is_short (opt) + +/* + The help format for a particular option is like: + + -xARG, -yARG, --long1=ARG, --long2=ARG Documentation... + + Where ARG will be omitted if there's no argument, for this option, or + will be surrounded by "[" and "]" appropriately if the argument is + optional. The documentation string is word-wrapped appropriately, and if + the list of options is long enough, it will be started on a separate line. + If there are no short options for a given option, the first long option is + indented slightly in a way that's supposed to make most long options appear + to be in a separate column. + + For example, the following output (from ps): + + -p PID, --pid=PID List the process PID + --pgrp=PGRP List processes in the process group PGRP + -P, -x, --no-parent Include processes without parents + -Q, --all-fields Don't elide unusable fields (normally if there's + some reason ps can't print a field for any + process, it's removed from the output entirely) + -r, --reverse, --gratuitously-long-reverse-option + Reverse the order of any sort + --session[=SID] Add the processes from the session SID (which + defaults to the sid of the current process) + + Here are some more options: + -f ZOT, --foonly=ZOT Glork a foonly + -z, --zaza Snit a zar + + -?, --help Give this help list + --usage Give a short usage message + -V, --version Print program version + + The struct argp_option array for the above could look like: + + { + {"pid", 'p', "PID", 0, "List the process PID"}, + {"pgrp", OPT_PGRP, "PGRP", 0, "List processes in the process group PGRP"}, + {"no-parent", 'P', 0, 0, "Include processes without parents"}, + {0, 'x', 0, OPTION_ALIAS}, + {"all-fields",'Q', 0, 0, "Don't elide unusable fields (normally" + " if there's some reason ps can't" + " print a field for any process, it's" + " removed from the output entirely)" }, + {"reverse", 'r', 0, 0, "Reverse the order of any sort"}, + {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS}, + {"session", OPT_SESS, "SID", OPTION_ARG_OPTIONAL, + "Add the processes from the session" + " SID (which defaults to the sid of" + " the current process)" }, + + {0,0,0,0, "Here are some more options:"}, + {"foonly", 'f', "ZOT", 0, "Glork a foonly"}, + {"zaza", 'z', 0, 0, "Snit a zar"}, + + {0} + } + + Note that the last three options are automatically supplied by argp_parse, + unless you tell it not to with ARGP_NO_HELP. + +*/ + +/* Returns true if CH occurs between BEG and END. */ +static int +find_char (char ch, char *beg, char *end) +{ + while (beg < end) + if (*beg == ch) + return 1; + else + beg++; + return 0; +} + +struct hol_cluster; /* fwd decl */ + +struct hol_entry +{ + /* First option. */ + const struct argp_option *opt; + /* Number of options (including aliases). */ + unsigned num; + + /* A pointers into the HOL's short_options field, to the first short option + letter for this entry. The order of the characters following this point + corresponds to the order of options pointed to by OPT, and there are at + most NUM. A short option recorded in an option following OPT is only + valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's + probably been shadowed by some other entry). */ + char *short_options; + + /* Entries are sorted by their group first, in the order: + 1, 2, ..., n, 0, -m, ..., -2, -1 + and then alphabetically within each group. The default is 0. */ + int group; + + /* The cluster of options this entry belongs to, or 0 if none. */ + struct hol_cluster *cluster; + + /* The argp from which this option came. */ + const struct argp *argp; + + /* Position in the array */ + unsigned ord; +}; + +/* A cluster of entries to reflect the argp tree structure. */ +struct hol_cluster +{ + /* A descriptive header printed before options in this cluster. */ + const char *header; + + /* Used to order clusters within the same group with the same parent, + according to the order in which they occurred in the parent argp's child + list. */ + int index; + + /* How to sort this cluster with respect to options and other clusters at the + same depth (clusters always follow options in the same group). */ + int group; + + /* The cluster to which this cluster belongs, or 0 if it's at the base + level. */ + struct hol_cluster *parent; + + /* The argp from which this cluster is (eventually) derived. */ + const struct argp *argp; + + /* The distance this cluster is from the root. */ + int depth; + + /* Clusters in a given hol are kept in a linked list, to make freeing them + possible. */ + struct hol_cluster *next; +}; + +/* A list of options for help. */ +struct hol +{ + /* An array of hol_entry's. */ + struct hol_entry *entries; + /* The number of entries in this hol. If this field is zero, the others + are undefined. */ + unsigned num_entries; + + /* A string containing all short options in this HOL. Each entry contains + pointers into this string, so the order can't be messed with blindly. */ + char *short_options; + + /* Clusters of entries in this hol. */ + struct hol_cluster *clusters; +}; + +/* Create a struct hol from the options in ARGP. CLUSTER is the + hol_cluster in which these entries occur, or 0, if at the root. */ +static struct hol * +make_hol (const struct argp *argp, struct hol_cluster *cluster) +{ + char *so; + const struct argp_option *o; + const struct argp_option *opts = argp->options; + struct hol_entry *entry; + unsigned num_short_options = 0; + struct hol *hol = malloc (sizeof (struct hol)); + + assert (hol); + + hol->num_entries = 0; + hol->clusters = 0; + + if (opts) + { + int cur_group = 0; + + /* The first option must not be an alias. */ + assert (! oalias (opts)); + + /* Calculate the space needed. */ + for (o = opts; ! oend (o); o++) + { + if (! oalias (o)) + hol->num_entries++; + if (oshort (o)) + num_short_options++; /* This is an upper bound. */ + } + + hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries); + hol->short_options = malloc (num_short_options + 1); + + assert (hol->entries && hol->short_options); + if (SIZE_MAX <= UINT_MAX) + assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry)); + + /* Fill in the entries. */ + so = hol->short_options; + for (o = opts, entry = hol->entries; ! oend (o); entry++) + { + entry->opt = o; + entry->num = 0; + entry->short_options = so; + entry->group = cur_group = + o->group + ? o->group + : ((!o->name && !o->key) + ? cur_group + 1 + : cur_group); + entry->cluster = cluster; + entry->argp = argp; + + do + { + entry->num++; + if (oshort (o) && ! find_char (o->key, hol->short_options, so)) + /* O has a valid short option which hasn't already been used.*/ + *so++ = o->key; + o++; + } + while (! oend (o) && oalias (o)); + } + *so = '\0'; /* null terminated so we can find the length */ + } + + return hol; +} + +/* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the + associated argp child list entry), INDEX, and PARENT, and return a pointer + to it. ARGP is the argp that this cluster results from. */ +static struct hol_cluster * +hol_add_cluster (struct hol *hol, int group, const char *header, int index, + struct hol_cluster *parent, const struct argp *argp) +{ + struct hol_cluster *cl = malloc (sizeof (struct hol_cluster)); + if (cl) + { + cl->group = group; + cl->header = header; + + cl->index = index; + cl->parent = parent; + cl->argp = argp; + cl->depth = parent ? parent->depth + 1 : 0; + + cl->next = hol->clusters; + hol->clusters = cl; + } + return cl; +} + +/* Free HOL and any resources it uses. */ +static void +hol_free (struct hol *hol) +{ + struct hol_cluster *cl = hol->clusters; + + while (cl) + { + struct hol_cluster *next = cl->next; + free (cl); + cl = next; + } + + if (hol->num_entries > 0) + { + free (hol->entries); + free (hol->short_options); + } + + free (hol); +} + +static int +hol_entry_short_iterate (const struct hol_entry *entry, + int (*func)(const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie), + const char *domain, void *cookie) +{ + unsigned nopts; + int val = 0; + const struct argp_option *opt, *real = entry->opt; + char *so = entry->short_options; + + for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) + if (oshort (opt) && *so == opt->key) + { + if (!oalias (opt)) + real = opt; + if (ovisible (opt)) + val = (*func)(opt, real, domain, cookie); + so++; + } + + return val; +} + +static inline int +#if __GNUC__ >= 3 +__attribute__ ((always_inline)) +#endif +hol_entry_long_iterate (const struct hol_entry *entry, + int (*func)(const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie), + const char *domain, void *cookie) +{ + unsigned nopts; + int val = 0; + const struct argp_option *opt, *real = entry->opt; + + for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) + if (opt->name) + { + if (!oalias (opt)) + real = opt; + if (ovisible (opt)) + val = (*func)(opt, real, domain, cookie); + } + + return val; +} + +/* Iterator that returns true for the first short option. */ +static int +until_short (const struct argp_option *opt, const struct argp_option *real, + const char *domain, void *cookie) +{ + return oshort (opt) ? opt->key : 0; +} + +/* Returns the first valid short option in ENTRY, or 0 if there is none. */ +static char +hol_entry_first_short (const struct hol_entry *entry) +{ + return hol_entry_short_iterate (entry, until_short, + entry->argp->argp_domain, 0); +} + +/* Returns the first valid long option in ENTRY, or 0 if there is none. */ +static const char * +hol_entry_first_long (const struct hol_entry *entry) +{ + const struct argp_option *opt; + unsigned num; + for (opt = entry->opt, num = entry->num; num > 0; opt++, num--) + if (opt->name && ovisible (opt)) + return opt->name; + return 0; +} + +/* Returns the entry in HOL with the long option name NAME, or 0 if there is + none. */ +static struct hol_entry * +hol_find_entry (struct hol *hol, const char *name) +{ + struct hol_entry *entry = hol->entries; + unsigned num_entries = hol->num_entries; + + while (num_entries-- > 0) + { + const struct argp_option *opt = entry->opt; + unsigned num_opts = entry->num; + + while (num_opts-- > 0) + if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0) + return entry; + else + opt++; + + entry++; + } + + return 0; +} + +/* If an entry with the long option NAME occurs in HOL, set its special + sort position to GROUP. */ +static void +hol_set_group (struct hol *hol, const char *name, int group) +{ + struct hol_entry *entry = hol_find_entry (hol, name); + if (entry) + entry->group = group; +} + +/* Order by group: 0, 1, 2, ..., n, -m, ..., -2, -1. + EQ is what to return if GROUP1 and GROUP2 are the same. */ +static int +group_cmp (int group1, int group2, int eq) +{ + if (group1 == group2) + return eq; + else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0)) + return group1 - group2; + else + return group2 - group1; +} + +/* Compare clusters CL1 & CL2 by the order that they should appear in + output. */ +static int +hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2) +{ + /* If one cluster is deeper than the other, use its ancestor at the same + level, so that finding the common ancestor is straightforward. */ + while (cl1->depth > cl2->depth) + cl1 = cl1->parent; + while (cl2->depth > cl1->depth) + cl2 = cl2->parent; + + /* Now reduce both clusters to their ancestors at the point where both have + a common parent; these can be directly compared. */ + while (cl1->parent != cl2->parent) + cl1 = cl1->parent, cl2 = cl2->parent; + + return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index); +} + +/* Return the ancestor of CL that's just below the root (i.e., has a parent + of 0). */ +static struct hol_cluster * +hol_cluster_base (struct hol_cluster *cl) +{ + while (cl->parent) + cl = cl->parent; + return cl; +} + +/* Return true if CL1 is a child of CL2. */ +static int +hol_cluster_is_child (const struct hol_cluster *cl1, + const struct hol_cluster *cl2) +{ + while (cl1 && cl1 != cl2) + cl1 = cl1->parent; + return cl1 == cl2; +} + +/* Given the name of an OPTION_DOC option, modifies NAME to start at the tail + that should be used for comparisons, and returns true iff it should be + treated as a non-option. */ +static int +canon_doc_option (const char **name) +{ + int non_opt; + /* Skip initial whitespace. */ + while (isspace (**name)) + (*name)++; + /* Decide whether this looks like an option (leading '-') or not. */ + non_opt = (**name != '-'); + /* Skip until part of name used for sorting. */ + while (**name && !isalnum (**name)) + (*name)++; + return non_opt; +} + +#define HOL_ENTRY_PTRCMP(a,b) ((a)->ord < (b)->ord ? -1 : 1) + +/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help + listing. */ +static int +hol_entry_cmp (const struct hol_entry *entry1, + const struct hol_entry *entry2) +{ + /* The group numbers by which the entries should be ordered; if either is + in a cluster, then this is just the group within the cluster. */ + int group1 = entry1->group, group2 = entry2->group; + + if (entry1->cluster != entry2->cluster) + { + /* The entries are not within the same cluster, so we can't compare them + directly, we have to use the appropriate clustering level too. */ + if (! entry1->cluster) + /* ENTRY1 is at the 'base level', not in a cluster, so we have to + compare it's group number with that of the base cluster in which + ENTRY2 resides. Note that if they're in the same group, the + clustered option always comes last. */ + return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1); + else if (! entry2->cluster) + /* Likewise, but ENTRY2's not in a cluster. */ + return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1); + else + /* Both entries are in clusters, we can just compare the clusters. */ + return hol_cluster_cmp (entry1->cluster, entry2->cluster); + } + else if (group1 == group2) + /* The entries are both in the same cluster and group, so compare them + alphabetically. */ + { + int short1 = hol_entry_first_short (entry1); + int short2 = hol_entry_first_short (entry2); + int doc1 = odoc (entry1->opt); + int doc2 = odoc (entry2->opt); + const char *long1 = hol_entry_first_long (entry1); + const char *long2 = hol_entry_first_long (entry2); + + if (doc1) + doc1 = long1 != NULL && canon_doc_option (&long1); + if (doc2) + doc2 = long2 != NULL && canon_doc_option (&long2); + + if (doc1 != doc2) + /* 'documentation' options always follow normal options (or + documentation options that *look* like normal options). */ + return doc1 - doc2; + else if (!short1 && !short2 && long1 && long2) + /* Only long options. */ + return __strcasecmp (long1, long2); + else + /* Compare short/short, long/short, short/long, using the first + character of long options. Entries without *any* valid + options (such as options with OPTION_HIDDEN set) will be put + first, but as they're not displayed, it doesn't matter where + they are. */ + { + char first1 = short1 ? short1 : long1 ? *long1 : 0; + char first2 = short2 ? short2 : long2 ? *long2 : 0; +#ifdef _tolower + int lower_cmp = _tolower (first1) - _tolower (first2); +#else + int lower_cmp = tolower (first1) - tolower (first2); +#endif + /* Compare ignoring case, except when the options are both the + same letter, in which case lower-case always comes first. */ + return lower_cmp ? lower_cmp : first2 - first1; + } + } + else + /* Within the same cluster, but not the same group, so just compare + groups. */ + return group_cmp (group1, group2, 0); +} + +/* Version of hol_entry_cmp with correct signature for qsort. */ +static int +hol_entry_qcmp (const void *entry1_v, const void *entry2_v) +{ + return hol_entry_cmp (entry1_v, entry2_v); +} + +/* Sort HOL by group and alphabetically by option name (with short options + taking precedence over long). Since the sorting is for display purposes + only, the shadowing of options isn't effected. */ +static void +hol_sort (struct hol *hol) +{ + if (hol->num_entries > 0) + { + unsigned i; + struct hol_entry *e; + for (i = 0, e = hol->entries; i < hol->num_entries; i++, e++) + e->ord = i; + qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry), + hol_entry_qcmp); + } +} + +/* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow + any in MORE with the same name. */ +static void +hol_append (struct hol *hol, struct hol *more) +{ + struct hol_cluster **cl_end = &hol->clusters; + + /* Steal MORE's cluster list, and add it to the end of HOL's. */ + while (*cl_end) + cl_end = &(*cl_end)->next; + *cl_end = more->clusters; + more->clusters = 0; + + /* Merge entries. */ + if (more->num_entries > 0) + { + if (hol->num_entries == 0) + { + hol->num_entries = more->num_entries; + hol->entries = more->entries; + hol->short_options = more->short_options; + more->num_entries = 0; /* Mark MORE's fields as invalid. */ + } + else + /* Append the entries in MORE to those in HOL, taking care to only add + non-shadowed SHORT_OPTIONS values. */ + { + unsigned left; + char *so, *more_so; + struct hol_entry *e; + unsigned num_entries = hol->num_entries + more->num_entries; + struct hol_entry *entries = + malloc (num_entries * sizeof (struct hol_entry)); + unsigned hol_so_len = strlen (hol->short_options); + char *short_options = + malloc (hol_so_len + strlen (more->short_options) + 1); + + assert (entries && short_options); + if (SIZE_MAX <= UINT_MAX) + assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry)); + + __mempcpy (__mempcpy (entries, hol->entries, + hol->num_entries * sizeof (struct hol_entry)), + more->entries, + more->num_entries * sizeof (struct hol_entry)); + + __mempcpy (short_options, hol->short_options, hol_so_len); + + /* Fix up the short options pointers from HOL. */ + for (e = entries, left = hol->num_entries; left > 0; e++, left--) + e->short_options + = short_options + (e->short_options - hol->short_options); + + /* Now add the short options from MORE, fixing up its entries + too. */ + so = short_options + hol_so_len; + more_so = more->short_options; + for (left = more->num_entries; left > 0; e++, left--) + { + int opts_left; + const struct argp_option *opt; + + e->short_options = so; + + for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--) + { + int ch = *more_so; + if (oshort (opt) && ch == opt->key) + /* The next short option in MORE_SO, CH, is from OPT. */ + { + if (! find_char (ch, short_options, + short_options + hol_so_len)) + /* The short option CH isn't shadowed by HOL's options, + so add it to the sum. */ + *so++ = ch; + more_so++; + } + } + } + + *so = '\0'; + + free (hol->entries); + free (hol->short_options); + + hol->entries = entries; + hol->num_entries = num_entries; + hol->short_options = short_options; + } + } + + hol_free (more); +} + +/* Inserts enough spaces to make sure STREAM is at column COL. */ +static void +indent_to (argp_fmtstream_t stream, unsigned col) +{ + int needed = col - __argp_fmtstream_point (stream); + while (needed-- > 0) + __argp_fmtstream_putc (stream, ' '); +} + +/* Output to STREAM either a space, or a newline if there isn't room for at + least ENSURE characters before the right margin. */ +static void +space (argp_fmtstream_t stream, size_t ensure) +{ + if (__argp_fmtstream_point (stream) + ensure + >= __argp_fmtstream_rmargin (stream)) + __argp_fmtstream_putc (stream, '\n'); + else + __argp_fmtstream_putc (stream, ' '); +} + +/* If the option REAL has an argument, we print it in using the printf + format REQ_FMT or OPT_FMT depending on whether it's a required or + optional argument. */ +static void +arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt, + const char *domain, argp_fmtstream_t stream) +{ + if (real->arg) + { + if (real->flags & OPTION_ARG_OPTIONAL) + __argp_fmtstream_printf (stream, opt_fmt, + dgettext (domain, real->arg)); + else + __argp_fmtstream_printf (stream, req_fmt, + dgettext (domain, real->arg)); + } +} + +/* Helper functions for hol_entry_help. */ + +/* State used during the execution of hol_help. */ +struct hol_help_state +{ + /* PREV_ENTRY should contain the previous entry printed, or 0. */ + struct hol_entry *prev_entry; + + /* If an entry is in a different group from the previous one, and SEP_GROUPS + is true, then a blank line will be printed before any output. */ + int sep_groups; + + /* True if a duplicate option argument was suppressed (only ever set if + UPARAMS.dup_args is false). */ + int suppressed_dup_arg; +}; + +/* Some state used while printing a help entry (used to communicate with + helper functions). See the doc for hol_entry_help for more info, as most + of the fields are copied from its arguments. */ +struct pentry_state +{ + const struct hol_entry *entry; + argp_fmtstream_t stream; + struct hol_help_state *hhstate; + + /* True if nothing's been printed so far. */ + int first; + + /* If non-zero, the state that was used to print this help. */ + const struct argp_state *state; +}; + +/* If a user doc filter should be applied to DOC, do so. */ +static const char * +filter_doc (const char *doc, int key, const struct argp *argp, + const struct argp_state *state) +{ + if (argp && argp->help_filter) + /* We must apply a user filter to this output. */ + { + void *input = __argp_input (argp, state); + return (*argp->help_filter) (key, doc, input); + } + else + /* No filter. */ + return doc; +} + +/* Prints STR as a header line, with the margin lines set appropriately, and + notes the fact that groups should be separated with a blank line. ARGP is + the argp that should dictate any user doc filtering to take place. Note + that the previous wrap margin isn't restored, but the left margin is reset + to 0. */ +static void +print_header (const char *str, const struct argp *argp, + struct pentry_state *pest) +{ + const char *tstr = dgettext (argp->argp_domain, str); + const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state); + + if (fstr) + { + if (*fstr) + { + if (pest->hhstate->prev_entry) + /* Precede with a blank line. */ + __argp_fmtstream_putc (pest->stream, '\n'); + indent_to (pest->stream, uparams.header_col); + __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col); + __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col); + __argp_fmtstream_puts (pest->stream, fstr); + __argp_fmtstream_set_lmargin (pest->stream, 0); + __argp_fmtstream_putc (pest->stream, '\n'); + } + + pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */ + } + + if (fstr != tstr) + free ((char *) fstr); +} + +/* Inserts a comma if this isn't the first item on the line, and then makes + sure we're at least to column COL. If this *is* the first item on a line, + prints any pending whitespace/headers that should precede this line. Also + clears FIRST. */ +static void +comma (unsigned col, struct pentry_state *pest) +{ + if (pest->first) + { + const struct hol_entry *pe = pest->hhstate->prev_entry; + const struct hol_cluster *cl = pest->entry->cluster; + + if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group) + __argp_fmtstream_putc (pest->stream, '\n'); + + if (cl && cl->header && *cl->header + && (!pe + || (pe->cluster != cl + && !hol_cluster_is_child (pe->cluster, cl)))) + /* If we're changing clusters, then this must be the start of the + ENTRY's cluster unless that is an ancestor of the previous one + (in which case we had just popped into a sub-cluster for a bit). + If so, then print the cluster's header line. */ + { + int old_wm = __argp_fmtstream_wmargin (pest->stream); + print_header (cl->header, cl->argp, pest); + __argp_fmtstream_set_wmargin (pest->stream, old_wm); + } + + pest->first = 0; + } + else + __argp_fmtstream_puts (pest->stream, ", "); + + indent_to (pest->stream, col); +} + +/* Print help for ENTRY to STREAM. */ +static void +hol_entry_help (struct hol_entry *entry, const struct argp_state *state, + argp_fmtstream_t stream, struct hol_help_state *hhstate) +{ + unsigned num; + const struct argp_option *real = entry->opt, *opt; + char *so = entry->short_options; + int have_long_opt = 0; /* We have any long options. */ + /* Saved margins. */ + int old_lm = __argp_fmtstream_set_lmargin (stream, 0); + int old_wm = __argp_fmtstream_wmargin (stream); + /* PEST is a state block holding some of our variables that we'd like to + share with helper functions. */ + struct pentry_state pest = { entry, stream, hhstate, 1, state }; + + if (! odoc (real)) + for (opt = real, num = entry->num; num > 0; opt++, num--) + if (opt->name && ovisible (opt)) + { + have_long_opt = 1; + break; + } + + /* First emit short options. */ + __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */ + for (opt = real, num = entry->num; num > 0; opt++, num--) + if (oshort (opt) && opt->key == *so) + /* OPT has a valid (non shadowed) short option. */ + { + if (ovisible (opt)) + { + comma (uparams.short_opt_col, &pest); + __argp_fmtstream_putc (stream, '-'); + __argp_fmtstream_putc (stream, *so); + if (!have_long_opt || uparams.dup_args) + arg (real, " %s", "[%s]", + state == NULL ? NULL : state->root_argp->argp_domain, + stream); + else if (real->arg) + hhstate->suppressed_dup_arg = 1; + } + so++; + } + + /* Now, long options. */ + if (odoc (real)) + /* A "documentation" option. */ + { + __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); + for (opt = real, num = entry->num; num > 0; opt++, num--) + if (opt->name && ovisible (opt)) + { + comma (uparams.doc_opt_col, &pest); + /* Calling dgettext here isn't quite right, since sorting will + have been done on the original; but documentation options + should be pretty rare anyway... */ + __argp_fmtstream_puts (stream, + dgettext (state == NULL ? NULL + : state->root_argp->argp_domain, + opt->name)); + } + } + else + /* A real long option. */ + { + __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col); + for (opt = real, num = entry->num; num > 0; opt++, num--) + if (opt->name && ovisible (opt)) + { + comma (uparams.long_opt_col, &pest); + __argp_fmtstream_printf (stream, "--%s", opt->name); + arg (real, "=%s", "[=%s]", + state == NULL ? NULL : state->root_argp->argp_domain, stream); + } + } + + /* Next, documentation strings. */ + __argp_fmtstream_set_lmargin (stream, 0); + + if (pest.first) + { + /* Didn't print any switches, what's up? */ + if (!oshort (real) && !real->name) + /* This is a group header, print it nicely. */ + print_header (real->doc, entry->argp, &pest); + else + /* Just a totally shadowed option or null header; print nothing. */ + goto cleanup; /* Just return, after cleaning up. */ + } + else + { + const char *tstr = real->doc ? dgettext (state == NULL ? NULL + : state->root_argp->argp_domain, + real->doc) : 0; + const char *fstr = filter_doc (tstr, real->key, entry->argp, state); + if (fstr && *fstr) + { + unsigned int col = __argp_fmtstream_point (stream); + + __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col); + __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col); + + if (col > (unsigned int) (uparams.opt_doc_col + 3)) + __argp_fmtstream_putc (stream, '\n'); + else if (col >= (unsigned int) uparams.opt_doc_col) + __argp_fmtstream_puts (stream, " "); + else + indent_to (stream, uparams.opt_doc_col); + + __argp_fmtstream_puts (stream, fstr); + } + if (fstr && fstr != tstr) + free ((char *) fstr); + + /* Reset the left margin. */ + __argp_fmtstream_set_lmargin (stream, 0); + __argp_fmtstream_putc (stream, '\n'); + } + + hhstate->prev_entry = entry; + +cleanup: + __argp_fmtstream_set_lmargin (stream, old_lm); + __argp_fmtstream_set_wmargin (stream, old_wm); +} + +/* Output a long help message about the options in HOL to STREAM. */ +static void +hol_help (struct hol *hol, const struct argp_state *state, + argp_fmtstream_t stream) +{ + unsigned num; + struct hol_entry *entry; + struct hol_help_state hhstate = { 0, 0, 0 }; + + for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--) + hol_entry_help (entry, state, stream, &hhstate); + + if (hhstate.suppressed_dup_arg && uparams.dup_args_note) + { + const char *tstr = dgettext (state == NULL ? NULL + : state->root_argp->argp_domain, "\ +Mandatory or optional arguments to long options are also mandatory or \ +optional for any corresponding short options."); + const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE, + state ? state->root_argp : 0, state); + if (fstr && *fstr) + { + __argp_fmtstream_putc (stream, '\n'); + __argp_fmtstream_puts (stream, fstr); + __argp_fmtstream_putc (stream, '\n'); + } + if (fstr && fstr != tstr) + free ((char *) fstr); + } +} + +/* Helper functions for hol_usage. */ + +/* If OPT is a short option without an arg, append its key to the string + pointer pointer to by COOKIE, and advance the pointer. */ +static int +add_argless_short_opt (const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie) +{ + char **snao_end = cookie; + if (!(opt->arg || real->arg) + && !((opt->flags | real->flags) & OPTION_NO_USAGE)) + *(*snao_end)++ = opt->key; + return 0; +} + +/* If OPT is a short option with an arg, output a usage entry for it to the + stream pointed at by COOKIE. */ +static int +usage_argful_short_opt (const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie) +{ + argp_fmtstream_t stream = cookie; + const char *arg = opt->arg; + int flags = opt->flags | real->flags; + + if (! arg) + arg = real->arg; + + if (arg && !(flags & OPTION_NO_USAGE)) + { + arg = dgettext (domain, arg); + + if (flags & OPTION_ARG_OPTIONAL) + __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg); + else + { + /* Manually do line wrapping so that it (probably) won't + get wrapped at the embedded space. */ + space (stream, 6 + strlen (arg)); + __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg); + } + } + + return 0; +} + +/* Output a usage entry for the long option opt to the stream pointed at by + COOKIE. */ +static int +usage_long_opt (const struct argp_option *opt, + const struct argp_option *real, + const char *domain, void *cookie) +{ + argp_fmtstream_t stream = cookie; + const char *arg = opt->arg; + int flags = opt->flags | real->flags; + + if (! arg) + arg = real->arg; + + if (! (flags & OPTION_NO_USAGE)) + { + if (arg) + { + arg = dgettext (domain, arg); + if (flags & OPTION_ARG_OPTIONAL) + __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg); + else + __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg); + } + else + __argp_fmtstream_printf (stream, " [--%s]", opt->name); + } + + return 0; +} + +/* Print a short usage description for the arguments in HOL to STREAM. */ +static void +hol_usage (struct hol *hol, argp_fmtstream_t stream) +{ + if (hol->num_entries > 0) + { + unsigned nentries; + struct hol_entry *entry; + char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1); + char *snao_end = short_no_arg_opts; + + /* First we put a list of short options without arguments. */ + for (entry = hol->entries, nentries = hol->num_entries + ; nentries > 0 + ; entry++, nentries--) + hol_entry_short_iterate (entry, add_argless_short_opt, + entry->argp->argp_domain, &snao_end); + if (snao_end > short_no_arg_opts) + { + *snao_end++ = 0; + __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts); + } + + /* Now a list of short options *with* arguments. */ + for (entry = hol->entries, nentries = hol->num_entries + ; nentries > 0 + ; entry++, nentries--) + hol_entry_short_iterate (entry, usage_argful_short_opt, + entry->argp->argp_domain, stream); + + /* Finally, a list of long options (whew!). */ + for (entry = hol->entries, nentries = hol->num_entries + ; nentries > 0 + ; entry++, nentries--) + hol_entry_long_iterate (entry, usage_long_opt, + entry->argp->argp_domain, stream); + } +} + +/* Make a HOL containing all levels of options in ARGP. CLUSTER is the + cluster in which ARGP's entries should be clustered, or 0. */ +static struct hol * +argp_hol (const struct argp *argp, struct hol_cluster *cluster) +{ + const struct argp_child *child = argp->children; + struct hol *hol = make_hol (argp, cluster); + if (child) + while (child->argp) + { + struct hol_cluster *child_cluster = + ((child->group || child->header) + /* Put CHILD->argp within its own cluster. */ + ? hol_add_cluster (hol, child->group, child->header, + child - argp->children, cluster, argp) + /* Just merge it into the parent's cluster. */ + : cluster); + hol_append (hol, argp_hol (child->argp, child_cluster)) ; + child++; + } + return hol; +} + +/* Calculate how many different levels with alternative args strings exist in + ARGP. */ +static size_t +argp_args_levels (const struct argp *argp) +{ + size_t levels = 0; + const struct argp_child *child = argp->children; + + if (argp->args_doc && strchr (argp->args_doc, '\n')) + levels++; + + if (child) + while (child->argp) + levels += argp_args_levels ((child++)->argp); + + return levels; +} + +/* Print all the non-option args documented in ARGP to STREAM. Any output is + preceded by a space. LEVELS is a pointer to a byte vector the length + returned by argp_args_levels; it should be initialized to zero, and + updated by this routine for the next call if ADVANCE is true. True is + returned as long as there are more patterns to output. */ +static int +argp_args_usage (const struct argp *argp, const struct argp_state *state, + char **levels, int advance, argp_fmtstream_t stream) +{ + char *our_level = *levels; + int multiple = 0; + const struct argp_child *child = argp->children; + const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0; + const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state); + + if (fdoc) + { + const char *cp = fdoc; + nl = __strchrnul (cp, '\n'); + if (*nl != '\0') + /* This is a 'multi-level' args doc; advance to the correct position + as determined by our state in LEVELS, and update LEVELS. */ + { + int i; + multiple = 1; + for (i = 0; i < *our_level; i++) + cp = nl + 1, nl = __strchrnul (cp, '\n'); + (*levels)++; + } + + /* Manually do line wrapping so that it (probably) won't get wrapped at + any embedded spaces. */ + space (stream, 1 + mbsnwidth (cp, nl - cp, MBSW_STOP_AT_NUL)); + + __argp_fmtstream_write (stream, cp, nl - cp); + } + if (fdoc && fdoc != tdoc) + free ((char *)fdoc); /* Free user's modified doc string. */ + + if (child) + while (child->argp) + advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream); + + if (advance && multiple) + { + /* Need to increment our level. */ + if (*nl) + /* There's more we can do here. */ + { + (*our_level)++; + advance = 0; /* Our parent shouldn't advance also. */ + } + else if (*our_level > 0) + /* We had multiple levels, but used them up; reset to zero. */ + *our_level = 0; + } + + return !advance; +} + +/* Print the documentation for ARGP to STREAM; if POST is false, then + everything preceding a '\v' character in the documentation strings (or + the whole string, for those with none) is printed, otherwise, everything + following the '\v' character (nothing for strings without). Each separate + bit of documentation is separated a blank line, and if PRE_BLANK is true, + then the first is as well. If FIRST_ONLY is true, only the first + occurrence is output. Returns true if anything was output. */ +static int +argp_doc (const struct argp *argp, const struct argp_state *state, + int post, int pre_blank, int first_only, + argp_fmtstream_t stream) +{ + const char *text; + const char *inp_text; + void *input = 0; + int anything = 0; + size_t inp_text_limit = 0; + const char *doc = dgettext (argp->argp_domain, argp->doc); + const struct argp_child *child = argp->children; + + if (doc) + { + char *vt = strchr (doc, '\v'); + inp_text = post ? (vt ? vt + 1 : 0) : doc; + inp_text_limit = (!post && vt) ? (vt - doc) : 0; + } + else + inp_text = 0; + + if (argp->help_filter) + /* We have to filter the doc strings. */ + { + if (inp_text_limit) + /* Copy INP_TEXT so that it's nul-terminated. */ + inp_text = __strndup (inp_text, inp_text_limit); + input = __argp_input (argp, state); + text = + (*argp->help_filter) (post + ? ARGP_KEY_HELP_POST_DOC + : ARGP_KEY_HELP_PRE_DOC, + inp_text, input); + } + else + text = (const char *) inp_text; + + if (text) + { + if (pre_blank) + __argp_fmtstream_putc (stream, '\n'); + + if (text == inp_text && inp_text_limit) + __argp_fmtstream_write (stream, inp_text, inp_text_limit); + else + __argp_fmtstream_puts (stream, text); + + if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream)) + __argp_fmtstream_putc (stream, '\n'); + + anything = 1; + } + + if (text && text != inp_text) + free ((char *) text); /* Free TEXT returned from the help filter. */ + if (inp_text && inp_text_limit && argp->help_filter) + free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */ + + if (post && argp->help_filter) + /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text. */ + { + text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input); + if (text) + { + if (anything || pre_blank) + __argp_fmtstream_putc (stream, '\n'); + __argp_fmtstream_puts (stream, text); + free ((char *) text); + if (__argp_fmtstream_point (stream) + > __argp_fmtstream_lmargin (stream)) + __argp_fmtstream_putc (stream, '\n'); + anything = 1; + } + } + + if (child) + while (child->argp && !(first_only && anything)) + anything |= + argp_doc ((child++)->argp, state, + post, anything || pre_blank, first_only, + stream); + + return anything; +} + +/* Output a usage message for ARGP to STREAM. If called from + argp_state_help, STATE is the relevent parsing state. FLAGS are from the + set ARGP_HELP_*. NAME is what to use wherever a 'program name' is + needed. */ +static void +_help (const struct argp *argp, const struct argp_state *state, FILE *stream, + unsigned flags, char *name) +{ + int anything = 0; /* Whether we've output anything. */ + struct hol *hol = 0; + argp_fmtstream_t fs; + + if (! stream) + return; + +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __flockfile (stream); +#endif + + if (! uparams.valid) + fill_in_uparams (state); + + fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); + if (! fs) + { +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __funlockfile (stream); +#endif + return; + } + + if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG)) + { + hol = argp_hol (argp, 0); + + /* If present, these options always come last. */ + hol_set_group (hol, "help", -1); + hol_set_group (hol, "version", -1); + + hol_sort (hol); + } + + if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE)) + /* Print a short "Usage:" message. */ + { + int first_pattern = 1, more_patterns; + size_t num_pattern_levels = argp_args_levels (argp); + char *pattern_levels = alloca (num_pattern_levels); + + memset (pattern_levels, 0, num_pattern_levels); + + do + { + int old_lm; + int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent); + char *levels = pattern_levels; + + if (first_pattern) + __argp_fmtstream_printf (fs, "%s %s", + dgettext (argp->argp_domain, "Usage:"), + name); + else + __argp_fmtstream_printf (fs, "%s %s", + dgettext (argp->argp_domain, " or: "), + name); + + /* We set the lmargin as well as the wmargin, because hol_usage + manually wraps options with newline to avoid annoying breaks. */ + old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent); + + if (flags & ARGP_HELP_SHORT_USAGE) + /* Just show where the options go. */ + { + if (hol->num_entries > 0) + __argp_fmtstream_puts (fs, dgettext (argp->argp_domain, + " [OPTION...]")); + } + else + /* Actually print the options. */ + { + hol_usage (hol, fs); + flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once. */ + } + + more_patterns = argp_args_usage (argp, state, &levels, 1, fs); + + __argp_fmtstream_set_wmargin (fs, old_wm); + __argp_fmtstream_set_lmargin (fs, old_lm); + + __argp_fmtstream_putc (fs, '\n'); + anything = 1; + + first_pattern = 0; + } + while (more_patterns); + } + + if (flags & ARGP_HELP_PRE_DOC) + anything |= argp_doc (argp, state, 0, 0, 1, fs); + + if (flags & ARGP_HELP_SEE) + { + __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\ +Try '%s --help' or '%s --usage' for more information.\n"), + name, name); + anything = 1; + } + + if (flags & ARGP_HELP_LONG) + /* Print a long, detailed help message. */ + { + /* Print info about all the options. */ + if (hol->num_entries > 0) + { + if (anything) + __argp_fmtstream_putc (fs, '\n'); + hol_help (hol, state, fs); + anything = 1; + } + } + + if (flags & ARGP_HELP_POST_DOC) + /* Print any documentation strings at the end. */ + anything |= argp_doc (argp, state, 1, anything, 0, fs); + + if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address) + { + if (anything) + __argp_fmtstream_putc (fs, '\n'); + __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, + "Report bugs to %s.\n"), + argp_program_bug_address); + anything = 1; + } + +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __funlockfile (stream); +#endif + + if (hol) + hol_free (hol); + + __argp_fmtstream_free (fs); +} + +/* Output a usage message for ARGP to STREAM. FLAGS are from the set + ARGP_HELP_*. NAME is what to use wherever a 'program name' is needed. */ +void __argp_help (const struct argp *argp, FILE *stream, + unsigned flags, char *name) +{ + _help (argp, 0, stream, flags, name); +} +#ifdef weak_alias +weak_alias (__argp_help, argp_help) +#endif + +#if ! (defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME) +char * +__argp_short_program_name (void) +{ +# if HAVE_DECL_PROGRAM_INVOCATION_NAME + char *name = strrchr (program_invocation_name, '/'); + return name ? name + 1 : program_invocation_name; +# else + /* FIXME: What now? Miles suggests that it is better to use NULL, + but currently the value is passed on directly to fputs_unlocked, + so that requires more changes. */ +# if __GNUC__ +# warning No reasonable value to return +# endif /* __GNUC__ */ + return ""; +# endif +} +#endif + +/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are + from the set ARGP_HELP_*. */ +void +__argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) +{ + if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream) + { + if (state && (state->flags & ARGP_LONG_ONLY)) + flags |= ARGP_HELP_LONG_ONLY; + + _help (state ? state->root_argp : 0, state, stream, flags, + state ? state->name : __argp_short_program_name ()); + + if (!state || ! (state->flags & ARGP_NO_EXIT)) + { + if (flags & ARGP_HELP_EXIT_ERR) + exit (argp_err_exit_status); + if (flags & ARGP_HELP_EXIT_OK) + exit (0); + } + } +} +#ifdef weak_alias +weak_alias (__argp_state_help, argp_state_help) +#endif + +/* If appropriate, print the printf string FMT and following args, preceded + by the program name and ':', to stderr, and followed by a "Try ... --help" + message, then exit (1). */ +void +__argp_error (const struct argp_state *state, const char *fmt, ...) +{ + if (!state || !(state->flags & ARGP_NO_ERRS)) + { + FILE *stream = state ? state->err_stream : stderr; + + if (stream) + { + va_list ap; + +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __flockfile (stream); +#endif + + va_start (ap, fmt); + +#ifdef _LIBC + char *buf; + + if (_IO_vasprintf (&buf, fmt, ap) < 0) + buf = NULL; + + __fxprintf (stream, "%s: %s\n", + state ? state->name : __argp_short_program_name (), buf); + + free (buf); +#else + fputs_unlocked (state ? state->name : __argp_short_program_name (), + stream); + putc_unlocked (':', stream); + putc_unlocked (' ', stream); + + vfprintf (stream, fmt, ap); + + putc_unlocked ('\n', stream); +#endif + + __argp_state_help (state, stream, ARGP_HELP_STD_ERR); + + va_end (ap); + +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __funlockfile (stream); +#endif + } + } +} +#ifdef weak_alias +weak_alias (__argp_error, argp_error) +#endif + +/* Similar to the standard gnu error-reporting function error(), but will + respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print + to STATE->err_stream. This is useful for argument parsing code that is + shared between program startup (when exiting is desired) and runtime + option parsing (when typically an error code is returned instead). The + difference between this function and argp_error is that the latter is for + *parsing errors*, and the former is for other problems that occur during + parsing but don't reflect a (syntactic) problem with the input. */ +void +__argp_failure (const struct argp_state *state, int status, int errnum, + const char *fmt, ...) +{ + if (!state || !(state->flags & ARGP_NO_ERRS)) + { + FILE *stream = state ? state->err_stream : stderr; + + if (stream) + { +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __flockfile (stream); +#endif + +#ifdef _LIBC + __fxprintf (stream, "%s", + state ? state->name : __argp_short_program_name ()); +#else + fputs_unlocked (state ? state->name : __argp_short_program_name (), + stream); +#endif + + if (fmt) + { + va_list ap; + + va_start (ap, fmt); +#ifdef _LIBC + char *buf; + + if (_IO_vasprintf (&buf, fmt, ap) < 0) + buf = NULL; + + __fxprintf (stream, ": %s", buf); + + free (buf); +#else + putc_unlocked (':', stream); + putc_unlocked (' ', stream); + + vfprintf (stream, fmt, ap); +#endif + + va_end (ap); + } + + if (errnum) + { + char buf[200]; + +#ifdef _LIBC + __fxprintf (stream, ": %s", + __strerror_r (errnum, buf, sizeof (buf))); +#else + char const *s = NULL; + putc_unlocked (':', stream); + putc_unlocked (' ', stream); +# if GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R +# if !GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P + s = __strerror_r (errnum, buf, sizeof buf); +# else + if (__strerror_r (errnum, buf, sizeof buf) == 0) + s = buf; +# endif +# endif + if (! s && ! (s = strerror (errnum))) + s = dgettext (state->root_argp->argp_domain, + "Unknown system error"); + fputs_unlocked (s, stream); +#endif + } + +#if _LIBC + if (_IO_fwide (stream, 0) > 0) + putwc_unlocked (L'\n', stream); + else +#endif + putc_unlocked ('\n', stream); + +#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) + __funlockfile (stream); +#endif + + if (status && (!state || !(state->flags & ARGP_NO_EXIT))) + exit (status); + } + } +} +#ifdef weak_alias +weak_alias (__argp_failure, argp_failure) +#endif diff --git a/grub-core/lib/gnulib/argp-namefrob.h b/grub-core/lib/gnulib/argp-namefrob.h new file mode 100644 index 0000000..2fb9ac4 --- /dev/null +++ b/grub-core/lib/gnulib/argp-namefrob.h @@ -0,0 +1,157 @@ +/* Name frobnication for compiling argp outside of glibc + Copyright (C) 1997-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#if !_LIBC +/* This code is written for inclusion in gnu-libc, and uses names in the + namespace reserved for libc. If we're not compiling in libc, define those + names to be the normal ones instead. */ + +/* argp-parse functions */ +#undef __argp_parse +#define __argp_parse argp_parse +#undef __option_is_end +#define __option_is_end _option_is_end +#undef __option_is_short +#define __option_is_short _option_is_short +#undef __argp_input +#define __argp_input _argp_input + +/* argp-help functions */ +#undef __argp_help +#define __argp_help argp_help +#undef __argp_error +#define __argp_error argp_error +#undef __argp_failure +#define __argp_failure argp_failure +#undef __argp_state_help +#define __argp_state_help argp_state_help +#undef __argp_usage +#define __argp_usage argp_usage + +/* argp-fmtstream functions */ +#undef __argp_make_fmtstream +#define __argp_make_fmtstream argp_make_fmtstream +#undef __argp_fmtstream_free +#define __argp_fmtstream_free argp_fmtstream_free +#undef __argp_fmtstream_putc +#define __argp_fmtstream_putc argp_fmtstream_putc +#undef __argp_fmtstream_puts +#define __argp_fmtstream_puts argp_fmtstream_puts +#undef __argp_fmtstream_write +#define __argp_fmtstream_write argp_fmtstream_write +#undef __argp_fmtstream_printf +#define __argp_fmtstream_printf argp_fmtstream_printf +#undef __argp_fmtstream_set_lmargin +#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin +#undef __argp_fmtstream_set_rmargin +#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin +#undef __argp_fmtstream_set_wmargin +#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin +#undef __argp_fmtstream_point +#define __argp_fmtstream_point argp_fmtstream_point +#undef __argp_fmtstream_update +#define __argp_fmtstream_update _argp_fmtstream_update +#undef __argp_fmtstream_ensure +#define __argp_fmtstream_ensure _argp_fmtstream_ensure +#undef __argp_fmtstream_lmargin +#define __argp_fmtstream_lmargin argp_fmtstream_lmargin +#undef __argp_fmtstream_rmargin +#define __argp_fmtstream_rmargin argp_fmtstream_rmargin +#undef __argp_fmtstream_wmargin +#define __argp_fmtstream_wmargin argp_fmtstream_wmargin + +/* normal libc functions we call */ +#undef __flockfile +#define __flockfile flockfile +#undef __funlockfile +#define __funlockfile funlockfile +#undef __mempcpy +#define __mempcpy mempcpy +#undef __sleep +#define __sleep sleep +#undef __strcasecmp +#define __strcasecmp strcasecmp +#undef __strchrnul +#define __strchrnul strchrnul +#undef __strerror_r +#define __strerror_r strerror_r +#undef __strndup +#define __strndup strndup +#undef __vsnprintf +#define __vsnprintf vsnprintf + +#if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED +# define clearerr_unlocked(x) clearerr (x) +#endif +#if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED +# define feof_unlocked(x) feof (x) +#endif +#if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED +# define ferror_unlocked(x) ferror (x) +#endif +#if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED +# define fflush_unlocked(x) fflush (x) +#endif +#if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED +# define fgets_unlocked(x,y,z) fgets (x,y,z) +#endif +#if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED +# define fputc_unlocked(x,y) fputc (x,y) +#endif +#if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED +# define fputs_unlocked(x,y) fputs (x,y) +#endif +#if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED +# define fread_unlocked(w,x,y,z) fread (w,x,y,z) +#endif +#if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED +# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) +#endif +#if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED +# define getc_unlocked(x) getc (x) +#endif +#if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED +# define getchar_unlocked() getchar () +#endif +#if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED +# define putc_unlocked(x,y) putc (x,y) +#endif +#if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED +# define putchar_unlocked(x) putchar (x) +#endif + +#endif /* !_LIBC */ + +#ifndef __set_errno +#define __set_errno(e) (errno = (e)) +#endif + +#if defined GNULIB_ARGP_DISABLE_DIRNAME +# define __argp_base_name(arg) arg +#elif defined GNULIB_ARGP_EXTERN_BASENAME +extern char *__argp_base_name (const char *arg); +#else +# include "dirname.h" +# define __argp_base_name last_component +#endif + +#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME +# define __argp_short_program_name() (program_invocation_short_name) +#else +extern char *__argp_short_program_name (void); +#endif diff --git a/grub-core/lib/gnulib/argp-parse.c b/grub-core/lib/gnulib/argp-parse.c new file mode 100644 index 0000000..900adad --- /dev/null +++ b/grub-core/lib/gnulib/argp-parse.c @@ -0,0 +1,957 @@ +/* Hierarchical argument parsing, layered over getopt + Copyright (C) 1995-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <alloca.h> +#include <stdalign.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> +#include <getopt.h> +#include <getopt_int.h> + +#ifdef _LIBC +# include <libintl.h> +# undef dgettext +# define dgettext(domain, msgid) \ + __dcgettext (domain, msgid, LC_MESSAGES) +#else +# include "gettext.h" +#endif +#define N_(msgid) msgid + +#include "argp.h" +#include "argp-namefrob.h" + +#define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d)) + +/* Getopt return values. */ +#define KEY_END (-1) /* The end of the options. */ +#define KEY_ARG 1 /* A non-option argument. */ +#define KEY_ERR '?' /* An error parsing the options. */ + +/* The meta-argument used to prevent any further arguments being interpreted + as options. */ +#define QUOTE "--" + +/* The number of bits we steal in a long-option value for our own use. */ +#define GROUP_BITS CHAR_BIT + +/* The number of bits available for the user value. */ +#define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS) +#define USER_MASK ((1 << USER_BITS) - 1) + +/* EZ alias for ARGP_ERR_UNKNOWN. */ +#define EBADKEY ARGP_ERR_UNKNOWN + +/* Default options. */ + +/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep + for one second intervals, decrementing _ARGP_HANG until it's zero. Thus + you can force the program to continue by attaching a debugger and setting + it to 0 yourself. */ +static volatile int _argp_hang; + +#define OPT_PROGNAME -2 +#define OPT_USAGE -3 +#define OPT_HANG -4 + +static const struct argp_option argp_default_options[] = +{ + {"help", '?', 0, 0, N_("give this help list"), -1}, + {"usage", OPT_USAGE, 0, 0, N_("give a short usage message"), 0}, + {"program-name",OPT_PROGNAME, N_("NAME"), OPTION_HIDDEN, + N_("set the program name"), 0}, + {"HANG", OPT_HANG, N_("SECS"), OPTION_ARG_OPTIONAL | OPTION_HIDDEN, + N_("hang for SECS seconds (default 3600)"), 0}, + {NULL, 0, 0, 0, NULL, 0} +}; + +static error_t +argp_default_parser (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case '?': + __argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP); + break; + case OPT_USAGE: + __argp_state_help (state, state->out_stream, + ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); + break; + + case OPT_PROGNAME: /* Set the program name. */ +#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME + program_invocation_name = arg; +#endif + /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka + __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined + to be that, so we have to be a bit careful here.] */ + + /* Update what we use for messages. */ + state->name = __argp_base_name (arg); + +#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME + program_invocation_short_name = state->name; +#endif + + if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS)) + == ARGP_PARSE_ARGV0) + /* Update what getopt uses too. */ + state->argv[0] = arg; + + break; + + case OPT_HANG: + _argp_hang = atoi (arg ? arg : "3600"); + while (_argp_hang-- > 0) + __sleep (1); + break; + + default: + return EBADKEY; + } + return 0; +} + +static const struct argp argp_default_argp = + {argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"}; + + +static const struct argp_option argp_version_options[] = +{ + {"version", 'V', 0, 0, N_("print program version"), -1}, + {NULL, 0, 0, 0, NULL, 0} +}; + +static error_t +argp_version_parser (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case 'V': + if (argp_program_version_hook) + (*argp_program_version_hook) (state->out_stream, state); + else if (argp_program_version) + fprintf (state->out_stream, "%s\n", argp_program_version); + else + __argp_error (state, "%s", + dgettext (state->root_argp->argp_domain, + "(PROGRAM ERROR) No version known!?")); + if (! (state->flags & ARGP_NO_EXIT)) + exit (0); + break; + default: + return EBADKEY; + } + return 0; +} + +static const struct argp argp_version_argp = + {argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"}; + +/* Returns the offset into the getopt long options array LONG_OPTIONS of a + long option with called NAME, or -1 if none is found. Passing NULL as + NAME will return the number of options. */ +static int +find_long_option (struct option *long_options, const char *name) +{ + struct option *l = long_options; + while (l->name != NULL) + if (name != NULL && strcmp (l->name, name) == 0) + return l - long_options; + else + l++; + if (name == NULL) + return l - long_options; + else + return -1; +} + + +/* The state of a "group" during parsing. Each group corresponds to a + particular argp structure from the tree of such descending from the top + level argp passed to argp_parse. */ +struct group +{ + /* This group's parsing function. */ + argp_parser_t parser; + + /* Which argp this group is from. */ + const struct argp *argp; + + /* Points to the point in SHORT_OPTS corresponding to the end of the short + options for this group. We use it to determine from which group a + particular short options is from. */ + char *short_end; + + /* The number of non-option args successfully handled by this parser. */ + unsigned args_processed; + + /* This group's parser's parent's group. */ + struct group *parent; + unsigned parent_index; /* And the our position in the parent. */ + + /* These fields are swapped into and out of the state structure when + calling this group's parser. */ + void *input, **child_inputs; + void *hook; +}; + +/* Call GROUP's parser with KEY and ARG, swapping any group-specific info + from STATE before calling, and back into state afterwards. If GROUP has + no parser, EBADKEY is returned. */ +static error_t +group_parse (struct group *group, struct argp_state *state, int key, char *arg) +{ + if (group->parser) + { + error_t err; + state->hook = group->hook; + state->input = group->input; + state->child_inputs = group->child_inputs; + state->arg_num = group->args_processed; + err = (*group->parser)(key, arg, state); + group->hook = state->hook; + return err; + } + else + return EBADKEY; +} + +struct parser +{ + const struct argp *argp; + + /* SHORT_OPTS is the getopt short options string for the union of all the + groups of options. */ + char *short_opts; + /* LONG_OPTS is the array of getop long option structures for the union of + all the groups of options. */ + struct option *long_opts; + /* OPT_DATA is the getopt data used for the re-entrant getopt. */ + struct _getopt_data opt_data; + + /* States of the various parsing groups. */ + struct group *groups; + /* The end of the GROUPS array. */ + struct group *egroup; + /* A vector containing storage for the CHILD_INPUTS field in all groups. */ + void **child_inputs; + + /* True if we think using getopt is still useful; if false, then + remaining arguments are just passed verbatim with ARGP_KEY_ARG. This is + cleared whenever getopt returns KEY_END, but may be set again if the user + moves the next argument pointer backwards. */ + int try_getopt; + + /* State block supplied to parsing routines. */ + struct argp_state state; + + /* Memory used by this parser. */ + void *storage; +}; + +/* The next usable entries in the various parser tables being filled in by + convert_options. */ +struct parser_convert_state +{ + struct parser *parser; + char *short_end; + struct option *long_end; + void **child_inputs_end; +}; + +/* Converts all options in ARGP (which is put in GROUP) and ancestors + into getopt options stored in SHORT_OPTS and LONG_OPTS; SHORT_END and + CVT->LONG_END are the points at which new options are added. Returns the + next unused group entry. CVT holds state used during the conversion. */ +static struct group * +convert_options (const struct argp *argp, + struct group *parent, unsigned parent_index, + struct group *group, struct parser_convert_state *cvt) +{ + /* REAL is the most recent non-alias value of OPT. */ + const struct argp_option *real = argp->options; + const struct argp_child *children = argp->children; + + if (real || argp->parser) + { + const struct argp_option *opt; + + if (real) + for (opt = real; !__option_is_end (opt); opt++) + { + if (! (opt->flags & OPTION_ALIAS)) + /* OPT isn't an alias, so we can use values from it. */ + real = opt; + + if (! (real->flags & OPTION_DOC)) + /* A real option (not just documentation). */ + { + if (__option_is_short (opt)) + /* OPT can be used as a short option. */ + { + *cvt->short_end++ = opt->key; + if (real->arg) + { + *cvt->short_end++ = ':'; + if (real->flags & OPTION_ARG_OPTIONAL) + *cvt->short_end++ = ':'; + } + *cvt->short_end = '\0'; /* keep 0 terminated */ + } + + if (opt->name + && find_long_option (cvt->parser->long_opts, opt->name) < 0) + /* OPT can be used as a long option. */ + { + cvt->long_end->name = opt->name; + cvt->long_end->has_arg = + (real->arg + ? (real->flags & OPTION_ARG_OPTIONAL + ? optional_argument + : required_argument) + : no_argument); + cvt->long_end->flag = 0; + /* we add a disambiguating code to all the user's + values (which is removed before we actually call + the function to parse the value); this means that + the user loses use of the high 8 bits in all his + values (the sign of the lower bits is preserved + however)... */ + cvt->long_end->val = + ((opt->key ? opt->key : real->key) & USER_MASK) + + (((group - cvt->parser->groups) + 1) << USER_BITS); + + /* Keep the LONG_OPTS list terminated. */ + (++cvt->long_end)->name = NULL; + } + } + } + + group->parser = argp->parser; + group->argp = argp; + group->short_end = cvt->short_end; + group->args_processed = 0; + group->parent = parent; + group->parent_index = parent_index; + group->input = 0; + group->hook = 0; + group->child_inputs = 0; + + if (children) + /* Assign GROUP's CHILD_INPUTS field some space from + CVT->child_inputs_end.*/ + { + unsigned num_children = 0; + while (children[num_children].argp) + num_children++; + group->child_inputs = cvt->child_inputs_end; + cvt->child_inputs_end += num_children; + } + + parent = group++; + } + else + parent = 0; + + if (children) + { + unsigned index = 0; + while (children->argp) + group = + convert_options (children++->argp, parent, index++, group, cvt); + } + + return group; +} + +/* Find the merged set of getopt options, with keys appropriately prefixed. */ +static void +parser_convert (struct parser *parser, const struct argp *argp, int flags) +{ + struct parser_convert_state cvt; + + cvt.parser = parser; + cvt.short_end = parser->short_opts; + cvt.long_end = parser->long_opts; + cvt.child_inputs_end = parser->child_inputs; + + if (flags & ARGP_IN_ORDER) + *cvt.short_end++ = '-'; + else if (flags & ARGP_NO_ARGS) + *cvt.short_end++ = '+'; + *cvt.short_end = '\0'; + + cvt.long_end->name = NULL; + + parser->argp = argp; + + if (argp) + parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt); + else + parser->egroup = parser->groups; /* No parsers at all! */ +} + +/* Lengths of various parser fields which we will allocated. */ +struct parser_sizes +{ + size_t short_len; /* Getopt short options string. */ + size_t long_len; /* Getopt long options vector. */ + size_t num_groups; /* Group structures we allocate. */ + size_t num_child_inputs; /* Child input slots. */ +}; + +/* For ARGP, increments the NUM_GROUPS field in SZS by the total number of + argp structures descended from it, and the SHORT_LEN & LONG_LEN fields by + the maximum lengths of the resulting merged getopt short options string and + long-options array, respectively. */ +static void +calc_sizes (const struct argp *argp, struct parser_sizes *szs) +{ + const struct argp_child *child = argp->children; + const struct argp_option *opt = argp->options; + + if (opt || argp->parser) + { + szs->num_groups++; + if (opt) + { + int num_opts = 0; + while (!__option_is_end (opt++)) + num_opts++; + szs->short_len += num_opts * 3; /* opt + up to 2 ':'s */ + szs->long_len += num_opts; + } + } + + if (child) + while (child->argp) + { + calc_sizes ((child++)->argp, szs); + szs->num_child_inputs++; + } +} + +/* Initializes PARSER to parse ARGP in a manner described by FLAGS. */ +static error_t +parser_init (struct parser *parser, const struct argp *argp, + int argc, char **argv, int flags, void *input) +{ + error_t err = 0; + struct group *group; + struct parser_sizes szs; + struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER; + char *storage; + size_t glen, gsum; + size_t clen, csum; + size_t llen, lsum; + size_t slen, ssum; + + szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1; + szs.long_len = 0; + szs.num_groups = 0; + szs.num_child_inputs = 0; + + if (argp) + calc_sizes (argp, &szs); + + /* Lengths of the various bits of storage used by PARSER. */ + glen = (szs.num_groups + 1) * sizeof (struct group); + clen = szs.num_child_inputs * sizeof (void *); + llen = (szs.long_len + 1) * sizeof (struct option); + slen = szs.short_len + 1; + + /* Sums of previous lengths, properly aligned. There's no need to + align gsum, since struct group is aligned at least as strictly as + void * (since it contains a void * member). And there's no need + to align lsum, since struct option is aligned at least as + strictly as char. */ + gsum = glen; + csum = alignto (gsum + clen, alignof (struct option)); + lsum = csum + llen; + ssum = lsum + slen; + + parser->storage = malloc (ssum); + if (! parser->storage) + return ENOMEM; + + storage = parser->storage; + parser->groups = parser->storage; + parser->child_inputs = (void **) (storage + gsum); + parser->long_opts = (struct option *) (storage + csum); + parser->short_opts = storage + lsum; + parser->opt_data = opt_data; + + memset (parser->child_inputs, 0, clen); + parser_convert (parser, argp, flags); + + memset (&parser->state, 0, sizeof (struct argp_state)); + parser->state.root_argp = parser->argp; + parser->state.argc = argc; + parser->state.argv = argv; + parser->state.flags = flags; + parser->state.err_stream = stderr; + parser->state.out_stream = stdout; + parser->state.next = 0; /* Tell getopt to initialize. */ + parser->state.pstate = parser; + + parser->try_getopt = 1; + + /* Call each parser for the first time, giving it a chance to propagate + values to child parsers. */ + if (parser->groups < parser->egroup) + parser->groups->input = input; + for (group = parser->groups; + group < parser->egroup && (!err || err == EBADKEY); + group++) + { + if (group->parent) + /* If a child parser, get the initial input value from the parent. */ + group->input = group->parent->child_inputs[group->parent_index]; + + if (!group->parser + && group->argp->children && group->argp->children->argp) + /* For the special case where no parsing function is supplied for an + argp, propagate its input to its first child, if any (this just + makes very simple wrapper argps more convenient). */ + group->child_inputs[0] = group->input; + + err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0); + } + if (err == EBADKEY) + err = 0; /* Some parser didn't understand. */ + + if (err) + return err; + + if (parser->state.flags & ARGP_NO_ERRS) + { + parser->opt_data.opterr = 0; + if (parser->state.flags & ARGP_PARSE_ARGV0) + /* getopt always skips ARGV[0], so we have to fake it out. As long + as OPTERR is 0, then it shouldn't actually try to access it. */ + parser->state.argv--, parser->state.argc++; + } + else + parser->opt_data.opterr = 1; /* Print error messages. */ + + if (parser->state.argv == argv && argv[0]) + /* There's an argv[0]; use it for messages. */ + parser->state.name = __argp_base_name (argv[0]); + else + parser->state.name = __argp_short_program_name (); + + return 0; +} + +/* Free any storage consumed by PARSER (but not PARSER itself). */ +static error_t +parser_finalize (struct parser *parser, + error_t err, int arg_ebadkey, int *end_index) +{ + struct group *group; + + if (err == EBADKEY && arg_ebadkey) + /* Suppress errors generated by unparsed arguments. */ + err = 0; + + if (! err) + { + if (parser->state.next == parser->state.argc) + /* We successfully parsed all arguments! Call all the parsers again, + just a few more times... */ + { + for (group = parser->groups; + group < parser->egroup && (!err || err==EBADKEY); + group++) + if (group->args_processed == 0) + err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0); + for (group = parser->egroup - 1; + group >= parser->groups && (!err || err==EBADKEY); + group--) + err = group_parse (group, &parser->state, ARGP_KEY_END, 0); + + if (err == EBADKEY) + err = 0; /* Some parser didn't understand. */ + + /* Tell the user that all arguments are parsed. */ + if (end_index) + *end_index = parser->state.next; + } + else if (end_index) + /* Return any remaining arguments to the user. */ + *end_index = parser->state.next; + else + /* No way to return the remaining arguments, they must be bogus. */ + { + if (!(parser->state.flags & ARGP_NO_ERRS) + && parser->state.err_stream) + fprintf (parser->state.err_stream, + dgettext (parser->argp->argp_domain, + "%s: Too many arguments\n"), + parser->state.name); + err = EBADKEY; + } + } + + /* Okay, we're all done, with either an error or success; call the parsers + to indicate which one. */ + + if (err) + { + /* Maybe print an error message. */ + if (err == EBADKEY) + /* An appropriate message describing what the error was should have + been printed earlier. */ + __argp_state_help (&parser->state, parser->state.err_stream, + ARGP_HELP_STD_ERR); + + /* Since we didn't exit, give each parser an error indication. */ + for (group = parser->groups; group < parser->egroup; group++) + group_parse (group, &parser->state, ARGP_KEY_ERROR, 0); + } + else + /* Notify parsers of success, and propagate back values from parsers. */ + { + /* We pass over the groups in reverse order so that child groups are + given a chance to do there processing before passing back a value to + the parent. */ + for (group = parser->egroup - 1 + ; group >= parser->groups && (!err || err == EBADKEY) + ; group--) + err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0); + if (err == EBADKEY) + err = 0; /* Some parser didn't understand. */ + } + + /* Call parsers once more, to do any final cleanup. Errors are ignored. */ + for (group = parser->egroup - 1; group >= parser->groups; group--) + group_parse (group, &parser->state, ARGP_KEY_FINI, 0); + + if (err == EBADKEY) + err = EINVAL; + + free (parser->storage); + + return err; +} + +/* Call the user parsers to parse the non-option argument VAL, at the current + position, returning any error. The state NEXT pointer is assumed to have + been adjusted (by getopt) to point after this argument; this function will + adjust it correctly to reflect however many args actually end up being + consumed. */ +static error_t +parser_parse_arg (struct parser *parser, char *val) +{ + /* Save the starting value of NEXT, first adjusting it so that the arg + we're parsing is again the front of the arg vector. */ + int index = --parser->state.next; + error_t err = EBADKEY; + struct group *group; + int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */ + + /* Try to parse the argument in each parser. */ + for (group = parser->groups + ; group < parser->egroup && err == EBADKEY + ; group++) + { + parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */ + key = ARGP_KEY_ARG; + err = group_parse (group, &parser->state, key, val); + + if (err == EBADKEY) + /* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */ + { + parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */ + key = ARGP_KEY_ARGS; + err = group_parse (group, &parser->state, key, 0); + } + } + + if (! err) + { + if (key == ARGP_KEY_ARGS) + /* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't + changed by the user, *all* arguments should be considered + consumed. */ + parser->state.next = parser->state.argc; + + if (parser->state.next > index) + /* Remember that we successfully processed a non-option + argument -- but only if the user hasn't gotten tricky and set + the clock back. */ + (--group)->args_processed += (parser->state.next - index); + else + /* The user wants to reparse some args, give getopt another try. */ + parser->try_getopt = 1; + } + + return err; +} + +/* Call the user parsers to parse the option OPT, with argument VAL, at the + current position, returning any error. */ +static error_t +parser_parse_opt (struct parser *parser, int opt, char *val) +{ + /* The group key encoded in the high bits; 0 for short opts or + group_number + 1 for long opts. */ + int group_key = opt >> USER_BITS; + error_t err = EBADKEY; + + if (group_key == 0) + /* A short option. By comparing OPT's position in SHORT_OPTS to the + various starting positions in each group's SHORT_END field, we can + determine which group OPT came from. */ + { + struct group *group; + char *short_index = strchr (parser->short_opts, opt); + + if (short_index) + for (group = parser->groups; group < parser->egroup; group++) + if (group->short_end > short_index) + { + err = group_parse (group, &parser->state, opt, + parser->opt_data.optarg); + break; + } + } + else + /* A long option. Preserve the sign in the user key, without + invoking undefined behavior. Assume two's complement. */ + { + int user_key = + ((opt & (1 << (USER_BITS - 1))) ? ~USER_MASK : 0) | (opt & USER_MASK); + err = + group_parse (&parser->groups[group_key - 1], &parser->state, + user_key, parser->opt_data.optarg); + } + + if (err == EBADKEY) + /* At least currently, an option not recognized is an error in the + parser, because we pre-compute which parser is supposed to deal + with each option. */ + { + static const char bad_key_err[] = + N_("(PROGRAM ERROR) Option should have been recognized!?"); + if (group_key == 0) + __argp_error (&parser->state, "-%c: %s", opt, + dgettext (parser->argp->argp_domain, bad_key_err)); + else + { + struct option *long_opt = parser->long_opts; + while (long_opt->val != opt && long_opt->name) + long_opt++; + __argp_error (&parser->state, "--%s: %s", + long_opt->name ? long_opt->name : "???", + dgettext (parser->argp->argp_domain, bad_key_err)); + } + } + + return err; +} + +/* Parse the next argument in PARSER (as indicated by PARSER->state.next). + Any error from the parsers is returned, and *ARGP_EBADKEY indicates + whether a value of EBADKEY is due to an unrecognized argument (which is + generally not fatal). */ +static error_t +parser_parse_next (struct parser *parser, int *arg_ebadkey) +{ + int opt; + error_t err = 0; + + if (parser->state.quoted && parser->state.next < parser->state.quoted) + /* The next argument pointer has been moved to before the quoted + region, so pretend we never saw the quoting "--", and give getopt + another chance. If the user hasn't removed it, getopt will just + process it again. */ + parser->state.quoted = 0; + + if (parser->try_getopt && !parser->state.quoted) + /* Give getopt a chance to parse this. */ + { + /* Put it back in OPTIND for getopt. */ + parser->opt_data.optind = parser->state.next; + /* Distinguish KEY_ERR from a real option. */ + parser->opt_data.optopt = KEY_END; + if (parser->state.flags & ARGP_LONG_ONLY) + opt = _getopt_long_only_r (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0, + &parser->opt_data); + else + opt = _getopt_long_r (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0, + &parser->opt_data); + /* And see what getopt did. */ + parser->state.next = parser->opt_data.optind; + + if (opt == KEY_END) + /* Getopt says there are no more options, so stop using + getopt; we'll continue if necessary on our own. */ + { + parser->try_getopt = 0; + if (parser->state.next > 1 + && strcmp (parser->state.argv[parser->state.next - 1], QUOTE) + == 0) + /* Not only is this the end of the options, but it's a + "quoted" region, which may have args that *look* like + options, so we definitely shouldn't try to use getopt past + here, whatever happens. */ + parser->state.quoted = parser->state.next; + } + else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END) + /* KEY_ERR can have the same value as a valid user short + option, but in the case of a real error, getopt sets OPTOPT + to the offending character, which can never be KEY_END. */ + { + *arg_ebadkey = 0; + return EBADKEY; + } + } + else + opt = KEY_END; + + if (opt == KEY_END) + { + /* We're past what getopt considers the options. */ + if (parser->state.next >= parser->state.argc + || (parser->state.flags & ARGP_NO_ARGS)) + /* Indicate that we're done. */ + { + *arg_ebadkey = 1; + return EBADKEY; + } + else + /* A non-option arg; simulate what getopt might have done. */ + { + opt = KEY_ARG; + parser->opt_data.optarg = parser->state.argv[parser->state.next++]; + } + } + + if (opt == KEY_ARG) + /* A non-option argument; try each parser in turn. */ + err = parser_parse_arg (parser, parser->opt_data.optarg); + else + err = parser_parse_opt (parser, opt, parser->opt_data.optarg); + + if (err == EBADKEY) + *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG); + + return err; +} + +/* Parse the options strings in ARGC & ARGV according to the argp in ARGP. + FLAGS is one of the ARGP_ flags above. If END_INDEX is non-NULL, the + index in ARGV of the first unparsed option is returned in it. If an + unknown option is present, EINVAL is returned; if some parser routine + returned a non-zero value, it is returned; otherwise 0 is returned. */ +error_t +__argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, + int *end_index, void *input) +{ + error_t err; + struct parser parser; + + /* If true, then err == EBADKEY is a result of a non-option argument failing + to be parsed (which in some cases isn't actually an error). */ + int arg_ebadkey = 0; + +#ifndef _LIBC + if (!(flags & ARGP_PARSE_ARGV0)) + { +#if HAVE_DECL_PROGRAM_INVOCATION_NAME + if (!program_invocation_name) + program_invocation_name = argv[0]; +#endif +#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME + if (!program_invocation_short_name) + program_invocation_short_name = __argp_base_name (argv[0]); +#endif + } +#endif + + if (! (flags & ARGP_NO_HELP)) + /* Add our own options. */ + { + struct argp_child *child = alloca (4 * sizeof (struct argp_child)); + struct argp *top_argp = alloca (sizeof (struct argp)); + + /* TOP_ARGP has no options, it just serves to group the user & default + argps. */ + memset (top_argp, 0, sizeof (*top_argp)); + top_argp->children = child; + + memset (child, 0, 4 * sizeof (struct argp_child)); + + if (argp) + (child++)->argp = argp; + (child++)->argp = &argp_default_argp; + if (argp_program_version || argp_program_version_hook) + (child++)->argp = &argp_version_argp; + child->argp = 0; + + argp = top_argp; + } + + /* Construct a parser for these arguments. */ + err = parser_init (&parser, argp, argc, argv, flags, input); + + if (! err) + /* Parse! */ + { + while (! err) + err = parser_parse_next (&parser, &arg_ebadkey); + err = parser_finalize (&parser, err, arg_ebadkey, end_index); + } + + return err; +} +#ifdef weak_alias +weak_alias (__argp_parse, argp_parse) +#endif + +/* Return the input field for ARGP in the parser corresponding to STATE; used + by the help routines. */ +void * +__argp_input (const struct argp *argp, const struct argp_state *state) +{ + if (state && state->pstate) + { + struct group *group; + struct parser *parser = state->pstate; + + for (group = parser->groups; group < parser->egroup; group++) + if (group->argp == argp) + return group->input; + } + + return 0; +} +#ifdef weak_alias +weak_alias (__argp_input, _argp_input) +#endif diff --git a/grub-core/lib/gnulib/argp-pin.c b/grub-core/lib/gnulib/argp-pin.c new file mode 100644 index 0000000..ece7423 --- /dev/null +++ b/grub-core/lib/gnulib/argp-pin.c @@ -0,0 +1,33 @@ +/* Full and short program names for argp module + Copyright (C) 2005, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME +char *program_invocation_short_name = 0; +#endif +#ifndef HAVE_PROGRAM_INVOCATION_NAME +char *program_invocation_name = 0; +#endif + +#if (defined HAVE_PROGRAM_INVOCATION_SHORT_NAME \ + && defined HAVE_PROGRAM_INVOCATION_NAME) +/* This declaration is solely to ensure that after preprocessing + this file is never empty. */ +typedef int dummy; +#endif diff --git a/grub-core/lib/gnulib/argp-pv.c b/grub-core/lib/gnulib/argp-pv.c new file mode 100644 index 0000000..f76b365 --- /dev/null +++ b/grub-core/lib/gnulib/argp-pv.c @@ -0,0 +1,33 @@ +/* Default definition for ARGP_PROGRAM_VERSION. + Copyright (C) 1996-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* If set by the user program to a non-zero value, then a default option + --version is added (unless the ARGP_NO_HELP flag is used), which will + print this string followed by a newline and exit (unless the + ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ +const char *argp_program_version +/* This variable should be zero-initialized. On most systems, putting it into + BSS is sufficient. Not so on Mac OS X 10.3 and 10.4, see + <https://lists.gnu.org/r/bug-gnulib/2009-01/msg00329.html> + <https://lists.gnu.org/r/bug-gnulib/2009-08/msg00096.html>. */ +#if defined __ELF__ + /* On ELF systems, variables in BSS behave well. */ +#else + = (const char *) 0 +#endif + ; diff --git a/grub-core/lib/gnulib/argp-pvh.c b/grub-core/lib/gnulib/argp-pvh.c new file mode 100644 index 0000000..be73e33 --- /dev/null +++ b/grub-core/lib/gnulib/argp-pvh.c @@ -0,0 +1,30 @@ +/* Default definition for ARGP_PROGRAM_VERSION_HOOK. + Copyright (C) 1996-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "argp.h" + +/* If set by the user program to a non-zero value, then a default option + --version is added (unless the ARGP_NO_HELP flag is used), which calls + this function with a stream to print the version to and a pointer to the + current parsing state, and then exits (unless the ARGP_NO_EXIT flag is + used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ +void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = NULL; diff --git a/grub-core/lib/gnulib/argp-xinl.c b/grub-core/lib/gnulib/argp-xinl.c new file mode 100644 index 0000000..ebc032f --- /dev/null +++ b/grub-core/lib/gnulib/argp-xinl.c @@ -0,0 +1,46 @@ +/* Real definitions for extern inline functions in argp.h + Copyright (C) 1997-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined _LIBC || defined HAVE_FEATURES_H +# include <features.h> +#endif + +#ifndef __USE_EXTERN_INLINES +# define __USE_EXTERN_INLINES 1 +#endif +#ifdef _LIBC +# define ARGP_EI +#else +# define ARGP_EI _GL_EXTERN_INLINE +#endif +#undef __OPTIMIZE__ +#define __OPTIMIZE__ 1 +#include "argp.h" + +/* Add weak aliases. */ +#if _LIBC - 0 && defined (weak_alias) + +weak_alias (__argp_usage, argp_usage) +weak_alias (__option_is_short, _option_is_short) +weak_alias (__option_is_end, _option_is_end) + +#endif diff --git a/grub-core/lib/gnulib/argp.h b/grub-core/lib/gnulib/argp.h new file mode 100644 index 0000000..317ac03 --- /dev/null +++ b/grub-core/lib/gnulib/argp.h @@ -0,0 +1,631 @@ +/* Hierarchical argument parsing, layered over getopt. + Copyright (C) 1995-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Miles Bader <miles@gnu.ai.mit.edu>. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _ARGP_H +#define _ARGP_H + +#include <stdio.h> +#include <ctype.h> +#include <getopt.h> +#include <limits.h> + +#define __need_error_t +#include <errno.h> + +#ifndef __THROW +# define __THROW +#endif +#ifndef __NTH +# define __NTH(fct) fct __THROW +#endif + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The __-protected variants of the attributes 'format' and 'printf' are + accepted by gcc versions 2.6.4 (effectively 2.7) and later. + We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because + gnulib and libintl do '#define printf __printf__' when they override + the 'printf' function. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +#endif + +/* GCC 2.95 and later have "__restrict"; C99 compilers have + "restrict", and "configure" may have defined "restrict". + Other compilers use __restrict, __restrict__, and _Restrict, and + 'configure' might #define 'restrict' to those words. */ +#ifndef __restrict +# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) +# if 199901L <= __STDC_VERSION__ +# define __restrict restrict +# else +# define __restrict +# endif +# endif +#endif + +#ifndef __error_t_defined +typedef int error_t; +# define __error_t_defined +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* A description of a particular option. A pointer to an array of + these is passed in the OPTIONS field of an argp structure. Each option + entry can correspond to one long option and/or one short option; more + names for the same option can be added by following an entry in an option + array with options having the OPTION_ALIAS flag set. */ +struct argp_option +{ + /* The long option name. For more than one name for the same option, you + can use following options with the OPTION_ALIAS flag set. */ + const char *name; + + /* What key is returned for this option. If > 0 and printable, then it's + also accepted as a short option. */ + int key; + + /* If non-NULL, this is the name of the argument associated with this + option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */ + const char *arg; + + /* OPTION_ flags. */ + int flags; + + /* The doc string for this option. If both NAME and KEY are 0, This string + will be printed outdented from the normal option column, making it + useful as a group header (it will be the first thing printed in its + group); in this usage, it's conventional to end the string with a ':'. + + Write the initial value as N_("TEXT") if you want xgettext to collect + it into a POT file. */ + const char *doc; + + /* The group this option is in. In a long help message, options are sorted + alphabetically within each group, and the groups presented in the order + 0, 1, 2, ..., n, -m, ..., -2, -1. Every entry in an options array with + if this field 0 will inherit the group number of the previous entry, or + zero if it's the first one, unless its a group header (NAME and KEY both + 0), in which case, the previous entry + 1 is the default. Automagic + options such as --help are put into group -1. */ + int group; +}; + +/* The argument associated with this option is optional. */ +#define OPTION_ARG_OPTIONAL 0x1 + +/* This option isn't displayed in any help messages. */ +#define OPTION_HIDDEN 0x2 + +/* This option is an alias for the closest previous non-alias option. This + means that it will be displayed in the same help entry, and will inherit + fields other than NAME and KEY from the aliased option. */ +#define OPTION_ALIAS 0x4 + +/* This option isn't actually an option (and so should be ignored by the + actual option parser), but rather an arbitrary piece of documentation that + should be displayed in much the same manner as the options. If this flag + is set, then the option NAME field is displayed unmodified (e.g., no '--' + prefix is added) at the left-margin (where a *short* option would normally + be displayed), and the documentation string in the normal place. The NAME + field will be translated using gettext, unless OPTION_NO_TRANS is set (see + below). For purposes of sorting, any leading whitespace and punctuation is + ignored, except that if the first non-whitespace character is not '-', this + entry is displayed after all options (and OPTION_DOC entries with a leading + '-') in the same group. */ +#define OPTION_DOC 0x8 + +/* This option shouldn't be included in "long" usage messages (but is still + included in help messages). This is mainly intended for options that are + completely documented in an argp's ARGS_DOC field, in which case including + the option in the generic usage list would be redundant. For instance, + if ARGS_DOC is "FOO BAR\n-x BLAH", and the '-x' option's purpose is to + distinguish these two cases, -x should probably be marked + OPTION_NO_USAGE. */ +#define OPTION_NO_USAGE 0x10 + +/* Valid only in conjunction with OPTION_DOC. This option disables translation + of option name. */ +#define OPTION_NO_TRANS 0x20 + +struct argp; /* fwd declare this type */ +struct argp_state; /* " */ +struct argp_child; /* " */ + +/* The type of a pointer to an argp parsing function. */ +typedef error_t (*argp_parser_t) (int __key, char *__arg, + struct argp_state *__state); + +/* What to return for unrecognized keys. For special ARGP_KEY_ keys, such + returns will simply be ignored. For user keys, this error will be turned + into EINVAL (if the call to argp_parse is such that errors are propagated + back to the user instead of exiting); returning EINVAL itself would result + in an immediate stop to parsing in *all* cases. */ +#define ARGP_ERR_UNKNOWN E2BIG /* Hurd should never need E2BIG. XXX */ + +/* Special values for the KEY argument to an argument parsing function. + ARGP_ERR_UNKNOWN should be returned if they aren't understood. + + The sequence of keys to a parsing function is either (where each + uppercased word should be prefixed by 'ARGP_KEY_' and opt is a user key): + + INIT opt... NO_ARGS END SUCCESS -- No non-option arguments at all + or INIT (opt | ARG)... END SUCCESS -- All non-option args parsed + or INIT (opt | ARG)... SUCCESS -- Some non-option arg unrecognized + + The third case is where every parser returned ARGP_KEY_UNKNOWN for an + argument, in which case parsing stops at that argument (returning the + unparsed arguments to the caller of argp_parse if requested, or stopping + with an error message if not). + + If an error occurs (either detected by argp, or because the parsing + function returned an error value), then the parser is called with + ARGP_KEY_ERROR, and no further calls are made. */ + +/* This is not an option at all, but rather a command line argument. If a + parser receiving this key returns success, the fact is recorded, and the + ARGP_KEY_NO_ARGS case won't be used. HOWEVER, if while processing the + argument, a parser function decrements the NEXT field of the state it's + passed, the option won't be considered processed; this is to allow you to + actually modify the argument (perhaps into an option), and have it + processed again. */ +#define ARGP_KEY_ARG 0 +/* There are remaining arguments not parsed by any parser, which may be found + starting at (STATE->argv + STATE->next). If success is returned, but + STATE->next left untouched, it's assumed that all arguments were consume, + otherwise, the parser should adjust STATE->next to reflect any arguments + consumed. */ +#define ARGP_KEY_ARGS 0x1000006 +/* There are no more command line arguments at all. */ +#define ARGP_KEY_END 0x1000001 +/* Because it's common to want to do some special processing if there aren't + any non-option args, user parsers are called with this key if they didn't + successfully process any non-option arguments. Called just before + ARGP_KEY_END (where more general validity checks on previously parsed + arguments can take place). */ +#define ARGP_KEY_NO_ARGS 0x1000002 +/* Passed in before any parsing is done. Afterwards, the values of each + element of the CHILD_INPUT field, if any, in the state structure is + copied to each child's state to be the initial value of the INPUT field. */ +#define ARGP_KEY_INIT 0x1000003 +/* Use after all other keys, including SUCCESS & END. */ +#define ARGP_KEY_FINI 0x1000007 +/* Passed in when parsing has successfully been completed (even if there are + still arguments remaining). */ +#define ARGP_KEY_SUCCESS 0x1000004 +/* Passed in if an error occurs. */ +#define ARGP_KEY_ERROR 0x1000005 + +/* An argp structure contains a set of options declarations, a function to + deal with parsing one, documentation string, a possible vector of child + argp's, and perhaps a function to filter help output. When actually + parsing options, getopt is called with the union of all the argp + structures chained together through their CHILD pointers, with conflicts + being resolved in favor of the first occurrence in the chain. */ +struct argp +{ + /* An array of argp_option structures, terminated by an entry with both + NAME and KEY having a value of 0. */ + const struct argp_option *options; + + /* What to do with an option from this structure. KEY is the key + associated with the option, and ARG is any associated argument (NULL if + none was supplied). If KEY isn't understood, ARGP_ERR_UNKNOWN should be + returned. If a non-zero, non-ARGP_ERR_UNKNOWN value is returned, then + parsing is stopped immediately, and that value is returned from + argp_parse(). For special (non-user-supplied) values of KEY, see the + ARGP_KEY_ definitions below. */ + argp_parser_t parser; + + /* A string describing what other arguments are wanted by this program. It + is only used by argp_usage to print the "Usage:" message. If it + contains newlines, the strings separated by them are considered + alternative usage patterns, and printed on separate lines (lines after + the first are prefix by " or: " instead of "Usage:"). */ + const char *args_doc; + + /* If non-NULL, a string containing extra text to be printed before and + after the options in a long help message (separated by a vertical tab + '\v' character). + Write the initial value as N_("BEFORE-TEXT") "\v" N_("AFTER-TEXT") if + you want xgettext to collect the two pieces of text into a POT file. */ + const char *doc; + + /* A vector of argp_children structures, terminated by a member with a 0 + argp field, pointing to child argps should be parsed with this one. Any + conflicts are resolved in favor of this argp, or early argps in the + CHILDREN list. This field is useful if you use libraries that supply + their own argp structure, which you want to use in conjunction with your + own. */ + const struct argp_child *children; + + /* If non-zero, this should be a function to filter the output of help + messages. KEY is either a key from an option, in which case TEXT is + that option's help text, or a special key from the ARGP_KEY_HELP_ + defines, below, describing which other help text TEXT is. The function + should return either TEXT, if it should be used as-is, a replacement + string, which should be malloced, and will be freed by argp, or NULL, + meaning "print nothing". The value for TEXT is *after* any translation + has been done, so if any of the replacement text also needs translation, + that should be done by the filter function. INPUT is either the input + supplied to argp_parse, or NULL, if argp_help was called directly. */ + char *(*help_filter) (int __key, const char *__text, void *__input); + + /* If non-zero the strings used in the argp library are translated using + the domain described by this string. Otherwise the currently installed + default domain is used. */ + const char *argp_domain; +}; + +/* Possible KEY arguments to a help filter function. */ +#define ARGP_KEY_HELP_PRE_DOC 0x2000001 /* Help text preceding options. */ +#define ARGP_KEY_HELP_POST_DOC 0x2000002 /* Help text following options. */ +#define ARGP_KEY_HELP_HEADER 0x2000003 /* Option header string. */ +#define ARGP_KEY_HELP_EXTRA 0x2000004 /* After all other documentation; + TEXT is NULL for this key. */ +/* Explanatory note emitted when duplicate option arguments have been + suppressed. */ +#define ARGP_KEY_HELP_DUP_ARGS_NOTE 0x2000005 +#define ARGP_KEY_HELP_ARGS_DOC 0x2000006 /* Argument doc string. */ + +/* When an argp has a non-zero CHILDREN field, it should point to a vector of + argp_child structures, each of which describes a subsidiary argp. */ +struct argp_child +{ + /* The child parser. */ + const struct argp *argp; + + /* Flags for this child. */ + int flags; + + /* If non-zero, an optional header to be printed in help output before the + child options. As a side-effect, a non-zero value forces the child + options to be grouped together; to achieve this effect without actually + printing a header string, use a value of "". */ + const char *header; + + /* Where to group the child options relative to the other ("consolidated") + options in the parent argp; the values are the same as the GROUP field + in argp_option structs, but all child-groupings follow parent options at + a particular group level. If both this field and HEADER are zero, then + they aren't grouped at all, but rather merged with the parent options + (merging the child's grouping levels with the parents). */ + int group; +}; + +/* Parsing state. This is provided to parsing functions called by argp, + which may examine and, as noted, modify fields. */ +struct argp_state +{ + /* The top level ARGP being parsed. */ + const struct argp *root_argp; + + /* The argument vector being parsed. May be modified. */ + int argc; + char **argv; + + /* The index in ARGV of the next arg that to be parsed. May be modified. */ + int next; + + /* The flags supplied to argp_parse. May be modified. */ + unsigned flags; + + /* While calling a parsing function with a key of ARGP_KEY_ARG, this is the + number of the current arg, starting at zero, and incremented after each + such call returns. At all other times, this is the number of such + arguments that have been processed. */ + unsigned arg_num; + + /* If non-zero, the index in ARGV of the first argument following a special + '--' argument (which prevents anything following being interpreted as an + option). Only set once argument parsing has proceeded past this point. */ + int quoted; + + /* An arbitrary pointer passed in from the user. */ + void *input; + /* Values to pass to child parsers. This vector will be the same length as + the number of children for the current parser. */ + void **child_inputs; + + /* For the parser's use. Initialized to 0. */ + void *hook; + + /* The name used when printing messages. This is initialized to ARGV[0], + or PROGRAM_INVOCATION_NAME if that is unavailable. */ + char *name; + + /* Streams used when argp prints something. */ + FILE *err_stream; /* For errors; initialized to stderr. */ + FILE *out_stream; /* For information; initialized to stdout. */ + + void *pstate; /* Private, for use by argp. */ +}; + +/* Flags for argp_parse (note that the defaults are those that are + convenient for program command line parsing): */ + +/* Don't ignore the first element of ARGV. Normally (and always unless + ARGP_NO_ERRS is set) the first element of the argument vector is + skipped for option parsing purposes, as it corresponds to the program name + in a command line. */ +#define ARGP_PARSE_ARGV0 0x01 + +/* Don't print error messages for unknown options to stderr; unless this flag + is set, ARGP_PARSE_ARGV0 is ignored, as ARGV[0] is used as the program + name in the error messages. This flag implies ARGP_NO_EXIT (on the + assumption that silent exiting upon errors is bad behaviour). */ +#define ARGP_NO_ERRS 0x02 + +/* Don't parse any non-option args. Normally non-option args are parsed by + calling the parse functions with a key of ARGP_KEY_ARG, and the actual arg + as the value. Since it's impossible to know which parse function wants to + handle it, each one is called in turn, until one returns 0 or an error + other than ARGP_ERR_UNKNOWN; if an argument is handled by no one, the + argp_parse returns prematurely (but with a return value of 0). If all + args have been parsed without error, all parsing functions are called one + last time with a key of ARGP_KEY_END. This flag needn't normally be set, + as the normal behavior is to stop parsing as soon as some argument can't + be handled. */ +#define ARGP_NO_ARGS 0x04 + +/* Parse options and arguments in the same order they occur on the command + line -- normally they're rearranged so that all options come first. */ +#define ARGP_IN_ORDER 0x08 + +/* Don't provide the standard long option --help, which causes usage and + option help information to be output to stdout, and exit (0) called. */ +#define ARGP_NO_HELP 0x10 + +/* Don't exit on errors (they may still result in error messages). */ +#define ARGP_NO_EXIT 0x20 + +/* Use the gnu getopt "long-only" rules for parsing arguments. */ +#define ARGP_LONG_ONLY 0x40 + +/* Turns off any message-printing/exiting options. */ +#define ARGP_SILENT (ARGP_NO_EXIT | ARGP_NO_ERRS | ARGP_NO_HELP) + +/* Parse the options strings in ARGC & ARGV according to the options in ARGP. + FLAGS is one of the ARGP_ flags above. If ARG_INDEX is non-NULL, the + index in ARGV of the first unparsed option is returned in it. If an + unknown option is present, ARGP_ERR_UNKNOWN is returned; if some parser + routine returned a non-zero value, it is returned; otherwise 0 is + returned. This function may also call exit unless the ARGP_NO_HELP flag + is set. INPUT is a pointer to a value to be passed in to the parser. */ +extern error_t argp_parse (const struct argp *__restrict __argp, + int /*argc*/, char **__restrict /*argv*/, + unsigned __flags, int *__restrict __arg_index, + void *__restrict __input); +extern error_t __argp_parse (const struct argp *__restrict __argp, + int /*argc*/, char **__restrict /*argv*/, + unsigned __flags, int *__restrict __arg_index, + void *__restrict __input); + +/* Global variables. */ + +/* GNULIB makes sure both program_invocation_name and + program_invocation_short_name are available */ +#ifdef GNULIB_PROGRAM_INVOCATION_NAME +extern char *program_invocation_name; +# undef HAVE_DECL_PROGRAM_INVOCATION_NAME +# define HAVE_DECL_PROGRAM_INVOCATION_NAME 1 +#endif + +#ifdef GNULIB_PROGRAM_INVOCATION_SHORT_NAME +extern char *program_invocation_short_name; +# undef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME +# define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME 1 +#endif + +/* If defined or set by the user program to a non-zero value, then a default + option --version is added (unless the ARGP_NO_HELP flag is used), which + will print this string followed by a newline and exit (unless the + ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ +extern const char *argp_program_version; + +/* If defined or set by the user program to a non-zero value, then a default + option --version is added (unless the ARGP_NO_HELP flag is used), which + calls this function with a stream to print the version to and a pointer to + the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is + used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ +extern void (*argp_program_version_hook) (FILE *__restrict __stream, + struct argp_state *__restrict + __state); + +/* If defined or set by the user program, it should point to string that is + the bug-reporting address for the program. It will be printed by + argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various + standard help messages), embedded in a sentence that says something like + "Report bugs to ADDR." */ +extern const char *argp_program_bug_address; + +/* The exit status that argp will use when exiting due to a parsing error. + If not defined or set by the user program, this defaults to EX_USAGE from + <sysexits.h>. */ +extern error_t argp_err_exit_status; + +/* Flags for argp_help. */ +#define ARGP_HELP_USAGE 0x01 /* a Usage: message. */ +#define ARGP_HELP_SHORT_USAGE 0x02 /* " but don't actually print options. */ +#define ARGP_HELP_SEE 0x04 /* a "Try ... for more help" message. */ +#define ARGP_HELP_LONG 0x08 /* a long help message. */ +#define ARGP_HELP_PRE_DOC 0x10 /* doc string preceding long help. */ +#define ARGP_HELP_POST_DOC 0x20 /* doc string following long help. */ +#define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC) +#define ARGP_HELP_BUG_ADDR 0x40 /* bug report address */ +#define ARGP_HELP_LONG_ONLY 0x80 /* modify output appropriately to + reflect ARGP_LONG_ONLY mode. */ + +/* These ARGP_HELP flags are only understood by argp_state_help. */ +#define ARGP_HELP_EXIT_ERR 0x100 /* Call exit(1) instead of returning. */ +#define ARGP_HELP_EXIT_OK 0x200 /* Call exit(0) instead of returning. */ + +/* The standard thing to do after a program command line parsing error, if an + error message has already been printed. */ +#define ARGP_HELP_STD_ERR \ + (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) +/* The standard thing to do after a program command line parsing error, if no + more specific error message has been printed. */ +#define ARGP_HELP_STD_USAGE \ + (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) +/* The standard thing to do in response to a --help option. */ +#define ARGP_HELP_STD_HELP \ + (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \ + | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR) + +/* Output a usage message for ARGP to STREAM. FLAGS are from the set + ARGP_HELP_*. */ +extern void argp_help (const struct argp *__restrict __argp, + FILE *__restrict __stream, + unsigned __flags, char *__restrict __name); +extern void __argp_help (const struct argp *__restrict __argp, + FILE *__restrict __stream, unsigned __flags, + char *__name); + +/* The following routines are intended to be called from within an argp + parsing routine (thus taking an argp_state structure as the first + argument). They may or may not print an error message and exit, depending + on the flags in STATE -- in any case, the caller should be prepared for + them *not* to exit, and should return an appropriate error after calling + them. [argp_usage & argp_error should probably be called argp_state_..., + but they're used often enough that they should be short] */ + +/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are + from the set ARGP_HELP_*. */ +extern void argp_state_help (const struct argp_state *__restrict __state, + FILE *__restrict __stream, + unsigned int __flags); +extern void __argp_state_help (const struct argp_state *__restrict __state, + FILE *__restrict __stream, + unsigned int __flags); + +#if _LIBC +/* Possibly output the standard usage message for ARGP to stderr and exit. */ +extern void argp_usage (const struct argp_state *__state); +extern void __argp_usage (const struct argp_state *__state); +#endif + +/* If appropriate, print the printf string FMT and following args, preceded + by the program name and ':', to stderr, and followed by a "Try ... --help" + message, then exit (1). */ +extern void argp_error (const struct argp_state *__restrict __state, + const char *__restrict __fmt, ...) + _GL_ATTRIBUTE_FORMAT ((__printf__, 2, 3)); +extern void __argp_error (const struct argp_state *__restrict __state, + const char *__restrict __fmt, ...) + _GL_ATTRIBUTE_FORMAT ((__printf__, 2, 3)); + +/* Similar to the standard gnu error-reporting function error(), but will + respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print + to STATE->err_stream. This is useful for argument parsing code that is + shared between program startup (when exiting is desired) and runtime + option parsing (when typically an error code is returned instead). The + difference between this function and argp_error is that the latter is for + *parsing errors*, and the former is for other problems that occur during + parsing but don't reflect a (syntactic) problem with the input. */ +extern void argp_failure (const struct argp_state *__restrict __state, + int __status, int __errnum, + const char *__restrict __fmt, ...) + _GL_ATTRIBUTE_FORMAT ((__printf__, 4, 5)); +extern void __argp_failure (const struct argp_state *__restrict __state, + int __status, int __errnum, + const char *__restrict __fmt, ...) + _GL_ATTRIBUTE_FORMAT ((__printf__, 4, 5)); + +#if _LIBC +/* Returns true if the option OPT is a valid short option. */ +extern int _option_is_short (const struct argp_option *__opt) __THROW; +extern int __option_is_short (const struct argp_option *__opt) __THROW; + +/* Returns true if the option OPT is in fact the last (unused) entry in an + options array. */ +extern int _option_is_end (const struct argp_option *__opt) __THROW; +extern int __option_is_end (const struct argp_option *__opt) __THROW; +#endif + +/* Return the input field for ARGP in the parser corresponding to STATE; used + by the help routines. */ +extern void *_argp_input (const struct argp *__restrict __argp, + const struct argp_state *__restrict __state) + __THROW; +extern void *__argp_input (const struct argp *__restrict __argp, + const struct argp_state *__restrict __state) + __THROW; + +#if !_LIBC || defined __USE_EXTERN_INLINES + +# if !_LIBC +# define __argp_usage argp_usage +# define __argp_state_help argp_state_help +# define __option_is_short _option_is_short +# define __option_is_end _option_is_end +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +# ifndef ARGP_EI +# define ARGP_EI _GL_INLINE +# endif +# endif + +# ifndef ARGP_EI +# define ARGP_EI __extern_inline +# endif + +ARGP_EI void +__argp_usage (const struct argp_state *__state) +{ + __argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE); +} + +ARGP_EI int +__NTH (__option_is_short (const struct argp_option *__opt)) +{ + if (__opt->flags & OPTION_DOC) + return 0; + else + { + int __key = __opt->key; + return __key > 0 && __key <= UCHAR_MAX && isprint (__key); + } +} + +ARGP_EI int +__NTH (__option_is_end (const struct argp_option *__opt)) +{ + return !__opt->key && !__opt->name && !__opt->doc && !__opt->group; +} + +# if !_LIBC +# undef __argp_usage +# undef __argp_state_help +# undef __option_is_short +# undef __option_is_end +_GL_INLINE_HEADER_END +# endif +#endif /* Use extern inlines. */ + +#ifdef __cplusplus +} +#endif + +#endif /* argp.h */ diff --git a/grub-core/lib/gnulib/asnprintf.c b/grub-core/lib/gnulib/asnprintf.c new file mode 100644 index 0000000..d2a8c09 --- /dev/null +++ b/grub-core/lib/gnulib/asnprintf.c @@ -0,0 +1,34 @@ +/* Formatted output to strings. + Copyright (C) 1999, 2002, 2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "vasnprintf.h" + +#include <stdarg.h> + +char * +asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) +{ + va_list args; + char *result; + + va_start (args, format); + result = vasnprintf (resultbuf, lengthp, format, args); + va_end (args); + return result; +} diff --git a/grub-core/lib/gnulib/assure.h b/grub-core/lib/gnulib/assure.h new file mode 100644 index 0000000..c21b6a6 --- /dev/null +++ b/grub-core/lib/gnulib/assure.h @@ -0,0 +1,37 @@ +/* Run-time assert-like macros. + + Copyright (C) 2014-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +#ifndef _GL_ASSURE_H +#define _GL_ASSURE_H + +#include <assert.h> + +/* Check E's value at runtime, and report an error and abort if not. + However, do nothing if NDEBUG is defined. + + Unlike standard 'assert', this macro always compiles E even when NDEBUG + is defined, so as to catch typos and avoid some GCC warnings. */ + +#ifdef NDEBUG +# define assure(E) ((void) (0 && (E))) +#else +# define assure(E) assert (E) +#endif + +#endif diff --git a/grub-core/lib/gnulib/base64.c b/grub-core/lib/gnulib/base64.c new file mode 100644 index 0000000..84a4e82 --- /dev/null +++ b/grub-core/lib/gnulib/base64.c @@ -0,0 +1,605 @@ +/* base64.c -- Encode binary data using printable characters. + Copyright (C) 1999-2001, 2004-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Simon Josefsson. Partially adapted from GNU MailUtils + * (mailbox/filter_trans.c, as of 2004-11-28). Improved by review + * from Paul Eggert, Bruno Haible, and Stepan Kasal. + * + * See also RFC 4648 <https://www.ietf.org/rfc/rfc4648.txt>. + * + * Be careful with error checking. Here is how you would typically + * use these functions: + * + * bool ok = base64_decode_alloc (in, inlen, &out, &outlen); + * if (!ok) + * FAIL: input was not valid base64 + * if (out == NULL) + * FAIL: memory allocation error + * OK: data in OUT/OUTLEN + * + * size_t outlen = base64_encode_alloc (in, inlen, &out); + * if (out == NULL && outlen == 0 && inlen != 0) + * FAIL: input too long + * if (out == NULL) + * FAIL: memory allocation error + * OK: data in OUT/OUTLEN. + * + */ + +#include <config.h> + +/* Get prototype. */ +#include "base64.h" + +/* Get malloc. */ +#include <stdlib.h> + +/* Get UCHAR_MAX. */ +#include <limits.h> + +#include <string.h> + +/* C89 compliant way to cast 'char' to 'unsigned char'. */ +static unsigned char +to_uchar (char ch) +{ + return ch; +} + +static const char b64c[64] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* Base64 encode IN array of size INLEN into OUT array. OUT needs + to be of length >= BASE64_LENGTH(INLEN), and INLEN needs to be + a multiple of 3. */ +static void +base64_encode_fast (const char *restrict in, size_t inlen, char *restrict out) +{ + while (inlen) + { + *out++ = b64c[to_uchar (in[0]) >> 2]; + *out++ = b64c[((to_uchar (in[0]) << 4) + (to_uchar (in[1]) >> 4)) & 0x3f]; + *out++ = b64c[((to_uchar (in[1]) << 2) + (to_uchar (in[2]) >> 6)) & 0x3f]; + *out++ = b64c[to_uchar (in[2]) & 0x3f]; + + inlen -= 3; + in += 3; + } +} + +/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN. + If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as + possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero + terminate the output buffer. */ +void +base64_encode (const char *restrict in, size_t inlen, + char *restrict out, size_t outlen) +{ + /* Note this outlen constraint can be enforced at compile time. + I.E. that the output buffer is exactly large enough to hold + the encoded inlen bytes. The inlen constraints (of corresponding + to outlen, and being a multiple of 3) can change at runtime + at the end of input. However the common case when reading + large inputs is to have both constraints satisfied, so we depend + on both in base_encode_fast(). */ + if (outlen % 4 == 0 && inlen == outlen / 4 * 3) + { + base64_encode_fast (in, inlen, out); + return; + } + + while (inlen && outlen) + { + *out++ = b64c[to_uchar (in[0]) >> 2]; + if (!--outlen) + break; + *out++ = b64c[((to_uchar (in[0]) << 4) + + (--inlen ? to_uchar (in[1]) >> 4 : 0)) + & 0x3f]; + if (!--outlen) + break; + *out++ = + (inlen + ? b64c[((to_uchar (in[1]) << 2) + + (--inlen ? to_uchar (in[2]) >> 6 : 0)) + & 0x3f] + : '='); + if (!--outlen) + break; + *out++ = inlen ? b64c[to_uchar (in[2]) & 0x3f] : '='; + if (!--outlen) + break; + if (inlen) + inlen--; + if (inlen) + in += 3; + } + + if (outlen) + *out = '\0'; +} + +/* Allocate a buffer and store zero terminated base64 encoded data + from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e., + the length of the encoded data, excluding the terminating zero. On + return, the OUT variable will hold a pointer to newly allocated + memory that must be deallocated by the caller. If output string + length would overflow, 0 is returned and OUT is set to NULL. If + memory allocation failed, OUT is set to NULL, and the return value + indicates length of the requested memory block, i.e., + BASE64_LENGTH(inlen) + 1. */ +size_t +base64_encode_alloc (const char *in, size_t inlen, char **out) +{ + size_t outlen = 1 + BASE64_LENGTH (inlen); + + /* Check for overflow in outlen computation. + * + * If there is no overflow, outlen >= inlen. + * + * If the operation (inlen + 2) overflows then it yields at most +1, so + * outlen is 0. + * + * If the multiplication overflows, we lose at least half of the + * correct value, so the result is < ((inlen + 2) / 3) * 2, which is + * less than (inlen + 2) * 0.66667, which is less than inlen as soon as + * (inlen > 4). + */ + if (inlen > outlen) + { + *out = NULL; + return 0; + } + + *out = malloc (outlen); + if (!*out) + return outlen; + + base64_encode (in, inlen, *out, outlen); + + return outlen - 1; +} + +/* With this approach this file works independent of the charset used + (think EBCDIC). However, it does assume that the characters in the + Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX + 1003.1-2001 require that char and unsigned char are 8-bit + quantities, though, taking care of that problem. But this may be a + potential problem on non-POSIX C99 platforms. + + IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_" + as the formal parameter rather than "x". */ +#define B64(_) \ + ((_) == 'A' ? 0 \ + : (_) == 'B' ? 1 \ + : (_) == 'C' ? 2 \ + : (_) == 'D' ? 3 \ + : (_) == 'E' ? 4 \ + : (_) == 'F' ? 5 \ + : (_) == 'G' ? 6 \ + : (_) == 'H' ? 7 \ + : (_) == 'I' ? 8 \ + : (_) == 'J' ? 9 \ + : (_) == 'K' ? 10 \ + : (_) == 'L' ? 11 \ + : (_) == 'M' ? 12 \ + : (_) == 'N' ? 13 \ + : (_) == 'O' ? 14 \ + : (_) == 'P' ? 15 \ + : (_) == 'Q' ? 16 \ + : (_) == 'R' ? 17 \ + : (_) == 'S' ? 18 \ + : (_) == 'T' ? 19 \ + : (_) == 'U' ? 20 \ + : (_) == 'V' ? 21 \ + : (_) == 'W' ? 22 \ + : (_) == 'X' ? 23 \ + : (_) == 'Y' ? 24 \ + : (_) == 'Z' ? 25 \ + : (_) == 'a' ? 26 \ + : (_) == 'b' ? 27 \ + : (_) == 'c' ? 28 \ + : (_) == 'd' ? 29 \ + : (_) == 'e' ? 30 \ + : (_) == 'f' ? 31 \ + : (_) == 'g' ? 32 \ + : (_) == 'h' ? 33 \ + : (_) == 'i' ? 34 \ + : (_) == 'j' ? 35 \ + : (_) == 'k' ? 36 \ + : (_) == 'l' ? 37 \ + : (_) == 'm' ? 38 \ + : (_) == 'n' ? 39 \ + : (_) == 'o' ? 40 \ + : (_) == 'p' ? 41 \ + : (_) == 'q' ? 42 \ + : (_) == 'r' ? 43 \ + : (_) == 's' ? 44 \ + : (_) == 't' ? 45 \ + : (_) == 'u' ? 46 \ + : (_) == 'v' ? 47 \ + : (_) == 'w' ? 48 \ + : (_) == 'x' ? 49 \ + : (_) == 'y' ? 50 \ + : (_) == 'z' ? 51 \ + : (_) == '0' ? 52 \ + : (_) == '1' ? 53 \ + : (_) == '2' ? 54 \ + : (_) == '3' ? 55 \ + : (_) == '4' ? 56 \ + : (_) == '5' ? 57 \ + : (_) == '6' ? 58 \ + : (_) == '7' ? 59 \ + : (_) == '8' ? 60 \ + : (_) == '9' ? 61 \ + : (_) == '+' ? 62 \ + : (_) == '/' ? 63 \ + : -1) + +static const signed char b64[0x100] = { + B64 (0), B64 (1), B64 (2), B64 (3), + B64 (4), B64 (5), B64 (6), B64 (7), + B64 (8), B64 (9), B64 (10), B64 (11), + B64 (12), B64 (13), B64 (14), B64 (15), + B64 (16), B64 (17), B64 (18), B64 (19), + B64 (20), B64 (21), B64 (22), B64 (23), + B64 (24), B64 (25), B64 (26), B64 (27), + B64 (28), B64 (29), B64 (30), B64 (31), + B64 (32), B64 (33), B64 (34), B64 (35), + B64 (36), B64 (37), B64 (38), B64 (39), + B64 (40), B64 (41), B64 (42), B64 (43), + B64 (44), B64 (45), B64 (46), B64 (47), + B64 (48), B64 (49), B64 (50), B64 (51), + B64 (52), B64 (53), B64 (54), B64 (55), + B64 (56), B64 (57), B64 (58), B64 (59), + B64 (60), B64 (61), B64 (62), B64 (63), + B64 (64), B64 (65), B64 (66), B64 (67), + B64 (68), B64 (69), B64 (70), B64 (71), + B64 (72), B64 (73), B64 (74), B64 (75), + B64 (76), B64 (77), B64 (78), B64 (79), + B64 (80), B64 (81), B64 (82), B64 (83), + B64 (84), B64 (85), B64 (86), B64 (87), + B64 (88), B64 (89), B64 (90), B64 (91), + B64 (92), B64 (93), B64 (94), B64 (95), + B64 (96), B64 (97), B64 (98), B64 (99), + B64 (100), B64 (101), B64 (102), B64 (103), + B64 (104), B64 (105), B64 (106), B64 (107), + B64 (108), B64 (109), B64 (110), B64 (111), + B64 (112), B64 (113), B64 (114), B64 (115), + B64 (116), B64 (117), B64 (118), B64 (119), + B64 (120), B64 (121), B64 (122), B64 (123), + B64 (124), B64 (125), B64 (126), B64 (127), + B64 (128), B64 (129), B64 (130), B64 (131), + B64 (132), B64 (133), B64 (134), B64 (135), + B64 (136), B64 (137), B64 (138), B64 (139), + B64 (140), B64 (141), B64 (142), B64 (143), + B64 (144), B64 (145), B64 (146), B64 (147), + B64 (148), B64 (149), B64 (150), B64 (151), + B64 (152), B64 (153), B64 (154), B64 (155), + B64 (156), B64 (157), B64 (158), B64 (159), + B64 (160), B64 (161), B64 (162), B64 (163), + B64 (164), B64 (165), B64 (166), B64 (167), + B64 (168), B64 (169), B64 (170), B64 (171), + B64 (172), B64 (173), B64 (174), B64 (175), + B64 (176), B64 (177), B64 (178), B64 (179), + B64 (180), B64 (181), B64 (182), B64 (183), + B64 (184), B64 (185), B64 (186), B64 (187), + B64 (188), B64 (189), B64 (190), B64 (191), + B64 (192), B64 (193), B64 (194), B64 (195), + B64 (196), B64 (197), B64 (198), B64 (199), + B64 (200), B64 (201), B64 (202), B64 (203), + B64 (204), B64 (205), B64 (206), B64 (207), + B64 (208), B64 (209), B64 (210), B64 (211), + B64 (212), B64 (213), B64 (214), B64 (215), + B64 (216), B64 (217), B64 (218), B64 (219), + B64 (220), B64 (221), B64 (222), B64 (223), + B64 (224), B64 (225), B64 (226), B64 (227), + B64 (228), B64 (229), B64 (230), B64 (231), + B64 (232), B64 (233), B64 (234), B64 (235), + B64 (236), B64 (237), B64 (238), B64 (239), + B64 (240), B64 (241), B64 (242), B64 (243), + B64 (244), B64 (245), B64 (246), B64 (247), + B64 (248), B64 (249), B64 (250), B64 (251), + B64 (252), B64 (253), B64 (254), B64 (255) +}; + +#if UCHAR_MAX == 255 +# define uchar_in_range(c) true +#else +# define uchar_in_range(c) ((c) <= 255) +#endif + +/* Return true if CH is a character from the Base64 alphabet, and + false otherwise. Note that '=' is padding and not considered to be + part of the alphabet. */ +bool +isbase64 (char ch) +{ + return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)]; +} + +/* Initialize decode-context buffer, CTX. */ +void +base64_decode_ctx_init (struct base64_decode_context *ctx) +{ + ctx->i = 0; +} + +/* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and + none of those four is a newline, then return *IN. Otherwise, copy up to + 4 - CTX->i non-newline bytes from that range into CTX->buf, starting at + index CTX->i and setting CTX->i to reflect the number of bytes copied, + and return CTX->buf. In either case, advance *IN to point to the byte + after the last one processed, and set *N_NON_NEWLINE to the number of + verified non-newline bytes accessible through the returned pointer. */ +static char * +get_4 (struct base64_decode_context *ctx, + char const *restrict *in, char const *restrict in_end, + size_t *n_non_newline) +{ + if (ctx->i == 4) + ctx->i = 0; + + if (ctx->i == 0) + { + char const *t = *in; + if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL) + { + /* This is the common case: no newline. */ + *in += 4; + *n_non_newline = 4; + return (char *) t; + } + } + + { + /* Copy non-newline bytes into BUF. */ + char const *p = *in; + while (p < in_end) + { + char c = *p++; + if (c != '\n') + { + ctx->buf[ctx->i++] = c; + if (ctx->i == 4) + break; + } + } + + *in = p; + *n_non_newline = ctx->i; + return ctx->buf; + } +} + +#define return_false \ + do \ + { \ + *outp = out; \ + return false; \ + } \ + while (false) + +/* Decode up to four bytes of base64-encoded data, IN, of length INLEN + into the output buffer, *OUT, of size *OUTLEN bytes. Return true if + decoding is successful, false otherwise. If *OUTLEN is too small, + as many bytes as possible are written to *OUT. On return, advance + *OUT to point to the byte after the last one written, and decrement + *OUTLEN to reflect the number of bytes remaining in *OUT. */ +static bool +decode_4 (char const *restrict in, size_t inlen, + char *restrict *outp, size_t *outleft) +{ + char *out = *outp; + if (inlen < 2) + return false; + + if (!isbase64 (in[0]) || !isbase64 (in[1])) + return false; + + if (*outleft) + { + *out++ = ((b64[to_uchar (in[0])] << 2) + | (b64[to_uchar (in[1])] >> 4)); + --*outleft; + } + + if (inlen == 2) + return_false; + + if (in[2] == '=') + { + if (inlen != 4) + return_false; + + if (in[3] != '=') + return_false; + } + else + { + if (!isbase64 (in[2])) + return_false; + + if (*outleft) + { + *out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0) + | (b64[to_uchar (in[2])] >> 2)); + --*outleft; + } + + if (inlen == 3) + return_false; + + if (in[3] == '=') + { + if (inlen != 4) + return_false; + } + else + { + if (!isbase64 (in[3])) + return_false; + + if (*outleft) + { + *out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0) + | b64[to_uchar (in[3])]); + --*outleft; + } + } + } + + *outp = out; + return true; +} + +/* Decode base64-encoded input array IN of length INLEN to output array + OUT that can hold *OUTLEN bytes. The input data may be interspersed + with newlines. Return true if decoding was successful, i.e. if the + input was valid base64 data, false otherwise. If *OUTLEN is too + small, as many bytes as possible will be written to OUT. On return, + *OUTLEN holds the length of decoded bytes in OUT. Note that as soon + as any non-alphabet, non-newline character is encountered, decoding + is stopped and false is returned. If INLEN is zero, then process + only whatever data is stored in CTX. + + Initially, CTX must have been initialized via base64_decode_ctx_init. + Subsequent calls to this function must reuse whatever state is recorded + in that buffer. It is necessary for when a quadruple of base64 input + bytes spans two input buffers. + + If CTX is NULL then newlines are treated as garbage and the input + buffer is processed as a unit. */ + +bool +base64_decode_ctx (struct base64_decode_context *ctx, + const char *restrict in, size_t inlen, + char *restrict out, size_t *outlen) +{ + size_t outleft = *outlen; + bool ignore_newlines = ctx != NULL; + bool flush_ctx = false; + unsigned int ctx_i = 0; + + if (ignore_newlines) + { + ctx_i = ctx->i; + flush_ctx = inlen == 0; + } + + + while (true) + { + size_t outleft_save = outleft; + if (ctx_i == 0 && !flush_ctx) + { + while (true) + { + /* Save a copy of outleft, in case we need to re-parse this + block of four bytes. */ + outleft_save = outleft; + if (!decode_4 (in, inlen, &out, &outleft)) + break; + + in += 4; + inlen -= 4; + } + } + + if (inlen == 0 && !flush_ctx) + break; + + /* Handle the common case of 72-byte wrapped lines. + This also handles any other multiple-of-4-byte wrapping. */ + if (inlen && *in == '\n' && ignore_newlines) + { + ++in; + --inlen; + continue; + } + + /* Restore OUT and OUTLEFT. */ + out -= outleft_save - outleft; + outleft = outleft_save; + + { + char const *in_end = in + inlen; + char const *non_nl; + + if (ignore_newlines) + non_nl = get_4 (ctx, &in, in_end, &inlen); + else + non_nl = in; /* Might have nl in this case. */ + + /* If the input is empty or consists solely of newlines (0 non-newlines), + then we're done. Likewise if there are fewer than 4 bytes when not + flushing context and not treating newlines as garbage. */ + if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines)) + { + inlen = 0; + break; + } + if (!decode_4 (non_nl, inlen, &out, &outleft)) + break; + + inlen = in_end - in; + } + } + + *outlen -= outleft; + + return inlen == 0; +} + +/* Allocate an output buffer in *OUT, and decode the base64 encoded + data stored in IN of size INLEN to the *OUT buffer. On return, the + size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL, + if the caller is not interested in the decoded length. *OUT may be + NULL to indicate an out of memory error, in which case *OUTLEN + contains the size of the memory block needed. The function returns + true on successful decoding and memory allocation errors. (Use the + *OUT and *OUTLEN parameters to differentiate between successful + decoding and memory error.) The function returns false if the + input was invalid, in which case *OUT is NULL and *OUTLEN is + undefined. */ +bool +base64_decode_alloc_ctx (struct base64_decode_context *ctx, + const char *in, size_t inlen, char **out, + size_t *outlen) +{ + /* This may allocate a few bytes too many, depending on input, + but it's not worth the extra CPU time to compute the exact size. + The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the + input ends with "=" and minus another 1 if the input ends with "==". + Dividing before multiplying avoids the possibility of overflow. */ + size_t needlen = 3 * (inlen / 4) + 3; + + *out = malloc (needlen); + if (!*out) + return true; + + if (!base64_decode_ctx (ctx, in, inlen, *out, &needlen)) + { + free (*out); + *out = NULL; + return false; + } + + if (outlen) + *outlen = needlen; + + return true; +} diff --git a/grub-core/lib/gnulib/base64.h b/grub-core/lib/gnulib/base64.h new file mode 100644 index 0000000..392978f --- /dev/null +++ b/grub-core/lib/gnulib/base64.h @@ -0,0 +1,74 @@ +/* base64.h -- Encode binary data using printable characters. + Copyright (C) 2004-2006, 2009-2019 Free Software Foundation, Inc. + Written by Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef BASE64_H +# define BASE64_H + +/* Get size_t. */ +# include <stddef.h> + +#ifndef GRUB_POSIX_BOOL_DEFINED +typedef enum { false = 0, true = 1 } bool; +#define GRUB_POSIX_BOOL_DEFINED 1 +#endif + +#ifndef _GL_ATTRIBUTE_CONST +# define _GL_ATTRIBUTE_CONST /* empty */ +#endif + +# ifdef __cplusplus +extern "C" { +# endif + +/* This uses that the expression (n+(k-1))/k means the smallest + integer >= n/k, i.e., the ceiling of n/k. */ +# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4) + +struct base64_decode_context +{ + unsigned int i; + char buf[4]; +}; + +extern bool isbase64 (char ch) _GL_ATTRIBUTE_CONST; + +extern void base64_encode (const char *restrict in, size_t inlen, + char *restrict out, size_t outlen); + +extern size_t base64_encode_alloc (const char *in, size_t inlen, char **out); + +extern void base64_decode_ctx_init (struct base64_decode_context *ctx); + +extern bool base64_decode_ctx (struct base64_decode_context *ctx, + const char *restrict in, size_t inlen, + char *restrict out, size_t *outlen); + +extern bool base64_decode_alloc_ctx (struct base64_decode_context *ctx, + const char *in, size_t inlen, + char **out, size_t *outlen); + +#define base64_decode(in, inlen, out, outlen) \ + base64_decode_ctx (NULL, in, inlen, out, outlen) + +#define base64_decode_alloc(in, inlen, out, outlen) \ + base64_decode_alloc_ctx (NULL, in, inlen, out, outlen) + +# ifdef __cplusplus +} +# endif + +#endif /* BASE64_H */ diff --git a/grub-core/lib/gnulib/basename-lgpl.c b/grub-core/lib/gnulib/basename-lgpl.c new file mode 100644 index 0000000..0ae04ee --- /dev/null +++ b/grub-core/lib/gnulib/basename-lgpl.c @@ -0,0 +1,75 @@ +/* basename.c -- return the last element in a file name + + Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2019 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "dirname.h" + +#include <string.h> + +/* Return the address of the last file name component of NAME. If + NAME has no relative file name components because it is a file + system root, return the empty string. */ + +char * +last_component (char const *name) +{ + char const *base = name + FILE_SYSTEM_PREFIX_LEN (name); + char const *p; + bool saw_slash = false; + + while (ISSLASH (*base)) + base++; + + for (p = base; *p; p++) + { + if (ISSLASH (*p)) + saw_slash = true; + else if (saw_slash) + { + base = p; + saw_slash = false; + } + } + + return (char *) base; +} + +/* Return the length of the basename NAME. Typically NAME is the + value returned by base_name or last_component. Act like strlen + (NAME), except omit all trailing slashes. */ + +size_t +base_len (char const *name) +{ + size_t len; + size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name); + + for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--) + continue; + + if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1 + && ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2]) + return 2; + + if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len + && len == prefix_len && ISSLASH (name[prefix_len])) + return prefix_len + 1; + + return len; +} diff --git a/grub-core/lib/gnulib/btowc.c b/grub-core/lib/gnulib/btowc.c new file mode 100644 index 0000000..9e2496d --- /dev/null +++ b/grub-core/lib/gnulib/btowc.c @@ -0,0 +1,39 @@ +/* Convert unibyte character to wide character. + Copyright (C) 2008, 2010-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <wchar.h> + +#include <stdio.h> +#include <stdlib.h> + +wint_t +btowc (int c) +{ + if (c != EOF) + { + char buf[1]; + wchar_t wc; + + buf[0] = c; + if (mbtowc (&wc, buf, 1) >= 0) + return wc; + } + return WEOF; +} diff --git a/grub-core/lib/gnulib/c++defs.h b/grub-core/lib/gnulib/c++defs.h new file mode 100644 index 0000000..87d0716 --- /dev/null +++ b/grub-core/lib/gnulib/c++defs.h @@ -0,0 +1,316 @@ +/* C++ compatible function declaration macros. + Copyright (C) 2010-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _GL_CXXDEFS_H +#define _GL_CXXDEFS_H + +/* Begin/end the GNULIB_NAMESPACE namespace. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_BEGIN_NAMESPACE namespace GNULIB_NAMESPACE { +# define _GL_END_NAMESPACE } +#else +# define _GL_BEGIN_NAMESPACE +# define _GL_END_NAMESPACE +#endif + +/* The three most frequent use cases of these macros are: + + * For providing a substitute for a function that is missing on some + platforms, but is declared and works fine on the platforms on which + it exists: + + #if @GNULIB_FOO@ + # if !@HAVE_FOO@ + _GL_FUNCDECL_SYS (foo, ...); + # endif + _GL_CXXALIAS_SYS (foo, ...); + _GL_CXXALIASWARN (foo); + #elif defined GNULIB_POSIXCHECK + ... + #endif + + * For providing a replacement for a function that exists on all platforms, + but is broken/insufficient and needs to be replaced on some platforms: + + #if @GNULIB_FOO@ + # if @REPLACE_FOO@ + # if !(defined __cplusplus && defined GNULIB_NAMESPACE) + # undef foo + # define foo rpl_foo + # endif + _GL_FUNCDECL_RPL (foo, ...); + _GL_CXXALIAS_RPL (foo, ...); + # else + _GL_CXXALIAS_SYS (foo, ...); + # endif + _GL_CXXALIASWARN (foo); + #elif defined GNULIB_POSIXCHECK + ... + #endif + + * For providing a replacement for a function that exists on some platforms + but is broken/insufficient and needs to be replaced on some of them and + is additionally either missing or undeclared on some other platforms: + + #if @GNULIB_FOO@ + # if @REPLACE_FOO@ + # if !(defined __cplusplus && defined GNULIB_NAMESPACE) + # undef foo + # define foo rpl_foo + # endif + _GL_FUNCDECL_RPL (foo, ...); + _GL_CXXALIAS_RPL (foo, ...); + # else + # if !@HAVE_FOO@ or if !@HAVE_DECL_FOO@ + _GL_FUNCDECL_SYS (foo, ...); + # endif + _GL_CXXALIAS_SYS (foo, ...); + # endif + _GL_CXXALIASWARN (foo); + #elif defined GNULIB_POSIXCHECK + ... + #endif +*/ + +/* _GL_EXTERN_C declaration; + performs the declaration with C linkage. */ +#if defined __cplusplus +# define _GL_EXTERN_C extern "C" +#else +# define _GL_EXTERN_C extern +#endif + +/* _GL_FUNCDECL_RPL (func, rettype, parameters_and_attributes); + declares a replacement function, named rpl_func, with the given prototype, + consisting of return type, parameters, and attributes. + Example: + _GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...) + _GL_ARG_NONNULL ((1))); + */ +#define _GL_FUNCDECL_RPL(func,rettype,parameters_and_attributes) \ + _GL_FUNCDECL_RPL_1 (rpl_##func, rettype, parameters_and_attributes) +#define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters_and_attributes) \ + _GL_EXTERN_C rettype rpl_func parameters_and_attributes + +/* _GL_FUNCDECL_SYS (func, rettype, parameters_and_attributes); + declares the system function, named func, with the given prototype, + consisting of return type, parameters, and attributes. + Example: + _GL_FUNCDECL_SYS (open, int, (const char *filename, int flags, ...) + _GL_ARG_NONNULL ((1))); + */ +#define _GL_FUNCDECL_SYS(func,rettype,parameters_and_attributes) \ + _GL_EXTERN_C rettype func parameters_and_attributes + +/* _GL_CXXALIAS_RPL (func, rettype, parameters); + declares a C++ alias called GNULIB_NAMESPACE::func + that redirects to rpl_func, if GNULIB_NAMESPACE is defined. + Example: + _GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...)); + + Wrapping rpl_func in an object with an inline conversion operator + avoids a reference to rpl_func unless GNULIB_NAMESPACE::func is + actually used in the program. */ +#define _GL_CXXALIAS_RPL(func,rettype,parameters) \ + _GL_CXXALIAS_RPL_1 (func, rpl_##func, rettype, parameters) +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ + namespace GNULIB_NAMESPACE \ + { \ + static const struct _gl_ ## func ## _wrapper \ + { \ + typedef rettype (*type) parameters; \ + \ + inline operator type () const \ + { \ + return ::rpl_func; \ + } \ + } func = {}; \ + } \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#else +# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters); + is like _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters); + except that the C function rpl_func may have a slightly different + declaration. A cast is used to silence the "invalid conversion" error + that would otherwise occur. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ + namespace GNULIB_NAMESPACE \ + { \ + static const struct _gl_ ## func ## _wrapper \ + { \ + typedef rettype (*type) parameters; \ + \ + inline operator type () const \ + { \ + return reinterpret_cast<type>(::rpl_func); \ + } \ + } func = {}; \ + } \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#else +# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIAS_SYS (func, rettype, parameters); + declares a C++ alias called GNULIB_NAMESPACE::func + that redirects to the system provided function func, if GNULIB_NAMESPACE + is defined. + Example: + _GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); + + Wrapping func in an object with an inline conversion operator + avoids a reference to func unless GNULIB_NAMESPACE::func is + actually used in the program. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIAS_SYS(func,rettype,parameters) \ + namespace GNULIB_NAMESPACE \ + { \ + static const struct _gl_ ## func ## _wrapper \ + { \ + typedef rettype (*type) parameters; \ + \ + inline operator type () const \ + { \ + return ::func; \ + } \ + } func = {}; \ + } \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#else +# define _GL_CXXALIAS_SYS(func,rettype,parameters) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters); + is like _GL_CXXALIAS_SYS (func, rettype, parameters); + except that the C function func may have a slightly different declaration. + A cast is used to silence the "invalid conversion" error that would + otherwise occur. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ + namespace GNULIB_NAMESPACE \ + { \ + static const struct _gl_ ## func ## _wrapper \ + { \ + typedef rettype (*type) parameters; \ + \ + inline operator type () const \ + { \ + return reinterpret_cast<type>(::func); \ + } \ + } func = {}; \ + } \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#else +# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2); + is like _GL_CXXALIAS_SYS (func, rettype, parameters); + except that the C function is picked among a set of overloaded functions, + namely the one with rettype2 and parameters2. Two consecutive casts + are used to silence the "cannot find a match" and "invalid conversion" + errors that would otherwise occur. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE + /* The outer cast must be a reinterpret_cast. + The inner cast: When the function is defined as a set of overloaded + functions, it works as a static_cast<>, choosing the designated variant. + When the function is defined as a single variant, it works as a + reinterpret_cast<>. The parenthesized cast syntax works both ways. */ +# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ + namespace GNULIB_NAMESPACE \ + { \ + static const struct _gl_ ## func ## _wrapper \ + { \ + typedef rettype (*type) parameters; \ + \ + inline operator type () const \ + { \ + return reinterpret_cast<type>((rettype2 (*) parameters2)(::func)); \ + } \ + } func = {}; \ + } \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#else +# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIASWARN (func); + causes a warning to be emitted when ::func is used but not when + GNULIB_NAMESPACE::func is used. func must be defined without overloaded + variants. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIASWARN(func) \ + _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE) +# define _GL_CXXALIASWARN_1(func,namespace) \ + _GL_CXXALIASWARN_2 (func, namespace) +/* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>, + we enable the warning only when not optimizing. */ +# if !__OPTIMIZE__ +# define _GL_CXXALIASWARN_2(func,namespace) \ + _GL_WARN_ON_USE (func, \ + "The symbol ::" #func " refers to the system function. " \ + "Use " #namespace "::" #func " instead.") +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING +# define _GL_CXXALIASWARN_2(func,namespace) \ + extern __typeof__ (func) func +# else +# define _GL_CXXALIASWARN_2(func,namespace) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +# endif +#else +# define _GL_CXXALIASWARN(func) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes); + causes a warning to be emitted when the given overloaded variant of ::func + is used but not when GNULIB_NAMESPACE::func is used. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ + _GL_CXXALIASWARN1_1 (func, rettype, parameters_and_attributes, \ + GNULIB_NAMESPACE) +# define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \ + _GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace) +/* To work around GCC bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>, + we enable the warning only when not optimizing. */ +# if !__OPTIMIZE__ +# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ + _GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \ + "The symbol ::" #func " refers to the system function. " \ + "Use " #namespace "::" #func " instead.") +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING +# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ + extern __typeof__ (func) func +# else +# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +# endif +#else +# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +#endif /* _GL_CXXDEFS_H */ diff --git a/grub-core/lib/gnulib/cdefs.h b/grub-core/lib/gnulib/cdefs.h new file mode 100644 index 0000000..f7a1064 --- /dev/null +++ b/grub-core/lib/gnulib/cdefs.h @@ -0,0 +1,514 @@ +/* Copyright (C) 1992-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _SYS_CDEFS_H +#define _SYS_CDEFS_H 1 + +/* We are almost always included from features.h. */ +#ifndef _FEATURES_H +# include <features.h> +#endif + +/* The GNU libc does not support any K&R compilers or the traditional mode + of ISO C compilers anymore. Check for some of the combinations not + anymore supported. */ +#if defined __GNUC__ && !defined __STDC__ +# error "You need a ISO C conforming compiler to use the glibc headers" +#endif + +/* Some user header file might have defined this before. */ +#undef __P +#undef __PMT + +#ifdef __GNUC__ + +/* All functions, except those with callbacks or those that + synchronize memory, are leaf functions. */ +# if __GNUC_PREREQ (4, 6) && !defined _LIBC +# define __LEAF , __leaf__ +# define __LEAF_ATTR __attribute__ ((__leaf__)) +# else +# define __LEAF +# define __LEAF_ATTR +# endif + +/* GCC can always grok prototypes. For C++ programs we add throw() + to help it optimize the function calls. But this works only with + gcc 2.8.x and egcs. For gcc 3.2 and up we even mark C functions + as non-throwing using a function attribute since programs can use + the -fexceptions options for C code as well. */ +# if !defined __cplusplus && __GNUC_PREREQ (3, 3) +# define __THROW __attribute__ ((__nothrow__ __LEAF)) +# define __THROWNL __attribute__ ((__nothrow__)) +# define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct +# define __NTHNL(fct) __attribute__ ((__nothrow__)) fct +# else +# if defined __cplusplus && __GNUC_PREREQ (2,8) +# define __THROW throw () +# define __THROWNL throw () +# define __NTH(fct) __LEAF_ATTR fct throw () +# define __NTHNL(fct) fct throw () +# else +# define __THROW +# define __THROWNL +# define __NTH(fct) fct +# define __NTHNL(fct) fct +# endif +# endif + +#else /* Not GCC. */ + +# if (defined __cplusplus \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) +# define __inline inline +# else +# define __inline /* No inline functions. */ +# endif + +# define __THROW +# define __THROWNL +# define __NTH(fct) fct + +#endif /* GCC. */ + +/* Compilers that are not clang may object to + #if defined __clang__ && __has_extension(...) + even though they do not need to evaluate the right-hand side of the &&. */ +#if defined __clang__ && defined __has_extension +# define __glibc_clang_has_extension(ext) __has_extension (ext) +#else +# define __glibc_clang_has_extension(ext) 0 +#endif + +/* These two macros are not used in glibc anymore. They are kept here + only because some other projects expect the macros to be defined. */ +#define __P(args) args +#define __PMT(args) args + +/* For these things, GCC behaves the ANSI way normally, + and the non-ANSI way under -traditional. */ + +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +/* This is not a typedef so `const __ptr_t' does the right thing. */ +#define __ptr_t void * + + +/* C++ needs to know that types and declarations are C, not C++. */ +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS +# define __END_DECLS +#endif + + +/* Fortify support. */ +#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) +#define __bos0(ptr) __builtin_object_size (ptr, 0) + +#if __GNUC_PREREQ (4,3) +# define __warndecl(name, msg) \ + extern void name (void) __attribute__((__warning__ (msg))) +# define __warnattr(msg) __attribute__((__warning__ (msg))) +# define __errordecl(name, msg) \ + extern void name (void) __attribute__((__error__ (msg))) +#else +# define __warndecl(name, msg) extern void name (void) +# define __warnattr(msg) +# define __errordecl(name, msg) extern void name (void) +#endif + +/* Support for flexible arrays. + Headers that should use flexible arrays only if they're "real" + (e.g. only if they won't affect sizeof()) should test + #if __glibc_c99_flexarr_available. */ +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L && !defined __HP_cc +# define __flexarr [] +# define __glibc_c99_flexarr_available 1 +#elif __GNUC_PREREQ (2,97) +/* GCC 2.97 supports C99 flexible array members as an extension, + even when in C89 mode or compiling C++ (any version). */ +# define __flexarr [] +# define __glibc_c99_flexarr_available 1 +#elif defined __GNUC__ +/* Pre-2.97 GCC did not support C99 flexible arrays but did have + an equivalent extension with slightly different notation. */ +# define __flexarr [0] +# define __glibc_c99_flexarr_available 1 +#else +/* Some other non-C99 compiler. Approximate with [1]. */ +# define __flexarr [1] +# define __glibc_c99_flexarr_available 0 +#endif + + +/* __asm__ ("xyz") is used throughout the headers to rename functions + at the assembly language level. This is wrapped by the __REDIRECT + macro, in order to support compilers that can do this some other + way. When compilers don't support asm-names at all, we have to do + preprocessor tricks instead (which don't have exactly the right + semantics, but it's the best we can do). + + Example: + int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */ + +#if defined __GNUC__ && __GNUC__ >= 2 + +# define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias)) +# ifdef __cplusplus +# define __REDIRECT_NTH(name, proto, alias) \ + name proto __THROW __asm__ (__ASMNAME (#alias)) +# define __REDIRECT_NTHNL(name, proto, alias) \ + name proto __THROWNL __asm__ (__ASMNAME (#alias)) +# else +# define __REDIRECT_NTH(name, proto, alias) \ + name proto __asm__ (__ASMNAME (#alias)) __THROW +# define __REDIRECT_NTHNL(name, proto, alias) \ + name proto __asm__ (__ASMNAME (#alias)) __THROWNL +# endif +# define __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname) +# define __ASMNAME2(prefix, cname) __STRING (prefix) cname + +/* +#elif __SOME_OTHER_COMPILER__ + +# define __REDIRECT(name, proto, alias) name proto; \ + _Pragma("let " #name " = " #alias) +*/ +#endif + +/* GCC has various useful declarations that can be made with the + `__attribute__' syntax. All of the ways we use this do fine if + they are omitted for compilers that don't understand it. */ +#if !defined __GNUC__ || __GNUC__ < 2 +# define __attribute__(xyz) /* Ignore */ +#endif + +/* At some point during the gcc 2.96 development the `malloc' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (2,96) +# define __attribute_malloc__ __attribute__ ((__malloc__)) +#else +# define __attribute_malloc__ /* Ignore */ +#endif + +/* Tell the compiler which arguments to an allocation function + indicate the size of the allocation. */ +#if __GNUC_PREREQ (4, 3) +# define __attribute_alloc_size__(params) \ + __attribute__ ((__alloc_size__ params)) +#else +# define __attribute_alloc_size__(params) /* Ignore. */ +#endif + +/* At some point during the gcc 2.96 development the `pure' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (2,96) +# define __attribute_pure__ __attribute__ ((__pure__)) +#else +# define __attribute_pure__ /* Ignore */ +#endif + +/* This declaration tells the compiler that the value is constant. */ +#if __GNUC_PREREQ (2,5) +# define __attribute_const__ __attribute__ ((__const__)) +#else +# define __attribute_const__ /* Ignore */ +#endif + +/* At some point during the gcc 3.1 development the `used' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (3,1) +# define __attribute_used__ __attribute__ ((__used__)) +# define __attribute_noinline__ __attribute__ ((__noinline__)) +#else +# define __attribute_used__ __attribute__ ((__unused__)) +# define __attribute_noinline__ /* Ignore */ +#endif + +/* Since version 3.2, gcc allows marking deprecated functions. */ +#if __GNUC_PREREQ (3,2) +# define __attribute_deprecated__ __attribute__ ((__deprecated__)) +#else +# define __attribute_deprecated__ /* Ignore */ +#endif + +/* Since version 4.5, gcc also allows one to specify the message printed + when a deprecated function is used. clang claims to be gcc 4.2, but + may also support this feature. */ +#if __GNUC_PREREQ (4,5) || \ + __glibc_clang_has_extension (__attribute_deprecated_with_message__) +# define __attribute_deprecated_msg__(msg) \ + __attribute__ ((__deprecated__ (msg))) +#else +# define __attribute_deprecated_msg__(msg) __attribute_deprecated__ +#endif + +/* At some point during the gcc 2.8 development the `format_arg' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. + If several `format_arg' attributes are given for the same function, in + gcc-3.0 and older, all but the last one are ignored. In newer gccs, + all designated arguments are considered. */ +#if __GNUC_PREREQ (2,8) +# define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x))) +#else +# define __attribute_format_arg__(x) /* Ignore */ +#endif + +/* At some point during the gcc 2.97 development the `strfmon' format + attribute for functions was introduced. We don't want to use it + unconditionally (although this would be possible) since it + generates warnings. */ +#if __GNUC_PREREQ (2,97) +# define __attribute_format_strfmon__(a,b) \ + __attribute__ ((__format__ (__strfmon__, a, b))) +#else +# define __attribute_format_strfmon__(a,b) /* Ignore */ +#endif + +/* The nonnull function attribute marks pointer parameters that + must not be NULL. Do not define __nonnull if it is already defined, + for portability when this file is used in Gnulib. */ +#ifndef __nonnull +# if __GNUC_PREREQ (3,3) +# define __nonnull(params) __attribute__ ((__nonnull__ params)) +# else +# define __nonnull(params) +# endif +#endif + +/* If fortification mode, we warn about unused results of certain + function calls which can lead to problems. */ +#if __GNUC_PREREQ (3,4) +# define __attribute_warn_unused_result__ \ + __attribute__ ((__warn_unused_result__)) +# if defined __USE_FORTIFY_LEVEL && __USE_FORTIFY_LEVEL > 0 +# define __wur __attribute_warn_unused_result__ +# endif +#else +# define __attribute_warn_unused_result__ /* empty */ +#endif +#ifndef __wur +# define __wur /* Ignore */ +#endif + +/* Forces a function to be always inlined. */ +#if __GNUC_PREREQ (3,2) +/* The Linux kernel defines __always_inline in stddef.h (283d7573), and + it conflicts with this definition. Therefore undefine it first to + allow either header to be included first. */ +# undef __always_inline +# define __always_inline __inline __attribute__ ((__always_inline__)) +#else +# undef __always_inline +# define __always_inline __inline +#endif + +/* Associate error messages with the source location of the call site rather + than with the source location inside the function. */ +#if __GNUC_PREREQ (4,3) +# define __attribute_artificial__ __attribute__ ((__artificial__)) +#else +# define __attribute_artificial__ /* Ignore */ +#endif + +/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. Using __GNUC_STDC_INLINE__ + or __GNUC_GNU_INLINE is not a good enough check for gcc because gcc versions + older than 4.3 may define these macros and still not guarantee GNU inlining + semantics. + + clang++ identifies itself as gcc-4.2, but has support for GNU inlining + semantics, that can be checked fot by using the __GNUC_STDC_INLINE_ and + __GNUC_GNU_INLINE__ macro definitions. */ +#if (!defined __cplusplus || __GNUC_PREREQ (4,3) \ + || (defined __clang__ && (defined __GNUC_STDC_INLINE__ \ + || defined __GNUC_GNU_INLINE__))) +# if defined __GNUC_STDC_INLINE__ || defined __cplusplus +# define __extern_inline extern __inline __attribute__ ((__gnu_inline__)) +# define __extern_always_inline \ + extern __always_inline __attribute__ ((__gnu_inline__)) +# else +# define __extern_inline extern __inline +# define __extern_always_inline extern __always_inline +# endif +#endif + +#ifdef __extern_always_inline +# define __fortify_function __extern_always_inline __attribute_artificial__ +#endif + +/* GCC 4.3 and above allow passing all anonymous arguments of an + __extern_always_inline function to some other vararg function. */ +#if __GNUC_PREREQ (4,3) +# define __va_arg_pack() __builtin_va_arg_pack () +# define __va_arg_pack_len() __builtin_va_arg_pack_len () +#endif + +/* It is possible to compile containing GCC extensions even if GCC is + run in pedantic mode if the uses are carefully marked using the + `__extension__' keyword. But this is not generally available before + version 2.8. */ +#if !__GNUC_PREREQ (2,8) +# define __extension__ /* Ignore */ +#endif + +/* __restrict is known in EGCS 1.2 and above. */ +#if !__GNUC_PREREQ (2,92) +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __restrict restrict +# else +# define __restrict /* Ignore */ +# endif +#endif + +/* ISO C99 also allows to declare arrays as non-overlapping. The syntax is + array_name[restrict] + GCC 3.1 supports this. */ +#if __GNUC_PREREQ (3,1) && !defined __GNUG__ +# define __restrict_arr __restrict +#else +# ifdef __GNUC__ +# define __restrict_arr /* Not supported in old GCC. */ +# else +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __restrict_arr restrict +# else +/* Some other non-C99 compiler. */ +# define __restrict_arr /* Not supported. */ +# endif +# endif +#endif + +#if __GNUC__ >= 3 +# define __glibc_unlikely(cond) __builtin_expect ((cond), 0) +# define __glibc_likely(cond) __builtin_expect ((cond), 1) +#else +# define __glibc_unlikely(cond) (cond) +# define __glibc_likely(cond) (cond) +#endif + +#ifdef __has_attribute +# define __glibc_has_attribute(attr) __has_attribute (attr) +#else +# define __glibc_has_attribute(attr) 0 +#endif + +#if (!defined _Noreturn \ + && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ + && !__GNUC_PREREQ (4,7)) +# if __GNUC_PREREQ (2,8) +# define _Noreturn __attribute__ ((__noreturn__)) +# else +# define _Noreturn +# endif +#endif + +#if __GNUC_PREREQ (8, 0) +/* Describes a char array whose address can safely be passed as the first + argument to strncpy and strncat, as the char array is not necessarily + a NUL-terminated string. */ +# define __attribute_nonstring__ __attribute__ ((__nonstring__)) +#else +# define __attribute_nonstring__ +#endif + +#if (!defined _Static_assert && !defined __cplusplus \ + && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ + && (!__GNUC_PREREQ (4, 6) || defined __STRICT_ANSI__)) +# define _Static_assert(expr, diagnostic) \ + extern int (*__Static_assert_function (void)) \ + [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })] +#endif + +/* The #ifndef lets Gnulib avoid including these on non-glibc + platforms, where the includes typically do not exist. */ +#ifndef __WORDSIZE +# include <bits/wordsize.h> +# include <bits/long-double.h> +#endif + +#if defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH +# define __LDBL_COMPAT 1 +# ifdef __REDIRECT +# define __LDBL_REDIR1(name, proto, alias) __REDIRECT (name, proto, alias) +# define __LDBL_REDIR(name, proto) \ + __LDBL_REDIR1 (name, proto, __nldbl_##name) +# define __LDBL_REDIR1_NTH(name, proto, alias) __REDIRECT_NTH (name, proto, alias) +# define __LDBL_REDIR_NTH(name, proto) \ + __LDBL_REDIR1_NTH (name, proto, __nldbl_##name) +# define __LDBL_REDIR1_DECL(name, alias) \ + extern __typeof (name) name __asm (__ASMNAME (#alias)); +# define __LDBL_REDIR_DECL(name) \ + extern __typeof (name) name __asm (__ASMNAME ("__nldbl_" #name)); +# define __REDIRECT_LDBL(name, proto, alias) \ + __LDBL_REDIR1 (name, proto, __nldbl_##alias) +# define __REDIRECT_NTH_LDBL(name, proto, alias) \ + __LDBL_REDIR1_NTH (name, proto, __nldbl_##alias) +# endif +#endif +#if !defined __LDBL_COMPAT || !defined __REDIRECT +# define __LDBL_REDIR1(name, proto, alias) name proto +# define __LDBL_REDIR(name, proto) name proto +# define __LDBL_REDIR1_NTH(name, proto, alias) name proto __THROW +# define __LDBL_REDIR_NTH(name, proto) name proto __THROW +# define __LDBL_REDIR_DECL(name) +# ifdef __REDIRECT +# define __REDIRECT_LDBL(name, proto, alias) __REDIRECT (name, proto, alias) +# define __REDIRECT_NTH_LDBL(name, proto, alias) \ + __REDIRECT_NTH (name, proto, alias) +# endif +#endif + +/* __glibc_macro_warning (MESSAGE) issues warning MESSAGE. This is + intended for use in preprocessor macros. + + Note: MESSAGE must be a _single_ string; concatenation of string + literals is not supported. */ +#if __GNUC_PREREQ (4,8) || __glibc_clang_prereq (3,5) +# define __glibc_macro_warning1(message) _Pragma (#message) +# define __glibc_macro_warning(message) \ + __glibc_macro_warning1 (GCC warning message) +#else +# define __glibc_macro_warning(msg) +#endif + +/* Generic selection (ISO C11) is a C-only feature, available in GCC + since version 4.9. Previous versions do not provide generic + selection, even though they might set __STDC_VERSION__ to 201112L, + when in -std=c11 mode. Thus, we must check for !defined __GNUC__ + when testing __STDC_VERSION__ for generic selection support. + On the other hand, Clang also defines __GNUC__, so a clang-specific + check is required to enable the use of generic selection. */ +#if !defined __cplusplus \ + && (__GNUC_PREREQ (4, 9) \ + || __glibc_clang_has_extension (c_generic_selections) \ + || (!defined __GNUC__ && defined __STDC_VERSION__ \ + && __STDC_VERSION__ >= 201112L)) +# define __HAVE_GENERIC_SELECTION 1 +#else +# define __HAVE_GENERIC_SELECTION 0 +#endif + +#endif /* sys/cdefs.h */ diff --git a/grub-core/lib/gnulib/chdir-long.c b/grub-core/lib/gnulib/chdir-long.c new file mode 100644 index 0000000..febdf59 --- /dev/null +++ b/grub-core/lib/gnulib/chdir-long.c @@ -0,0 +1,264 @@ +/* provide a chdir function that tries not to fail due to ENAMETOOLONG + Copyright (C) 2004-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* written by Jim Meyering */ + +#include <config.h> + +#include "chdir-long.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <stdbool.h> +#include <string.h> +#include <stdio.h> + +#include "assure.h" + +#ifndef PATH_MAX +# error "compile this file only if your system defines PATH_MAX" +#endif + +/* The results of openat() in this file are not leaked to any + single-threaded code that could use stdio. + FIXME - if the kernel ever adds support for multi-thread safety for + avoiding standard fds, then we should use openat_safer. */ + +struct cd_buf +{ + int fd; +}; + +static void +cdb_init (struct cd_buf *cdb) +{ + cdb->fd = AT_FDCWD; +} + +static int +cdb_fchdir (struct cd_buf const *cdb) +{ + return fchdir (cdb->fd); +} + +static void +cdb_free (struct cd_buf const *cdb) +{ + if (0 <= cdb->fd) + { + bool close_fail = close (cdb->fd); + assure (! close_fail); + } +} + +/* Given a file descriptor of an open directory (or AT_FDCWD), CDB->fd, + try to open the CDB->fd-relative directory, DIR. If the open succeeds, + update CDB->fd with the resulting descriptor, close the incoming file + descriptor, and return zero. Upon failure, return -1 and set errno. */ +static int +cdb_advance_fd (struct cd_buf *cdb, char const *dir) +{ + int new_fd = openat (cdb->fd, dir, + O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK); + if (new_fd < 0) + return -1; + + cdb_free (cdb); + cdb->fd = new_fd; + + return 0; +} + +/* Return a pointer to the first non-slash in S. */ +static char * _GL_ATTRIBUTE_PURE +find_non_slash (char const *s) +{ + size_t n_slash = strspn (s, "/"); + return (char *) s + n_slash; +} + +/* This is a function much like chdir, but without the PATH_MAX limitation + on the length of the directory name. A significant difference is that + it must be able to modify (albeit only temporarily) the directory + name. It handles an arbitrarily long directory name by operating + on manageable portions of the name. On systems without the openat + syscall, this means changing the working directory to more and more + "distant" points along the long directory name and then restoring + the working directory. If any of those attempts to save or restore + the working directory fails, this function exits nonzero. + + Note that this function may still fail with errno == ENAMETOOLONG, but + only if the specified directory name contains a component that is long + enough to provoke such a failure all by itself (e.g. if the component + has length PATH_MAX or greater on systems that define PATH_MAX). */ + +int +chdir_long (char *dir) +{ + int e = chdir (dir); + if (e == 0 || errno != ENAMETOOLONG) + return e; + + { + size_t len = strlen (dir); + char *dir_end = dir + len; + struct cd_buf cdb; + size_t n_leading_slash; + + cdb_init (&cdb); + + /* If DIR is the empty string, then the chdir above + must have failed and set errno to ENOENT. */ + assure (0 < len); + assure (PATH_MAX <= len); + + /* Count leading slashes. */ + n_leading_slash = strspn (dir, "/"); + + /* Handle any leading slashes as well as any name that matches + the regular expression, m!^//hostname[/]*! . Handling this + prefix separately usually results in a single additional + cdb_advance_fd call, but it's worthwhile, since it makes the + code in the following loop cleaner. */ + if (n_leading_slash == 2) + { + int err; + /* Find next slash. + We already know that dir[2] is neither a slash nor '\0'. */ + char *slash = memchr (dir + 3, '/', dir_end - (dir + 3)); + if (slash == NULL) + { + errno = ENAMETOOLONG; + return -1; + } + *slash = '\0'; + err = cdb_advance_fd (&cdb, dir); + *slash = '/'; + if (err != 0) + goto Fail; + dir = find_non_slash (slash + 1); + } + else if (n_leading_slash) + { + if (cdb_advance_fd (&cdb, "/") != 0) + goto Fail; + dir += n_leading_slash; + } + + assure (*dir != '/'); + assure (dir <= dir_end); + + while (PATH_MAX <= dir_end - dir) + { + int err; + /* Find a slash that is PATH_MAX or fewer bytes away from dir. + I.e. see if there is a slash that will give us a name of + length PATH_MAX-1 or less. */ + char *slash = memrchr (dir, '/', PATH_MAX); + if (slash == NULL) + { + errno = ENAMETOOLONG; + return -1; + } + + *slash = '\0'; + assure (slash - dir < PATH_MAX); + err = cdb_advance_fd (&cdb, dir); + *slash = '/'; + if (err != 0) + goto Fail; + + dir = find_non_slash (slash + 1); + } + + if (dir < dir_end) + { + if (cdb_advance_fd (&cdb, dir) != 0) + goto Fail; + } + + if (cdb_fchdir (&cdb) != 0) + goto Fail; + + cdb_free (&cdb); + return 0; + + Fail: + { + int saved_errno = errno; + cdb_free (&cdb); + errno = saved_errno; + return -1; + } + } +} + +#if TEST_CHDIR + +# include "closeout.h" +# include "error.h" + +int +main (int argc, char *argv[]) +{ + char *line = NULL; + size_t n = 0; + int len; + + atexit (close_stdout); + + len = getline (&line, &n, stdin); + if (len < 0) + { + int saved_errno = errno; + if (feof (stdin)) + exit (0); + + error (EXIT_FAILURE, saved_errno, + "reading standard input"); + } + else if (len == 0) + exit (0); + + if (line[len-1] == '\n') + line[len-1] = '\0'; + + if (chdir_long (line) != 0) + error (EXIT_FAILURE, errno, + "chdir_long failed: %s", line); + + if (argc <= 1) + { + /* Using 'pwd' here makes sense only if it is a robust implementation, + like the one in coreutils after the 2004-04-19 changes. */ + char const *cmd = "pwd"; + execlp (cmd, (char *) NULL); + error (EXIT_FAILURE, errno, "%s", cmd); + } + + fclose (stdin); + fclose (stderr); + + exit (EXIT_SUCCESS); +} +#endif + +/* +Local Variables: +compile-command: "gcc -DTEST_CHDIR=1 -g -O -W -Wall chdir-long.c libcoreutils.a" +End: +*/ diff --git a/grub-core/lib/gnulib/chdir-long.h b/grub-core/lib/gnulib/chdir-long.h new file mode 100644 index 0000000..43259d1 --- /dev/null +++ b/grub-core/lib/gnulib/chdir-long.h @@ -0,0 +1,30 @@ +/* provide a chdir function that tries not to fail due to ENAMETOOLONG + Copyright (C) 2004-2005, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Jim Meyering. */ + +#include <unistd.h> +#include <limits.h> + +#include "pathmax.h" + +/* On systems without PATH_MAX, presume that chdir accepts + arbitrarily long directory names. */ +#ifndef PATH_MAX +# define chdir_long(Dir) chdir (Dir) +#else +int chdir_long (char *dir); +#endif diff --git a/grub-core/lib/gnulib/cloexec.c b/grub-core/lib/gnulib/cloexec.c new file mode 100644 index 0000000..db42576 --- /dev/null +++ b/grub-core/lib/gnulib/cloexec.c @@ -0,0 +1,83 @@ +/* cloexec.c - set or clear the close-on-exec descriptor flag + + Copyright (C) 1991, 2004-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + + The code is taken from glibc/manual/llio.texi */ + +#include <config.h> + +#include "cloexec.h" + +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, + or clear the flag if VALUE is false. + Return 0 on success, or -1 on error with 'errno' set. + + Note that on MingW, this function does NOT protect DESC from being + inherited into spawned children. Instead, either use dup_cloexec + followed by closing the original DESC, or use interfaces such as + open or pipe2 that accept flags like O_CLOEXEC to create DESC + non-inheritable in the first place. */ + +int +set_cloexec_flag (int desc, bool value) +{ +#ifdef F_SETFD + + int flags = fcntl (desc, F_GETFD, 0); + + if (0 <= flags) + { + int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC); + + if (flags == newflags + || fcntl (desc, F_SETFD, newflags) != -1) + return 0; + } + + return -1; + +#else /* !F_SETFD */ + + /* Use dup2 to reject invalid file descriptors; the cloexec flag + will be unaffected. */ + if (desc < 0) + { + errno = EBADF; + return -1; + } + if (dup2 (desc, desc) < 0) + /* errno is EBADF here. */ + return -1; + + /* There is nothing we can do on this kind of platform. Punt. */ + return 0; +#endif /* !F_SETFD */ +} + + +/* Duplicates a file handle FD, while marking the copy to be closed + prior to exec or spawn. Returns -1 and sets errno if FD could not + be duplicated. */ + +int +dup_cloexec (int fd) +{ + return fcntl (fd, F_DUPFD_CLOEXEC, 0); +} diff --git a/grub-core/lib/gnulib/cloexec.h b/grub-core/lib/gnulib/cloexec.h new file mode 100644 index 0000000..06ad945 --- /dev/null +++ b/grub-core/lib/gnulib/cloexec.h @@ -0,0 +1,38 @@ +/* cloexec.c - set or clear the close-on-exec descriptor flag + + Copyright (C) 2004, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +*/ + +#include <stdbool.h> + +/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, + or clear the flag if VALUE is false. + Return 0 on success, or -1 on error with 'errno' set. + + Note that on MingW, this function does NOT protect DESC from being + inherited into spawned children. Instead, either use dup_cloexec + followed by closing the original DESC, or use interfaces such as + open or pipe2 that accept flags like O_CLOEXEC to create DESC + non-inheritable in the first place. */ + +int set_cloexec_flag (int desc, bool value); + +/* Duplicates a file handle FD, while marking the copy to be closed + prior to exec or spawn. Returns -1 and sets errno if FD could not + be duplicated. */ + +int dup_cloexec (int fd); diff --git a/grub-core/lib/gnulib/close.c b/grub-core/lib/gnulib/close.c new file mode 100644 index 0000000..40ce845 --- /dev/null +++ b/grub-core/lib/gnulib/close.c @@ -0,0 +1,71 @@ +/* close replacement. + Copyright (C) 2008-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <unistd.h> + +#include <errno.h> + +#include "fd-hook.h" +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +#endif + +#undef close + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static int +close_nothrow (int fd) +{ + int result; + + TRY_MSVC_INVAL + { + result = close (fd); + } + CATCH_MSVC_INVAL + { + result = -1; + errno = EBADF; + } + DONE_MSVC_INVAL; + + return result; +} +#else +# define close_nothrow close +#endif + +/* Override close() to call into other gnulib modules. */ + +int +rpl_close (int fd) +{ +#if WINDOWS_SOCKETS + int retval = execute_all_close_hooks (close_nothrow, fd); +#else + int retval = close_nothrow (fd); +#endif + +#if REPLACE_FCHDIR + if (retval >= 0) + _gl_unregister_fd (fd); +#endif + + return retval; +} diff --git a/grub-core/lib/gnulib/dirent.in.h b/grub-core/lib/gnulib/dirent.in.h new file mode 100644 index 0000000..a3c8eb3 --- /dev/null +++ b/grub-core/lib/gnulib/dirent.in.h @@ -0,0 +1,267 @@ +/* A GNU-like <dirent.h>. + Copyright (C) 2006-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _@GUARD_PREFIX@_DIRENT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_DIRENT_H@ +# @INCLUDE_NEXT@ @NEXT_DIRENT_H@ +#endif + +#ifndef _@GUARD_PREFIX@_DIRENT_H +#define _@GUARD_PREFIX@_DIRENT_H + +/* Get ino_t. Needed on some systems, including glibc 2.8. */ +#include <sys/types.h> + +#if !@HAVE_DIRENT_H@ +/* Define types DIR and 'struct dirent'. */ +# if !GNULIB_defined_struct_dirent +struct dirent +{ + char d_type; + char d_name[1]; +}; +/* Possible values for 'd_type'. */ +# define DT_UNKNOWN 0 +# define DT_FIFO 1 /* FIFO */ +# define DT_CHR 2 /* character device */ +# define DT_DIR 4 /* directory */ +# define DT_BLK 6 /* block device */ +# define DT_REG 8 /* regular file */ +# define DT_LNK 10 /* symbolic link */ +# define DT_SOCK 12 /* socket */ +# define DT_WHT 14 /* whiteout */ +typedef struct gl_directory DIR; +# define GNULIB_defined_struct_dirent 1 +# endif +#endif + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +# define _GL_ATTRIBUTE_PURE /* empty */ +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Declare overridden functions. */ + +#if @GNULIB_OPENDIR@ +# if @REPLACE_OPENDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef opendir +# define opendir rpl_opendir +# define GNULIB_defined_opendir 1 +# endif +_GL_FUNCDECL_RPL (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name)); +# else +# if !@HAVE_OPENDIR@ +_GL_FUNCDECL_SYS (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (opendir, DIR *, (const char *dir_name)); +# endif +_GL_CXXALIASWARN (opendir); +#elif defined GNULIB_POSIXCHECK +# undef opendir +# if HAVE_RAW_DECL_OPENDIR +_GL_WARN_ON_USE (opendir, "opendir is not portable - " + "use gnulib module opendir for portability"); +# endif +#endif + +#if @GNULIB_READDIR@ +# if !@HAVE_READDIR@ +_GL_FUNCDECL_SYS (readdir, struct dirent *, (DIR *dirp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (readdir, struct dirent *, (DIR *dirp)); +_GL_CXXALIASWARN (readdir); +#elif defined GNULIB_POSIXCHECK +# undef readdir +# if HAVE_RAW_DECL_READDIR +_GL_WARN_ON_USE (readdir, "readdir is not portable - " + "use gnulib module readdir for portability"); +# endif +#endif + +#if @GNULIB_REWINDDIR@ +# if !@HAVE_REWINDDIR@ +_GL_FUNCDECL_SYS (rewinddir, void, (DIR *dirp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (rewinddir, void, (DIR *dirp)); +_GL_CXXALIASWARN (rewinddir); +#elif defined GNULIB_POSIXCHECK +# undef rewinddir +# if HAVE_RAW_DECL_REWINDDIR +_GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - " + "use gnulib module rewinddir for portability"); +# endif +#endif + +#if @GNULIB_CLOSEDIR@ +# if @REPLACE_CLOSEDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef closedir +# define closedir rpl_closedir +# define GNULIB_defined_closedir 1 +# endif +_GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (closedir, int, (DIR *dirp)); +# else +# if !@HAVE_CLOSEDIR@ +_GL_FUNCDECL_SYS (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (closedir, int, (DIR *dirp)); +# endif +_GL_CXXALIASWARN (closedir); +#elif defined GNULIB_POSIXCHECK +# undef closedir +# if HAVE_RAW_DECL_CLOSEDIR +_GL_WARN_ON_USE (closedir, "closedir is not portable - " + "use gnulib module closedir for portability"); +# endif +#endif + +#if @GNULIB_DIRFD@ +/* Return the file descriptor associated with the given directory stream, + or -1 if none exists. */ +# if @REPLACE_DIRFD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef dirfd +# define dirfd rpl_dirfd +# endif +_GL_FUNCDECL_RPL (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (dirfd, int, (DIR *)); + +# ifdef __KLIBC__ +/* Gnulib internal hooks needed to maintain the dirfd metadata. */ +_GL_EXTERN_C int _gl_register_dirp_fd (int fd, DIR *dirp) + _GL_ARG_NONNULL ((2)); +_GL_EXTERN_C void _gl_unregister_dirp_fd (int fd); +# endif +# else +# if defined __cplusplus && defined GNULIB_NAMESPACE && defined dirfd + /* dirfd is defined as a macro and not as a function. + Turn it into a function and get rid of the macro. */ +static inline int (dirfd) (DIR *dp) { return dirfd (dp); } +# undef dirfd +# endif +# if !(@HAVE_DECL_DIRFD@ || defined dirfd) +_GL_FUNCDECL_SYS (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (dirfd, int, (DIR *)); +# endif +_GL_CXXALIASWARN (dirfd); +#elif defined GNULIB_POSIXCHECK +# undef dirfd +# if HAVE_RAW_DECL_DIRFD +_GL_WARN_ON_USE (dirfd, "dirfd is unportable - " + "use gnulib module dirfd for portability"); +# endif +#endif + +#if @GNULIB_FDOPENDIR@ +/* Open a directory stream visiting the given directory file + descriptor. Return NULL and set errno if fd is not visiting a + directory. On success, this function consumes fd (it will be + implicitly closed either by this function or by a subsequent + closedir). */ +# if @REPLACE_FDOPENDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fdopendir +# define fdopendir rpl_fdopendir +# endif +_GL_FUNCDECL_RPL (fdopendir, DIR *, (int fd)); +_GL_CXXALIAS_RPL (fdopendir, DIR *, (int fd)); +# else +# if !@HAVE_FDOPENDIR@ || !@HAVE_DECL_FDOPENDIR@ +_GL_FUNCDECL_SYS (fdopendir, DIR *, (int fd)); +# endif +_GL_CXXALIAS_SYS (fdopendir, DIR *, (int fd)); +# endif +_GL_CXXALIASWARN (fdopendir); +#elif defined GNULIB_POSIXCHECK +# undef fdopendir +# if HAVE_RAW_DECL_FDOPENDIR +_GL_WARN_ON_USE (fdopendir, "fdopendir is unportable - " + "use gnulib module fdopendir for portability"); +# endif +#endif + +#if @GNULIB_SCANDIR@ +/* Scan the directory DIR, calling FILTER on each directory entry. + Entries for which FILTER returns nonzero are individually malloc'd, + sorted using qsort with CMP, and collected in a malloc'd array in + *NAMELIST. Returns the number of entries selected, or -1 on error. */ +# if !@HAVE_SCANDIR@ +_GL_FUNCDECL_SYS (scandir, int, + (const char *dir, struct dirent ***namelist, + int (*filter) (const struct dirent *), + int (*cmp) (const struct dirent **, const struct dirent **)) + _GL_ARG_NONNULL ((1, 2, 4))); +# endif +/* Need to cast, because on glibc systems, the fourth parameter is + int (*cmp) (const void *, const void *). */ +_GL_CXXALIAS_SYS_CAST (scandir, int, + (const char *dir, struct dirent ***namelist, + int (*filter) (const struct dirent *), + int (*cmp) (const struct dirent **, const struct dirent **))); +_GL_CXXALIASWARN (scandir); +#elif defined GNULIB_POSIXCHECK +# undef scandir +# if HAVE_RAW_DECL_SCANDIR +_GL_WARN_ON_USE (scandir, "scandir is unportable - " + "use gnulib module scandir for portability"); +# endif +#endif + +#if @GNULIB_ALPHASORT@ +/* Compare two 'struct dirent' entries alphabetically. */ +# if !@HAVE_ALPHASORT@ +_GL_FUNCDECL_SYS (alphasort, int, + (const struct dirent **, const struct dirent **) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif +/* Need to cast, because on glibc systems, the parameters are + (const void *, const void *). */ +_GL_CXXALIAS_SYS_CAST (alphasort, int, + (const struct dirent **, const struct dirent **)); +_GL_CXXALIASWARN (alphasort); +#elif defined GNULIB_POSIXCHECK +# undef alphasort +# if HAVE_RAW_DECL_ALPHASORT +_GL_WARN_ON_USE (alphasort, "alphasort is unportable - " + "use gnulib module alphasort for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_DIRENT_H */ +#endif /* _@GUARD_PREFIX@_DIRENT_H */ diff --git a/grub-core/lib/gnulib/dirfd.c b/grub-core/lib/gnulib/dirfd.c new file mode 100644 index 0000000..bc858fd --- /dev/null +++ b/grub-core/lib/gnulib/dirfd.c @@ -0,0 +1,98 @@ +/* dirfd.c -- return the file descriptor associated with an open DIR* + + Copyright (C) 2001, 2006, 2008-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Jim Meyering. */ + +#include <config.h> + +#include <dirent.h> +#include <errno.h> + +#ifdef __KLIBC__ +# include <stdlib.h> +# include <io.h> + +static struct dirp_fd_list +{ + DIR *dirp; + int fd; + struct dirp_fd_list *next; +} *dirp_fd_start = NULL; + +/* Register fd associated with dirp to dirp_fd_list. */ +int +_gl_register_dirp_fd (int fd, DIR *dirp) +{ + struct dirp_fd_list *new_dirp_fd = malloc (sizeof *new_dirp_fd); + if (!new_dirp_fd) + return -1; + + new_dirp_fd->dirp = dirp; + new_dirp_fd->fd = fd; + new_dirp_fd->next = dirp_fd_start; + + dirp_fd_start = new_dirp_fd; + + return 0; +} + +/* Unregister fd from dirp_fd_list with closing it */ +void +_gl_unregister_dirp_fd (int fd) +{ + struct dirp_fd_list *dirp_fd; + struct dirp_fd_list *dirp_fd_prev; + + for (dirp_fd_prev = NULL, dirp_fd = dirp_fd_start; dirp_fd; + dirp_fd_prev = dirp_fd, dirp_fd = dirp_fd->next) + { + if (dirp_fd->fd == fd) + { + if (dirp_fd_prev) + dirp_fd_prev->next = dirp_fd->next; + else /* dirp_fd == dirp_fd_start */ + dirp_fd_start = dirp_fd_start->next; + + close (fd); + free (dirp_fd); + break; + } + } +} +#endif + +int +dirfd (DIR *dir_p) +{ + int fd = DIR_TO_FD (dir_p); + if (fd == -1) +#ifndef __KLIBC__ + errno = ENOTSUP; +#else + { + struct dirp_fd_list *dirp_fd; + + for (dirp_fd = dirp_fd_start; dirp_fd; dirp_fd = dirp_fd->next) + if (dirp_fd->dirp == dir_p) + return dirp_fd->fd; + + errno = EINVAL; + } +#endif + + return fd; +} diff --git a/grub-core/lib/gnulib/dirname-lgpl.c b/grub-core/lib/gnulib/dirname-lgpl.c new file mode 100644 index 0000000..7cf89d8 --- /dev/null +++ b/grub-core/lib/gnulib/dirname-lgpl.c @@ -0,0 +1,86 @@ +/* dirname.c -- return all but the last element in a file name + + Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2019 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "dirname.h" + +#include <stdlib.h> +#include <string.h> + +/* Return the length of the prefix of FILE that will be used by + dir_name. If FILE is in the working directory, this returns zero + even though 'dir_name (FILE)' will return ".". Works properly even + if there are trailing slashes (by effectively ignoring them). */ + +size_t +dir_len (char const *file) +{ + size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file); + size_t length; + + /* Advance prefix_length beyond important leading slashes. */ + prefix_length += (prefix_length != 0 + ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE + && ISSLASH (file[prefix_length])) + : (ISSLASH (file[0]) + ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT + && ISSLASH (file[1]) && ! ISSLASH (file[2]) + ? 2 : 1)) + : 0)); + + /* Strip the basename and any redundant slashes before it. */ + for (length = last_component (file) - file; + prefix_length < length; length--) + if (! ISSLASH (file[length - 1])) + break; + return length; +} + + +/* In general, we can't use the builtin 'dirname' function if available, + since it has different meanings in different environments. + In some environments the builtin 'dirname' modifies its argument. + + Return the leading directories part of FILE, allocated with malloc. + Works properly even if there are trailing slashes (by effectively + ignoring them). Return NULL on failure. + + If lstat (FILE) would succeed, then { chdir (dir_name (FILE)); + lstat (base_name (FILE)); } will access the same file. Likewise, + if the sequence { chdir (dir_name (FILE)); + rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE + to "foo" in the same directory FILE was in. */ + +char * +mdir_name (char const *file) +{ + size_t length = dir_len (file); + bool append_dot = (length == 0 + || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE + && length == FILE_SYSTEM_PREFIX_LEN (file) + && file[2] != '\0' && ! ISSLASH (file[2]))); + char *dir = malloc (length + append_dot + 1); + if (!dir) + return NULL; + memcpy (dir, file, length); + if (append_dot) + dir[length++] = '.'; + dir[length] = '\0'; + return dir; +} diff --git a/grub-core/lib/gnulib/dirname.h b/grub-core/lib/gnulib/dirname.h new file mode 100644 index 0000000..5791659 --- /dev/null +++ b/grub-core/lib/gnulib/dirname.h @@ -0,0 +1,54 @@ +/* Take file names apart into directory and base names. + + Copyright (C) 1998, 2001, 2003-2006, 2009-2019 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef DIRNAME_H_ +# define DIRNAME_H_ 1 + +# include <stdbool.h> +# include <stddef.h> +# include "dosname.h" + +# ifndef DIRECTORY_SEPARATOR +# define DIRECTORY_SEPARATOR '/' +# endif + +# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT +# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# if GNULIB_DIRNAME +char *base_name (char const *file) _GL_ATTRIBUTE_MALLOC; +char *dir_name (char const *file); +# endif + +char *mdir_name (char const *file); +size_t base_len (char const *file) _GL_ATTRIBUTE_PURE; +size_t dir_len (char const *file) _GL_ATTRIBUTE_PURE; +char *last_component (char const *file) _GL_ATTRIBUTE_PURE; + +bool strip_trailing_slashes (char *file); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* not DIRNAME_H_ */ diff --git a/grub-core/lib/gnulib/dosname.h b/grub-core/lib/gnulib/dosname.h new file mode 100644 index 0000000..c0ab684 --- /dev/null +++ b/grub-core/lib/gnulib/dosname.h @@ -0,0 +1,52 @@ +/* File names on MS-DOS/Windows systems. + + Copyright (C) 2000-2001, 2004-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + + From Paul Eggert and Jim Meyering. */ + +#ifndef _DOSNAME_H +#define _DOSNAME_H + +#if (defined _WIN32 || defined __CYGWIN__ \ + || defined __EMX__ || defined __MSDOS__ || defined __DJGPP__) + /* This internal macro assumes ASCII, but all hosts that support drive + letters use ASCII. */ +# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \ + <= 'z' - 'a') +# define FILE_SYSTEM_PREFIX_LEN(Filename) \ + (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0) +# ifndef __CYGWIN__ +# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1 +# endif +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +#else +# define FILE_SYSTEM_PREFIX_LEN(Filename) 0 +# define ISSLASH(C) ((C) == '/') +#endif + +#ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE +# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0 +#endif + +#if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE +# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)]) +# else +# define IS_ABSOLUTE_FILE_NAME(F) \ + (ISSLASH ((F)[0]) || FILE_SYSTEM_PREFIX_LEN (F) != 0) +#endif +#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F)) + +#endif /* DOSNAME_H_ */ diff --git a/grub-core/lib/gnulib/dup-safer-flag.c b/grub-core/lib/gnulib/dup-safer-flag.c new file mode 100644 index 0000000..485f741 --- /dev/null +++ b/grub-core/lib/gnulib/dup-safer-flag.c @@ -0,0 +1,38 @@ +/* Duplicate a file descriptor result, avoiding clobbering + STD{IN,OUT,ERR}_FILENO, with specific flags. + + Copyright (C) 2001, 2004-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert and Eric Blake. */ + +#include <config.h> + +/* Specification. */ +#include "unistd-safer.h" + +#include <fcntl.h> +#include <unistd.h> + +/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or + STDERR_FILENO. If FLAG contains O_CLOEXEC, behave like + fcntl(F_DUPFD_CLOEXEC) rather than fcntl(F_DUPFD). */ + +int +dup_safer_flag (int fd, int flag) +{ + return fcntl (fd, (flag & O_CLOEXEC) ? F_DUPFD_CLOEXEC : F_DUPFD, + STDERR_FILENO + 1); +} diff --git a/grub-core/lib/gnulib/dup-safer.c b/grub-core/lib/gnulib/dup-safer.c new file mode 100644 index 0000000..c0c5f2a --- /dev/null +++ b/grub-core/lib/gnulib/dup-safer.c @@ -0,0 +1,34 @@ +/* Invoke dup, but avoid some glitches. + + Copyright (C) 2001, 2004-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +#include <config.h> + +#include "unistd-safer.h" + +#include <fcntl.h> +#include <unistd.h> + +/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or + STDERR_FILENO. */ + +int +dup_safer (int fd) +{ + return fcntl (fd, F_DUPFD, STDERR_FILENO + 1); +} diff --git a/grub-core/lib/gnulib/dup2.c b/grub-core/lib/gnulib/dup2.c new file mode 100644 index 0000000..d3aafa4 --- /dev/null +++ b/grub-core/lib/gnulib/dup2.c @@ -0,0 +1,235 @@ +/* Duplicate an open file descriptor to a specified file descriptor. + + Copyright (C) 1999, 2004-2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* written by Paul Eggert */ + +#include <config.h> + +/* Specification. */ +#include <unistd.h> + +#include <errno.h> +#include <fcntl.h> + +#if HAVE_DUP2 + +# undef dup2 + +# if defined _WIN32 && ! defined __CYGWIN__ + +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +# endif + +/* Get _get_osfhandle. */ +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include <io.h> +# endif + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static int +dup2_nothrow (int fd, int desired_fd) +{ + int result; + + TRY_MSVC_INVAL + { + result = dup2 (fd, desired_fd); + } + CATCH_MSVC_INVAL + { + errno = EBADF; + result = -1; + } + DONE_MSVC_INVAL; + + return result; +} +# else +# define dup2_nothrow dup2 +# endif + +static int +ms_windows_dup2 (int fd, int desired_fd) +{ + int result; + + /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open, + dup2 (fd, fd) returns 0, but all further attempts to use fd in + future dup2 calls will hang. */ + if (fd == desired_fd) + { + if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return -1; + } + return fd; + } + + /* Wine 1.0.1 return 0 when desired_fd is negative but not -1: + https://bugs.winehq.org/show_bug.cgi?id=21289 */ + if (desired_fd < 0) + { + errno = EBADF; + return -1; + } + + result = dup2_nothrow (fd, desired_fd); + + if (result == 0) + result = desired_fd; + + return result; +} + +# define dup2 ms_windows_dup2 + +# elif defined __KLIBC__ + +# include <InnoTekLIBC/backend.h> + +static int +klibc_dup2dirfd (int fd, int desired_fd) +{ + int tempfd; + int dupfd; + + tempfd = open ("NUL", O_RDONLY); + if (tempfd == -1) + return -1; + + if (tempfd == desired_fd) + { + close (tempfd); + + char path[_MAX_PATH]; + if (__libc_Back_ioFHToPath (fd, path, sizeof (path))) + return -1; + + return open(path, O_RDONLY); + } + + dupfd = klibc_dup2dirfd (fd, desired_fd); + + close (tempfd); + + return dupfd; +} + +static int +klibc_dup2 (int fd, int desired_fd) +{ + int dupfd; + struct stat sbuf; + + dupfd = dup2 (fd, desired_fd); + if (dupfd == -1 && errno == ENOTSUP \ + && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) + { + close (desired_fd); + + return klibc_dup2dirfd (fd, desired_fd); + } + + return dupfd; +} + +# define dup2 klibc_dup2 +# endif + +int +rpl_dup2 (int fd, int desired_fd) +{ + int result; + +# ifdef F_GETFL + /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF. + On Cygwin 1.5.x, dup2 (1, 1) returns 0. + On Cygwin 1.7.17, dup2 (1, -1) dumps core. + On Cygwin 1.7.25, dup2 (1, 256) can dump core. + On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ +# if HAVE_SETDTABLESIZE + setdtablesize (desired_fd + 1); +# endif + if (desired_fd < 0) + fd = desired_fd; + if (fd == desired_fd) + return fcntl (fd, F_GETFL) == -1 ? -1 : fd; +# endif + + result = dup2 (fd, desired_fd); + + /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ + if (result == -1 && errno == EMFILE) + errno = EBADF; +# if REPLACE_FCHDIR + if (fd != desired_fd && result != -1) + result = _gl_register_dup (fd, result); +# endif + return result; +} + +#else /* !HAVE_DUP2 */ + +/* On older platforms, dup2 did not exist. */ + +# ifndef F_DUPFD +static int +dupfd (int fd, int desired_fd) +{ + int duplicated_fd = dup (fd); + if (duplicated_fd < 0 || duplicated_fd == desired_fd) + return duplicated_fd; + else + { + int r = dupfd (fd, desired_fd); + int e = errno; + close (duplicated_fd); + errno = e; + return r; + } +} +# endif + +int +dup2 (int fd, int desired_fd) +{ + int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd; + if (result == -1 || fd == desired_fd) + return result; + close (desired_fd); +# ifdef F_DUPFD + result = fcntl (fd, F_DUPFD, desired_fd); +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif +# else + result = dupfd (fd, desired_fd); +# endif + if (result == -1 && (errno == EMFILE || errno == EINVAL)) + errno = EBADF; + return result; +} +#endif /* !HAVE_DUP2 */ diff --git a/grub-core/lib/gnulib/errno.in.h b/grub-core/lib/gnulib/errno.in.h new file mode 100644 index 0000000..3bd27f1 --- /dev/null +++ b/grub-core/lib/gnulib/errno.in.h @@ -0,0 +1,279 @@ +/* A POSIX-like <errno.h>. + + Copyright (C) 2008-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _@GUARD_PREFIX@_ERRNO_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_ERRNO_H@ + +#ifndef _@GUARD_PREFIX@_ERRNO_H +#define _@GUARD_PREFIX@_ERRNO_H + + +/* On native Windows platforms, many macros are not defined. */ +# if defined _WIN32 && ! defined __CYGWIN__ + +/* These are the same values as defined by MSVC 10, for interoperability. */ + +# ifndef ENOMSG +# define ENOMSG 122 +# define GNULIB_defined_ENOMSG 1 +# endif + +# ifndef EIDRM +# define EIDRM 111 +# define GNULIB_defined_EIDRM 1 +# endif + +# ifndef ENOLINK +# define ENOLINK 121 +# define GNULIB_defined_ENOLINK 1 +# endif + +# ifndef EPROTO +# define EPROTO 134 +# define GNULIB_defined_EPROTO 1 +# endif + +# ifndef EBADMSG +# define EBADMSG 104 +# define GNULIB_defined_EBADMSG 1 +# endif + +# ifndef EOVERFLOW +# define EOVERFLOW 132 +# define GNULIB_defined_EOVERFLOW 1 +# endif + +# ifndef ENOTSUP +# define ENOTSUP 129 +# define GNULIB_defined_ENOTSUP 1 +# endif + +# ifndef ENETRESET +# define ENETRESET 117 +# define GNULIB_defined_ENETRESET 1 +# endif + +# ifndef ECONNABORTED +# define ECONNABORTED 106 +# define GNULIB_defined_ECONNABORTED 1 +# endif + +# ifndef ECANCELED +# define ECANCELED 105 +# define GNULIB_defined_ECANCELED 1 +# endif + +# ifndef EOWNERDEAD +# define EOWNERDEAD 133 +# define GNULIB_defined_EOWNERDEAD 1 +# endif + +# ifndef ENOTRECOVERABLE +# define ENOTRECOVERABLE 127 +# define GNULIB_defined_ENOTRECOVERABLE 1 +# endif + +# ifndef EINPROGRESS +# define EINPROGRESS 112 +# define EALREADY 103 +# define ENOTSOCK 128 +# define EDESTADDRREQ 109 +# define EMSGSIZE 115 +# define EPROTOTYPE 136 +# define ENOPROTOOPT 123 +# define EPROTONOSUPPORT 135 +# define EOPNOTSUPP 130 +# define EAFNOSUPPORT 102 +# define EADDRINUSE 100 +# define EADDRNOTAVAIL 101 +# define ENETDOWN 116 +# define ENETUNREACH 118 +# define ECONNRESET 108 +# define ENOBUFS 119 +# define EISCONN 113 +# define ENOTCONN 126 +# define ETIMEDOUT 138 +# define ECONNREFUSED 107 +# define ELOOP 114 +# define EHOSTUNREACH 110 +# define EWOULDBLOCK 140 +# define GNULIB_defined_ESOCK 1 +# endif + +# ifndef ETXTBSY +# define ETXTBSY 139 +# define ENODATA 120 /* not required by POSIX */ +# define ENOSR 124 /* not required by POSIX */ +# define ENOSTR 125 /* not required by POSIX */ +# define ETIME 137 /* not required by POSIX */ +# define EOTHER 131 /* not required by POSIX */ +# define GNULIB_defined_ESTREAMS 1 +# endif + +/* These are intentionally the same values as the WSA* error numbers, defined + in <winsock2.h>. */ +# define ESOCKTNOSUPPORT 10044 /* not required by POSIX */ +# define EPFNOSUPPORT 10046 /* not required by POSIX */ +# define ESHUTDOWN 10058 /* not required by POSIX */ +# define ETOOMANYREFS 10059 /* not required by POSIX */ +# define EHOSTDOWN 10064 /* not required by POSIX */ +# define EPROCLIM 10067 /* not required by POSIX */ +# define EUSERS 10068 /* not required by POSIX */ +# define EDQUOT 10069 +# define ESTALE 10070 +# define EREMOTE 10071 /* not required by POSIX */ +# define GNULIB_defined_EWINSOCK 1 + +# endif + + +/* On OSF/1 5.1, when _XOPEN_SOURCE_EXTENDED is not defined, the macros + EMULTIHOP, ENOLINK, EOVERFLOW are not defined. */ +# if @EMULTIHOP_HIDDEN@ +# define EMULTIHOP @EMULTIHOP_VALUE@ +# define GNULIB_defined_EMULTIHOP 1 +# endif +# if @ENOLINK_HIDDEN@ +# define ENOLINK @ENOLINK_VALUE@ +# define GNULIB_defined_ENOLINK 1 +# endif +# if @EOVERFLOW_HIDDEN@ +# define EOVERFLOW @EOVERFLOW_VALUE@ +# define GNULIB_defined_EOVERFLOW 1 +# endif + + +/* On OpenBSD 4.0 and on native Windows, the macros ENOMSG, EIDRM, ENOLINK, + EPROTO, EMULTIHOP, EBADMSG, EOVERFLOW, ENOTSUP, ECANCELED are not defined. + Likewise, on NonStop Kernel, EDQUOT is not defined. + Define them here. Values >= 2000 seem safe to use: Solaris ESTALE = 151, + HP-UX EWOULDBLOCK = 246, IRIX EDQUOT = 1133. + + Note: When one of these systems defines some of these macros some day, + binaries will have to be recompiled so that they recognizes the new + errno values from the system. */ + +# ifndef ENOMSG +# define ENOMSG 2000 +# define GNULIB_defined_ENOMSG 1 +# endif + +# ifndef EIDRM +# define EIDRM 2001 +# define GNULIB_defined_EIDRM 1 +# endif + +# ifndef ENOLINK +# define ENOLINK 2002 +# define GNULIB_defined_ENOLINK 1 +# endif + +# ifndef EPROTO +# define EPROTO 2003 +# define GNULIB_defined_EPROTO 1 +# endif + +# ifndef EMULTIHOP +# define EMULTIHOP 2004 +# define GNULIB_defined_EMULTIHOP 1 +# endif + +# ifndef EBADMSG +# define EBADMSG 2005 +# define GNULIB_defined_EBADMSG 1 +# endif + +# ifndef EOVERFLOW +# define EOVERFLOW 2006 +# define GNULIB_defined_EOVERFLOW 1 +# endif + +# ifndef ENOTSUP +# define ENOTSUP 2007 +# define GNULIB_defined_ENOTSUP 1 +# endif + +# ifndef ENETRESET +# define ENETRESET 2011 +# define GNULIB_defined_ENETRESET 1 +# endif + +# ifndef ECONNABORTED +# define ECONNABORTED 2012 +# define GNULIB_defined_ECONNABORTED 1 +# endif + +# ifndef ESTALE +# define ESTALE 2009 +# define GNULIB_defined_ESTALE 1 +# endif + +# ifndef EDQUOT +# define EDQUOT 2010 +# define GNULIB_defined_EDQUOT 1 +# endif + +# ifndef ECANCELED +# define ECANCELED 2008 +# define GNULIB_defined_ECANCELED 1 +# endif + +/* On many platforms, the macros EOWNERDEAD and ENOTRECOVERABLE are not + defined. */ + +# ifndef EOWNERDEAD +# if defined __sun + /* Use the same values as defined for Solaris >= 8, for + interoperability. */ +# define EOWNERDEAD 58 +# define ENOTRECOVERABLE 59 +# elif defined _WIN32 && ! defined __CYGWIN__ + /* We have a conflict here: pthreads-win32 defines these values + differently than MSVC 10. It's hairy to decide which one to use. */ +# if defined __MINGW32__ && !defined USE_WINDOWS_THREADS + /* Use the same values as defined by pthreads-win32, for + interoperability. */ +# define EOWNERDEAD 43 +# define ENOTRECOVERABLE 44 +# else + /* Use the same values as defined by MSVC 10, for + interoperability. */ +# define EOWNERDEAD 133 +# define ENOTRECOVERABLE 127 +# endif +# else +# define EOWNERDEAD 2013 +# define ENOTRECOVERABLE 2014 +# endif +# define GNULIB_defined_EOWNERDEAD 1 +# define GNULIB_defined_ENOTRECOVERABLE 1 +# endif + +# ifndef EILSEQ +# define EILSEQ 2015 +# define GNULIB_defined_EILSEQ 1 +# endif + +#endif /* _@GUARD_PREFIX@_ERRNO_H */ +#endif /* _@GUARD_PREFIX@_ERRNO_H */ diff --git a/grub-core/lib/gnulib/error.c b/grub-core/lib/gnulib/error.c new file mode 100644 index 0000000..7e532f0 --- /dev/null +++ b/grub-core/lib/gnulib/error.c @@ -0,0 +1,411 @@ +/* Error handler for noninteractive utilities + Copyright (C) 1990-1998, 2000-2007, 2009-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ + +#if !_LIBC +# include <config.h> +#endif + +#include "error.h" + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if !_LIBC && ENABLE_NLS +# include "gettext.h" +# define _(msgid) gettext (msgid) +#endif + +#ifdef _LIBC +# include <libintl.h> +# include <stdbool.h> +# include <stdint.h> +# include <wchar.h> +# define mbsrtowcs __mbsrtowcs +# define USE_UNLOCKED_IO 0 +# define _GL_ATTRIBUTE_FORMAT_PRINTF(a, b) +# define _GL_ARG_NONNULL(a) +#else +# include "getprogname.h" +#endif + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +#ifndef _ +# define _(String) String +#endif + +/* If NULL, error will flush stdout, then print on stderr the program + name, a colon and a space. Otherwise, error will call this + function without parameters instead. */ +void (*error_print_progname) (void); + +/* This variable is incremented each time 'error' is called. */ +unsigned int error_message_count; + +#ifdef _LIBC +/* In the GNU C library, there is a predefined variable for this. */ + +# define program_name program_invocation_name +# include <errno.h> +# include <limits.h> +# include <libio/libioP.h> + +/* In GNU libc we want do not want to use the common name 'error' directly. + Instead make it a weak alias. */ +extern void __error (int status, int errnum, const char *message, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +extern void __error_at_line (int status, int errnum, const char *file_name, + unsigned int line_number, const char *message, + ...) + __attribute__ ((__format__ (__printf__, 5, 6))); +# define error __error +# define error_at_line __error_at_line + +# include <libio/iolibio.h> +# define fflush(s) _IO_fflush (s) +# undef putc +# define putc(c, fp) _IO_putc (c, fp) + +# include <bits/libc-lock.h> + +#else /* not _LIBC */ + +# include <fcntl.h> +# include <unistd.h> + +# if defined _WIN32 && ! defined __CYGWIN__ +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +/* Get _get_osfhandle. */ +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include <io.h> +# endif +# endif + +/* The gnulib override of fcntl is not needed in this file. */ +# undef fcntl + +# if !(GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R) +# ifndef HAVE_DECL_STRERROR_R +"this configure-time declaration test was not run" +# endif +# if STRERROR_R_CHAR_P +char *strerror_r (int errnum, char *buf, size_t buflen); +# else +int strerror_r (int errnum, char *buf, size_t buflen); +# endif +# endif + +#define program_name getprogname () + +# if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r +# define __strerror_r strerror_r +# endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */ +#endif /* not _LIBC */ + +#if !_LIBC +/* Return non-zero if FD is open. */ +static int +is_open (int fd) +{ +# if defined _WIN32 && ! defined __CYGWIN__ + /* On native Windows: The initial state of unassigned standard file + descriptors is that they are open but point to an INVALID_HANDLE_VALUE. + There is no fcntl, and the gnulib replacement fcntl does not support + F_GETFL. */ + return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE; +# else +# ifndef F_GETFL +# error Please port fcntl to your platform +# endif + return 0 <= fcntl (fd, F_GETFL); +# endif +} +#endif + +static void +flush_stdout (void) +{ +#if !_LIBC + int stdout_fd; + +# if GNULIB_FREOPEN_SAFER + /* Use of gnulib's freopen-safer module normally ensures that + fileno (stdout) == 1 + whenever stdout is open. */ + stdout_fd = STDOUT_FILENO; +# else + /* POSIX states that fileno (stdout) after fclose is unspecified. But in + practice it is not a problem, because stdout is statically allocated and + the fd of a FILE stream is stored as a field in its allocated memory. */ + stdout_fd = fileno (stdout); +# endif + /* POSIX states that fflush (stdout) after fclose is unspecified; it + is safe in glibc, but not on all other platforms. fflush (NULL) + is always defined, but too draconian. */ + if (0 <= stdout_fd && is_open (stdout_fd)) +#endif + fflush (stdout); +} + +static void +print_errno_message (int errnum) +{ + char const *s; + +#if _LIBC || GNULIB_STRERROR_R_POSIX || defined HAVE_STRERROR_R + char errbuf[1024]; +# if _LIBC || (!GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P) + s = __strerror_r (errnum, errbuf, sizeof errbuf); +# else + if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) + s = errbuf; + else + s = 0; +# endif +#else + s = strerror (errnum); +#endif + +#if !_LIBC + if (! s) + s = _("Unknown system error"); +#endif + +#if _LIBC + __fxprintf (NULL, ": %s", s); +#else + fprintf (stderr, ": %s", s); +#endif +} + +static void _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) _GL_ARG_NONNULL ((3)) +error_tail (int status, int errnum, const char *message, va_list args) +{ +#if _LIBC + if (_IO_fwide (stderr, 0) > 0) + { + size_t len = strlen (message) + 1; + wchar_t *wmessage = NULL; + mbstate_t st; + size_t res; + const char *tmp; + bool use_malloc = false; + + while (1) + { + if (__libc_use_alloca (len * sizeof (wchar_t))) + wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); + else + { + if (!use_malloc) + wmessage = NULL; + + wchar_t *p = (wchar_t *) realloc (wmessage, + len * sizeof (wchar_t)); + if (p == NULL) + { + free (wmessage); + fputws_unlocked (L"out of memory\n", stderr); + return; + } + wmessage = p; + use_malloc = true; + } + + memset (&st, '\0', sizeof (st)); + tmp = message; + + res = mbsrtowcs (wmessage, &tmp, len, &st); + if (res != len) + break; + + if (__builtin_expect (len >= SIZE_MAX / sizeof (wchar_t) / 2, 0)) + { + /* This really should not happen if everything is fine. */ + res = (size_t) -1; + break; + } + + len *= 2; + } + + if (res == (size_t) -1) + { + /* The string cannot be converted. */ + if (use_malloc) + { + free (wmessage); + use_malloc = false; + } + wmessage = (wchar_t *) L"???"; + } + + __vfwprintf (stderr, wmessage, args); + + if (use_malloc) + free (wmessage); + } + else +#endif + vfprintf (stderr, message, args); + + ++error_message_count; + if (errnum) + print_errno_message (errnum); +#if _LIBC + __fxprintf (NULL, "\n"); +#else + putc ('\n', stderr); +#endif + fflush (stderr); + if (status) + exit (status); +} + + +/* Print the program name and error message MESSAGE, which is a printf-style + format string with optional args. + If ERRNUM is nonzero, print its corresponding system error message. + Exit with status STATUS if it is nonzero. */ +void +error (int status, int errnum, const char *message, ...) +{ + va_list args; + +#if defined _LIBC && defined __libc_ptf_call + /* We do not want this call to be cut short by a thread + cancellation. Therefore disable cancellation for now. */ + int state = PTHREAD_CANCEL_ENABLE; + __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), + 0); +#endif + + flush_stdout (); +#ifdef _LIBC + _IO_flockfile (stderr); +#endif + if (error_print_progname) + (*error_print_progname) (); + else + { +#if _LIBC + __fxprintf (NULL, "%s: ", program_name); +#else + fprintf (stderr, "%s: ", program_name); +#endif + } + + va_start (args, message); + error_tail (status, errnum, message, args); + va_end (args); + +#ifdef _LIBC + _IO_funlockfile (stderr); +# ifdef __libc_ptf_call + __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); +# endif +#endif +} + +/* Sometimes we want to have at most one error per line. This + variable controls whether this mode is selected or not. */ +int error_one_per_line; + +void +error_at_line (int status, int errnum, const char *file_name, + unsigned int line_number, const char *message, ...) +{ + va_list args; + + if (error_one_per_line) + { + static const char *old_file_name; + static unsigned int old_line_number; + + if (old_line_number == line_number + && (file_name == old_file_name + || (old_file_name != NULL + && file_name != NULL + && strcmp (old_file_name, file_name) == 0))) + + /* Simply return and print nothing. */ + return; + + old_file_name = file_name; + old_line_number = line_number; + } + +#if defined _LIBC && defined __libc_ptf_call + /* We do not want this call to be cut short by a thread + cancellation. Therefore disable cancellation for now. */ + int state = PTHREAD_CANCEL_ENABLE; + __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), + 0); +#endif + + flush_stdout (); +#ifdef _LIBC + _IO_flockfile (stderr); +#endif + if (error_print_progname) + (*error_print_progname) (); + else + { +#if _LIBC + __fxprintf (NULL, "%s:", program_name); +#else + fprintf (stderr, "%s:", program_name); +#endif + } + +#if _LIBC + __fxprintf (NULL, file_name != NULL ? "%s:%u: " : " ", + file_name, line_number); +#else + fprintf (stderr, file_name != NULL ? "%s:%u: " : " ", + file_name, line_number); +#endif + + va_start (args, message); + error_tail (status, errnum, message, args); + va_end (args); + +#ifdef _LIBC + _IO_funlockfile (stderr); +# ifdef __libc_ptf_call + __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); +# endif +#endif +} + +#ifdef _LIBC +/* Make the weak alias. */ +# undef error +# undef error_at_line +weak_alias (__error, error) +weak_alias (__error_at_line, error_at_line) +#endif diff --git a/grub-core/lib/gnulib/error.h b/grub-core/lib/gnulib/error.h new file mode 100644 index 0000000..3759f8a --- /dev/null +++ b/grub-core/lib/gnulib/error.h @@ -0,0 +1,75 @@ +/* Declaration for error-reporting function + Copyright (C) 1995-1997, 2003, 2006, 2008-2019 Free Software Foundation, + Inc. + This file is part of the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _ERROR_H +#define _ERROR_H 1 + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The __-protected variants of the attributes 'format' and 'printf' are + accepted by gcc versions 2.6.4 (effectively 2.7) and later. + We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because + gnulib and libintl do '#define printf __printf__' when they override + the 'printf' function. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +#endif + +/* On mingw, the flavor of printf depends on whether the extensions module + * is in use; the check for <stdio.h> determines the witness macro. */ +#ifndef _GL_ATTRIBUTE_SPEC_PRINTF +# if GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU +# define _GL_ATTRIBUTE_SPEC_PRINTF __gnu_printf__ +# else +# define _GL_ATTRIBUTE_SPEC_PRINTF __printf__ +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Print a message with 'fprintf (stderr, FORMAT, ...)'; + if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). + If STATUS is nonzero, terminate the program with 'exit (STATUS)'. */ + +extern void error (int __status, int __errnum, const char *__format, ...) + _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF, 3, 4)); + +extern void error_at_line (int __status, int __errnum, const char *__fname, + unsigned int __lineno, const char *__format, ...) + _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF, 5, 6)); + +/* If NULL, error will flush stdout, then print on stderr the program + name, a colon and a space. Otherwise, error will call this + function without parameters instead. */ +extern void (*error_print_progname) (void); + +/* This variable is incremented each time 'error' is called. */ +extern unsigned int error_message_count; + +/* Sometimes we want to have at most one error per line. This + variable controls whether this mode is selected or not. */ +extern int error_one_per_line; + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ diff --git a/grub-core/lib/gnulib/exitfail.c b/grub-core/lib/gnulib/exitfail.c new file mode 100644 index 0000000..69b3513 --- /dev/null +++ b/grub-core/lib/gnulib/exitfail.c @@ -0,0 +1,24 @@ +/* Failure exit status + + Copyright (C) 2002-2003, 2005-2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "exitfail.h" + +#include <stdlib.h> + +int volatile exit_failure = EXIT_FAILURE; diff --git a/grub-core/lib/gnulib/exitfail.h b/grub-core/lib/gnulib/exitfail.h new file mode 100644 index 0000000..480ad1a --- /dev/null +++ b/grub-core/lib/gnulib/exitfail.h @@ -0,0 +1,18 @@ +/* Failure exit status + + Copyright (C) 2002, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +extern int volatile exit_failure; diff --git a/grub-core/lib/gnulib/fchdir.c b/grub-core/lib/gnulib/fchdir.c new file mode 100644 index 0000000..38ab802 --- /dev/null +++ b/grub-core/lib/gnulib/fchdir.c @@ -0,0 +1,208 @@ +/* fchdir replacement. + Copyright (C) 2006-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <unistd.h> + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "assure.h" +#include "dosname.h" +#include "filenamecat.h" + +#ifndef REPLACE_OPEN_DIRECTORY +# define REPLACE_OPEN_DIRECTORY 0 +#endif + +/* This replacement assumes that a directory is not renamed while opened + through a file descriptor. + + FIXME: On mingw, this would be possible to enforce if we were to + also open a HANDLE to each directory currently visited by a file + descriptor, since mingw refuses to rename any in-use file system + object. */ + +/* Array of file descriptors opened. If REPLACE_OPEN_DIRECTORY or if it points + to a directory, it stores info about this directory. */ +typedef struct +{ + char *name; /* Absolute name of the directory, or NULL. */ + /* FIXME - add a DIR* member to make dirfd possible on mingw? */ +} dir_info_t; +static dir_info_t *dirs; +static size_t dirs_allocated; + +/* Try to ensure dirs has enough room for a slot at index fd; free any + contents already in that slot. Return false and set errno to + ENOMEM on allocation failure. */ +static bool +ensure_dirs_slot (size_t fd) +{ + if (fd < dirs_allocated) + free (dirs[fd].name); + else + { + size_t new_allocated; + dir_info_t *new_dirs; + + new_allocated = 2 * dirs_allocated + 1; + if (new_allocated <= fd) + new_allocated = fd + 1; + new_dirs = + (dirs != NULL + ? (dir_info_t *) realloc (dirs, new_allocated * sizeof *dirs) + : (dir_info_t *) malloc (new_allocated * sizeof *dirs)); + if (new_dirs == NULL) + return false; + memset (new_dirs + dirs_allocated, 0, + (new_allocated - dirs_allocated) * sizeof *dirs); + dirs = new_dirs; + dirs_allocated = new_allocated; + } + return true; +} + +/* Return an absolute name of DIR in malloc'd storage. */ +static char * +get_name (char const *dir) +{ + char *cwd; + char *result; + int saved_errno; + + if (IS_ABSOLUTE_FILE_NAME (dir)) + return strdup (dir); + + /* We often encounter "."; treat it as a special case. */ + cwd = getcwd (NULL, 0); + if (!cwd || (dir[0] == '.' && dir[1] == '\0')) + return cwd; + + result = mfile_name_concat (cwd, dir, NULL); + saved_errno = errno; + free (cwd); + errno = saved_errno; + return result; +} + +/* Hook into the gnulib replacements for open() and close() to keep track + of the open file descriptors. */ + +/* Close FD, cleaning up any fd to name mapping if fd was visiting a + directory. */ +void +_gl_unregister_fd (int fd) +{ + if (fd >= 0 && fd < dirs_allocated) + { + free (dirs[fd].name); + dirs[fd].name = NULL; + } +} + +/* Mark FD as visiting FILENAME. FD must be non-negative, and refer + to an open file descriptor. If REPLACE_OPEN_DIRECTORY is non-zero, + this should only be called if FD is visiting a directory. Close FD + and return -1 if there is insufficient memory to track the + directory name; otherwise return FD. */ +int +_gl_register_fd (int fd, const char *filename) +{ + struct stat statbuf; + + assure (0 <= fd); + if (REPLACE_OPEN_DIRECTORY + || (fstat (fd, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))) + { + if (!ensure_dirs_slot (fd) + || (dirs[fd].name = get_name (filename)) == NULL) + { + int saved_errno = errno; + close (fd); + errno = saved_errno; + return -1; + } + } + return fd; +} + +/* Mark NEWFD as a duplicate of OLDFD; useful from dup, dup2, dup3, + and fcntl. Both arguments must be valid and distinct file + descriptors. Close NEWFD and return -1 if OLDFD is tracking a + directory, but there is insufficient memory to track the same + directory in NEWFD; otherwise return NEWFD. */ +int +_gl_register_dup (int oldfd, int newfd) +{ + assure (0 <= oldfd && 0 <= newfd && oldfd != newfd); + if (oldfd < dirs_allocated && dirs[oldfd].name) + { + /* Duplicated a directory; must ensure newfd is allocated. */ + if (!ensure_dirs_slot (newfd) + || (dirs[newfd].name = strdup (dirs[oldfd].name)) == NULL) + { + int saved_errno = errno; + close (newfd); + errno = saved_errno; + newfd = -1; + } + } + else if (newfd < dirs_allocated) + { + /* Duplicated a non-directory; ensure newfd is cleared. */ + free (dirs[newfd].name); + dirs[newfd].name = NULL; + } + return newfd; +} + +/* If FD is currently visiting a directory, then return the name of + that directory. Otherwise, return NULL and set errno. */ +const char * +_gl_directory_name (int fd) +{ + if (0 <= fd && fd < dirs_allocated && dirs[fd].name != NULL) + return dirs[fd].name; + /* At this point, fd is either invalid, or open but not a directory. + If dup2 fails, errno is correctly EBADF. */ + if (0 <= fd) + { + if (dup2 (fd, fd) == fd) + errno = ENOTDIR; + } + else + errno = EBADF; + return NULL; +} + + +/* Implement fchdir() in terms of chdir(). */ + +int +fchdir (int fd) +{ + const char *name = _gl_directory_name (fd); + return name ? chdir (name) : -1; +} diff --git a/grub-core/lib/gnulib/fcntl.c b/grub-core/lib/gnulib/fcntl.c new file mode 100644 index 0000000..f602fad --- /dev/null +++ b/grub-core/lib/gnulib/fcntl.c @@ -0,0 +1,626 @@ +/* Provide file descriptor control. + + Copyright (C) 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Eric Blake <ebb9@byu.net>. */ + +#include <config.h> + +/* Specification. */ +#include <fcntl.h> + +#include <errno.h> +#include <limits.h> +#include <stdarg.h> +#include <unistd.h> + +#ifdef __KLIBC__ +# define INCL_DOS +# include <os2.h> +#endif + +#if defined _WIN32 && ! defined __CYGWIN__ +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> + +/* Get _get_osfhandle. */ +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include <io.h> +# endif + +/* Upper bound on getdtablesize(). See lib/getdtablesize.c. */ +# define OPEN_MAX_MAX 0x10000 + +/* Duplicate OLDFD into the first available slot of at least NEWFD, + which must be positive, with FLAGS determining whether the duplicate + will be inheritable. */ +static int +dupfd (int oldfd, int newfd, int flags) +{ + /* Mingw has no way to create an arbitrary fd. Iterate until all + file descriptors less than newfd are filled up. */ + HANDLE curr_process = GetCurrentProcess (); + HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd); + unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT]; + unsigned int fds_to_close_bound = 0; + int result; + BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE; + int mode; + + if (newfd < 0 || getdtablesize () <= newfd) + { + errno = EINVAL; + return -1; + } + if (old_handle == INVALID_HANDLE_VALUE + || (mode = setmode (oldfd, O_BINARY)) == -1) + { + /* oldfd is not open, or is an unassigned standard file + descriptor. */ + errno = EBADF; + return -1; + } + setmode (oldfd, mode); + flags |= mode; + + for (;;) + { + HANDLE new_handle; + int duplicated_fd; + unsigned int index; + + if (!DuplicateHandle (curr_process, /* SourceProcessHandle */ + old_handle, /* SourceHandle */ + curr_process, /* TargetProcessHandle */ + (PHANDLE) &new_handle, /* TargetHandle */ + (DWORD) 0, /* DesiredAccess */ + inherit, /* InheritHandle */ + DUPLICATE_SAME_ACCESS)) /* Options */ + { + switch (GetLastError ()) + { + case ERROR_TOO_MANY_OPEN_FILES: + errno = EMFILE; + break; + case ERROR_INVALID_HANDLE: + case ERROR_INVALID_TARGET_HANDLE: + case ERROR_DIRECT_ACCESS_HANDLE: + errno = EBADF; + break; + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_INVALID_ACCESS: + errno = EINVAL; + break; + default: + errno = EACCES; + break; + } + result = -1; + break; + } + duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags); + if (duplicated_fd < 0) + { + CloseHandle (new_handle); + result = -1; + break; + } + if (newfd <= duplicated_fd) + { + result = duplicated_fd; + break; + } + + /* Set the bit duplicated_fd in fds_to_close[]. */ + index = (unsigned int) duplicated_fd / CHAR_BIT; + if (fds_to_close_bound <= index) + { + if (sizeof fds_to_close <= index) + /* Need to increase OPEN_MAX_MAX. */ + abort (); + memset (fds_to_close + fds_to_close_bound, '\0', + index + 1 - fds_to_close_bound); + fds_to_close_bound = index + 1; + } + fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT); + } + + /* Close the previous fds that turned out to be too small. */ + { + int saved_errno = errno; + unsigned int duplicated_fd; + + for (duplicated_fd = 0; + duplicated_fd < fds_to_close_bound * CHAR_BIT; + duplicated_fd++) + if ((fds_to_close[duplicated_fd / CHAR_BIT] + >> (duplicated_fd % CHAR_BIT)) + & 1) + close (duplicated_fd); + + errno = saved_errno; + } + +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (oldfd, result); +# endif + return result; +} +#endif /* W32 */ + +/* Forward declarations, because we '#undef fcntl' in the middle of this + compilation unit. */ +/* Our implementation of fcntl (fd, F_DUPFD, target). */ +static int rpl_fcntl_DUPFD (int fd, int target); +/* Our implementation of fcntl (fd, F_DUPFD_CLOEXEC, target). */ +static int rpl_fcntl_DUPFD_CLOEXEC (int fd, int target); +#ifdef __KLIBC__ +/* Adds support for fcntl on directories. */ +static int klibc_fcntl (int fd, int action, /* arg */...); +#endif + + +/* Perform the specified ACTION on the file descriptor FD, possibly + using the argument ARG further described below. This replacement + handles the following actions, and forwards all others on to the + native fcntl. An unrecognized ACTION returns -1 with errno set to + EINVAL. + + F_DUPFD - duplicate FD, with int ARG being the minimum target fd. + If successful, return the duplicate, which will be inheritable; + otherwise return -1 and set errno. + + F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum + target fd. If successful, return the duplicate, which will not be + inheritable; otherwise return -1 and set errno. + + F_GETFD - ARG need not be present. If successful, return a + non-negative value containing the descriptor flags of FD (only + FD_CLOEXEC is portable, but other flags may be present); otherwise + return -1 and set errno. */ + +int +fcntl (int fd, int action, /* arg */...) +#undef fcntl +#ifdef __KLIBC__ +# define fcntl klibc_fcntl +#endif +{ + va_list arg; + int result = -1; + va_start (arg, action); + switch (action) + { + case F_DUPFD: + { + int target = va_arg (arg, int); + result = rpl_fcntl_DUPFD (fd, target); + break; + } + + case F_DUPFD_CLOEXEC: + { + int target = va_arg (arg, int); + result = rpl_fcntl_DUPFD_CLOEXEC (fd, target); + break; + } + +#if !HAVE_FCNTL + case F_GETFD: + { +# if defined _WIN32 && ! defined __CYGWIN__ + HANDLE handle = (HANDLE) _get_osfhandle (fd); + DWORD flags; + if (handle == INVALID_HANDLE_VALUE + || GetHandleInformation (handle, &flags) == 0) + errno = EBADF; + else + result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC; +# else /* !W32 */ + /* Use dup2 to reject invalid file descriptors. No way to + access this information, so punt. */ + if (0 <= dup2 (fd, fd)) + result = 0; +# endif /* !W32 */ + break; + } /* F_GETFD */ +#endif /* !HAVE_FCNTL */ + + /* Implementing F_SETFD on mingw is not trivial - there is no + API for changing the O_NOINHERIT bit on an fd, and merely + changing the HANDLE_FLAG_INHERIT bit on the underlying handle + can lead to odd state. It may be possible by duplicating the + handle, using _open_osfhandle with the right flags, then + using dup2 to move the duplicate onto the original, but that + is not supported for now. */ + + default: + { +#if HAVE_FCNTL + switch (action) + { + #ifdef F_BARRIERFSYNC /* macOS */ + case F_BARRIERFSYNC: + #endif + #ifdef F_CHKCLEAN /* macOS */ + case F_CHKCLEAN: + #endif + #ifdef F_CLOSEM /* NetBSD, HP-UX */ + case F_CLOSEM: + #endif + #ifdef F_FLUSH_DATA /* macOS */ + case F_FLUSH_DATA: + #endif + #ifdef F_FREEZE_FS /* macOS */ + case F_FREEZE_FS: + #endif + #ifdef F_FULLFSYNC /* macOS */ + case F_FULLFSYNC: + #endif + #ifdef F_GETCONFINED /* macOS */ + case F_GETCONFINED: + #endif + #ifdef F_GETDEFAULTPROTLEVEL /* macOS */ + case F_GETDEFAULTPROTLEVEL: + #endif + #ifdef F_GETFD /* POSIX */ + case F_GETFD: + #endif + #ifdef F_GETFL /* POSIX */ + case F_GETFL: + #endif + #ifdef F_GETLEASE /* Linux */ + case F_GETLEASE: + #endif + #ifdef F_GETNOSIGPIPE /* macOS */ + case F_GETNOSIGPIPE: + #endif + #ifdef F_GETOWN /* POSIX */ + case F_GETOWN: + #endif + #ifdef F_GETPIPE_SZ /* Linux */ + case F_GETPIPE_SZ: + #endif + #ifdef F_GETPROTECTIONCLASS /* macOS */ + case F_GETPROTECTIONCLASS: + #endif + #ifdef F_GETPROTECTIONLEVEL /* macOS */ + case F_GETPROTECTIONLEVEL: + #endif + #ifdef F_GET_SEALS /* Linux */ + case F_GET_SEALS: + #endif + #ifdef F_GETSIG /* Linux */ + case F_GETSIG: + #endif + #ifdef F_MAXFD /* NetBSD */ + case F_MAXFD: + #endif + #ifdef F_RECYCLE /* macOS */ + case F_RECYCLE: + #endif + #ifdef F_SETFIFOENH /* HP-UX */ + case F_SETFIFOENH: + #endif + #ifdef F_THAW_FS /* macOS */ + case F_THAW_FS: + #endif + /* These actions take no argument. */ + result = fcntl (fd, action); + break; + + #ifdef F_ADD_SEALS /* Linux */ + case F_ADD_SEALS: + #endif + #ifdef F_BADFD /* Solaris */ + case F_BADFD: + #endif + #ifdef F_CHECK_OPENEVT /* macOS */ + case F_CHECK_OPENEVT: + #endif + #ifdef F_DUP2FD /* FreeBSD, AIX, Solaris */ + case F_DUP2FD: + #endif + #ifdef F_DUP2FD_CLOEXEC /* FreeBSD, Solaris */ + case F_DUP2FD_CLOEXEC: + #endif + #ifdef F_DUP2FD_CLOFORK /* Solaris */ + case F_DUP2FD_CLOFORK: + #endif + #ifdef F_DUPFD /* POSIX */ + case F_DUPFD: + #endif + #ifdef F_DUPFD_CLOEXEC /* POSIX */ + case F_DUPFD_CLOEXEC: + #endif + #ifdef F_DUPFD_CLOFORK /* Solaris */ + case F_DUPFD_CLOFORK: + #endif + #ifdef F_GETXFL /* Solaris */ + case F_GETXFL: + #endif + #ifdef F_GLOBAL_NOCACHE /* macOS */ + case F_GLOBAL_NOCACHE: + #endif + #ifdef F_MAKECOMPRESSED /* macOS */ + case F_MAKECOMPRESSED: + #endif + #ifdef F_MOVEDATAEXTENTS /* macOS */ + case F_MOVEDATAEXTENTS: + #endif + #ifdef F_NOCACHE /* macOS */ + case F_NOCACHE: + #endif + #ifdef F_NODIRECT /* macOS */ + case F_NODIRECT: + #endif + #ifdef F_NOTIFY /* Linux */ + case F_NOTIFY: + #endif + #ifdef F_OPLKACK /* IRIX */ + case F_OPLKACK: + #endif + #ifdef F_OPLKREG /* IRIX */ + case F_OPLKREG: + #endif + #ifdef F_RDAHEAD /* macOS */ + case F_RDAHEAD: + #endif + #ifdef F_SETBACKINGSTORE /* macOS */ + case F_SETBACKINGSTORE: + #endif + #ifdef F_SETCONFINED /* macOS */ + case F_SETCONFINED: + #endif + #ifdef F_SETFD /* POSIX */ + case F_SETFD: + #endif + #ifdef F_SETFL /* POSIX */ + case F_SETFL: + #endif + #ifdef F_SETLEASE /* Linux */ + case F_SETLEASE: + #endif + #ifdef F_SETNOSIGPIPE /* macOS */ + case F_SETNOSIGPIPE: + #endif + #ifdef F_SETOWN /* POSIX */ + case F_SETOWN: + #endif + #ifdef F_SETPIPE_SZ /* Linux */ + case F_SETPIPE_SZ: + #endif + #ifdef F_SETPROTECTIONCLASS /* macOS */ + case F_SETPROTECTIONCLASS: + #endif + #ifdef F_SETSIG /* Linux */ + case F_SETSIG: + #endif + #ifdef F_SINGLE_WRITER /* macOS */ + case F_SINGLE_WRITER: + #endif + /* These actions take an 'int' argument. */ + { + int x = va_arg (arg, int); + result = fcntl (fd, action, x); + } + break; + + default: + /* Other actions take a pointer argument. */ + { + void *p = va_arg (arg, void *); + result = fcntl (fd, action, p); + } + break; + } +#else + errno = EINVAL; +#endif + break; + } + } + va_end (arg); + return result; +} + +static int +rpl_fcntl_DUPFD (int fd, int target) +{ + int result; +#if !HAVE_FCNTL + result = dupfd (fd, target, 0); +#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR + /* Detect invalid target; needed for cygwin 1.5.x. */ + if (target < 0 || getdtablesize () <= target) + { + result = -1; + errno = EINVAL; + } + else + { + /* Haiku alpha 2 loses fd flags on original. */ + int flags = fcntl (fd, F_GETFD); + if (flags < 0) + result = -1; + else + { + result = fcntl (fd, F_DUPFD, target); + if (0 <= result && fcntl (fd, F_SETFD, flags) == -1) + { + int saved_errno = errno; + close (result); + result = -1; + errno = saved_errno; + } +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif + } + } +#else + result = fcntl (fd, F_DUPFD, target); +#endif + return result; +} + +static int +rpl_fcntl_DUPFD_CLOEXEC (int fd, int target) +{ + int result; +#if !HAVE_FCNTL + result = dupfd (fd, target, O_CLOEXEC); +#else /* HAVE_FCNTL */ +# if defined __HAIKU__ + /* On Haiku, the system fcntl (fd, F_DUPFD_CLOEXEC, target) sets + the FD_CLOEXEC flag on fd, not on target. Therefore avoid the + system fcntl in this case. */ +# define have_dupfd_cloexec -1 +# else + /* Try the system call first, if the headers claim it exists + (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we + may be running with a glibc that has the macro but with an + older kernel that does not support it. Cache the + information on whether the system call really works, but + avoid caching failure if the corresponding F_DUPFD fails + for any reason. 0 = unknown, 1 = yes, -1 = no. */ + static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0; + if (0 <= have_dupfd_cloexec) + { + result = fcntl (fd, F_DUPFD_CLOEXEC, target); + if (0 <= result || errno != EINVAL) + { + have_dupfd_cloexec = 1; +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif + } + else + { + result = rpl_fcntl_DUPFD (fd, target); + if (result >= 0) + have_dupfd_cloexec = -1; + } + } + else +# endif + result = rpl_fcntl_DUPFD (fd, target); + if (0 <= result && have_dupfd_cloexec == -1) + { + int flags = fcntl (result, F_GETFD); + if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1) + { + int saved_errno = errno; + close (result); + errno = saved_errno; + result = -1; + } + } +#endif /* HAVE_FCNTL */ + return result; +} + +#undef fcntl + +#ifdef __KLIBC__ + +static int +klibc_fcntl (int fd, int action, /* arg */...); +{ + va_list arg_ptr; + int arg; + struct stat sbuf; + int result; + + va_start (arg_ptr, action); + arg = va_arg (arg_ptr, int); + result = fcntl (fd, action, arg); + /* EPERM for F_DUPFD, ENOTSUP for others */ + if (result == -1 && (errno == EPERM || errno == ENOTSUP) + && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) + { + ULONG ulMode; + + switch (action) + { + case F_DUPFD: + /* Find available fd */ + while (fcntl (arg, F_GETFL) != -1 || errno != EBADF) + arg++; + + result = dup2 (fd, arg); + break; + + /* Using underlying APIs is right ? */ + case F_GETFD: + if (DosQueryFHState (fd, &ulMode)) + break; + + result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0; + break; + + case F_SETFD: + if (arg & ~FD_CLOEXEC) + break; + + if (DosQueryFHState (fd, &ulMode)) + break; + + if (arg & FD_CLOEXEC) + ulMode |= OPEN_FLAGS_NOINHERIT; + else + ulMode &= ~OPEN_FLAGS_NOINHERIT; + + /* Filter supported flags. */ + ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR + | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT); + + if (DosSetFHState (fd, ulMode)) + break; + + result = 0; + break; + + case F_GETFL: + result = 0; + break; + + case F_SETFL: + if (arg != 0) + break; + + result = 0; + break; + + default: + errno = EINVAL; + break; + } + } + + va_end (arg_ptr); + + return result; +} + +#endif diff --git a/grub-core/lib/gnulib/fcntl.in.h b/grub-core/lib/gnulib/fcntl.in.h new file mode 100644 index 0000000..eb70dc6 --- /dev/null +++ b/grub-core/lib/gnulib/fcntl.in.h @@ -0,0 +1,366 @@ +/* Like <fcntl.h>, but with non-working flags defined to 0. + + Copyright (C) 2006-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* written by Paul Eggert */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_system_fcntl_h +/* Special invocation convention. */ + +/* Needed before <sys/stat.h>. + May also define off_t to a 64-bit type on native Windows. */ +#include <sys/types.h> +/* On some systems other than glibc, <sys/stat.h> is a prerequisite of + <fcntl.h>. On glibc systems, we would like to avoid namespace pollution. + But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an + extern "C" { ... } block, which leads to errors in C++ mode with the + overridden <sys/stat.h> from gnulib. These errors are known to be gone + with g++ version >= 4.3. */ +#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))) +# include <sys/stat.h> +#endif +#@INCLUDE_NEXT@ @NEXT_FCNTL_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_FCNTL_H + +/* Needed before <sys/stat.h>. + May also define off_t to a 64-bit type on native Windows. */ +#include <sys/types.h> +/* On some systems other than glibc, <sys/stat.h> is a prerequisite of + <fcntl.h>. On glibc systems, we would like to avoid namespace pollution. + But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an + extern "C" { ... } block, which leads to errors in C++ mode with the + overridden <sys/stat.h> from gnulib. These errors are known to be gone + with g++ version >= 4.3. */ +#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))) +# include <sys/stat.h> +#endif +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_FCNTL_H@ + +#ifndef _@GUARD_PREFIX@_FCNTL_H +#define _@GUARD_PREFIX@_FCNTL_H + +#ifndef __GLIBC__ /* Avoid namespace pollution on glibc systems. */ +# include <unistd.h> +#endif + +/* Native Windows platforms declare open(), creat() in <io.h>. */ +#if (@GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \ + && (defined _WIN32 && ! defined __CYGWIN__) +# include <io.h> +#endif + + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Declare overridden functions. */ + +#if @GNULIB_FCNTL@ +# if @REPLACE_FCNTL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fcntl +# define fcntl rpl_fcntl +# endif +_GL_FUNCDECL_RPL (fcntl, int, (int fd, int action, ...)); +_GL_CXXALIAS_RPL (fcntl, int, (int fd, int action, ...)); +# else +# if !@HAVE_FCNTL@ +_GL_FUNCDECL_SYS (fcntl, int, (int fd, int action, ...)); +# endif +_GL_CXXALIAS_SYS (fcntl, int, (int fd, int action, ...)); +# endif +_GL_CXXALIASWARN (fcntl); +#elif defined GNULIB_POSIXCHECK +# undef fcntl +# if HAVE_RAW_DECL_FCNTL +_GL_WARN_ON_USE (fcntl, "fcntl is not always POSIX compliant - " + "use gnulib module fcntl for portability"); +# endif +#endif + +#if @GNULIB_OPEN@ +# if @REPLACE_OPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef open +# define open rpl_open +# endif +_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...)); +# else +_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); +# endif +/* On HP-UX 11, in C++ mode, open() is defined as an inline function with a + default argument. _GL_CXXALIASWARN does not work in this case. */ +# if !defined __hpux +_GL_CXXALIASWARN (open); +# endif +#elif defined GNULIB_POSIXCHECK +# undef open +/* Assume open is always declared. */ +_GL_WARN_ON_USE (open, "open is not always POSIX compliant - " + "use gnulib module open for portability"); +#endif + +#if @GNULIB_OPENAT@ +# if @REPLACE_OPENAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef openat +# define openat rpl_openat +# endif +_GL_FUNCDECL_RPL (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...)); +# else +# if !@HAVE_OPENAT@ +_GL_FUNCDECL_SYS (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...)); +# endif +_GL_CXXALIASWARN (openat); +#elif defined GNULIB_POSIXCHECK +# undef openat +# if HAVE_RAW_DECL_OPENAT +_GL_WARN_ON_USE (openat, "openat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +/* Fix up the FD_* macros, only known to be missing on mingw. */ + +#ifndef FD_CLOEXEC +# define FD_CLOEXEC 1 +#endif + +/* Fix up the supported F_* macros. Intentionally leave other F_* + macros undefined. Only known to be missing on mingw. */ + +#ifndef F_DUPFD_CLOEXEC +# define F_DUPFD_CLOEXEC 0x40000000 +/* Witness variable: 1 if gnulib defined F_DUPFD_CLOEXEC, 0 otherwise. */ +# define GNULIB_defined_F_DUPFD_CLOEXEC 1 +#else +# define GNULIB_defined_F_DUPFD_CLOEXEC 0 +#endif + +#ifndef F_DUPFD +# define F_DUPFD 1 +#endif + +#ifndef F_GETFD +# define F_GETFD 2 +#endif + +/* Fix up the O_* macros. */ + +/* AIX 7.1 with XL C 12.1 defines O_CLOEXEC, O_NOFOLLOW, and O_TTY_INIT + to values outside 'int' range, so omit these misdefinitions. + But avoid namespace pollution on non-AIX systems. */ +#ifdef _AIX +# include <limits.h> +# if defined O_CLOEXEC && ! (INT_MIN <= O_CLOEXEC && O_CLOEXEC <= INT_MAX) +# undef O_CLOEXEC +# endif +# if defined O_NOFOLLOW && ! (INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX) +# undef O_NOFOLLOW +# endif +# if defined O_TTY_INIT && ! (INT_MIN <= O_TTY_INIT && O_TTY_INIT <= INT_MAX) +# undef O_TTY_INIT +# endif +#endif + +#if !defined O_DIRECT && defined O_DIRECTIO +/* Tru64 spells it 'O_DIRECTIO'. */ +# define O_DIRECT O_DIRECTIO +#endif + +#if !defined O_CLOEXEC && defined O_NOINHERIT +/* Mingw spells it 'O_NOINHERIT'. */ +# define O_CLOEXEC O_NOINHERIT +#endif + +#ifndef O_CLOEXEC +# define O_CLOEXEC 0x40000000 /* Try to not collide with system O_* flags. */ +# define GNULIB_defined_O_CLOEXEC 1 +#else +# define GNULIB_defined_O_CLOEXEC 0 +#endif + +#ifndef O_DIRECT +# define O_DIRECT 0 +#endif + +#ifndef O_DIRECTORY +# define O_DIRECTORY 0 +#endif + +#ifndef O_DSYNC +# define O_DSYNC 0 +#endif + +#ifndef O_EXEC +# define O_EXEC O_RDONLY /* This is often close enough in older systems. */ +#endif + +#ifndef O_IGNORE_CTTY +# define O_IGNORE_CTTY 0 +#endif + +#ifndef O_NDELAY +# define O_NDELAY 0 +#endif + +#ifndef O_NOATIME +# define O_NOATIME 0 +#endif + +#ifndef O_NONBLOCK +# define O_NONBLOCK O_NDELAY +#endif + +/* If the gnulib module 'nonblocking' is in use, guarantee a working non-zero + value of O_NONBLOCK. Otherwise, O_NONBLOCK is defined (above) to O_NDELAY + or to 0 as fallback. */ +#if @GNULIB_NONBLOCKING@ +# if O_NONBLOCK +# define GNULIB_defined_O_NONBLOCK 0 +# else +# define GNULIB_defined_O_NONBLOCK 1 +# undef O_NONBLOCK +# define O_NONBLOCK 0x40000000 +# endif +#endif + +#ifndef O_NOCTTY +# define O_NOCTTY 0 +#endif + +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif + +#ifndef O_NOLINK +# define O_NOLINK 0 +#endif + +#ifndef O_NOLINKS +# define O_NOLINKS 0 +#endif + +#ifndef O_NOTRANS +# define O_NOTRANS 0 +#endif + +#ifndef O_RSYNC +# define O_RSYNC 0 +#endif + +#ifndef O_SEARCH +# define O_SEARCH O_RDONLY /* This is often close enough in older systems. */ +#endif + +#ifndef O_SYNC +# define O_SYNC 0 +#endif + +#ifndef O_TTY_INIT +# define O_TTY_INIT 0 +#endif + +#if ~O_ACCMODE & (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH) +# undef O_ACCMODE +# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH) +#endif + +/* For systems that distinguish between text and binary I/O. + O_BINARY is usually declared in fcntl.h */ +#if !defined O_BINARY && defined _O_BINARY + /* For MSC-compatible compilers. */ +# define O_BINARY _O_BINARY +# define O_TEXT _O_TEXT +#endif + +#if defined __BEOS__ || defined __HAIKU__ + /* BeOS 5 and Haiku have O_BINARY and O_TEXT, but they have no effect. */ +# undef O_BINARY +# undef O_TEXT +#endif + +#ifndef O_BINARY +# define O_BINARY 0 +# define O_TEXT 0 +#endif + +/* Fix up the AT_* macros. */ + +/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its + value exceeds INT_MAX, so its use as an int doesn't conform to the + C standard, and GCC and Sun C complain in some cases. If the bug + is present, undef AT_FDCWD here, so it can be redefined below. */ +#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553 +# undef AT_FDCWD +#endif + +/* Use the same bit pattern as Solaris 9, but with the proper + signedness. The bit pattern is important, in case this actually is + Solaris with the above workaround. */ +#ifndef AT_FDCWD +# define AT_FDCWD (-3041965) +#endif + +/* Use the same values as Solaris 9. This shouldn't matter, but + there's no real reason to differ. */ +#ifndef AT_SYMLINK_NOFOLLOW +# define AT_SYMLINK_NOFOLLOW 4096 +#endif + +#ifndef AT_REMOVEDIR +# define AT_REMOVEDIR 1 +#endif + +/* Solaris 9 lacks these two, so just pick unique values. */ +#ifndef AT_SYMLINK_FOLLOW +# define AT_SYMLINK_FOLLOW 2 +#endif + +#ifndef AT_EACCESS +# define AT_EACCESS 4 +#endif + + +#endif /* _@GUARD_PREFIX@_FCNTL_H */ +#endif /* _@GUARD_PREFIX@_FCNTL_H */ +#endif diff --git a/grub-core/lib/gnulib/fd-hook.c b/grub-core/lib/gnulib/fd-hook.c new file mode 100644 index 0000000..7879119 --- /dev/null +++ b/grub-core/lib/gnulib/fd-hook.c @@ -0,0 +1,116 @@ +/* Hook for making file descriptor functions close(), ioctl() extensible. + Copyright (C) 2009-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2009. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "fd-hook.h" + +#include <stdlib.h> + +/* Currently, this entire code is only needed for the handling of sockets + on native Windows platforms. */ +#if WINDOWS_SOCKETS + +/* The first and last link in the doubly linked list. + Initially the list is empty. */ +static struct fd_hook anchor = { &anchor, &anchor, NULL, NULL }; + +int +execute_close_hooks (const struct fd_hook *remaining_list, gl_close_fn primary, + int fd) +{ + if (remaining_list == &anchor) + /* End of list reached. */ + return primary (fd); + else + return remaining_list->private_close_fn (remaining_list->private_next, + primary, fd); +} + +int +execute_all_close_hooks (gl_close_fn primary, int fd) +{ + return execute_close_hooks (anchor.private_next, primary, fd); +} + +int +execute_ioctl_hooks (const struct fd_hook *remaining_list, gl_ioctl_fn primary, + int fd, int request, void *arg) +{ + if (remaining_list == &anchor) + /* End of list reached. */ + return primary (fd, request, arg); + else + return remaining_list->private_ioctl_fn (remaining_list->private_next, + primary, fd, request, arg); +} + +int +execute_all_ioctl_hooks (gl_ioctl_fn primary, + int fd, int request, void *arg) +{ + return execute_ioctl_hooks (anchor.private_next, primary, fd, request, arg); +} + +void +register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, struct fd_hook *link) +{ + if (close_hook == NULL) + close_hook = execute_close_hooks; + if (ioctl_hook == NULL) + ioctl_hook = execute_ioctl_hooks; + + if (link->private_next == NULL && link->private_prev == NULL) + { + /* Add the link to the doubly linked list. */ + link->private_next = anchor.private_next; + link->private_prev = &anchor; + link->private_close_fn = close_hook; + link->private_ioctl_fn = ioctl_hook; + anchor.private_next->private_prev = link; + anchor.private_next = link; + } + else + { + /* The link is already in use. */ + if (link->private_close_fn != close_hook + || link->private_ioctl_fn != ioctl_hook) + abort (); + } +} + +void +unregister_fd_hook (struct fd_hook *link) +{ + struct fd_hook *next = link->private_next; + struct fd_hook *prev = link->private_prev; + + if (next != NULL && prev != NULL) + { + /* The link is in use. Remove it from the doubly linked list. */ + prev->private_next = next; + next->private_prev = prev; + /* Clear the link, to mark it unused. */ + link->private_next = NULL; + link->private_prev = NULL; + link->private_close_fn = NULL; + link->private_ioctl_fn = NULL; + } +} + +#endif diff --git a/grub-core/lib/gnulib/fd-hook.h b/grub-core/lib/gnulib/fd-hook.h new file mode 100644 index 0000000..bf07f00 --- /dev/null +++ b/grub-core/lib/gnulib/fd-hook.h @@ -0,0 +1,119 @@ +/* Hook for making file descriptor functions close(), ioctl() extensible. + Copyright (C) 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + + +#ifndef FD_HOOK_H +#define FD_HOOK_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Currently, this entire code is only needed for the handling of sockets + on native Windows platforms. */ +#if WINDOWS_SOCKETS + + +/* Type of function that closes FD. */ +typedef int (*gl_close_fn) (int fd); + +/* Type of function that applies a control request to FD. */ +typedef int (*gl_ioctl_fn) (int fd, int request, void *arg); + +/* An element of the list of file descriptor hooks. + In CLOS (Common Lisp Object System) speak, it consists of an "around" + method for the close() function and an "around" method for the ioctl() + function. + The fields of this structure are considered private. */ +struct fd_hook +{ + /* Doubly linked list. */ + struct fd_hook *private_next; + struct fd_hook *private_prev; + /* Function that treats the types of FD that it knows about and calls + execute_close_hooks (REMAINING_LIST, PRIMARY, FD) as a fallback. */ + int (*private_close_fn) (const struct fd_hook *remaining_list, + gl_close_fn primary, + int fd); + /* Function that treats the types of FD that it knows about and calls + execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG) as a + fallback. */ + int (*private_ioctl_fn) (const struct fd_hook *remaining_list, + gl_ioctl_fn primary, + int fd, int request, void *arg); +}; + +/* This type of function closes FD, applying special knowledge for the FD + types it knows about, and calls + execute_close_hooks (REMAINING_LIST, PRIMARY, FD) + for the other FD types. + In CLOS speak, REMAINING_LIST is the remaining list of "around" methods, + and PRIMARY is the "primary" method for close(). */ +typedef int (*close_hook_fn) (const struct fd_hook *remaining_list, + gl_close_fn primary, + int fd); + +/* Execute the close hooks in REMAINING_LIST, with PRIMARY as "primary" method. + Return 0 or -1, like close() would do. */ +extern int execute_close_hooks (const struct fd_hook *remaining_list, + gl_close_fn primary, + int fd); + +/* Execute all close hooks, with PRIMARY as "primary" method. + Return 0 or -1, like close() would do. */ +extern int execute_all_close_hooks (gl_close_fn primary, int fd); + +/* This type of function applies a control request to FD, applying special + knowledge for the FD types it knows about, and calls + execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG) + for the other FD types. + In CLOS speak, REMAINING_LIST is the remaining list of "around" methods, + and PRIMARY is the "primary" method for ioctl(). */ +typedef int (*ioctl_hook_fn) (const struct fd_hook *remaining_list, + gl_ioctl_fn primary, + int fd, int request, void *arg); + +/* Execute the ioctl hooks in REMAINING_LIST, with PRIMARY as "primary" method. + Return 0 or -1, like ioctl() would do. */ +extern int execute_ioctl_hooks (const struct fd_hook *remaining_list, + gl_ioctl_fn primary, + int fd, int request, void *arg); + +/* Execute all ioctl hooks, with PRIMARY as "primary" method. + Return 0 or -1, like ioctl() would do. */ +extern int execute_all_ioctl_hooks (gl_ioctl_fn primary, + int fd, int request, void *arg); + +/* Add a function pair to the list of file descriptor hooks. + CLOSE_HOOK and IOCTL_HOOK may be NULL, indicating no change. + The LINK variable points to a piece of memory which is guaranteed to be + accessible until the corresponding call to unregister_fd_hook. */ +extern void register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, + struct fd_hook *link); + +/* Removes a hook from the list of file descriptor hooks. */ +extern void unregister_fd_hook (struct fd_hook *link); + + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* FD_HOOK_H */ diff --git a/grub-core/lib/gnulib/fd-safer-flag.c b/grub-core/lib/gnulib/fd-safer-flag.c new file mode 100644 index 0000000..7c026ef --- /dev/null +++ b/grub-core/lib/gnulib/fd-safer-flag.c @@ -0,0 +1,52 @@ +/* Adjust a file descriptor result so that it avoids clobbering + STD{IN,OUT,ERR}_FILENO, with specific flags. + + Copyright (C) 2005-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert and Eric Blake. */ + +#include <config.h> + +/* Specification. */ +#include "unistd-safer.h" + +#include <errno.h> +#include <unistd.h> + +/* Return FD, unless FD would be a copy of standard input, output, or + error; in that case, return a duplicate of FD, closing FD. If FLAG + contains O_CLOEXEC, the returned FD will have close-on-exec + semantics. On failure to duplicate, close FD, set errno, and + return -1. Preserve errno if FD is negative, so that the caller + can always inspect errno when the returned value is negative. + + This function is usefully wrapped around functions that return file + descriptors, e.g., fd_safer_flag (open ("file", O_RDONLY | flag), flag). */ + +int +fd_safer_flag (int fd, int flag) +{ + if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) + { + int f = dup_safer_flag (fd, flag); + int e = errno; + close (fd); + errno = e; + fd = f; + } + + return fd; +} diff --git a/grub-core/lib/gnulib/fd-safer.c b/grub-core/lib/gnulib/fd-safer.c new file mode 100644 index 0000000..b5113e1 --- /dev/null +++ b/grub-core/lib/gnulib/fd-safer.c @@ -0,0 +1,49 @@ +/* Return a safer copy of a file descriptor. + + Copyright (C) 2005-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +#include <config.h> + +#include "unistd-safer.h" + +#include <errno.h> +#include <unistd.h> + +/* Return FD, unless FD would be a copy of standard input, output, or + error; in that case, return a duplicate of FD, closing FD. On + failure to duplicate, close FD, set errno, and return -1. Preserve + errno if FD is negative, so that the caller can always inspect + errno when the returned value is negative. + + This function is usefully wrapped around functions that return file + descriptors, e.g., fd_safer (open ("file", O_RDONLY)). */ + +int +fd_safer (int fd) +{ + if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) + { + int f = dup_safer (fd); + int e = errno; + close (fd); + errno = e; + fd = f; + } + + return fd; +} diff --git a/grub-core/lib/gnulib/filename.h b/grub-core/lib/gnulib/filename.h new file mode 100644 index 0000000..3ba3105 --- /dev/null +++ b/grub-core/lib/gnulib/filename.h @@ -0,0 +1,54 @@ +/* Basic filename support macros. + Copyright (C) 2001-2004, 2007-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _FILENAME_H +#define _FILENAME_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Pathname support. + ISSLASH(C) tests whether C is a directory separator character. + IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, + it may be concatenated to a directory pathname. + IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. + */ +#if defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Native Windows, Cygwin, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +# define HAS_DEVICE(P) \ + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ + && (P)[1] == ':') +# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) +# define IS_PATH_WITH_DIR(P) \ + (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) +# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0) +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) +# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) +# define FILE_SYSTEM_PREFIX_LEN(P) 0 +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _FILENAME_H */ diff --git a/grub-core/lib/gnulib/filenamecat-lgpl.c b/grub-core/lib/gnulib/filenamecat-lgpl.c new file mode 100644 index 0000000..98b105a --- /dev/null +++ b/grub-core/lib/gnulib/filenamecat-lgpl.c @@ -0,0 +1,87 @@ +/* Concatenate two arbitrary file names. + + Copyright (C) 1996-2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Jim Meyering. */ + +#include <config.h> + +/* Specification. */ +#include "filenamecat.h" + +#include <stdlib.h> +#include <string.h> + +#include "dirname.h" + +#if ! HAVE_MEMPCPY && ! defined mempcpy +# define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) +#endif + +/* Concatenate two file name components, DIR and BASE, in + newly-allocated storage and return the result. + The resulting file name F is such that the commands "ls F" and "(cd + DIR; ls ./BASE)" refer to the same file. If necessary, put + a separator between DIR and BASE in the result. Typically this + separator is "/", but in rare cases it might be ".". + In any case, if BASE_IN_RESULT is non-NULL, set + *BASE_IN_RESULT to point to the copy of BASE at the end of the + returned concatenation. + + Return NULL if malloc fails. */ + +char * +mfile_name_concat (char const *dir, char const *base, char **base_in_result) +{ + char const *dirbase = last_component (dir); + size_t dirbaselen = base_len (dirbase); + size_t dirlen = dirbase - dir + dirbaselen; + size_t baselen = strlen (base); + char sep = '\0'; + if (dirbaselen) + { + /* DIR is not a file system root, so separate with / if needed. */ + if (! ISSLASH (dir[dirlen - 1]) && ! ISSLASH (*base)) + sep = '/'; + } + else if (ISSLASH (*base)) + { + /* DIR is a file system root and BASE begins with a slash, so + separate with ".". For example, if DIR is "/" and BASE is + "/foo" then return "/./foo", as "//foo" would be wrong on + some POSIX systems. A fancier algorithm could omit "." in + some cases but is not worth the trouble. */ + sep = '.'; + } + + char *p_concat = malloc (dirlen + (sep != '\0') + baselen + 1); + char *p; + + if (p_concat == NULL) + return NULL; + + p = mempcpy (p_concat, dir, dirlen); + *p = sep; + p += sep != '\0'; + + if (base_in_result) + *base_in_result = p; + + p = mempcpy (p, base, baselen); + *p = '\0'; + + return p_concat; +} diff --git a/grub-core/lib/gnulib/filenamecat.h b/grub-core/lib/gnulib/filenamecat.h new file mode 100644 index 0000000..67b46b0 --- /dev/null +++ b/grub-core/lib/gnulib/filenamecat.h @@ -0,0 +1,27 @@ +/* Concatenate two arbitrary file names. + + Copyright (C) 1996-1997, 2003, 2005, 2007, 2009-2019 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Jim Meyering. */ + +#if GNULIB_FILENAMECAT +char *file_name_concat (char const *dir, char const *base, + char **base_in_result); +#endif + +char *mfile_name_concat (char const *dir, char const *base, + char **base_in_result); diff --git a/grub-core/lib/gnulib/flexmember.h b/grub-core/lib/gnulib/flexmember.h new file mode 100644 index 0000000..0d65f6d --- /dev/null +++ b/grub-core/lib/gnulib/flexmember.h @@ -0,0 +1,45 @@ +/* Sizes of structs with flexible array members. + + Copyright 2016-2019 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. + + Written by Paul Eggert. */ + +#include <stddef.h> + +/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below. + On older platforms without _Alignof, use a pessimistic bound that is + safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1. + On newer platforms, use _Alignof to get a tighter bound. */ + +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 +# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1)) +#else +# define FLEXALIGNOF(type) _Alignof (type) +#endif + +/* Upper bound on the size of a struct of type TYPE with a flexible + array member named MEMBER that is followed by N bytes of other data. + This is not simply sizeof (TYPE) + N, since it may require + alignment on unusually picky C11 platforms, and + FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms. + Yield a value less than N if and only if arithmetic overflow occurs. */ + +#define FLEXSIZEOF(type, member, n) \ + ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \ + & ~ (FLEXALIGNOF (type) - 1)) diff --git a/grub-core/lib/gnulib/float+.h b/grub-core/lib/gnulib/float+.h new file mode 100644 index 0000000..5af861f --- /dev/null +++ b/grub-core/lib/gnulib/float+.h @@ -0,0 +1,147 @@ +/* Supplemental information about the floating-point formats. + Copyright (C) 2007, 2009-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2007. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _FLOATPLUS_H +#define _FLOATPLUS_H + +#include <float.h> +#include <limits.h> + +/* Number of bits in the mantissa of a floating-point number, including the + "hidden bit". */ +#if FLT_RADIX == 2 +# define FLT_MANT_BIT FLT_MANT_DIG +# define DBL_MANT_BIT DBL_MANT_DIG +# define LDBL_MANT_BIT LDBL_MANT_DIG +#elif FLT_RADIX == 4 +# define FLT_MANT_BIT (FLT_MANT_DIG * 2) +# define DBL_MANT_BIT (DBL_MANT_DIG * 2) +# define LDBL_MANT_BIT (LDBL_MANT_DIG * 2) +#elif FLT_RADIX == 16 +# define FLT_MANT_BIT (FLT_MANT_DIG * 4) +# define DBL_MANT_BIT (DBL_MANT_DIG * 4) +# define LDBL_MANT_BIT (LDBL_MANT_DIG * 4) +#endif + +/* Bit mask that can be used to mask the exponent, as an unsigned number. */ +#define FLT_EXP_MASK ((FLT_MAX_EXP - FLT_MIN_EXP) | 7) +#define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7) +#define LDBL_EXP_MASK ((LDBL_MAX_EXP - LDBL_MIN_EXP) | 7) + +/* Number of bits used for the exponent of a floating-point number, including + the exponent's sign. */ +#define FLT_EXP_BIT \ + (FLT_EXP_MASK < 0x100 ? 8 : \ + FLT_EXP_MASK < 0x200 ? 9 : \ + FLT_EXP_MASK < 0x400 ? 10 : \ + FLT_EXP_MASK < 0x800 ? 11 : \ + FLT_EXP_MASK < 0x1000 ? 12 : \ + FLT_EXP_MASK < 0x2000 ? 13 : \ + FLT_EXP_MASK < 0x4000 ? 14 : \ + FLT_EXP_MASK < 0x8000 ? 15 : \ + FLT_EXP_MASK < 0x10000 ? 16 : \ + FLT_EXP_MASK < 0x20000 ? 17 : \ + FLT_EXP_MASK < 0x40000 ? 18 : \ + FLT_EXP_MASK < 0x80000 ? 19 : \ + FLT_EXP_MASK < 0x100000 ? 20 : \ + FLT_EXP_MASK < 0x200000 ? 21 : \ + FLT_EXP_MASK < 0x400000 ? 22 : \ + FLT_EXP_MASK < 0x800000 ? 23 : \ + FLT_EXP_MASK < 0x1000000 ? 24 : \ + FLT_EXP_MASK < 0x2000000 ? 25 : \ + FLT_EXP_MASK < 0x4000000 ? 26 : \ + FLT_EXP_MASK < 0x8000000 ? 27 : \ + FLT_EXP_MASK < 0x10000000 ? 28 : \ + FLT_EXP_MASK < 0x20000000 ? 29 : \ + FLT_EXP_MASK < 0x40000000 ? 30 : \ + FLT_EXP_MASK <= 0x7fffffff ? 31 : \ + 32) +#define DBL_EXP_BIT \ + (DBL_EXP_MASK < 0x100 ? 8 : \ + DBL_EXP_MASK < 0x200 ? 9 : \ + DBL_EXP_MASK < 0x400 ? 10 : \ + DBL_EXP_MASK < 0x800 ? 11 : \ + DBL_EXP_MASK < 0x1000 ? 12 : \ + DBL_EXP_MASK < 0x2000 ? 13 : \ + DBL_EXP_MASK < 0x4000 ? 14 : \ + DBL_EXP_MASK < 0x8000 ? 15 : \ + DBL_EXP_MASK < 0x10000 ? 16 : \ + DBL_EXP_MASK < 0x20000 ? 17 : \ + DBL_EXP_MASK < 0x40000 ? 18 : \ + DBL_EXP_MASK < 0x80000 ? 19 : \ + DBL_EXP_MASK < 0x100000 ? 20 : \ + DBL_EXP_MASK < 0x200000 ? 21 : \ + DBL_EXP_MASK < 0x400000 ? 22 : \ + DBL_EXP_MASK < 0x800000 ? 23 : \ + DBL_EXP_MASK < 0x1000000 ? 24 : \ + DBL_EXP_MASK < 0x2000000 ? 25 : \ + DBL_EXP_MASK < 0x4000000 ? 26 : \ + DBL_EXP_MASK < 0x8000000 ? 27 : \ + DBL_EXP_MASK < 0x10000000 ? 28 : \ + DBL_EXP_MASK < 0x20000000 ? 29 : \ + DBL_EXP_MASK < 0x40000000 ? 30 : \ + DBL_EXP_MASK <= 0x7fffffff ? 31 : \ + 32) +#define LDBL_EXP_BIT \ + (LDBL_EXP_MASK < 0x100 ? 8 : \ + LDBL_EXP_MASK < 0x200 ? 9 : \ + LDBL_EXP_MASK < 0x400 ? 10 : \ + LDBL_EXP_MASK < 0x800 ? 11 : \ + LDBL_EXP_MASK < 0x1000 ? 12 : \ + LDBL_EXP_MASK < 0x2000 ? 13 : \ + LDBL_EXP_MASK < 0x4000 ? 14 : \ + LDBL_EXP_MASK < 0x8000 ? 15 : \ + LDBL_EXP_MASK < 0x10000 ? 16 : \ + LDBL_EXP_MASK < 0x20000 ? 17 : \ + LDBL_EXP_MASK < 0x40000 ? 18 : \ + LDBL_EXP_MASK < 0x80000 ? 19 : \ + LDBL_EXP_MASK < 0x100000 ? 20 : \ + LDBL_EXP_MASK < 0x200000 ? 21 : \ + LDBL_EXP_MASK < 0x400000 ? 22 : \ + LDBL_EXP_MASK < 0x800000 ? 23 : \ + LDBL_EXP_MASK < 0x1000000 ? 24 : \ + LDBL_EXP_MASK < 0x2000000 ? 25 : \ + LDBL_EXP_MASK < 0x4000000 ? 26 : \ + LDBL_EXP_MASK < 0x8000000 ? 27 : \ + LDBL_EXP_MASK < 0x10000000 ? 28 : \ + LDBL_EXP_MASK < 0x20000000 ? 29 : \ + LDBL_EXP_MASK < 0x40000000 ? 30 : \ + LDBL_EXP_MASK <= 0x7fffffff ? 31 : \ + 32) + +/* Number of bits used for a floating-point number: the mantissa (not + counting the "hidden bit", since it may or may not be explicit), the + exponent, and the sign. */ +#define FLT_TOTAL_BIT ((FLT_MANT_BIT - 1) + FLT_EXP_BIT + 1) +#define DBL_TOTAL_BIT ((DBL_MANT_BIT - 1) + DBL_EXP_BIT + 1) +#define LDBL_TOTAL_BIT ((LDBL_MANT_BIT - 1) + LDBL_EXP_BIT + 1) + +/* Number of bytes used for a floating-point number. + This can be smaller than the 'sizeof'. For example, on i386 systems, + 'long double' most often have LDBL_MANT_BIT = 64, LDBL_EXP_BIT = 16, hence + LDBL_TOTAL_BIT = 80 bits, i.e. 10 bytes of consecutive memory, but + sizeof (long double) = 12 or = 16. */ +#define SIZEOF_FLT ((FLT_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) +#define SIZEOF_DBL ((DBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) +#define SIZEOF_LDBL ((LDBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) + +/* Verify that SIZEOF_FLT <= sizeof (float) etc. */ +typedef int verify_sizeof_flt[SIZEOF_FLT <= sizeof (float) ? 1 : -1]; +typedef int verify_sizeof_dbl[SIZEOF_DBL <= sizeof (double) ? 1 : - 1]; +typedef int verify_sizeof_ldbl[SIZEOF_LDBL <= sizeof (long double) ? 1 : - 1]; + +#endif /* _FLOATPLUS_H */ diff --git a/grub-core/lib/gnulib/float.c b/grub-core/lib/gnulib/float.c new file mode 100644 index 0000000..8872deb --- /dev/null +++ b/grub-core/lib/gnulib/float.c @@ -0,0 +1,33 @@ +/* Auxiliary definitions for <float.h>. + Copyright (C) 2011-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <float.h> + +#if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__ +const union gl_long_double_union gl_LDBL_MAX = + { { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL } }; +#elif defined __i386__ +const union gl_long_double_union gl_LDBL_MAX = + { { 0xFFFFFFFF, 0xFFFFFFFF, 32766 } }; +#else +/* This declaration is solely to ensure that after preprocessing + this file is never empty. */ +typedef int dummy; +#endif diff --git a/grub-core/lib/gnulib/float.in.h b/grub-core/lib/gnulib/float.in.h new file mode 100644 index 0000000..ba094a8 --- /dev/null +++ b/grub-core/lib/gnulib/float.in.h @@ -0,0 +1,188 @@ +/* A correct <float.h>. + + Copyright (C) 2007-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _@GUARD_PREFIX@_FLOAT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_FLOAT_H@ + +#ifndef _@GUARD_PREFIX@_FLOAT_H +#define _@GUARD_PREFIX@_FLOAT_H + +/* 'long double' properties. */ + +#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__) +/* Number of mantissa units, in base FLT_RADIX. */ +# undef LDBL_MANT_DIG +# define LDBL_MANT_DIG 64 +/* Number of decimal digits that is sufficient for representing a number. */ +# undef LDBL_DIG +# define LDBL_DIG 18 +/* x-1 where x is the smallest representable number > 1. */ +# undef LDBL_EPSILON +# define LDBL_EPSILON 1.0842021724855044340E-19L +/* Minimum e such that FLT_RADIX^(e-1) is a normalized number. */ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP (-16381) +/* Maximum e such that FLT_RADIX^(e-1) is a representable finite number. */ +# undef LDBL_MAX_EXP +# define LDBL_MAX_EXP 16384 +/* Minimum positive normalized number. */ +# undef LDBL_MIN +# define LDBL_MIN 3.3621031431120935063E-4932L +/* Maximum representable finite number. */ +# undef LDBL_MAX +# define LDBL_MAX 1.1897314953572317650E+4932L +/* Minimum e such that 10^e is in the range of normalized numbers. */ +# undef LDBL_MIN_10_EXP +# define LDBL_MIN_10_EXP (-4931) +/* Maximum e such that 10^e is in the range of representable finite numbers. */ +# undef LDBL_MAX_10_EXP +# define LDBL_MAX_10_EXP 4932 +#endif + +/* On FreeBSD/x86 6.4, the 'long double' type really has only 53 bits of + precision in the compiler but 64 bits of precision at runtime. See + <https://lists.gnu.org/r/bug-gnulib/2008-07/msg00063.html>. */ +#if defined __i386__ && (defined __FreeBSD__ || defined __DragonFly__) +/* Number of mantissa units, in base FLT_RADIX. */ +# undef LDBL_MANT_DIG +# define LDBL_MANT_DIG 64 +/* Number of decimal digits that is sufficient for representing a number. */ +# undef LDBL_DIG +# define LDBL_DIG 18 +/* x-1 where x is the smallest representable number > 1. */ +# undef LDBL_EPSILON +# define LDBL_EPSILON 1.084202172485504434007452800869941711426e-19L /* 2^-63 */ +/* Minimum e such that FLT_RADIX^(e-1) is a normalized number. */ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP (-16381) +/* Maximum e such that FLT_RADIX^(e-1) is a representable finite number. */ +# undef LDBL_MAX_EXP +# define LDBL_MAX_EXP 16384 +/* Minimum positive normalized number. */ +# undef LDBL_MIN +# define LDBL_MIN 3.362103143112093506262677817321752E-4932L /* = 0x1p-16382L */ +/* Maximum representable finite number. */ +# undef LDBL_MAX +/* LDBL_MAX is represented as { 0xFFFFFFFF, 0xFFFFFFFF, 32766 }. + But the largest literal that GCC allows us to write is + 0x0.fffffffffffff8p16384L = { 0xFFFFF800, 0xFFFFFFFF, 32766 }. + So, define it like this through a reference to an external variable + + const unsigned int LDBL_MAX[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 32766 }; + extern const long double LDBL_MAX; + + Unfortunately, this is not a constant expression. */ +union gl_long_double_union + { + struct { unsigned int lo; unsigned int hi; unsigned int exponent; } xd; + long double ld; + }; +extern const union gl_long_double_union gl_LDBL_MAX; +# define LDBL_MAX (gl_LDBL_MAX.ld) +/* Minimum e such that 10^e is in the range of normalized numbers. */ +# undef LDBL_MIN_10_EXP +# define LDBL_MIN_10_EXP (-4931) +/* Maximum e such that 10^e is in the range of representable finite numbers. */ +# undef LDBL_MAX_10_EXP +# define LDBL_MAX_10_EXP 4932 +#endif + +/* On AIX 7.1 with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_MAX are + wrong. + On Linux/PowerPC with gcc 4.4, the value of LDBL_MAX is wrong. */ +#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP DBL_MIN_EXP +# undef LDBL_MIN_10_EXP +# define LDBL_MIN_10_EXP DBL_MIN_10_EXP +# undef LDBL_MIN +# define LDBL_MIN 2.22507385850720138309023271733240406422e-308L /* DBL_MIN = 2^-1022 */ +#endif +#if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__ +# undef LDBL_MAX +/* LDBL_MAX is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xFFFFFFFF }. + It is not easy to define: + #define LDBL_MAX 1.79769313486231580793728971405302307166e308L + is too small, whereas + #define LDBL_MAX 1.79769313486231580793728971405302307167e308L + is too large. Apparently a bug in GCC decimal-to-binary conversion. + Also, I can't get values larger than + #define LDBL63 ((long double) (1ULL << 63)) + #define LDBL882 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) + #define LDBL945 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) + #define LDBL1008 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) + #define LDBL_MAX (LDBL1008 * 65535.0L + LDBL945 * (long double) 9223372036821221375ULL + LDBL882 * (long double) 4611686018427387904ULL) + which is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xF8000000 }. + So, define it like this through a reference to an external variable + + const double LDBL_MAX[2] = { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL }; + extern const long double LDBL_MAX; + + or through a pointer cast + + #define LDBL_MAX \ + (*(const long double *) (double[]) { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL }) + + Unfortunately, this is not a constant expression, and the latter expression + does not work well when GCC is optimizing.. */ +union gl_long_double_union + { + struct { double hi; double lo; } dd; + long double ld; + }; +extern const union gl_long_double_union gl_LDBL_MAX; +# define LDBL_MAX (gl_LDBL_MAX.ld) +#endif + +/* On IRIX 6.5, with cc, the value of LDBL_MANT_DIG is wrong. + On IRIX 6.5, with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_EPSILON + are wrong. */ +#if defined __sgi && (LDBL_MANT_DIG >= 106) +# undef LDBL_MANT_DIG +# define LDBL_MANT_DIG 106 +# if defined __GNUC__ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP DBL_MIN_EXP +# undef LDBL_MIN_10_EXP +# define LDBL_MIN_10_EXP DBL_MIN_10_EXP +# undef LDBL_MIN +# define LDBL_MIN 2.22507385850720138309023271733240406422e-308L /* DBL_MIN = 2^-1022 */ +# undef LDBL_EPSILON +# define LDBL_EPSILON 2.46519032881566189191165176650870696773e-32L /* 2^-105 */ +# endif +#endif + +#if @REPLACE_ITOLD@ +/* Pull in a function that fixes the 'int' to 'long double' conversion + of glibc 2.7. */ +extern +# ifdef __cplusplus +"C" +# endif +void _Qp_itoq (long double *, int); +static void (*_gl_float_fix_itold) (long double *, int) = _Qp_itoq; +#endif + +#endif /* _@GUARD_PREFIX@_FLOAT_H */ +#endif /* _@GUARD_PREFIX@_FLOAT_H */ diff --git a/grub-core/lib/gnulib/fnmatch.c b/grub-core/lib/gnulib/fnmatch.c new file mode 100644 index 0000000..dbcd290 --- /dev/null +++ b/grub-core/lib/gnulib/fnmatch.c @@ -0,0 +1,356 @@ +/* Copyright (C) 1991-1993, 1996-2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _LIBC +# include <config.h> +#endif + +/* Enable GNU extensions in fnmatch.h. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#include <fnmatch.h> + +#include <alloca.h> +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <stddef.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#define WIDE_CHAR_SUPPORT \ + (HAVE_WCTYPE_H && HAVE_BTOWC && HAVE_ISWCTYPE \ + && HAVE_WMEMCHR && (HAVE_WMEMCPY || HAVE_WMEMPCPY)) + +/* For platform which support the ISO C amendment 1 functionality we + support user defined character classes. */ +#if defined _LIBC || WIDE_CHAR_SUPPORT +# include <wctype.h> +# include <wchar.h> +#endif + +/* We need some of the locale data (the collation sequence information) + but there is no interface to get this information in general. Therefore + we support a correct implementation only in glibc. */ +#ifdef _LIBC +# include "../locale/localeinfo.h" +# include "../locale/elem-hash.h" +# include "../locale/coll-lookup.h" +# include <shlib-compat.h> + +# define CONCAT(a,b) __CONCAT(a,b) +# define mbsrtowcs __mbsrtowcs +# define fnmatch __fnmatch +extern int fnmatch (const char *pattern, const char *string, int flags); +#endif + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +#include "flexmember.h" + +#ifndef FALLTHROUGH +# if __GNUC__ < 7 +# define FALLTHROUGH ((void) 0) +# else +# define FALLTHROUGH __attribute__ ((__fallthrough__)) +# endif +#endif + +/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */ +#define NO_LEADING_PERIOD(flags) \ + ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD)) + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself, and have not detected a bug + in the library. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand 'configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU + + +# if ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK)) +# define isblank(c) ((c) == ' ' || (c) == '\t') +# endif + +# define STREQ(s1, s2) (strcmp (s1, s2) == 0) + +# if defined _LIBC || WIDE_CHAR_SUPPORT +/* The GNU C library provides support for user-defined character classes + and the functions from ISO C amendment 1. */ +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else +/* This shouldn't happen but some implementation might still have this + problem. Use a reasonable default value. */ +# define CHAR_CLASS_MAX_LENGTH 256 +# endif + +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif + +# ifdef _LIBC +# define ISWCTYPE(WC, WT) __iswctype (WC, WT) +# else +# define ISWCTYPE(WC, WT) iswctype (WC, WT) +# endif + +# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC +/* In this case we are implementing the multibyte character handling. */ +# define HANDLE_MULTIBYTE 1 +# endif + +# else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, 'xdigit'. */ + +# define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) +# endif + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +/* Global variable. */ +static int posixly_correct; + +# ifndef internal_function +/* Inside GNU libc we mark some function in a special way. In other + environments simply ignore the marking. */ +# define internal_function +# endif + +/* Note that this evaluates C many times. */ +# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) +# define CHAR char +# define UCHAR unsigned char +# define INT int +# define FCT internal_fnmatch +# define EXT ext_match +# define END end_pattern +# define L_(CS) CS +# ifdef _LIBC +# define BTOWC(C) __btowc (C) +# else +# define BTOWC(C) btowc (C) +# endif +# define STRLEN(S) strlen (S) +# define STRCAT(D, S) strcat (D, S) +# ifdef _LIBC +# define MEMPCPY(D, S, N) __mempcpy (D, S, N) +# else +# if HAVE_MEMPCPY +# define MEMPCPY(D, S, N) mempcpy (D, S, N) +# else +# define MEMPCPY(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) +# endif +# endif +# define MEMCHR(S, C, N) memchr (S, C, N) +# include "fnmatch_loop.c" + + +# if HANDLE_MULTIBYTE +# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c)) +# define CHAR wchar_t +# define UCHAR wint_t +# define INT wint_t +# define FCT internal_fnwmatch +# define EXT ext_wmatch +# define END end_wpattern +# define L_(CS) L##CS +# define BTOWC(C) (C) +# ifdef _LIBC +# define STRLEN(S) __wcslen (S) +# define STRCAT(D, S) __wcscat (D, S) +# define MEMPCPY(D, S, N) __wmempcpy (D, S, N) +# else +# define STRLEN(S) wcslen (S) +# define STRCAT(D, S) wcscat (D, S) +# if HAVE_WMEMPCPY +# define MEMPCPY(D, S, N) wmempcpy (D, S, N) +# else +# define MEMPCPY(D, S, N) (wmemcpy (D, S, N) + (N)) +# endif +# endif +# define MEMCHR(S, C, N) wmemchr (S, C, N) +# define WIDE_CHAR_VERSION 1 + +# undef IS_CHAR_CLASS +/* We have to convert the wide character string in a multibyte string. But + we know that the character class names consist of alphanumeric characters + from the portable character set, and since the wide character encoding + for a member of the portable character set is the same code point as + its single-byte encoding, we can use a simplified method to convert the + string to a multibyte character string. */ +static wctype_t +is_char_class (const wchar_t *wcs) +{ + char s[CHAR_CLASS_MAX_LENGTH + 1]; + char *cp = s; + + do + { + /* Test for a printable character from the portable character set. */ +# ifdef _LIBC + if (*wcs < 0x20 || *wcs > 0x7e + || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60) + return (wctype_t) 0; +# else + switch (*wcs) + { + case L' ': case L'!': case L'"': case L'#': case L'%': + case L'&': case L'\'': case L'(': case L')': case L'*': + case L'+': case L',': case L'-': case L'.': case L'/': + case L'0': case L'1': case L'2': case L'3': case L'4': + case L'5': case L'6': case L'7': case L'8': case L'9': + case L':': case L';': case L'<': case L'=': case L'>': + case L'?': + case L'A': case L'B': case L'C': case L'D': case L'E': + case L'F': case L'G': case L'H': case L'I': case L'J': + case L'K': case L'L': case L'M': case L'N': case L'O': + case L'P': case L'Q': case L'R': case L'S': case L'T': + case L'U': case L'V': case L'W': case L'X': case L'Y': + case L'Z': + case L'[': case L'\\': case L']': case L'^': case L'_': + case L'a': case L'b': case L'c': case L'd': case L'e': + case L'f': case L'g': case L'h': case L'i': case L'j': + case L'k': case L'l': case L'm': case L'n': case L'o': + case L'p': case L'q': case L'r': case L's': case L't': + case L'u': case L'v': case L'w': case L'x': case L'y': + case L'z': case L'{': case L'|': case L'}': case L'~': + break; + default: + return (wctype_t) 0; + } +# endif + + /* Avoid overrunning the buffer. */ + if (cp == s + CHAR_CLASS_MAX_LENGTH) + return (wctype_t) 0; + + *cp++ = (char) *wcs++; + } + while (*wcs != L'\0'); + + *cp = '\0'; + +# ifdef _LIBC + return __wctype (s); +# else + return wctype (s); +# endif +} +# define IS_CHAR_CLASS(string) is_char_class (string) + +# include "fnmatch_loop.c" +# endif + + +int +fnmatch (const char *pattern, const char *string, int flags) +{ +# if HANDLE_MULTIBYTE +# define ALLOCA_LIMIT 2000 + if (__builtin_expect (MB_CUR_MAX, 1) != 1) + { + mbstate_t ps; + size_t patsize; + size_t strsize; + size_t totsize; + wchar_t *wpattern; + wchar_t *wstring; + int res; + + /* Calculate the size needed to convert the strings to + wide characters. */ + memset (&ps, '\0', sizeof (ps)); + patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1; + if (__builtin_expect (patsize != 0, 1)) + { + assert (mbsinit (&ps)); + strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1; + if (__builtin_expect (strsize != 0, 1)) + { + assert (mbsinit (&ps)); + totsize = patsize + strsize; + if (__builtin_expect (! (patsize <= totsize + && totsize <= SIZE_MAX / sizeof (wchar_t)), + 0)) + { + errno = ENOMEM; + return -1; + } + + /* Allocate room for the wide characters. */ + if (__builtin_expect (totsize < ALLOCA_LIMIT, 1)) + wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t)); + else + { + wpattern = malloc (totsize * sizeof (wchar_t)); + if (__builtin_expect (! wpattern, 0)) + { + errno = ENOMEM; + return -1; + } + } + wstring = wpattern + patsize; + + /* Convert the strings into wide characters. */ + mbsrtowcs (wpattern, &pattern, patsize, &ps); + assert (mbsinit (&ps)); + mbsrtowcs (wstring, &string, strsize, &ps); + + res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1, + flags & FNM_PERIOD, flags); + + if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0)) + free (wpattern); + return res; + } + } + } + +# endif /* HANDLE_MULTIBYTE */ + + return internal_fnmatch (pattern, string, string + strlen (string), + flags & FNM_PERIOD, flags); +} + +# ifdef _LIBC +# undef fnmatch +versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3); +# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3) +strong_alias (__fnmatch, __fnmatch_old) +compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0); +# endif +libc_hidden_ver (__fnmatch, fnmatch) +# endif + +#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/grub-core/lib/gnulib/fnmatch.in.h b/grub-core/lib/gnulib/fnmatch.in.h new file mode 100644 index 0000000..2ead782 --- /dev/null +++ b/grub-core/lib/gnulib/fnmatch.in.h @@ -0,0 +1,110 @@ +/* Substitute for and wrapper around <fnmatch.h>. + Copyright (C) 1991-1993, 1996-1999, 2001-2003, 2005, 2007, 2009-2019 Free + Software Foundation, Inc. + + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _@GUARD_PREFIX@_FNMATCH_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_FNMATCH_H@ && !@REPLACE_FNMATCH@ +# @INCLUDE_NEXT@ @NEXT_FNMATCH_H@ +#endif + +#ifndef _@GUARD_PREFIX@_FNMATCH_H +#define _@GUARD_PREFIX@_FNMATCH_H + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +#if !@HAVE_FNMATCH_H@ || @REPLACE_FNMATCH@ + +/* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in <unistd.h>. */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to 'fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match '/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading '.' is matched only explicitly. */ + +#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE +# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +# define FNM_LEADING_DIR (1 << 3) /* Ignore '/...' after a match. */ +# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +# define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */ +#endif + +/* Value returned by 'fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* This value is returned if the implementation does not support + 'fnmatch'. Since this is not the case here it will never be + returned but the conformance test suites still require the symbol + to be defined. */ +#ifdef _XOPEN_SOURCE +# define FNM_NOSYS (-1) +#endif + +#endif + + +#if @GNULIB_FNMATCH@ +/* Match NAME against the file name pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +# if @REPLACE_FNMATCH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fnmatch rpl_fnmatch +# endif +_GL_FUNCDECL_RPL (fnmatch, int, + (const char *pattern, const char *name, int flags) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (fnmatch, int, + (const char *pattern, const char *name, int flags)); +# else +# if !@HAVE_FNMATCH@ +_GL_FUNCDECL_SYS (fnmatch, int, + (const char *pattern, const char *name, int flags) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (fnmatch, int, + (const char *pattern, const char *name, int flags)); +# endif +# if !GNULIB_FNMATCH_GNU +_GL_CXXALIASWARN (fnmatch); +# endif +#elif defined GNULIB_POSIXCHECK +# undef fnmatch +# if HAVE_RAW_DECL_FNMATCH +_GL_WARN_ON_USE (fnmatch, + "fnmatch does not portably work - " + "use gnulib module fnmatch for portability or gnulib module fnmatch-gnu for a glibc compatible implementation"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_FNMATCH_H */ +#endif /* _@GUARD_PREFIX@_FNMATCH_H */ diff --git a/grub-core/lib/gnulib/fnmatch_loop.c b/grub-core/lib/gnulib/fnmatch_loop.c new file mode 100644 index 0000000..82a7cee --- /dev/null +++ b/grub-core/lib/gnulib/fnmatch_loop.c @@ -0,0 +1,1217 @@ +/* Copyright (C) 1991-1993, 1996-2006, 2009-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Match STRING against the file name pattern PATTERN, returning zero if + it matches, nonzero if not. */ +static int EXT (INT opt, const CHAR *pattern, const CHAR *string, + const CHAR *string_end, bool no_leading_period, int flags) + internal_function; +static const CHAR *END (const CHAR *patternp) internal_function; + +static int +internal_function +FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, + bool no_leading_period, int flags) +{ + register const CHAR *p = pattern, *n = string; + register UCHAR c; +#ifdef _LIBC +# if WIDE_CHAR_VERSION + const char *collseq = (const char *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); +# else + const UCHAR *collseq = (const UCHAR *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); +# endif +#endif + + while ((c = *p++) != L_('\0')) + { + bool new_no_leading_period = false; + c = FOLD (c); + + switch (c) + { + case L_('?'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, + flags); + if (res != -1) + return res; + } + + if (n == string_end) + return FNM_NOMATCH; + else if (*n == L_('/') && (flags & FNM_FILE_NAME)) + return FNM_NOMATCH; + else if (*n == L_('.') && no_leading_period) + return FNM_NOMATCH; + break; + + case L_('\\'): + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + if (c == L_('\0')) + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD (c); + } + if (n == string_end || FOLD ((UCHAR) *n) != c) + return FNM_NOMATCH; + break; + + case L_('*'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, + flags); + if (res != -1) + return res; + } + + if (n != string_end && *n == L_('.') && no_leading_period) + return FNM_NOMATCH; + + for (c = *p++; c == L_('?') || c == L_('*'); c = *p++) + { + if (*p == L_('(') && (flags & FNM_EXTMATCH) != 0) + { + const CHAR *endp = END (p); + if (endp != p) + { + /* This is a pattern. Skip over it. */ + p = endp; + continue; + } + } + + if (c == L_('?')) + { + /* A ? needs to match one character. */ + if (n == string_end) + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else if (*n == L_('/') + && __builtin_expect (flags & FNM_FILE_NAME, 0)) + /* A slash does not match a wildcard under + FNM_FILE_NAME. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == L_('\0')) + /* The wildcard(s) is/are the last element of the pattern. + If the name is a file name and contains another slash + this means it cannot match, unless the FNM_LEADING_DIR + flag is set. */ + { + int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH; + + if (flags & FNM_FILE_NAME) + { + if (flags & FNM_LEADING_DIR) + result = 0; + else + { + if (MEMCHR (n, L_('/'), string_end - n) == NULL) + result = 0; + } + } + + return result; + } + else + { + const CHAR *endp; + + endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L_('/') : L_('\0'), + string_end - n); + if (endp == NULL) + endp = string_end; + + if (c == L_('[') + || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0 + && (c == L_('@') || c == L_('+') || c == L_('!')) + && *p == L_('('))) + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + bool no_leading_period2 = no_leading_period; + + for (--p; n < endp; ++n, no_leading_period2 = false) + if (FCT (p, n, string_end, no_leading_period2, flags2) + == 0) + return 0; + } + else if (c == L_('/') && (flags & FNM_FILE_NAME)) + { + while (n < string_end && *n != L_('/')) + ++n; + if (n < string_end && *n == L_('/') + && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags) + == 0)) + return 0; + } + else + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + int no_leading_period2 = no_leading_period; + + if (c == L_('\\') && !(flags & FNM_NOESCAPE)) + c = *p; + c = FOLD (c); + for (--p; n < endp; ++n, no_leading_period2 = false) + if (FOLD ((UCHAR) *n) == c + && (FCT (p, n, string_end, no_leading_period2, flags2) + == 0)) + return 0; + } + } + + /* If we come here no match is possible with the wildcard. */ + return FNM_NOMATCH; + + case L_('['): + { + /* Nonzero if the sense of the character class is inverted. */ + const CHAR *p_init = p; + const CHAR *n_init = n; + register bool not; + CHAR cold; + UCHAR fn; + + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + if (n == string_end) + return FNM_NOMATCH; + + if (*n == L_('.') && no_leading_period) + return FNM_NOMATCH; + + if (*n == L_('/') && (flags & FNM_FILE_NAME)) + /* '/' cannot be matched. */ + return FNM_NOMATCH; + + not = (*p == L_('!') || (posixly_correct < 0 && *p == L_('^'))); + if (not) + ++p; + + fn = FOLD ((UCHAR) *n); + + c = *p++; + for (;;) + { + bool is_range = false; + + if (!(flags & FNM_NOESCAPE) && c == L_('\\')) + { + if (*p == L_('\0')) + return FNM_NOMATCH; + c = FOLD ((UCHAR) *p); + ++p; + + goto normal_bracket; + } + else if (c == L_('[') && *p == L_(':')) + { + /* Leave room for the null. */ + CHAR str[CHAR_CLASS_MAX_LENGTH + 1]; + size_t c1 = 0; +#if defined _LIBC || WIDE_CHAR_SUPPORT + wctype_t wt; +#endif + const CHAR *startp = p; + + for (;;) + { + if (c1 == CHAR_CLASS_MAX_LENGTH) + /* The name is too long and therefore the pattern + is ill-formed. */ + return FNM_NOMATCH; + + c = *++p; + if (c == L_(':') && p[1] == L_(']')) + { + p += 2; + break; + } + if (c < L_('a') || c >= L_('z')) + { + /* This cannot possibly be a character class name. + Match it as a normal range. */ + p = startp; + c = L_('['); + goto normal_bracket; + } + str[c1++] = c; + } + str[c1] = L_('\0'); + +#if defined _LIBC || WIDE_CHAR_SUPPORT + wt = IS_CHAR_CLASS (str); + if (wt == 0) + /* Invalid character class name. */ + return FNM_NOMATCH; + +# if defined _LIBC && ! WIDE_CHAR_VERSION + /* The following code is glibc specific but does + there a good job in speeding up the code since + we can avoid the btowc() call. */ + if (_ISCTYPE ((UCHAR) *n, wt)) + goto matched; +# else + if (ISWCTYPE (BTOWC ((UCHAR) *n), wt)) + goto matched; +# endif +#else + if ((STREQ (str, L_("alnum")) && isalnum ((UCHAR) *n)) + || (STREQ (str, L_("alpha")) && isalpha ((UCHAR) *n)) + || (STREQ (str, L_("blank")) && isblank ((UCHAR) *n)) + || (STREQ (str, L_("cntrl")) && iscntrl ((UCHAR) *n)) + || (STREQ (str, L_("digit")) && isdigit ((UCHAR) *n)) + || (STREQ (str, L_("graph")) && isgraph ((UCHAR) *n)) + || (STREQ (str, L_("lower")) && islower ((UCHAR) *n)) + || (STREQ (str, L_("print")) && isprint ((UCHAR) *n)) + || (STREQ (str, L_("punct")) && ispunct ((UCHAR) *n)) + || (STREQ (str, L_("space")) && isspace ((UCHAR) *n)) + || (STREQ (str, L_("upper")) && isupper ((UCHAR) *n)) + || (STREQ (str, L_("xdigit")) && isxdigit ((UCHAR) *n))) + goto matched; +#endif + c = *p++; + } +#ifdef _LIBC + else if (c == L_('[') && *p == L_('=')) + { + UCHAR str[1]; + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const CHAR *startp = p; + + c = *++p; + if (c == L_('\0')) + { + p = startp; + c = L_('['); + goto normal_bracket; + } + str[0] = c; + + c = *++p; + if (c != L_('=') || p[1] != L_(']')) + { + p = startp; + c = L_('['); + goto normal_bracket; + } + p += 2; + + if (nrules == 0) + { + if ((UCHAR) *n == str[0]) + goto matched; + } + else + { + const int32_t *table; +# if WIDE_CHAR_VERSION + const int32_t *weights; + const int32_t *extra; +# else + const unsigned char *weights; + const unsigned char *extra; +# endif + const int32_t *indirect; + int32_t idx; + const UCHAR *cp = (const UCHAR *) str; + + /* This #include defines a local function! */ +# if WIDE_CHAR_VERSION +# include <locale/weightwc.h> +# else +# include <locale/weight.h> +# endif + +# if WIDE_CHAR_VERSION + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); + weights = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); + extra = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); +# else + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); +# endif + + idx = findidx (&cp); + if (idx != 0) + { + /* We found a table entry. Now see whether the + character we are currently at has the same + equivalence class value. */ + int len = weights[idx & 0xffffff]; + int32_t idx2; + const UCHAR *np = (const UCHAR *) n; + + idx2 = findidx (&np); + if (idx2 != 0 + && (idx >> 24) == (idx2 >> 24) + && len == weights[idx2 & 0xffffff]) + { + int cnt = 0; + + idx &= 0xffffff; + idx2 &= 0xffffff; + + while (cnt < len + && (weights[idx + 1 + cnt] + == weights[idx2 + 1 + cnt])) + ++cnt; + + if (cnt == len) + goto matched; + } + } + } + + c = *p++; + } +#endif + else if (c == L_('\0')) + { + /* [ unterminated, treat as normal character. */ + p = p_init; + n = n_init; + c = L_('['); + goto normal_match; + } + else + { +#ifdef _LIBC + bool is_seqval = false; + + if (c == L_('[') && *p == L_('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const CHAR *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L_('.') && p[1] == L_(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = *p == L_('-') && p[1] != L_('\0'); + + if (nrules == 0) + { + /* There are no names defined in the collation + data. Therefore we only accept the trivial + names consisting of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + if (!is_range && *n == startp[1]) + goto matched; + + cold = startp[1]; + c = *p++; + } + else + { + int32_t table_size; + const int32_t *symb_table; +# ifdef WIDE_CHAR_VERSION + char str[c1]; + size_t strcnt; +# else +# define str (startp + 1) +# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + +# ifdef WIDE_CHAR_VERSION + /* We have to convert the name to a single-byte + string. This is possible since the names + consist of ASCII characters and the internal + representation is UCS4. */ + for (strcnt = 0; strcnt < c1; ++strcnt) + str[strcnt] = startp[1 + strcnt]; +# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing table. */ + hash = elem_hash (str, c1); + + idx = 0; + elem = hash % table_size; + if (symb_table[2 * elem] != 0) + { + second = hash % (table_size - 2) + 1; + + do + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && (c1 + == extra[symb_table[2 * elem + 1]]) + && memcmp (str, + &extra[symb_table[2 * elem + + 1] + + 1], c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + while (symb_table[2 * elem] != 0); + } + + if (symb_table[2 * elem] != 0) + { + /* Compare the byte sequence but only if + this is not part of a range. */ +# ifdef WIDE_CHAR_VERSION + int32_t *wextra; + + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + + wextra = (int32_t *) &extra[idx + 4]; +# endif + + if (! is_range) + { +# ifdef WIDE_CHAR_VERSION + for (c1 = 0; + (int32_t) c1 < wextra[idx]; + ++c1) + if (n[c1] != wextra[1 + c1]) + break; + + if ((int32_t) c1 == wextra[idx]) + goto matched; +# else + for (c1 = 0; c1 < extra[idx]; ++c1) + if (n[c1] != extra[1 + c1]) + break; + + if (c1 == extra[idx]) + goto matched; +# endif + } + + /* Get the collation sequence value. */ + is_seqval = true; +# ifdef WIDE_CHAR_VERSION + cold = wextra[1 + wextra[idx]]; +# else + /* Adjust for the alignment. */ + idx += 1 + extra[idx]; + idx = (idx + 3) & ~4; + cold = *((int32_t *) &extra[idx]); +# endif + + c = *p++; + } + else if (c1 == 1) + { + /* No valid character. Match it as a + single byte. */ + if (!is_range && *n == str[0]) + goto matched; + + cold = str[0]; + c = *p++; + } + else + return FNM_NOMATCH; + } + } + else +# undef str +#endif + { + c = FOLD (c); + normal_bracket: + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = (*p == L_('-') && p[1] != L_('\0') + && p[1] != L_(']')); + + if (!is_range && c == fn) + goto matched; + +#if _LIBC + /* This is needed if we goto normal_bracket; from + outside of is_seqval's scope. */ + is_seqval = false; +#endif + + cold = c; + c = *p++; + } + + if (c == L_('-') && *p != L_(']')) + { +#if _LIBC + /* We have to find the collation sequence + value for C. Collation sequence is nothing + we can regularly access. The sequence + value is defined by the order in which the + definitions of the collation values for the + various characters appear in the source + file. A strange concept, nowhere + documented. */ + uint32_t fcollseq; + uint32_t lcollseq; + UCHAR cend = *p++; + +# ifdef WIDE_CHAR_VERSION + /* Search in the 'names' array for the characters. */ + fcollseq = __collseq_table_lookup (collseq, fn); + if (fcollseq == ~((uint32_t) 0)) + /* XXX We don't know anything about the character + we are supposed to match. This means we are + failing. */ + goto range_not_matched; + + if (is_seqval) + lcollseq = cold; + else + lcollseq = __collseq_table_lookup (collseq, cold); +# else + fcollseq = collseq[fn]; + lcollseq = is_seqval ? cold : collseq[(UCHAR) cold]; +# endif + + is_seqval = false; + if (cend == L_('[') && *p == L_('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_NRULES); + const CHAR *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L_('.') && p[1] == L_(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + if (nrules == 0) + { + /* There are no names defined in the + collation data. Therefore we only + accept the trivial names consisting + of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + cend = startp[1]; + } + else + { + int32_t table_size; + const int32_t *symb_table; +# ifdef WIDE_CHAR_VERSION + char str[c1]; + size_t strcnt; +# else +# define str (startp + 1) +# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + +# ifdef WIDE_CHAR_VERSION + /* We have to convert the name to a single-byte + string. This is possible since the names + consist of ASCII characters and the internal + representation is UCS4. */ + for (strcnt = 0; strcnt < c1; ++strcnt) + str[strcnt] = startp[1 + strcnt]; +# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing + table. */ + hash = elem_hash (str, c1); + + idx = 0; + elem = hash % table_size; + if (symb_table[2 * elem] != 0) + { + second = hash % (table_size - 2) + 1; + + do + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && (c1 + == extra[symb_table[2 * elem + 1]]) + && memcmp (str, + &extra[symb_table[2 * elem + 1] + + 1], c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + while (symb_table[2 * elem] != 0); + } + + if (symb_table[2 * elem] != 0) + { + /* Compare the byte sequence but only if + this is not part of a range. */ +# ifdef WIDE_CHAR_VERSION + int32_t *wextra; + + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~4; + + wextra = (int32_t *) &extra[idx + 4]; +# endif + /* Get the collation sequence value. */ + is_seqval = true; +# ifdef WIDE_CHAR_VERSION + cend = wextra[1 + wextra[idx]]; +# else + /* Adjust for the alignment. */ + idx += 1 + extra[idx]; + idx = (idx + 3) & ~4; + cend = *((int32_t *) &extra[idx]); +# endif + } + else if (symb_table[2 * elem] != 0 && c1 == 1) + { + cend = str[0]; + c = *p++; + } + else + return FNM_NOMATCH; + } +# undef str + } + else + { + if (!(flags & FNM_NOESCAPE) && cend == L_('\\')) + cend = *p++; + if (cend == L_('\0')) + return FNM_NOMATCH; + cend = FOLD (cend); + } + + /* XXX It is not entirely clear to me how to handle + characters which are not mentioned in the + collation specification. */ + if ( +# ifdef WIDE_CHAR_VERSION + lcollseq == 0xffffffff || +# endif + lcollseq <= fcollseq) + { + /* We have to look at the upper bound. */ + uint32_t hcollseq; + + if (is_seqval) + hcollseq = cend; + else + { +# ifdef WIDE_CHAR_VERSION + hcollseq = + __collseq_table_lookup (collseq, cend); + if (hcollseq == ~((uint32_t) 0)) + { + /* Hum, no information about the upper + bound. The matching succeeds if the + lower bound is matched exactly. */ + if (lcollseq != fcollseq) + goto range_not_matched; + + goto matched; + } +# else + hcollseq = collseq[cend]; +# endif + } + + if (lcollseq <= hcollseq && fcollseq <= hcollseq) + goto matched; + } +# ifdef WIDE_CHAR_VERSION + range_not_matched: +# endif +#else + /* We use a boring value comparison of the character + values. This is better than comparing using + 'strcoll' since the latter would have surprising + and sometimes fatal consequences. */ + UCHAR cend = *p++; + + if (!(flags & FNM_NOESCAPE) && cend == L_('\\')) + cend = *p++; + if (cend == L_('\0')) + return FNM_NOMATCH; + + /* It is a range. */ + if (cold <= fn && fn <= cend) + goto matched; +#endif + + c = *p++; + } + } + + if (c == L_(']')) + break; + } + + if (!not) + return FNM_NOMATCH; + break; + + matched: + /* Skip the rest of the [...] that already matched. */ + do + { + ignore_next: + c = *p++; + + if (c == L_('\0')) + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + if (!(flags & FNM_NOESCAPE) && c == L_('\\')) + { + if (*p == L_('\0')) + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + else if (c == L_('[') && *p == L_(':')) + { + int c1 = 0; + const CHAR *startp = p; + + while (1) + { + c = *++p; + if (++c1 == CHAR_CLASS_MAX_LENGTH) + return FNM_NOMATCH; + + if (*p == L_(':') && p[1] == L_(']')) + break; + + if (c < L_('a') || c >= L_('z')) + { + p = startp; + goto ignore_next; + } + } + p += 2; + c = *p++; + } + else if (c == L_('[') && *p == L_('=')) + { + c = *++p; + if (c == L_('\0')) + return FNM_NOMATCH; + c = *++p; + if (c != L_('=') || p[1] != L_(']')) + return FNM_NOMATCH; + p += 2; + c = *p++; + } + else if (c == L_('[') && *p == L_('.')) + { + ++p; + while (1) + { + c = *++p; + if (c == '\0') + return FNM_NOMATCH; + + if (*p == L_('.') && p[1] == L_(']')) + break; + } + p += 2; + c = *p++; + } + } + while (c != L_(']')); + if (not) + return FNM_NOMATCH; + } + break; + + case L_('+'): + case L_('@'): + case L_('!'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, flags); + if (res != -1) + return res; + } + goto normal_match; + + case L_('/'): + if (NO_LEADING_PERIOD (flags)) + { + if (n == string_end || c != (UCHAR) *n) + return FNM_NOMATCH; + + new_no_leading_period = true; + break; + } + FALLTHROUGH; + default: + normal_match: + if (n == string_end || c != FOLD ((UCHAR) *n)) + return FNM_NOMATCH; + } + + no_leading_period = new_no_leading_period; + ++n; + } + + if (n == string_end) + return 0; + + if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L_('/')) + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; +} + + +static const CHAR * +internal_function +END (const CHAR *pattern) +{ + const CHAR *p = pattern; + + while (1) + if (*++p == L_('\0')) + /* This is an invalid pattern. */ + return pattern; + else if (*p == L_('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L_(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L_(']')) + if (*p++ == L_('\0')) + /* This is no valid pattern. */ + return pattern; + } + else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@') + || *p == L_('!')) && p[1] == L_('(')) + p = END (p + 1); + else if (*p == L_(')')) + break; + + return p + 1; +} + + +static int +internal_function +EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, + bool no_leading_period, int flags) +{ + const CHAR *startp; + size_t level; + struct patternlist + { + struct patternlist *next; + CHAR str[FLEXIBLE_ARRAY_MEMBER]; + } *list = NULL; + struct patternlist **lastp = &list; + size_t pattern_len = STRLEN (pattern); + const CHAR *p; + const CHAR *rs; + enum { ALLOCA_LIMIT = 8000 }; + + /* Parse the pattern. Store the individual parts in the list. */ + level = 0; + for (startp = p = pattern + 1; ; ++p) + if (*p == L_('\0')) + /* This is an invalid pattern. */ + return -1; + else if (*p == L_('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L_(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L_(']')) + if (*p++ == L_('\0')) + /* This is no valid pattern. */ + return -1; + } + else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@') + || *p == L_('!')) && p[1] == L_('(')) + /* Remember the nesting level. */ + ++level; + else if (*p == L_(')')) + { + if (level-- == 0) + { + /* This means we found the end of the pattern. */ +#define NEW_PATTERN \ + struct patternlist *newp; \ + size_t plen; \ + size_t plensize; \ + size_t newpsize; \ + \ + plen = (opt == L_('?') || opt == L_('@') \ + ? pattern_len \ + : p - startp + 1UL); \ + plensize = plen * sizeof (CHAR); \ + newpsize = FLEXSIZEOF (struct patternlist, str, plensize); \ + if ((size_t) -1 / sizeof (CHAR) < plen \ + || newpsize < offsetof (struct patternlist, str) \ + || ALLOCA_LIMIT <= newpsize) \ + return -1; \ + newp = (struct patternlist *) alloca (newpsize); \ + *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0'); \ + newp->next = NULL; \ + *lastp = newp; \ + lastp = &newp->next + NEW_PATTERN; + break; + } + } + else if (*p == L_('|')) + { + if (level == 0) + { + NEW_PATTERN; + startp = p + 1; + } + } + assert (list != NULL); + assert (p[-1] == L_(')')); +#undef NEW_PATTERN + + switch (opt) + { + case L_('*'): + if (FCT (p, string, string_end, no_leading_period, flags) == 0) + return 0; + FALLTHROUGH; + case L_('+'): + do + { + for (rs = string; rs <= string_end; ++rs) + /* First match the prefix with the current pattern with the + current pattern. */ + if (FCT (list->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0 + /* This was successful. Now match the rest with the rest + of the pattern. */ + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags), + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD) == 0 + /* This didn't work. Try the whole pattern. */ + || (rs != string + && FCT (pattern - 1, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags), + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD) == 0))) + /* It worked. Signal success. */ + return 0; + } + while ((list = list->next) != NULL); + + /* None of the patterns lead to a match. */ + return FNM_NOMATCH; + + case L_('?'): + if (FCT (p, string, string_end, no_leading_period, flags) == 0) + return 0; + FALLTHROUGH; + case L_('@'): + do + /* I cannot believe it but 'strcat' is actually acceptable + here. Match the entire string with the prefix from the + pattern list and the rest of the pattern following the + pattern list. */ + if (FCT (STRCAT (list->str, p), string, string_end, + no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) + /* It worked. Signal success. */ + return 0; + while ((list = list->next) != NULL); + + /* None of the patterns lead to a match. */ + return FNM_NOMATCH; + + case L_('!'): + for (rs = string; rs <= string_end; ++rs) + { + struct patternlist *runp; + + for (runp = list; runp != NULL; runp = runp->next) + if (FCT (runp->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) + break; + + /* If none of the patterns matched see whether the rest does. */ + if (runp == NULL + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags), + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) + == 0)) + /* This is successful. */ + return 0; + } + + /* None of the patterns together with the rest of the pattern + lead to a match. */ + return FNM_NOMATCH; + + default: + assert (! "Invalid extended matching operator"); + break; + } + + return -1; +} + + +#undef FOLD +#undef CHAR +#undef UCHAR +#undef INT +#undef FCT +#undef EXT +#undef END +#undef MEMPCPY +#undef MEMCHR +#undef STRLEN +#undef STRCAT +#undef L_ +#undef BTOWC diff --git a/grub-core/lib/gnulib/fstat.c b/grub-core/lib/gnulib/fstat.c new file mode 100644 index 0000000..4f0e618 --- /dev/null +++ b/grub-core/lib/gnulib/fstat.c @@ -0,0 +1,90 @@ +/* fstat() replacement. + Copyright (C) 2011-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* If the user's config.h happens to include <sys/stat.h>, let it include only + the system's <sys/stat.h> here, so that orig_fstat doesn't recurse to + rpl_fstat. */ +#define __need_system_sys_stat_h +#include <config.h> + +/* Get the original definition of fstat. It might be defined as a macro. */ +#include <sys/types.h> +#include <sys/stat.h> +#undef __need_system_sys_stat_h + +#if defined _WIN32 && ! defined __CYGWIN__ +# define WINDOWS_NATIVE +#endif + +#if !defined WINDOWS_NATIVE + +static int +orig_fstat (int fd, struct stat *buf) +{ + return fstat (fd, buf); +} + +#endif + +/* Specification. */ +/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include <sys/stat.h> + above. */ +#include "sys/stat.h" + +#include "stat-time.h" + +#include <errno.h> +#include <unistd.h> +#ifdef WINDOWS_NATIVE +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include <io.h> +# endif +# include "stat-w32.h" +#endif + +int +rpl_fstat (int fd, struct stat *buf) +{ +#if REPLACE_FCHDIR && REPLACE_OPEN_DIRECTORY + /* Handle the case when rpl_open() used a dummy file descriptor to work + around an open() that can't normally visit directories. */ + const char *name = _gl_directory_name (fd); + if (name != NULL) + return stat (name, buf); +#endif + +#ifdef WINDOWS_NATIVE + /* Fill the fields ourselves, because the original fstat function returns + values for st_atime, st_mtime, st_ctime that depend on the current time + zone. See + <https://lists.gnu.org/r/bug-gnulib/2017-04/msg00134.html> */ + HANDLE h = (HANDLE) _get_osfhandle (fd); + + if (h == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return -1; + } + return _gl_fstat_by_handle (h, NULL, buf); +#else + return stat_time_normalize (orig_fstat (fd, buf), buf); +#endif +} diff --git a/grub-core/lib/gnulib/getcwd-lgpl.c b/grub-core/lib/gnulib/getcwd-lgpl.c new file mode 100644 index 0000000..b224cfc --- /dev/null +++ b/grub-core/lib/gnulib/getcwd-lgpl.c @@ -0,0 +1,126 @@ +/* Copyright (C) 2011-2019 Free Software Foundation, Inc. + This file is part of gnulib. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification */ +#include <unistd.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#if GNULIB_GETCWD +/* Favor GPL getcwd.c if both getcwd and getcwd-lgpl modules are in use. */ +typedef int dummy; +#else + +/* Get the name of the current working directory, and put it in SIZE + bytes of BUF. Returns NULL if the directory couldn't be determined + (perhaps because the absolute name was longer than PATH_MAX, or + because of missing read/search permissions on parent directories) + or SIZE was too small. If successful, returns BUF. If BUF is + NULL, an array is allocated with 'malloc'; the array is SIZE bytes + long, unless SIZE == 0, in which case it is as big as + necessary. */ + +# undef getcwd +char * +rpl_getcwd (char *buf, size_t size) +{ + char *ptr; + char *result; + + /* Handle single size operations. */ + if (buf) + { + if (!size) + { + errno = EINVAL; + return NULL; + } + return getcwd (buf, size); + } + + if (size) + { + buf = malloc (size); + if (!buf) + { + errno = ENOMEM; + return NULL; + } + result = getcwd (buf, size); + if (!result) + { + int saved_errno = errno; + free (buf); + errno = saved_errno; + } + return result; + } + + /* Flexible sizing requested. Avoid over-allocation for the common + case of a name that fits within a 4k page, minus some space for + local variables, to be sure we don't skip over a guard page. */ + { + char tmp[4032]; + size = sizeof tmp; + ptr = getcwd (tmp, size); + if (ptr) + { + result = strdup (ptr); + if (!result) + errno = ENOMEM; + return result; + } + if (errno != ERANGE) + return NULL; + } + + /* My what a large directory name we have. */ + do + { + size <<= 1; + ptr = realloc (buf, size); + if (ptr == NULL) + { + free (buf); + errno = ENOMEM; + return NULL; + } + buf = ptr; + result = getcwd (buf, size); + } + while (!result && errno == ERANGE); + + if (!result) + { + int saved_errno = errno; + free (buf); + errno = saved_errno; + } + else + { + /* Trim to fit, if possible. */ + result = realloc (buf, strlen (buf) + 1); + if (!result) + result = buf; + } + return result; +} + +#endif diff --git a/grub-core/lib/gnulib/getdelim.c b/grub-core/lib/gnulib/getdelim.c new file mode 100644 index 0000000..528678c --- /dev/null +++ b/grub-core/lib/gnulib/getdelim.c @@ -0,0 +1,147 @@ +/* getdelim.c --- Implementation of replacement getdelim function. + Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2019 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Ported from glibc by Simon Josefsson. */ + +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below. */ +#define _GL_ARG_NONNULL(params) + +#include <config.h> + +#include <stdio.h> + +#include <limits.h> +#include <stdint.h> +#include <stdlib.h> +#include <errno.h> + +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +# define getc_maybe_unlocked(fp) getc(fp) +#elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED +# undef flockfile +# undef funlockfile +# define flockfile(x) ((void) 0) +# define funlockfile(x) ((void) 0) +# define getc_maybe_unlocked(fp) getc(fp) +#else +# define getc_maybe_unlocked(fp) getc_unlocked(fp) +#endif + +static void +alloc_failed (void) +{ +#if defined _WIN32 && ! defined __CYGWIN__ + /* Avoid errno problem without using the realloc module; see: + https://lists.gnu.org/r/bug-gnulib/2016-08/msg00025.html */ + errno = ENOMEM; +#endif +} + +/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and + NUL-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'ed as + necessary. Returns the number of characters read (not including + the null terminator), or -1 on error or EOF. */ + +ssize_t +getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) +{ + ssize_t result; + size_t cur_len = 0; + + if (lineptr == NULL || n == NULL || fp == NULL) + { + errno = EINVAL; + return -1; + } + + flockfile (fp); + + if (*lineptr == NULL || *n == 0) + { + char *new_lineptr; + *n = 120; + new_lineptr = (char *) realloc (*lineptr, *n); + if (new_lineptr == NULL) + { + alloc_failed (); + result = -1; + goto unlock_return; + } + *lineptr = new_lineptr; + } + + for (;;) + { + int i; + + i = getc_maybe_unlocked (fp); + if (i == EOF) + { + result = -1; + break; + } + + /* Make enough space for len+1 (for final NUL) bytes. */ + if (cur_len + 1 >= *n) + { + size_t needed_max = + SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; + size_t needed = 2 * *n + 1; /* Be generous. */ + char *new_lineptr; + + if (needed_max < needed) + needed = needed_max; + if (cur_len + 1 >= needed) + { + result = -1; + errno = EOVERFLOW; + goto unlock_return; + } + + new_lineptr = (char *) realloc (*lineptr, needed); + if (new_lineptr == NULL) + { + alloc_failed (); + result = -1; + goto unlock_return; + } + + *lineptr = new_lineptr; + *n = needed; + } + + (*lineptr)[cur_len] = i; + cur_len++; + + if (i == delimiter) + break; + } + (*lineptr)[cur_len] = '\0'; + result = cur_len ? cur_len : result; + + unlock_return: + funlockfile (fp); /* doesn't set errno */ + + return result; +} diff --git a/grub-core/lib/gnulib/getdtablesize.c b/grub-core/lib/gnulib/getdtablesize.c new file mode 100644 index 0000000..03a9243 --- /dev/null +++ b/grub-core/lib/gnulib/getdtablesize.c @@ -0,0 +1,124 @@ +/* getdtablesize() function: Return maximum possible file descriptor value + 1. + Copyright (C) 2008-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <unistd.h> + +#if defined _WIN32 && ! defined __CYGWIN__ + +# include <stdio.h> + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +# endif + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static int +_setmaxstdio_nothrow (int newmax) +{ + int result; + + TRY_MSVC_INVAL + { + result = _setmaxstdio (newmax); + } + CATCH_MSVC_INVAL + { + result = -1; + } + DONE_MSVC_INVAL; + + return result; +} +# else +# define _setmaxstdio_nothrow _setmaxstdio +# endif + +/* Cache for the previous getdtablesize () result. Safe to cache because + Windows also lacks setrlimit. */ +static int dtablesize; + +int +getdtablesize (void) +{ + if (dtablesize == 0) + { + /* We are looking for the number N such that the valid file descriptors + are 0..N-1. It can be obtained through a loop as follows: + { + int fd; + for (fd = 3; fd < 65536; fd++) + if (dup2 (0, fd) == -1) + break; + return fd; + } + On Windows XP, the result is 2048. + The drawback of this loop is that it allocates memory for a libc + internal array that is never freed. + + The number N can also be obtained as the upper bound for + _getmaxstdio (). _getmaxstdio () returns the maximum number of open + FILE objects. The sanity check in _setmaxstdio reveals the maximum + number of file descriptors. This too allocates memory, but it is + freed when we call _setmaxstdio with the original value. */ + int orig_max_stdio = _getmaxstdio (); + unsigned int bound; + for (bound = 0x10000; _setmaxstdio_nothrow (bound) < 0; bound = bound / 2) + ; + _setmaxstdio_nothrow (orig_max_stdio); + dtablesize = bound; + } + return dtablesize; +} + +#else + +# include <limits.h> +# include <sys/resource.h> + +# ifndef RLIM_SAVED_CUR +# define RLIM_SAVED_CUR RLIM_INFINITY +# endif +# ifndef RLIM_SAVED_MAX +# define RLIM_SAVED_MAX RLIM_INFINITY +# endif + +# ifdef __CYGWIN__ + /* Cygwin 1.7.25 auto-increases the RLIMIT_NOFILE soft limit until it + hits the compile-time constant hard limit of 3200. We might as + well just report the hard limit. */ +# define rlim_cur rlim_max +# endif + +int +getdtablesize (void) +{ + struct rlimit lim; + + if (getrlimit (RLIMIT_NOFILE, &lim) == 0 + && 0 <= lim.rlim_cur && lim.rlim_cur <= INT_MAX + && lim.rlim_cur != RLIM_INFINITY + && lim.rlim_cur != RLIM_SAVED_CUR + && lim.rlim_cur != RLIM_SAVED_MAX) + return lim.rlim_cur; + + return INT_MAX; +} + +#endif diff --git a/grub-core/lib/gnulib/getline.c b/grub-core/lib/gnulib/getline.c new file mode 100644 index 0000000..40882fb --- /dev/null +++ b/grub-core/lib/gnulib/getline.c @@ -0,0 +1,27 @@ +/* getline.c --- Implementation of replacement getline function. + Copyright (C) 2005-2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Simon Josefsson. */ + +#include <config.h> + +#include <stdio.h> + +ssize_t +getline (char **lineptr, size_t *n, FILE *stream) +{ + return getdelim (lineptr, n, '\n', stream); +} diff --git a/grub-core/lib/gnulib/getopt-cdefs.in.h b/grub-core/lib/gnulib/getopt-cdefs.in.h new file mode 100644 index 0000000..049145b --- /dev/null +++ b/grub-core/lib/gnulib/getopt-cdefs.in.h @@ -0,0 +1,67 @@ +/* getopt-on-non-glibc compatibility macros. + Copyright (C) 1989-2019 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library. + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with gnulib; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _GETOPT_CDEFS_H +#define _GETOPT_CDEFS_H 1 + +/* This header should not be used directly; include getopt.h or + unistd.h instead. It does not have a protective #error, because + the guard macro for getopt.h in gnulib is not fixed. */ + +/* getopt-core.h and getopt-ext.h are shared with GNU libc, and expect + a number of the internal macros supplied to GNU libc's headers by + sys/cdefs.h. Provide fallback definitions for all of them. */ +#if @HAVE_SYS_CDEFS_H@ +# include <sys/cdefs.h> +#endif + +#ifndef __BEGIN_DECLS +# ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# else +# define __BEGIN_DECLS /* nothing */ +# endif +#endif +#ifndef __END_DECLS +# ifdef __cplusplus +# define __END_DECLS } +# else +# define __END_DECLS /* nothing */ +# endif +#endif + +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_VERSION__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + +#ifndef __THROW +# if defined __cplusplus && __GNUC_PREREQ (2,8) +# define __THROW throw () +# else +# define __THROW +# endif +#endif + +#endif /* _GETOPT_CDEFS_H */ diff --git a/grub-core/lib/gnulib/getopt-core.h b/grub-core/lib/gnulib/getopt-core.h new file mode 100644 index 0000000..6360ad6 --- /dev/null +++ b/grub-core/lib/gnulib/getopt-core.h @@ -0,0 +1,96 @@ +/* Declarations for getopt (basic, portable features only). + Copyright (C) 1989-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _GETOPT_CORE_H +#define _GETOPT_CORE_H 1 + +/* This header should not be used directly; include getopt.h or + unistd.h instead. Unlike most bits headers, it does not have + a protective #error, because the guard macro for getopt.h in + gnulib is not fixed. */ + +__BEGIN_DECLS + +/* For communication from 'getopt' to the caller. + When 'getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when 'ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to 'getopt'. + + On entry to 'getopt', zero means this is the first call; initialize. + + When 'getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, 'optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message 'getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, 'optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in 'optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU 'getopt'. + + The argument '--' causes premature termination of argument + scanning, explicitly telling 'getopt' that there are no more + options. + + If OPTS begins with '-', then non-option arguments are treated as + arguments to the option '\1'. This behavior is specific to the GNU + 'getopt'. If OPTS begins with '+', or POSIXLY_CORRECT is set in + the environment, then do not permute arguments. + + For standards compliance, the 'argv' argument has the type + char *const *, but this is inaccurate; if argument permutation is + enabled, the argv array (not the strings it points to) must be + writable. */ + +extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) + __THROW _GL_ARG_NONNULL ((2, 3)); + +__END_DECLS + +#endif /* _GETOPT_CORE_H */ diff --git a/grub-core/lib/gnulib/getopt-ext.h b/grub-core/lib/gnulib/getopt-ext.h new file mode 100644 index 0000000..13cb007 --- /dev/null +++ b/grub-core/lib/gnulib/getopt-ext.h @@ -0,0 +1,77 @@ +/* Declarations for getopt (GNU extensions). + Copyright (C) 1989-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _GETOPT_EXT_H +#define _GETOPT_EXT_H 1 + +/* This header should not be used directly; include getopt.h instead. + Unlike most bits headers, it does not have a protective #error, + because the guard macro for getopt.h in gnulib is not fixed. */ + +__BEGIN_DECLS + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of 'struct option' terminated by an element containing a name which is + zero. + + The field 'has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field 'flag' is not NULL, it points to a variable that is set + to the value given in the field 'val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an 'int' to + a compiled-in constant, such as set a value from 'optarg', set the + option's 'flag' field to zero and its 'val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero 'flag' field, 'getopt' + returns the contents of the 'val' field. */ + +struct option +{ + const char *name; + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the 'has_arg' field of 'struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW _GL_ARG_NONNULL ((2, 3)); +extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW _GL_ARG_NONNULL ((2, 3)); + +__END_DECLS + +#endif /* _GETOPT_EXT_H */ diff --git a/grub-core/lib/gnulib/getopt-pfx-core.h b/grub-core/lib/gnulib/getopt-pfx-core.h new file mode 100644 index 0000000..8fac269 --- /dev/null +++ b/grub-core/lib/gnulib/getopt-pfx-core.h @@ -0,0 +1,59 @@ +/* getopt (basic, portable features) gnulib wrapper header. + Copyright (C) 1989-2019 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library. + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with gnulib; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _GETOPT_PFX_CORE_H +#define _GETOPT_PFX_CORE_H 1 + +/* This header should not be used directly; include getopt.h or + unistd.h instead. It does not have a protective #error, because + the guard macro for getopt.h in gnulib is not fixed. */ + +/* Standalone applications should #define __GETOPT_PREFIX to an + identifier that prefixes the external functions and variables + defined in getopt-core.h and getopt-ext.h. Systematically + rename identifiers so that they do not collide with the system + functions and variables. Renaming avoids problems with some + compilers and linkers. */ +#ifdef __GETOPT_PREFIX +# ifndef __GETOPT_ID +# define __GETOPT_CONCAT(x, y) x ## y +# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) +# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) +# endif +# undef getopt +# undef optarg +# undef opterr +# undef optind +# undef optopt +# define getopt __GETOPT_ID (getopt) +# define optarg __GETOPT_ID (optarg) +# define opterr __GETOPT_ID (opterr) +# define optind __GETOPT_ID (optind) +# define optopt __GETOPT_ID (optopt) + +/* The system's getopt.h may have already included getopt-core.h to + declare the unprefixed identifiers. Undef _GETOPT_CORE_H so that + getopt-core.h declares them with prefixes. */ +# undef _GETOPT_CORE_H +#endif + +#include <getopt-core.h> + +#endif /* _GETOPT_PFX_CORE_H */ diff --git a/grub-core/lib/gnulib/getopt-pfx-ext.h b/grub-core/lib/gnulib/getopt-pfx-ext.h new file mode 100644 index 0000000..0e21aef --- /dev/null +++ b/grub-core/lib/gnulib/getopt-pfx-ext.h @@ -0,0 +1,71 @@ +/* getopt (GNU extensions) gnulib wrapper header. + Copyright (C) 1989-2019 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library. + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with gnulib; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _GETOPT_PFX_EXT_H +#define _GETOPT_PFX_EXT_H 1 + +/* This header should not be used directly; include getopt.h instead. + It does not have a protective #error, because the guard macro for + getopt.h in gnulib is not fixed. */ + +/* Standalone applications should #define __GETOPT_PREFIX to an + identifier that prefixes the external functions and variables + defined in getopt-core.h and getopt-ext.h. Systematically + rename identifiers so that they do not collide with the system + functions and variables. Renaming avoids problems with some + compilers and linkers. */ +#ifdef __GETOPT_PREFIX +# ifndef __GETOPT_ID +# define __GETOPT_CONCAT(x, y) x ## y +# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) +# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) +# endif +# undef getopt_long +# undef getopt_long_only +# undef option +# undef _getopt_internal +# define getopt_long __GETOPT_ID (getopt_long) +# define getopt_long_only __GETOPT_ID (getopt_long_only) +# define option __GETOPT_ID (option) +# define _getopt_internal __GETOPT_ID (getopt_internal) + +/* The system's getopt.h may have already included getopt-ext.h to + declare the unprefixed identifiers. Undef _GETOPT_EXT_H so that + getopt-ext.h declares them with prefixes. */ +# undef _GETOPT_EXT_H +#endif + +/* Standalone applications get correct prototypes for getopt_long and + getopt_long_only; they declare "char **argv". For backward + compatibility with old applications, if __GETOPT_PREFIX is not + defined, we supply GNU-libc-compatible, but incorrect, prototypes + using "char *const *argv". (GNU libc is stuck with the incorrect + prototypes, as they are baked into older versions of LSB.) */ +#ifndef __getopt_argv_const +# if defined __GETOPT_PREFIX +# define __getopt_argv_const /* empty */ +# else +# define __getopt_argv_const const +# endif +#endif + +#include <getopt-ext.h> + +#endif /* _GETOPT_PFX_EXT_H */ diff --git a/grub-core/lib/gnulib/getopt.c b/grub-core/lib/gnulib/getopt.c new file mode 100644 index 0000000..8ee075a --- /dev/null +++ b/grub-core/lib/gnulib/getopt.c @@ -0,0 +1,811 @@ +/* Getopt for GNU. + Copyright (C) 1987-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _LIBC +# include <config.h> +#endif + +#include "getopt.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef _LIBC +/* When used as part of glibc, error printing must be done differently + for standards compliance. getopt is not a cancellation point, so + it must not call functions that are, and it is specified by an + older standard than stdio locking, so it must not refer to + functions in the "user namespace" related to stdio locking. + Finally, it must use glibc's internal message translation so that + the messages are looked up in the proper text domain. */ +# include <libintl.h> +# define fprintf __fxprintf_nocancel +# define flockfile(fp) _IO_flockfile (fp) +# define funlockfile(fp) _IO_funlockfile (fp) +#else +# include "gettext.h" +# define _(msgid) gettext (msgid) +/* When used standalone, flockfile and funlockfile might not be + available. */ +# if (!defined _POSIX_THREAD_SAFE_FUNCTIONS \ + || (defined _WIN32 && ! defined __CYGWIN__)) +# define flockfile(fp) /* nop */ +# define funlockfile(fp) /* nop */ +# endif +/* When used standalone, do not attempt to use alloca. */ +# define __libc_use_alloca(size) 0 +# undef alloca +# define alloca(size) (abort (), (void *)0) +#endif + +/* This implementation of 'getopt' has three modes for handling + options interspersed with non-option arguments. It can stop + scanning for options at the first non-option argument encountered, + as POSIX specifies. It can continue scanning for options after the + first non-option argument, but permute 'argv' as it goes so that, + after 'getopt' is done, all the options precede all the non-option + arguments and 'optind' points to the first non-option argument. + Or, it can report non-option arguments as if they were arguments to + the option character '\x01'. + + The default behavior of 'getopt_long' is to permute the argument list. + When this implementation is used standalone, the default behavior of + 'getopt' is to stop at the first non-option argument, but when it is + used as part of GNU libc it also permutes the argument list. In both + cases, setting the environment variable POSIXLY_CORRECT to any value + disables permutation. + + If the first character of the OPTSTRING argument to 'getopt' or + 'getopt_long' is '+', both functions will stop at the first + non-option argument. If it is '-', both functions will report + non-option arguments as arguments to the option character '\x01'. */ + +#include "getopt_int.h" + +/* For communication from 'getopt' to the caller. + When 'getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when 'ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to 'getopt'. + + On entry to 'getopt', zero means this is the first call; initialize. + + When 'getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, 'optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Keep a global copy of all internal members of getopt_data. */ + +static struct _getopt_data getopt_data; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + 'first_nonopt' and 'last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (char **argv, struct _getopt_data *d) +{ + int bottom = d->__first_nonopt; + int middle = d->__last_nonopt; + int top = d->optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + d->__first_nonopt += (d->optind - d->__last_nonopt); + d->__last_nonopt = d->optind; +} + +/* Process the argument starting with d->__nextchar as a long option. + d->optind should *not* have been advanced over this argument. + + If the value returned is -1, it was not actually a long option, the + state is unchanged, and the argument should be processed as a set + of short options (this can only happen when long_only is true). + Otherwise, the option (and its argument, if any) have been consumed + and the return value is the value to return from _getopt_internal_r. */ +static int +process_long_option (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, struct _getopt_data *d, + int print_errors, const char *prefix) +{ + char *nameend; + size_t namelen; + const struct option *p; + const struct option *pfound = NULL; + int n_options; + int option_index; + + for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + namelen = nameend - d->__nextchar; + + /* First look for an exact match, counting the options as a side + effect. */ + for (p = longopts, n_options = 0; p->name; p++, n_options++) + if (!strncmp (p->name, d->__nextchar, namelen) + && namelen == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + option_index = n_options; + break; + } + + if (pfound == NULL) + { + /* Didn't find an exact match, so look for abbreviations. */ + unsigned char *ambig_set = NULL; + int ambig_malloced = 0; + int ambig_fallback = 0; + int indfound = -1; + + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, d->__nextchar, namelen)) + { + if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) + { + /* Second or later nonexact match found. */ + if (!ambig_fallback) + { + if (!print_errors) + /* Don't waste effort tracking the ambig set if + we're not going to print it anyway. */ + ambig_fallback = 1; + else if (!ambig_set) + { + if (__libc_use_alloca (n_options)) + ambig_set = alloca (n_options); + else if ((ambig_set = malloc (n_options)) == NULL) + /* Fall back to simpler error message. */ + ambig_fallback = 1; + else + ambig_malloced = 1; + + if (ambig_set) + { + memset (ambig_set, 0, n_options); + ambig_set[indfound] = 1; + } + } + if (ambig_set) + ambig_set[option_index] = 1; + } + } + } + + if (ambig_set || ambig_fallback) + { + if (print_errors) + { + if (ambig_fallback) + fprintf (stderr, _("%s: option '%s%s' is ambiguous\n"), + argv[0], prefix, d->__nextchar); + else + { + flockfile (stderr); + fprintf (stderr, + _("%s: option '%s%s' is ambiguous; possibilities:"), + argv[0], prefix, d->__nextchar); + + for (option_index = 0; option_index < n_options; option_index++) + if (ambig_set[option_index]) + fprintf (stderr, " '%s%s'", + prefix, longopts[option_index].name); + + /* This must use 'fprintf' even though it's only + printing a single character, so that it goes through + __fxprintf_nocancel when compiled as part of glibc. */ + fprintf (stderr, "\n"); + funlockfile (stderr); + } + } + if (ambig_malloced) + free (ambig_set); + d->__nextchar += strlen (d->__nextchar); + d->optind++; + d->optopt = 0; + return '?'; + } + + option_index = indfound; + } + + if (pfound == NULL) + { + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short option, + then it's an error. */ + if (!long_only || argv[d->optind][1] == '-' + || strchr (optstring, *d->__nextchar) == NULL) + { + if (print_errors) + fprintf (stderr, _("%s: unrecognized option '%s%s'\n"), + argv[0], prefix, d->__nextchar); + + d->__nextchar = NULL; + d->optind++; + d->optopt = 0; + return '?'; + } + + /* Otherwise interpret it as a short option. */ + return -1; + } + + /* We have found a matching long option. Consume it. */ + d->optind++; + d->__nextchar = NULL; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + fprintf (stderr, + _("%s: option '%s%s' doesn't allow an argument\n"), + argv[0], prefix, pfound->name); + + d->optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + fprintf (stderr, + _("%s: option '%s%s' requires an argument\n"), + argv[0], prefix, pfound->name); + + d->optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; +} + +/* Initialize internal data upon the first call to getopt. */ + +static const char * +_getopt_initialize (int argc _GL_UNUSED, + char **argv _GL_UNUSED, const char *optstring, + struct _getopt_data *d, int posixly_correct) +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + if (d->optind == 0) + d->optind = 1; + + d->__first_nonopt = d->__last_nonopt = d->optind; + d->__nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + if (optstring[0] == '-') + { + d->__ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + d->__ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct || !!getenv ("POSIXLY_CORRECT")) + d->__ordering = REQUIRE_ORDER; + else + d->__ordering = PERMUTE; + + d->__initialized = 1; + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If 'getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If 'getopt' finds another option character, it returns that character, + updating 'optind' and 'nextchar' so that the next call to 'getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, 'getopt' returns -1. + Then 'optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set 'opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in 'optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in 'optarg', otherwise 'optarg' is set to zero. + + If OPTSTRING starts with '-' or '+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with '--' instead of '-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a '=', or else the in next ARGV-element. + When 'getopt' finds a long-named option, it returns 0 if that option's + 'flag' field is nonzero, the value of the option's 'val' field + if the 'flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of 'struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal_r (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, struct _getopt_data *d, int posixly_correct) +{ + int print_errors = d->opterr; + + if (argc < 1) + return -1; + + d->optarg = NULL; + + if (d->optind == 0 || !d->__initialized) + optstring = _getopt_initialize (argc, argv, optstring, d, posixly_correct); + else if (optstring[0] == '-' || optstring[0] == '+') + optstring++; + + if (optstring[0] == ':') + print_errors = 0; + + /* Test whether ARGV[optind] points to a non-option argument. */ +#define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') + + if (d->__nextchar == NULL || *d->__nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (d->__last_nonopt > d->optind) + d->__last_nonopt = d->optind; + if (d->__first_nonopt > d->optind) + d->__first_nonopt = d->optind; + + if (d->__ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange (argv, d); + else if (d->__last_nonopt != d->optind) + d->__first_nonopt = d->optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (d->optind < argc && NONOPTION_P) + d->optind++; + d->__last_nonopt = d->optind; + } + + /* The special ARGV-element '--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (d->optind != argc && !strcmp (argv[d->optind], "--")) + { + d->optind++; + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange (argv, d); + else if (d->__first_nonopt == d->__last_nonopt) + d->__first_nonopt = d->optind; + d->__last_nonopt = argc; + + d->optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (d->optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (d->__first_nonopt != d->__last_nonopt) + d->optind = d->__first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (d->__ordering == REQUIRE_ORDER) + return -1; + d->optarg = argv[d->optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Check whether it might be a long option. */ + if (longopts) + { + if (argv[d->optind][1] == '-') + { + /* "--foo" is always a long option. The special option + "--" was handled above. */ + d->__nextchar = argv[d->optind] + 2; + return process_long_option (argc, argv, optstring, longopts, + longind, long_only, d, + print_errors, "--"); + } + + /* If long_only and the ARGV-element has the form "-f", + where f is a valid short option, don't consider it an + abbreviated form of a long option that starts with f. + Otherwise there would be no way to give the -f short + option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an + abbreviation of the long option, just like "--fu", and + not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + if (long_only && (argv[d->optind][2] + || !strchr (optstring, argv[d->optind][1]))) + { + int code; + d->__nextchar = argv[d->optind] + 1; + code = process_long_option (argc, argv, optstring, longopts, + longind, long_only, d, + print_errors, "-"); + if (code != -1) + return code; + } + } + + /* It is not a long option. Skip the initial punctuation. */ + d->__nextchar = argv[d->optind] + 1; + } + + /* Look at and handle the next short option-character. */ + + { + char c = *d->__nextchar++; + const char *temp = strchr (optstring, c); + + /* Increment 'optind' when we start to process its last character. */ + if (*d->__nextchar == '\0') + ++d->optind; + + if (temp == NULL || c == ':' || c == ';') + { + if (print_errors) + fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c); + d->optopt = c; + return '?'; + } + + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';' && longopts != NULL) + { + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + d->optarg = d->__nextchar; + else if (d->optind == argc) + { + if (print_errors) + fprintf (stderr, + _("%s: option requires an argument -- '%c'\n"), + argv[0], c); + + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + d->optarg = argv[d->optind]; + + d->__nextchar = d->optarg; + d->optarg = NULL; + return process_long_option (argc, argv, optstring, longopts, longind, + 0 /* long_only */, d, print_errors, "-W "); + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else + d->optarg = NULL; + d->__nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + fprintf (stderr, + _("%s: option requires an argument -- '%c'\n"), + argv[0], c); + + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented 'optind' once; + increment it again when taking next ARGV-elt as argument. */ + d->optarg = argv[d->optind++]; + d->__nextchar = NULL; + } + } + return c; + } +} + +int +_getopt_internal (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, int long_only, + int posixly_correct) +{ + int result; + + getopt_data.optind = optind; + getopt_data.opterr = opterr; + + result = _getopt_internal_r (argc, argv, optstring, longopts, + longind, long_only, &getopt_data, + posixly_correct); + + optind = getopt_data.optind; + optarg = getopt_data.optarg; + optopt = getopt_data.optopt; + + return result; +} + +/* glibc gets a LSB-compliant getopt and a POSIX-complaint __posix_getopt. + Standalone applications just get a POSIX-compliant getopt. + POSIX and LSB both require these functions to take 'char *const *argv' + even though this is incorrect (because of the permutation). */ +#define GETOPT_ENTRY(NAME, POSIXLY_CORRECT) \ + int \ + NAME (int argc, char *const *argv, const char *optstring) \ + { \ + return _getopt_internal (argc, (char **)argv, optstring, \ + 0, 0, 0, POSIXLY_CORRECT); \ + } + +#ifdef _LIBC +GETOPT_ENTRY(getopt, 0) +GETOPT_ENTRY(__posix_getopt, 1) +#else +GETOPT_ENTRY(getopt, 1) +#endif + + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of 'getopt'. */ + +int +main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value '%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/grub-core/lib/gnulib/getopt.in.h b/grub-core/lib/gnulib/getopt.in.h new file mode 100644 index 0000000..c77f34c --- /dev/null +++ b/grub-core/lib/gnulib/getopt.in.h @@ -0,0 +1,61 @@ +/* Declarations for getopt. + Copyright (C) 1989-2019 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library, which supplies a different version of + this file. + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3 of + the License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with gnulib; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _@GUARD_PREFIX@_GETOPT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. We must + also inform the replacement unistd.h to not recursively use + <getopt.h>; our definitions will be present soon enough. */ +#if @HAVE_GETOPT_H@ +# define _GL_SYSTEM_GETOPT +# @INCLUDE_NEXT@ @NEXT_GETOPT_H@ +# undef _GL_SYSTEM_GETOPT +#endif + +#define _@GUARD_PREFIX@_GETOPT_H 1 + +/* Standalone applications should #define __GETOPT_PREFIX to an + identifier that prefixes the external functions and variables + defined in getopt-core.h and getopt-ext.h. When this happens, + include the headers that might declare getopt so that they will not + cause confusion if included after this file (if the system had + <getopt.h>, we have already included it). */ +#if defined __GETOPT_PREFIX +# if !@HAVE_GETOPT_H@ +# define __need_system_stdlib_h +# include <stdlib.h> +# undef __need_system_stdlib_h +# include <stdio.h> +# include <unistd.h> +# endif +#endif + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +#include <getopt-cdefs.h> +#include <getopt-pfx-core.h> +#include <getopt-pfx-ext.h> + +#endif /* _@GUARD_PREFIX@_GETOPT_H */ diff --git a/grub-core/lib/gnulib/getopt1.c b/grub-core/lib/gnulib/getopt1.c new file mode 100644 index 0000000..883aa6b --- /dev/null +++ b/grub-core/lib/gnulib/getopt1.c @@ -0,0 +1,159 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _LIBC +# include <config.h> +#endif + +#include "getopt.h" +#include "getopt_int.h" + +int +getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, (char **) argv, options, long_options, + opt_index, 0, 0); +} + +int +_getopt_long_r (int argc, char **argv, const char *options, + const struct option *long_options, int *opt_index, + struct _getopt_data *d) +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 0, d, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (int argc, char *__getopt_argv_const *argv, + const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, (char **) argv, options, long_options, + opt_index, 1, 0); +} + +int +_getopt_long_only_r (int argc, char **argv, const char *options, + const struct option *long_options, int *opt_index, + struct _getopt_data *d) +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 1, d, 0); +} + + +#ifdef TEST + +#include <stdio.h> +#include <stdlib.h> + +int +main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static const struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value '%s'\n", optarg); + break; + + case 'd': + printf ("option d with value '%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/grub-core/lib/gnulib/getopt_int.h b/grub-core/lib/gnulib/getopt_int.h new file mode 100644 index 0000000..e63706f --- /dev/null +++ b/grub-core/lib/gnulib/getopt_int.h @@ -0,0 +1,118 @@ +/* Internal declarations for getopt. + Copyright (C) 1989-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _GETOPT_INT_H +#define _GETOPT_INT_H 1 + +#include <getopt.h> + +extern int _getopt_internal (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only, int __posixly_correct); + + +/* Reentrant versions which can handle parsing multiple argument + vectors at the same time. */ + +/* Describe how to deal with options that follow non-option ARGV-elements. + + REQUIRE_ORDER means don't recognize them as options; stop option + processing when the first non-option is seen. This is what POSIX + specifies should happen. + + PERMUTE means permute the contents of ARGV as we scan, so that + eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written + to expect this. + + RETURN_IN_ORDER is an option available to programs that were + written to expect options and other ARGV-elements in any order + and that care about the ordering of the two. We describe each + non-option ARGV-element as if it were the argument of an option + with character code 1. + + The special argument '--' forces an end of option-scanning regardless + of the value of 'ordering'. In the case of RETURN_IN_ORDER, only + '--' can cause 'getopt' to return -1 with 'optind' != ARGC. */ + +enum __ord + { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER + }; + +/* Data type for reentrant functions. */ +struct _getopt_data +{ + /* These have exactly the same meaning as the corresponding global + variables, except that they are used for the reentrant + versions of getopt. */ + int optind; + int opterr; + int optopt; + char *optarg; + + /* Internal members. */ + + /* True if the internal members have been initialized. */ + int __initialized; + + /* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + char *__nextchar; + + /* See __ord above. */ + enum __ord __ordering; + + /* Handle permutation of arguments. */ + + /* Describe the part of ARGV that contains non-options that have + been skipped. 'first_nonopt' is the index in ARGV of the first + of them; 'last_nonopt' is the index after the last of them. */ + + int __first_nonopt; + int __last_nonopt; +}; + +/* The initializer is necessary to set OPTIND and OPTERR to their + default values and to clear the initialization flag. */ +#define _GETOPT_DATA_INITIALIZER { 1, 1 } + +extern int _getopt_internal_r (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only, struct _getopt_data *__data, + int __posixly_correct); + +extern int _getopt_long_r (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + struct _getopt_data *__data); + +extern int _getopt_long_only_r (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, + int *__longind, + struct _getopt_data *__data); + +#endif /* getopt_int.h */ diff --git a/grub-core/lib/gnulib/getprogname.c b/grub-core/lib/gnulib/getprogname.c new file mode 100644 index 0000000..96fa759 --- /dev/null +++ b/grub-core/lib/gnulib/getprogname.c @@ -0,0 +1,255 @@ +/* Program name management. + Copyright (C) 2016-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "getprogname.h" + +#include <errno.h> /* get program_invocation_name declaration */ +#include <stdlib.h> /* get __argv declaration */ + +#ifdef _AIX +# include <unistd.h> +# include <procinfo.h> +# include <string.h> +#endif + +#ifdef __MVS__ +# ifndef _OPEN_SYS +# define _OPEN_SYS +# endif +# include <string.h> +# include <sys/ps.h> +#endif + +#ifdef __hpux +# include <unistd.h> +# include <sys/param.h> +# include <sys/pstat.h> +# include <string.h> +#endif + +#ifdef __sgi +# include <string.h> +# include <unistd.h> +# include <stdio.h> +# include <fcntl.h> +# include <sys/procfs.h> +#endif + +#include "dirname.h" + +#ifndef HAVE_GETPROGNAME /* not Mac OS X, FreeBSD, NetBSD, OpenBSD >= 5.4, Cygwin */ +char const * +getprogname (void) +{ +# if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME /* glibc, BeOS */ + /* https://www.gnu.org/software/libc/manual/html_node/Error-Messages.html */ + return program_invocation_short_name; +# elif HAVE_DECL_PROGRAM_INVOCATION_NAME /* glibc, BeOS */ + /* https://www.gnu.org/software/libc/manual/html_node/Error-Messages.html */ + return last_component (program_invocation_name); +# elif HAVE_GETEXECNAME /* Solaris */ + /* https://docs.oracle.com/cd/E19253-01/816-5168/6mbb3hrb1/index.html */ + const char *p = getexecname (); + if (!p) + p = "?"; + return last_component (p); +# elif HAVE_DECL___ARGV /* mingw, MSVC */ + /* https://msdn.microsoft.com/en-us/library/dn727674.aspx */ + const char *p = __argv && __argv[0] ? __argv[0] : "?"; + return last_component (p); +# elif HAVE_VAR___PROGNAME /* OpenBSD, QNX */ + /* https://man.openbsd.org/style.9 */ + /* http://www.qnx.de/developers/docs/6.5.0/index.jsp?topic=%2Fcom.qnx.doc.neutrino_lib_ref%2Fp%2F__progname.html */ + /* Be careful to declare this only when we absolutely need it + (OpenBSD 5.1), rather than when it's available. Otherwise, + its mere declaration makes program_invocation_short_name + malfunction (have zero length) with Fedora 25's glibc. */ + extern char *__progname; + const char *p = __progname; + return p && p[0] ? p : "?"; +# elif _AIX /* AIX */ + /* Idea by Bastien ROUCARIÈS, + https://lists.gnu.org/r/bug-gnulib/2010-12/msg00095.html + Reference: https://www.ibm.com/support/knowledgecenter/en/ssw_aix_61/com.ibm.aix.basetrf1/getprocs.htm + */ + static char *p; + static int first = 1; + if (first) + { + first = 0; + pid_t pid = getpid (); + struct procentry64 procs; + p = (0 < getprocs64 (&procs, sizeof procs, NULL, 0, &pid, 1) + ? strdup (procs.pi_comm) + : NULL); + if (!p) + p = "?"; + } + return p; +# elif defined __hpux + static char *p; + static int first = 1; + if (first) + { + first = 0; + pid_t pid = getpid (); + struct pst_status status; + if (pstat_getproc (&status, sizeof status, 0, pid) > 0) + { + char *ucomm = status.pst_ucomm; + char *cmd = status.pst_cmd; + if (strlen (ucomm) < PST_UCOMMLEN - 1) + p = ucomm; + else + { + /* ucomm is truncated to length PST_UCOMMLEN - 1. + Look at cmd instead. */ + char *space = strchr (cmd, ' '); + if (space != NULL) + *space = '\0'; + p = strrchr (cmd, '/'); + if (p != NULL) + p++; + else + p = cmd; + if (strlen (p) > PST_UCOMMLEN - 1 + && memcmp (p, ucomm, PST_UCOMMLEN - 1) == 0) + /* p is less truncated than ucomm. */ + ; + else + p = ucomm; + } + p = strdup (p); + } + else + { +# if !defined __LP64__ + /* Support for 32-bit programs running in 64-bit HP-UX. + The documented way to do this is to use the same source code + as above, but in a compilation unit where '#define _PSTAT64 1' + is in effect. I prefer a single compilation unit; the struct + size and the offsets are not going to change. */ + char status64[1216]; + if (__pstat_getproc64 (status64, sizeof status64, 0, pid) > 0) + { + char *ucomm = status64 + 288; + char *cmd = status64 + 168; + if (strlen (ucomm) < PST_UCOMMLEN - 1) + p = ucomm; + else + { + /* ucomm is truncated to length PST_UCOMMLEN - 1. + Look at cmd instead. */ + char *space = strchr (cmd, ' '); + if (space != NULL) + *space = '\0'; + p = strrchr (cmd, '/'); + if (p != NULL) + p++; + else + p = cmd; + if (strlen (p) > PST_UCOMMLEN - 1 + && memcmp (p, ucomm, PST_UCOMMLEN - 1) == 0) + /* p is less truncated than ucomm. */ + ; + else + p = ucomm; + } + p = strdup (p); + } + else +# endif + p = NULL; + } + if (!p) + p = "?"; + } + return p; +# elif __MVS__ /* z/OS */ + /* https://www.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.bpxbd00/rtwgetp.htm */ + static char *p = "?"; + static int first = 1; + if (first) + { + pid_t pid = getpid (); + int token; + W_PSPROC buf; + first = 0; + memset (&buf, 0, sizeof(buf)); + buf.ps_cmdptr = (char *) malloc (buf.ps_cmdlen = PS_CMDBLEN_LONG); + buf.ps_conttyptr = (char *) malloc (buf.ps_conttylen = PS_CONTTYBLEN); + buf.ps_pathptr = (char *) malloc (buf.ps_pathlen = PS_PATHBLEN); + if (buf.ps_cmdptr && buf.ps_conttyptr && buf.ps_pathptr) + { + for (token = 0; token >= 0; + token = w_getpsent (token, &buf, sizeof(buf))) + { + if (token > 0 && buf.ps_pid == pid) + { + char *s = strdup (last_component (buf.ps_pathptr)); + if (s) + p = s; + break; + } + } + } + free (buf.ps_cmdptr); + free (buf.ps_conttyptr); + free (buf.ps_pathptr); + } + return p; +# elif defined __sgi /* IRIX */ + char filename[50]; + int fd; + + sprintf (filename, "/proc/pinfo/%d", (int) getpid ()); + fd = open (filename, O_RDONLY); + if (0 <= fd) + { + prpsinfo_t buf; + int ioctl_ok = 0 <= ioctl (fd, PIOCPSINFO, &buf); + close (fd); + if (ioctl_ok) + { + char *name = buf.pr_fname; + size_t namesize = sizeof buf.pr_fname; + char *namenul = memchr (name, '\0', namesize); + size_t namelen = namenul ? namenul - name : namesize; + char *namecopy = malloc (namelen + 1); + if (namecopy) + { + namecopy[namelen] = 0; + return memcpy (namecopy, name, namelen); + } + } + } + return NULL; +# else +# error "getprogname module not ported to this OS" +# endif +} + +#endif + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/grub-core/lib/gnulib/getprogname.h b/grub-core/lib/gnulib/getprogname.h new file mode 100644 index 0000000..1590b38 --- /dev/null +++ b/grub-core/lib/gnulib/getprogname.h @@ -0,0 +1,40 @@ +/* Program name management. + Copyright (C) 2016-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _GL_GETPROGNAME_H +#define _GL_GETPROGNAME_H + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Return the base name of the executing program. + On native Windows this will usually end in ".exe" or ".EXE". */ +#ifndef HAVE_GETPROGNAME +extern char const *getprogname (void) +# ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME + _GL_ATTRIBUTE_PURE +# endif + ; +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/grub-core/lib/gnulib/gettext.h b/grub-core/lib/gnulib/gettext.h new file mode 100644 index 0000000..89f53d9 --- /dev/null +++ b/grub-core/lib/gnulib/gettext.h @@ -0,0 +1,294 @@ +/* Convenience header for conditional use of GNU <libintl.h>. + Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2019 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option + or through "#define ENABLE NLS 0" before including this file. */ +#if defined ENABLE_NLS && ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include <libintl.h> + +/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by + the gettext() and ngettext() macros. This is an alternative to calling + textdomain(), and is useful for libraries. */ +# ifdef DEFAULT_TEXT_DOMAIN +# undef gettext +# define gettext(Msgid) \ + dgettext (DEFAULT_TEXT_DOMAIN, Msgid) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) +# endif + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of <locale.h> a NOP. We don't include <libintl.h> + as well because people using "gettext.h" will not include <libintl.h>, + and also including <libintl.h> would fail on SunOS 4, whereas <locale.h> + is OK. */ +#if defined(__sun) +# include <locale.h> +#endif + +/* Many header files from the libstdc++ coming with g++ 3.3 or newer include + <libintl.h>, which chokes if dcgettext is defined as a macro. So include + it now, to make later inclusions of <libintl.h> a NOP. */ +#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) +# include <cstdlib> +# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H +# include <libintl.h> +# endif +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# undef gettext +# define gettext(Msgid) ((const char *) (Msgid)) +# undef dgettext +# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) +# undef dcgettext +# define dcgettext(Domainname, Msgid, Category) \ + ((void) (Category), dgettext (Domainname, Msgid)) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 \ + ? ((void) (Msgid2), (const char *) (Msgid1)) \ + : ((void) (Msgid1), (const char *) (Msgid2))) +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) +# undef textdomain +# define textdomain(Domainname) ((const char *) (Domainname)) +# undef bindtextdomain +# define bindtextdomain(Domainname, Dirname) \ + ((void) (Domainname), (const char *) (Dirname)) +# undef bind_textdomain_codeset +# define bind_textdomain_codeset(Domainname, Codeset) \ + ((void) (Domainname), (const char *) (Codeset)) + +#endif + +/* Prefer gnulib's setlocale override over libintl's setlocale override. */ +#ifdef GNULIB_defined_setlocale +# undef setlocale +# define setlocale rpl_setlocale +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +/* The separator between msgctxt and msgid in a .mo file. */ +#define GETTEXT_CONTEXT_GLUE "\004" + +/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a + MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be + short and rarely need to change. + The letter 'p' stands for 'particular' or 'special'. */ +#ifdef DEFAULT_TEXT_DOMAIN +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#else +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#endif +#define dpgettext(Domainname, Msgctxt, Msgid) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) +#ifdef DEFAULT_TEXT_DOMAIN +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#else +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#endif +#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +pgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + int category) +{ + const char *translation = dcgettext (domain, msg_ctxt_id, category); + if (translation == msg_ctxt_id) + return msgid; + else + return translation; +} + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +npgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + const char *translation = + dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); + if (translation == msg_ctxt_id || translation == msgid_plural) + return (n == 1 ? msgid : msgid_plural); + else + return translation; +} + +/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID + can be arbitrary expressions. But for string literals these macros are + less efficient than those above. */ + +#include <string.h> + +#if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \ + /* || (__STDC_VERSION__ == 199901L && !defined __HP_cc) + || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ ) +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 +#else +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 +#endif + +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS +#include <stdlib.h> +#endif + +#define pgettext_expr(Msgctxt, Msgid) \ + dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) +#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ + dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + int found_translation; + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcgettext (domain, msg_ctxt_id, category); + found_translation = (translation != msg_ctxt_id); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (found_translation) + return translation; + } + return msgid; +} + +#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcnpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + int found_translation; + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); + found_translation = !(translation == msg_ctxt_id || translation == msgid_plural); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (found_translation) + return translation; + } + return (n == 1 ? msgid : msgid_plural); +} + +#endif /* _LIBGETTEXT_H */ diff --git a/grub-core/lib/gnulib/glthread/lock.c b/grub-core/lib/gnulib/glthread/lock.c new file mode 100644 index 0000000..a4498cb --- /dev/null +++ b/grub-core/lib/gnulib/glthread/lock.c @@ -0,0 +1,1221 @@ +/* Locking in multithreaded situations. + Copyright (C) 2005-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2005. + Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, + gthr-win32.h. */ + +#include <config.h> + +#include "glthread/lock.h" + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1))) + +# ifdef PTHREAD_RWLOCK_INITIALIZER + +# if !HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER + /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */ + +int +glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock) +{ + pthread_rwlockattr_t attributes; + int err; + + err = pthread_rwlockattr_init (&attributes); + if (err != 0) + return err; + /* Note: PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP is the only value that + causes the writer to be preferred. PTHREAD_RWLOCK_PREFER_WRITER_NP does not + do this; see + http://man7.org/linux/man-pages/man3/pthread_rwlockattr_setkind_np.3.html */ + err = pthread_rwlockattr_setkind_np (&attributes, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); + if (err == 0) + err = pthread_rwlock_init(lock, &attributes); + /* pthread_rwlockattr_destroy always returns 0. It cannot influence the + return value. */ + pthread_rwlockattr_destroy (&attributes); + return err; +} + +# endif +# else + +int +glthread_rwlock_init_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_rwlock_init (&lock->rwlock, NULL); + if (err != 0) + return err; + lock->initialized = 1; + return 0; +} + +int +glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) +{ + if (!lock->initialized) + { + int err; + + err = pthread_mutex_lock (&lock->guard); + if (err != 0) + return err; + if (!lock->initialized) + { + err = glthread_rwlock_init_multithreaded (lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->guard); + return err; + } + } + err = pthread_mutex_unlock (&lock->guard); + if (err != 0) + return err; + } + return pthread_rwlock_rdlock (&lock->rwlock); +} + +int +glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) +{ + if (!lock->initialized) + { + int err; + + err = pthread_mutex_lock (&lock->guard); + if (err != 0) + return err; + if (!lock->initialized) + { + err = glthread_rwlock_init_multithreaded (lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->guard); + return err; + } + } + err = pthread_mutex_unlock (&lock->guard); + if (err != 0) + return err; + } + return pthread_rwlock_wrlock (&lock->rwlock); +} + +int +glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) +{ + if (!lock->initialized) + return EINVAL; + return pthread_rwlock_unlock (&lock->rwlock); +} + +int +glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) +{ + int err; + + if (!lock->initialized) + return EINVAL; + err = pthread_rwlock_destroy (&lock->rwlock); + if (err != 0) + return err; + lock->initialized = 0; + return 0; +} + +# endif + +# else + +int +glthread_rwlock_init_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_mutex_init (&lock->lock, NULL); + if (err != 0) + return err; + err = pthread_cond_init (&lock->waiting_readers, NULL); + if (err != 0) + return err; + err = pthread_cond_init (&lock->waiting_writers, NULL); + if (err != 0) + return err; + lock->waiting_writers_count = 0; + lock->runcount = 0; + return 0; +} + +int +glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_mutex_lock (&lock->lock); + if (err != 0) + return err; + /* Test whether only readers are currently running, and whether the runcount + field will not overflow, and whether no writer is waiting. The latter + condition is because POSIX recommends that "write locks shall take + precedence over read locks", to avoid "writer starvation". */ + while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0)) + { + /* This thread has to wait for a while. Enqueue it among the + waiting_readers. */ + err = pthread_cond_wait (&lock->waiting_readers, &lock->lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->lock); + return err; + } + } + lock->runcount++; + return pthread_mutex_unlock (&lock->lock); +} + +int +glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_mutex_lock (&lock->lock); + if (err != 0) + return err; + /* Test whether no readers or writers are currently running. */ + while (!(lock->runcount == 0)) + { + /* This thread has to wait for a while. Enqueue it among the + waiting_writers. */ + lock->waiting_writers_count++; + err = pthread_cond_wait (&lock->waiting_writers, &lock->lock); + if (err != 0) + { + lock->waiting_writers_count--; + pthread_mutex_unlock (&lock->lock); + return err; + } + lock->waiting_writers_count--; + } + lock->runcount--; /* runcount becomes -1 */ + return pthread_mutex_unlock (&lock->lock); +} + +int +glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_mutex_lock (&lock->lock); + if (err != 0) + return err; + if (lock->runcount < 0) + { + /* Drop a writer lock. */ + if (!(lock->runcount == -1)) + { + pthread_mutex_unlock (&lock->lock); + return EINVAL; + } + lock->runcount = 0; + } + else + { + /* Drop a reader lock. */ + if (!(lock->runcount > 0)) + { + pthread_mutex_unlock (&lock->lock); + return EINVAL; + } + lock->runcount--; + } + if (lock->runcount == 0) + { + /* POSIX recommends that "write locks shall take precedence over read + locks", to avoid "writer starvation". */ + if (lock->waiting_writers_count > 0) + { + /* Wake up one of the waiting writers. */ + err = pthread_cond_signal (&lock->waiting_writers); + if (err != 0) + { + pthread_mutex_unlock (&lock->lock); + return err; + } + } + else + { + /* Wake up all waiting readers. */ + err = pthread_cond_broadcast (&lock->waiting_readers); + if (err != 0) + { + pthread_mutex_unlock (&lock->lock); + return err; + } + } + } + return pthread_mutex_unlock (&lock->lock); +} + +int +glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) +{ + int err; + + err = pthread_mutex_destroy (&lock->lock); + if (err != 0) + return err; + err = pthread_cond_destroy (&lock->waiting_readers); + if (err != 0) + return err; + err = pthread_cond_destroy (&lock->waiting_writers); + if (err != 0) + return err; + return 0; +} + +# endif + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +# if HAVE_PTHREAD_MUTEX_RECURSIVE + +# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP + +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) +{ + pthread_mutexattr_t attributes; + int err; + + err = pthread_mutexattr_init (&attributes); + if (err != 0) + return err; + err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutex_init (lock, &attributes); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutexattr_destroy (&attributes); + if (err != 0) + return err; + return 0; +} + +# else + +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) +{ + pthread_mutexattr_t attributes; + int err; + + err = pthread_mutexattr_init (&attributes); + if (err != 0) + return err; + err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutex_init (&lock->recmutex, &attributes); + if (err != 0) + { + pthread_mutexattr_destroy (&attributes); + return err; + } + err = pthread_mutexattr_destroy (&attributes); + if (err != 0) + return err; + lock->initialized = 1; + return 0; +} + +int +glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) +{ + if (!lock->initialized) + { + int err; + + err = pthread_mutex_lock (&lock->guard); + if (err != 0) + return err; + if (!lock->initialized) + { + err = glthread_recursive_lock_init_multithreaded (lock); + if (err != 0) + { + pthread_mutex_unlock (&lock->guard); + return err; + } + } + err = pthread_mutex_unlock (&lock->guard); + if (err != 0) + return err; + } + return pthread_mutex_lock (&lock->recmutex); +} + +int +glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) +{ + if (!lock->initialized) + return EINVAL; + return pthread_mutex_unlock (&lock->recmutex); +} + +int +glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) +{ + int err; + + if (!lock->initialized) + return EINVAL; + err = pthread_mutex_destroy (&lock->recmutex); + if (err != 0) + return err; + lock->initialized = 0; + return 0; +} + +# endif + +# else + +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) +{ + int err; + + err = pthread_mutex_init (&lock->mutex, NULL); + if (err != 0) + return err; + lock->owner = (pthread_t) 0; + lock->depth = 0; + return 0; +} + +int +glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) +{ + pthread_t self = pthread_self (); + if (lock->owner != self) + { + int err; + + err = pthread_mutex_lock (&lock->mutex); + if (err != 0) + return err; + lock->owner = self; + } + if (++(lock->depth) == 0) /* wraparound? */ + { + lock->depth--; + return EAGAIN; + } + return 0; +} + +int +glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) +{ + if (lock->owner != pthread_self ()) + return EPERM; + if (lock->depth == 0) + return EINVAL; + if (--(lock->depth) == 0) + { + lock->owner = (pthread_t) 0; + return pthread_mutex_unlock (&lock->mutex); + } + else + return 0; +} + +int +glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) +{ + if (lock->owner != (pthread_t) 0) + return EBUSY; + return pthread_mutex_destroy (&lock->mutex); +} + +# endif + +/* -------------------------- gl_once_t datatype -------------------------- */ + +static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT; + +int +glthread_once_singlethreaded (pthread_once_t *once_control) +{ + /* We don't know whether pthread_once_t is an integer type, a floating-point + type, a pointer type, or a structure type. */ + char *firstbyte = (char *)once_control; + if (*firstbyte == *(const char *)&fresh_once) + { + /* First time use of once_control. Invert the first byte. */ + *firstbyte = ~ *(const char *)&fresh_once; + return 1; + } + else + return 0; +} + +#endif + +/* ========================================================================= */ + +#if USE_PTH_THREADS + +/* Use the GNU Pth threads library. */ + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +# if !HAVE_PTH_RWLOCK_ACQUIRE_PREFER_WRITER + +int +glthread_rwlock_init_multithreaded (gl_rwlock_t *lock) +{ + if (!pth_mutex_init (&lock->lock)) + return errno; + if (!pth_cond_init (&lock->waiting_readers)) + return errno; + if (!pth_cond_init (&lock->waiting_writers)) + return errno; + lock->waiting_writers_count = 0; + lock->runcount = 0; + lock->initialized = 1; + return 0; +} + +int +glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) +{ + if (!lock->initialized) + glthread_rwlock_init_multithreaded (lock); + if (!pth_mutex_acquire (&lock->lock, 0, NULL)) + return errno; + /* Test whether only readers are currently running, and whether the runcount + field will not overflow, and whether no writer is waiting. The latter + condition is because POSIX recommends that "write locks shall take + precedence over read locks", to avoid "writer starvation". */ + while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0)) + { + /* This thread has to wait for a while. Enqueue it among the + waiting_readers. */ + if (!pth_cond_await (&lock->waiting_readers, &lock->lock, NULL)) + { + int err = errno; + pth_mutex_release (&lock->lock); + return err; + } + } + lock->runcount++; + return (!pth_mutex_release (&lock->lock) ? errno : 0); +} + +int +glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) +{ + if (!lock->initialized) + glthread_rwlock_init_multithreaded (lock); + if (!pth_mutex_acquire (&lock->lock, 0, NULL)) + return errno; + /* Test whether no readers or writers are currently running. */ + while (!(lock->runcount == 0)) + { + /* This thread has to wait for a while. Enqueue it among the + waiting_writers. */ + lock->waiting_writers_count++; + if (!pth_cond_await (&lock->waiting_writers, &lock->lock, NULL)) + { + int err = errno; + lock->waiting_writers_count--; + pth_mutex_release (&lock->lock); + return err; + } + lock->waiting_writers_count--; + } + lock->runcount--; /* runcount becomes -1 */ + return (!pth_mutex_release (&lock->lock) ? errno : 0); +} + +int +glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) +{ + int err; + + if (!lock->initialized) + return EINVAL; + if (!pth_mutex_acquire (&lock->lock, 0, NULL)) + return errno; + if (lock->runcount < 0) + { + /* Drop a writer lock. */ + if (!(lock->runcount == -1)) + { + pth_mutex_release (&lock->lock); + return EINVAL; + } + lock->runcount = 0; + } + else + { + /* Drop a reader lock. */ + if (!(lock->runcount > 0)) + { + pth_mutex_release (&lock->lock); + return EINVAL; + } + lock->runcount--; + } + if (lock->runcount == 0) + { + /* POSIX recommends that "write locks shall take precedence over read + locks", to avoid "writer starvation". */ + if (lock->waiting_writers_count > 0) + { + /* Wake up one of the waiting writers. */ + if (!pth_cond_notify (&lock->waiting_writers, FALSE)) + { + int err = errno; + pth_mutex_release (&lock->lock); + return err; + } + } + else + { + /* Wake up all waiting readers. */ + if (!pth_cond_notify (&lock->waiting_readers, TRUE)) + { + int err = errno; + pth_mutex_release (&lock->lock); + return err; + } + } + } + return (!pth_mutex_release (&lock->lock) ? errno : 0); +} + +int +glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) +{ + lock->initialized = 0; + return 0; +} + +# endif + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +/* -------------------------- gl_once_t datatype -------------------------- */ + +static void +glthread_once_call (void *arg) +{ + void (**gl_once_temp_addr) (void) = (void (**) (void)) arg; + void (*initfunction) (void) = *gl_once_temp_addr; + initfunction (); +} + +int +glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void)) +{ + void (*temp) (void) = initfunction; + return (!pth_once (once_control, glthread_once_call, &temp) ? errno : 0); +} + +int +glthread_once_singlethreaded (pth_once_t *once_control) +{ + /* We know that pth_once_t is an integer type. */ + if (*once_control == PTH_ONCE_INIT) + { + /* First time use of once_control. Invert the marker. */ + *once_control = ~ PTH_ONCE_INIT; + return 1; + } + else + return 0; +} + +#endif + +/* ========================================================================= */ + +#if USE_SOLARIS_THREADS + +/* Use the old Solaris threads library. */ + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +int +glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) +{ + int err; + + err = mutex_init (&lock->mutex, USYNC_THREAD, NULL); + if (err != 0) + return err; + lock->owner = (thread_t) 0; + lock->depth = 0; + return 0; +} + +int +glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) +{ + thread_t self = thr_self (); + if (lock->owner != self) + { + int err; + + err = mutex_lock (&lock->mutex); + if (err != 0) + return err; + lock->owner = self; + } + if (++(lock->depth) == 0) /* wraparound? */ + { + lock->depth--; + return EAGAIN; + } + return 0; +} + +int +glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) +{ + if (lock->owner != thr_self ()) + return EPERM; + if (lock->depth == 0) + return EINVAL; + if (--(lock->depth) == 0) + { + lock->owner = (thread_t) 0; + return mutex_unlock (&lock->mutex); + } + else + return 0; +} + +int +glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) +{ + if (lock->owner != (thread_t) 0) + return EBUSY; + return mutex_destroy (&lock->mutex); +} + +/* -------------------------- gl_once_t datatype -------------------------- */ + +int +glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void)) +{ + if (!once_control->inited) + { + int err; + + /* Use the mutex to guarantee that if another thread is already calling + the initfunction, this thread waits until it's finished. */ + err = mutex_lock (&once_control->mutex); + if (err != 0) + return err; + if (!once_control->inited) + { + once_control->inited = 1; + initfunction (); + } + return mutex_unlock (&once_control->mutex); + } + else + return 0; +} + +int +glthread_once_singlethreaded (gl_once_t *once_control) +{ + /* We know that gl_once_t contains an integer type. */ + if (!once_control->inited) + { + /* First time use of once_control. Invert the marker. */ + once_control->inited = ~ 0; + return 1; + } + else + return 0; +} + +#endif + +/* ========================================================================= */ + +#if USE_WINDOWS_THREADS + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +void +glthread_lock_init_func (gl_lock_t *lock) +{ + InitializeCriticalSection (&lock->lock); + lock->guard.done = 1; +} + +int +glthread_lock_lock_func (gl_lock_t *lock) +{ + if (!lock->guard.done) + { + if (InterlockedIncrement (&lock->guard.started) == 0) + /* This thread is the first one to need this lock. Initialize it. */ + glthread_lock_init (lock); + else + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } + EnterCriticalSection (&lock->lock); + return 0; +} + +int +glthread_lock_unlock_func (gl_lock_t *lock) +{ + if (!lock->guard.done) + return EINVAL; + LeaveCriticalSection (&lock->lock); + return 0; +} + +int +glthread_lock_destroy_func (gl_lock_t *lock) +{ + if (!lock->guard.done) + return EINVAL; + DeleteCriticalSection (&lock->lock); + lock->guard.done = 0; + return 0; +} + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +/* In this file, the waitqueues are implemented as circular arrays. */ +#define gl_waitqueue_t gl_carray_waitqueue_t + +static void +gl_waitqueue_init (gl_waitqueue_t *wq) +{ + wq->array = NULL; + wq->count = 0; + wq->alloc = 0; + wq->offset = 0; +} + +/* Enqueues the current thread, represented by an event, in a wait queue. + Returns INVALID_HANDLE_VALUE if an allocation failure occurs. */ +static HANDLE +gl_waitqueue_add (gl_waitqueue_t *wq) +{ + HANDLE event; + unsigned int index; + + if (wq->count == wq->alloc) + { + unsigned int new_alloc = 2 * wq->alloc + 1; + HANDLE *new_array = + (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE)); + if (new_array == NULL) + /* No more memory. */ + return INVALID_HANDLE_VALUE; + /* Now is a good opportunity to rotate the array so that its contents + starts at offset 0. */ + if (wq->offset > 0) + { + unsigned int old_count = wq->count; + unsigned int old_alloc = wq->alloc; + unsigned int old_offset = wq->offset; + unsigned int i; + if (old_offset + old_count > old_alloc) + { + unsigned int limit = old_offset + old_count - old_alloc; + for (i = 0; i < limit; i++) + new_array[old_alloc + i] = new_array[i]; + } + for (i = 0; i < old_count; i++) + new_array[i] = new_array[old_offset + i]; + wq->offset = 0; + } + wq->array = new_array; + wq->alloc = new_alloc; + } + /* Whether the created event is a manual-reset one or an auto-reset one, + does not matter, since we will wait on it only once. */ + event = CreateEvent (NULL, TRUE, FALSE, NULL); + if (event == INVALID_HANDLE_VALUE) + /* No way to allocate an event. */ + return INVALID_HANDLE_VALUE; + index = wq->offset + wq->count; + if (index >= wq->alloc) + index -= wq->alloc; + wq->array[index] = event; + wq->count++; + return event; +} + +/* Notifies the first thread from a wait queue and dequeues it. */ +static void +gl_waitqueue_notify_first (gl_waitqueue_t *wq) +{ + SetEvent (wq->array[wq->offset + 0]); + wq->offset++; + wq->count--; + if (wq->count == 0 || wq->offset == wq->alloc) + wq->offset = 0; +} + +/* Notifies all threads from a wait queue and dequeues them all. */ +static void +gl_waitqueue_notify_all (gl_waitqueue_t *wq) +{ + unsigned int i; + + for (i = 0; i < wq->count; i++) + { + unsigned int index = wq->offset + i; + if (index >= wq->alloc) + index -= wq->alloc; + SetEvent (wq->array[index]); + } + wq->count = 0; + wq->offset = 0; +} + +void +glthread_rwlock_init_func (gl_rwlock_t *lock) +{ + InitializeCriticalSection (&lock->lock); + gl_waitqueue_init (&lock->waiting_readers); + gl_waitqueue_init (&lock->waiting_writers); + lock->runcount = 0; + lock->guard.done = 1; +} + +int +glthread_rwlock_rdlock_func (gl_rwlock_t *lock) +{ + if (!lock->guard.done) + { + if (InterlockedIncrement (&lock->guard.started) == 0) + /* This thread is the first one to need this lock. Initialize it. */ + glthread_rwlock_init (lock); + else + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } + EnterCriticalSection (&lock->lock); + /* Test whether only readers are currently running, and whether the runcount + field will not overflow, and whether no writer is waiting. The latter + condition is because POSIX recommends that "write locks shall take + precedence over read locks", to avoid "writer starvation". */ + if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0)) + { + /* This thread has to wait for a while. Enqueue it among the + waiting_readers. */ + HANDLE event = gl_waitqueue_add (&lock->waiting_readers); + if (event != INVALID_HANDLE_VALUE) + { + DWORD result; + LeaveCriticalSection (&lock->lock); + /* Wait until another thread signals this event. */ + result = WaitForSingleObject (event, INFINITE); + if (result == WAIT_FAILED || result == WAIT_TIMEOUT) + abort (); + CloseHandle (event); + /* The thread which signalled the event already did the bookkeeping: + removed us from the waiting_readers, incremented lock->runcount. */ + if (!(lock->runcount > 0)) + abort (); + return 0; + } + else + { + /* Allocation failure. Weird. */ + do + { + LeaveCriticalSection (&lock->lock); + Sleep (1); + EnterCriticalSection (&lock->lock); + } + while (!(lock->runcount + 1 > 0)); + } + } + lock->runcount++; + LeaveCriticalSection (&lock->lock); + return 0; +} + +int +glthread_rwlock_wrlock_func (gl_rwlock_t *lock) +{ + if (!lock->guard.done) + { + if (InterlockedIncrement (&lock->guard.started) == 0) + /* This thread is the first one to need this lock. Initialize it. */ + glthread_rwlock_init (lock); + else + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } + EnterCriticalSection (&lock->lock); + /* Test whether no readers or writers are currently running. */ + if (!(lock->runcount == 0)) + { + /* This thread has to wait for a while. Enqueue it among the + waiting_writers. */ + HANDLE event = gl_waitqueue_add (&lock->waiting_writers); + if (event != INVALID_HANDLE_VALUE) + { + DWORD result; + LeaveCriticalSection (&lock->lock); + /* Wait until another thread signals this event. */ + result = WaitForSingleObject (event, INFINITE); + if (result == WAIT_FAILED || result == WAIT_TIMEOUT) + abort (); + CloseHandle (event); + /* The thread which signalled the event already did the bookkeeping: + removed us from the waiting_writers, set lock->runcount = -1. */ + if (!(lock->runcount == -1)) + abort (); + return 0; + } + else + { + /* Allocation failure. Weird. */ + do + { + LeaveCriticalSection (&lock->lock); + Sleep (1); + EnterCriticalSection (&lock->lock); + } + while (!(lock->runcount == 0)); + } + } + lock->runcount--; /* runcount becomes -1 */ + LeaveCriticalSection (&lock->lock); + return 0; +} + +int +glthread_rwlock_unlock_func (gl_rwlock_t *lock) +{ + if (!lock->guard.done) + return EINVAL; + EnterCriticalSection (&lock->lock); + if (lock->runcount < 0) + { + /* Drop a writer lock. */ + if (!(lock->runcount == -1)) + abort (); + lock->runcount = 0; + } + else + { + /* Drop a reader lock. */ + if (!(lock->runcount > 0)) + { + LeaveCriticalSection (&lock->lock); + return EPERM; + } + lock->runcount--; + } + if (lock->runcount == 0) + { + /* POSIX recommends that "write locks shall take precedence over read + locks", to avoid "writer starvation". */ + if (lock->waiting_writers.count > 0) + { + /* Wake up one of the waiting writers. */ + lock->runcount--; + gl_waitqueue_notify_first (&lock->waiting_writers); + } + else + { + /* Wake up all waiting readers. */ + lock->runcount += lock->waiting_readers.count; + gl_waitqueue_notify_all (&lock->waiting_readers); + } + } + LeaveCriticalSection (&lock->lock); + return 0; +} + +int +glthread_rwlock_destroy_func (gl_rwlock_t *lock) +{ + if (!lock->guard.done) + return EINVAL; + if (lock->runcount != 0) + return EBUSY; + DeleteCriticalSection (&lock->lock); + if (lock->waiting_readers.array != NULL) + free (lock->waiting_readers.array); + if (lock->waiting_writers.array != NULL) + free (lock->waiting_writers.array); + lock->guard.done = 0; + return 0; +} + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +void +glthread_recursive_lock_init_func (gl_recursive_lock_t *lock) +{ + lock->owner = 0; + lock->depth = 0; + InitializeCriticalSection (&lock->lock); + lock->guard.done = 1; +} + +int +glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock) +{ + if (!lock->guard.done) + { + if (InterlockedIncrement (&lock->guard.started) == 0) + /* This thread is the first one to need this lock. Initialize it. */ + glthread_recursive_lock_init (lock); + else + /* Yield the CPU while waiting for another thread to finish + initializing this lock. */ + while (!lock->guard.done) + Sleep (0); + } + { + DWORD self = GetCurrentThreadId (); + if (lock->owner != self) + { + EnterCriticalSection (&lock->lock); + lock->owner = self; + } + if (++(lock->depth) == 0) /* wraparound? */ + { + lock->depth--; + return EAGAIN; + } + } + return 0; +} + +int +glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock) +{ + if (lock->owner != GetCurrentThreadId ()) + return EPERM; + if (lock->depth == 0) + return EINVAL; + if (--(lock->depth) == 0) + { + lock->owner = 0; + LeaveCriticalSection (&lock->lock); + } + return 0; +} + +int +glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock) +{ + if (lock->owner != 0) + return EBUSY; + DeleteCriticalSection (&lock->lock); + lock->guard.done = 0; + return 0; +} + +/* -------------------------- gl_once_t datatype -------------------------- */ + +void +glthread_once_func (gl_once_t *once_control, void (*initfunction) (void)) +{ + if (once_control->inited <= 0) + { + if (InterlockedIncrement (&once_control->started) == 0) + { + /* This thread is the first one to come to this once_control. */ + InitializeCriticalSection (&once_control->lock); + EnterCriticalSection (&once_control->lock); + once_control->inited = 0; + initfunction (); + once_control->inited = 1; + LeaveCriticalSection (&once_control->lock); + } + else + { + /* Undo last operation. */ + InterlockedDecrement (&once_control->started); + /* Some other thread has already started the initialization. + Yield the CPU while waiting for the other thread to finish + initializing and taking the lock. */ + while (once_control->inited < 0) + Sleep (0); + if (once_control->inited <= 0) + { + /* Take the lock. This blocks until the other thread has + finished calling the initfunction. */ + EnterCriticalSection (&once_control->lock); + LeaveCriticalSection (&once_control->lock); + if (!(once_control->inited > 0)) + abort (); + } + } + } +} + +#endif + +/* ========================================================================= */ diff --git a/grub-core/lib/gnulib/glthread/lock.h b/grub-core/lib/gnulib/glthread/lock.h new file mode 100644 index 0000000..636b089 --- /dev/null +++ b/grub-core/lib/gnulib/glthread/lock.h @@ -0,0 +1,988 @@ +/* Locking in multithreaded situations. + Copyright (C) 2005-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2005. + Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, + gthr-win32.h. */ + +/* This file contains locking primitives for use with a given thread library. + It does not contain primitives for creating threads or for other + synchronization primitives. + + Normal (non-recursive) locks: + Type: gl_lock_t + Declaration: gl_lock_define(extern, name) + Initializer: gl_lock_define_initialized(, name) + Initialization: gl_lock_init (name); + Taking the lock: gl_lock_lock (name); + Releasing the lock: gl_lock_unlock (name); + De-initialization: gl_lock_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_lock_init (&name); + Taking the lock: err = glthread_lock_lock (&name); + Releasing the lock: err = glthread_lock_unlock (&name); + De-initialization: err = glthread_lock_destroy (&name); + + Read-Write (non-recursive) locks: + Type: gl_rwlock_t + Declaration: gl_rwlock_define(extern, name) + Initializer: gl_rwlock_define_initialized(, name) + Initialization: gl_rwlock_init (name); + Taking the lock: gl_rwlock_rdlock (name); + gl_rwlock_wrlock (name); + Releasing the lock: gl_rwlock_unlock (name); + De-initialization: gl_rwlock_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_rwlock_init (&name); + Taking the lock: err = glthread_rwlock_rdlock (&name); + err = glthread_rwlock_wrlock (&name); + Releasing the lock: err = glthread_rwlock_unlock (&name); + De-initialization: err = glthread_rwlock_destroy (&name); + + Recursive locks: + Type: gl_recursive_lock_t + Declaration: gl_recursive_lock_define(extern, name) + Initializer: gl_recursive_lock_define_initialized(, name) + Initialization: gl_recursive_lock_init (name); + Taking the lock: gl_recursive_lock_lock (name); + Releasing the lock: gl_recursive_lock_unlock (name); + De-initialization: gl_recursive_lock_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_recursive_lock_init (&name); + Taking the lock: err = glthread_recursive_lock_lock (&name); + Releasing the lock: err = glthread_recursive_lock_unlock (&name); + De-initialization: err = glthread_recursive_lock_destroy (&name); + + Once-only execution: + Type: gl_once_t + Initializer: gl_once_define(extern, name) + Execution: gl_once (name, initfunction); + Equivalent functions with control of error handling: + Execution: err = glthread_once (&name, initfunction); +*/ + + +#ifndef _LOCK_H +#define _LOCK_H + +#include <errno.h> +#include <stdlib.h> + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +/* Use the POSIX threads library. */ + +# include <pthread.h> + +# ifdef __cplusplus +extern "C" { +# endif + +# if PTHREAD_IN_USE_DETECTION_HARD + +/* The pthread_in_use() detection needs to be done at runtime. */ +# define pthread_in_use() \ + glthread_in_use () +extern int glthread_in_use (void); + +# endif + +# if USE_POSIX_THREADS_WEAK + +/* Use weak references to the POSIX threads library. */ + +/* Weak references avoid dragging in external libraries if the other parts + of the program don't use them. Here we use them, because we don't want + every program that uses libintl to depend on libpthread. This assumes + that libpthread would not be loaded after libintl; i.e. if libintl is + loaded first, by an executable that does not depend on libpthread, and + then a module is dynamically loaded that depends on libpthread, libintl + will not be multithread-safe. */ + +/* The way to test at runtime whether libpthread is present is to test + whether a function pointer's value, such as &pthread_mutex_init, is + non-NULL. However, some versions of GCC have a bug through which, in + PIC mode, &foo != NULL always evaluates to true if there is a direct + call to foo(...) in the same function. To avoid this, we test the + address of a function in libpthread that we don't use. */ + +# pragma weak pthread_mutex_init +# pragma weak pthread_mutex_lock +# pragma weak pthread_mutex_unlock +# pragma weak pthread_mutex_destroy +# pragma weak pthread_rwlock_init +# pragma weak pthread_rwlock_rdlock +# pragma weak pthread_rwlock_wrlock +# pragma weak pthread_rwlock_unlock +# pragma weak pthread_rwlock_destroy +# pragma weak pthread_once +# pragma weak pthread_cond_init +# pragma weak pthread_cond_wait +# pragma weak pthread_cond_signal +# pragma weak pthread_cond_broadcast +# pragma weak pthread_cond_destroy +# pragma weak pthread_mutexattr_init +# pragma weak pthread_mutexattr_settype +# pragma weak pthread_mutexattr_destroy +# pragma weak pthread_rwlockattr_init +# if __GNU_LIBRARY__ > 1 +# pragma weak pthread_rwlockattr_setkind_np +# endif +# pragma weak pthread_rwlockattr_destroy +# ifndef pthread_self +# pragma weak pthread_self +# endif + +# if !PTHREAD_IN_USE_DETECTION_HARD + /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols + can be used to determine whether libpthread is in use. These are: + pthread_mutexattr_gettype + pthread_rwlockattr_destroy + pthread_rwlockattr_init + */ +# pragma weak pthread_mutexattr_gettype +# define pthread_in_use() (pthread_mutexattr_gettype != NULL) +# endif + +# else + +# if !PTHREAD_IN_USE_DETECTION_HARD +# define pthread_in_use() 1 +# endif + +# endif + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +typedef pthread_mutex_t gl_lock_t; +# define gl_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS pthread_mutex_t NAME; +# define gl_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer; +# define gl_lock_initializer \ + PTHREAD_MUTEX_INITIALIZER +# define glthread_lock_init(LOCK) \ + (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0) +# define glthread_lock_lock(LOCK) \ + (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0) +# define glthread_lock_unlock(LOCK) \ + (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0) +# define glthread_lock_destroy(LOCK) \ + (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0) + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1))) + +# ifdef PTHREAD_RWLOCK_INITIALIZER + +typedef pthread_rwlock_t gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS pthread_rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer; +# if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER +# define gl_rwlock_initializer \ + PTHREAD_RWLOCK_INITIALIZER +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0) +# else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */ +# define gl_rwlock_initializer \ + PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0) +extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock); +# endif +# define glthread_rwlock_rdlock(LOCK) \ + (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0) + +# else + +typedef struct + { + int initialized; + pthread_mutex_t guard; /* protects the initialization */ + pthread_rwlock_t rwlock; /* read-write lock */ + } + gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + { 0, PTHREAD_MUTEX_INITIALIZER } +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) +extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); + +# endif + +# else + +typedef struct + { + pthread_mutex_t lock; /* protects the remaining fields */ + pthread_cond_t waiting_readers; /* waiting readers */ + pthread_cond_t waiting_writers; /* waiting writers */ + unsigned int waiting_writers_count; /* number of waiting writers */ + int runcount; /* number of readers running, or -1 when a writer runs */ + } + gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 } +# define glthread_rwlock_init(LOCK) \ + (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) +extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); + +# endif + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +# if HAVE_PTHREAD_MUTEX_RECURSIVE + +# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP + +typedef pthread_mutex_t gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS pthread_mutex_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer; +# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER +# define gl_recursive_lock_initializer \ + PTHREAD_RECURSIVE_MUTEX_INITIALIZER +# else +# define gl_recursive_lock_initializer \ + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +# endif +# define glthread_recursive_lock_init(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0) +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); + +# else + +typedef struct + { + pthread_mutex_t recmutex; /* recursive mutex */ + pthread_mutex_t guard; /* protects the initialization */ + int initialized; + } + gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; +# define gl_recursive_lock_initializer \ + { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 } +# define glthread_recursive_lock_init(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); + +# endif + +# else + +/* Old versions of POSIX threads on Solaris did not have recursive locks. + We have to implement them ourselves. */ + +typedef struct + { + pthread_mutex_t mutex; + pthread_t owner; + unsigned long depth; + } + gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; +# define gl_recursive_lock_initializer \ + { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 } +# define glthread_recursive_lock_init(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); + +# endif + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef pthread_once_t gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (pthread_in_use () \ + ? pthread_once (ONCE_CONTROL, INITFUNCTION) \ + : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) +extern int glthread_once_singlethreaded (pthread_once_t *once_control); + +# ifdef __cplusplus +} +# endif + +#endif + +/* ========================================================================= */ + +#if USE_PTH_THREADS + +/* Use the GNU Pth threads library. */ + +# include <pth.h> + +# ifdef __cplusplus +extern "C" { +# endif + +# if USE_PTH_THREADS_WEAK + +/* Use weak references to the GNU Pth threads library. */ + +# pragma weak pth_mutex_init +# pragma weak pth_mutex_acquire +# pragma weak pth_mutex_release +# pragma weak pth_rwlock_init +# pragma weak pth_rwlock_acquire +# pragma weak pth_rwlock_release +# pragma weak pth_once +# pragma weak pth_cond_init +# pragma weak pth_cond_await +# pragma weak pth_cond_notify + +# pragma weak pth_cancel +# define pth_in_use() (pth_cancel != NULL) + +# else + +# define pth_in_use() 1 + +# endif + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +typedef pth_mutex_t gl_lock_t; +# define gl_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS pth_mutex_t NAME; +# define gl_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pth_mutex_t NAME = gl_lock_initializer; +# define gl_lock_initializer \ + PTH_MUTEX_INIT +# define glthread_lock_init(LOCK) \ + (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0) +# define glthread_lock_lock(LOCK) \ + (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0) +# define glthread_lock_unlock(LOCK) \ + (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0) +# define glthread_lock_destroy(LOCK) \ + ((void)(LOCK), 0) + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +/* Pth pth_rwlock_acquire always prefers readers. No autoconf test so far. */ +# if HAVE_PTH_RWLOCK_ACQUIRE_PREFER_WRITER + +typedef pth_rwlock_t gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS pth_rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + PTH_RWLOCK_INIT +# define glthread_rwlock_init(LOCK) \ + (pth_in_use () && !pth_rwlock_init (LOCK) ? errno : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RD, 0, NULL) ? errno : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RW, 0, NULL) ? errno : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pth_in_use () && !pth_rwlock_release (LOCK) ? errno : 0) +# define glthread_rwlock_destroy(LOCK) \ + ((void)(LOCK), 0) + +# else + +typedef struct + { + int initialized; + pth_mutex_t lock; /* protects the remaining fields */ + pth_cond_t waiting_readers; /* waiting readers */ + pth_cond_t waiting_writers; /* waiting writers */ + unsigned int waiting_writers_count; /* number of waiting writers */ + int runcount; /* number of readers running, or -1 when a writer runs */ + } + gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + { 0 } +# define glthread_rwlock_init(LOCK) \ + (pth_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (pth_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (pth_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (pth_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (pth_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0) +extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock); +extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock); + +# endif + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +/* In Pth, mutexes are recursive by default. */ +typedef pth_mutex_t gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS pth_mutex_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer; +# define gl_recursive_lock_initializer \ + PTH_MUTEX_INIT +# define glthread_recursive_lock_init(LOCK) \ + (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + ((void)(LOCK), 0) + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef pth_once_t gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (pth_in_use () \ + ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \ + : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) +extern int glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void)); +extern int glthread_once_singlethreaded (pth_once_t *once_control); + +# ifdef __cplusplus +} +# endif + +#endif + +/* ========================================================================= */ + +#if USE_SOLARIS_THREADS + +/* Use the old Solaris threads library. */ + +# include <thread.h> +# include <synch.h> + +# ifdef __cplusplus +extern "C" { +# endif + +# if USE_SOLARIS_THREADS_WEAK + +/* Use weak references to the old Solaris threads library. */ + +# pragma weak mutex_init +# pragma weak mutex_lock +# pragma weak mutex_unlock +# pragma weak mutex_destroy +# pragma weak rwlock_init +# pragma weak rw_rdlock +# pragma weak rw_wrlock +# pragma weak rw_unlock +# pragma weak rwlock_destroy +# pragma weak thr_self + +# pragma weak thr_suspend +# define thread_in_use() (thr_suspend != NULL) + +# else + +# define thread_in_use() 1 + +# endif + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +typedef mutex_t gl_lock_t; +# define gl_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS mutex_t NAME; +# define gl_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS mutex_t NAME = gl_lock_initializer; +# define gl_lock_initializer \ + DEFAULTMUTEX +# define glthread_lock_init(LOCK) \ + (thread_in_use () ? mutex_init (LOCK, USYNC_THREAD, NULL) : 0) +# define glthread_lock_lock(LOCK) \ + (thread_in_use () ? mutex_lock (LOCK) : 0) +# define glthread_lock_unlock(LOCK) \ + (thread_in_use () ? mutex_unlock (LOCK) : 0) +# define glthread_lock_destroy(LOCK) \ + (thread_in_use () ? mutex_destroy (LOCK) : 0) + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +typedef rwlock_t gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + DEFAULTRWLOCK +# define glthread_rwlock_init(LOCK) \ + (thread_in_use () ? rwlock_init (LOCK, USYNC_THREAD, NULL) : 0) +# define glthread_rwlock_rdlock(LOCK) \ + (thread_in_use () ? rw_rdlock (LOCK) : 0) +# define glthread_rwlock_wrlock(LOCK) \ + (thread_in_use () ? rw_wrlock (LOCK) : 0) +# define glthread_rwlock_unlock(LOCK) \ + (thread_in_use () ? rw_unlock (LOCK) : 0) +# define glthread_rwlock_destroy(LOCK) \ + (thread_in_use () ? rwlock_destroy (LOCK) : 0) + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +/* Old Solaris threads did not have recursive locks. + We have to implement them ourselves. */ + +typedef struct + { + mutex_t mutex; + thread_t owner; + unsigned long depth; + } + gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; +# define gl_recursive_lock_initializer \ + { DEFAULTMUTEX, (thread_t) 0, 0 } +# define glthread_recursive_lock_init(LOCK) \ + (thread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_lock(LOCK) \ + (thread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_unlock(LOCK) \ + (thread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0) +# define glthread_recursive_lock_destroy(LOCK) \ + (thread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0) +extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock); + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef struct + { + volatile int inited; + mutex_t mutex; + } + gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX }; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (thread_in_use () \ + ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \ + : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0)) +extern int glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void)); +extern int glthread_once_singlethreaded (gl_once_t *once_control); + +# ifdef __cplusplus +} +# endif + +#endif + +/* ========================================================================= */ + +#if USE_WINDOWS_THREADS + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include <windows.h> + +# ifdef __cplusplus +extern "C" { +# endif + +/* We can use CRITICAL_SECTION directly, rather than the native Windows Event, + Mutex, Semaphore types, because + - we need only to synchronize inside a single process (address space), + not inter-process locking, + - we don't need to support trylock operations. (TryEnterCriticalSection + does not work on Windows 95/98/ME. Packages that need trylock usually + define their own mutex type.) */ + +/* There is no way to statically initialize a CRITICAL_SECTION. It needs + to be done lazily, once only. For this we need spinlocks. */ + +typedef struct { volatile int done; volatile long started; } gl_spinlock_t; + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +typedef struct + { + gl_spinlock_t guard; /* protects the initialization */ + CRITICAL_SECTION lock; + } + gl_lock_t; +# define gl_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_lock_t NAME; +# define gl_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_lock_t NAME = gl_lock_initializer; +# define gl_lock_initializer \ + { { 0, -1 } } +# define glthread_lock_init(LOCK) \ + (glthread_lock_init_func (LOCK), 0) +# define glthread_lock_lock(LOCK) \ + glthread_lock_lock_func (LOCK) +# define glthread_lock_unlock(LOCK) \ + glthread_lock_unlock_func (LOCK) +# define glthread_lock_destroy(LOCK) \ + glthread_lock_destroy_func (LOCK) +extern void glthread_lock_init_func (gl_lock_t *lock); +extern int glthread_lock_lock_func (gl_lock_t *lock); +extern int glthread_lock_unlock_func (gl_lock_t *lock); +extern int glthread_lock_destroy_func (gl_lock_t *lock); + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +/* It is impossible to implement read-write locks using plain locks, without + introducing an extra thread dedicated to managing read-write locks. + Therefore here we need to use the low-level Event type. */ + +typedef struct + { + HANDLE *array; /* array of waiting threads, each represented by an event */ + unsigned int count; /* number of waiting threads */ + unsigned int alloc; /* length of allocated array */ + unsigned int offset; /* index of first waiting thread in array */ + } + gl_carray_waitqueue_t; +typedef struct + { + gl_spinlock_t guard; /* protects the initialization */ + CRITICAL_SECTION lock; /* protects the remaining fields */ + gl_carray_waitqueue_t waiting_readers; /* waiting readers */ + gl_carray_waitqueue_t waiting_writers; /* waiting writers */ + int runcount; /* number of readers running, or -1 when a writer runs */ + } + gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME; +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer; +# define gl_rwlock_initializer \ + { { 0, -1 } } +# define glthread_rwlock_init(LOCK) \ + (glthread_rwlock_init_func (LOCK), 0) +# define glthread_rwlock_rdlock(LOCK) \ + glthread_rwlock_rdlock_func (LOCK) +# define glthread_rwlock_wrlock(LOCK) \ + glthread_rwlock_wrlock_func (LOCK) +# define glthread_rwlock_unlock(LOCK) \ + glthread_rwlock_unlock_func (LOCK) +# define glthread_rwlock_destroy(LOCK) \ + glthread_rwlock_destroy_func (LOCK) +extern void glthread_rwlock_init_func (gl_rwlock_t *lock); +extern int glthread_rwlock_rdlock_func (gl_rwlock_t *lock); +extern int glthread_rwlock_wrlock_func (gl_rwlock_t *lock); +extern int glthread_rwlock_unlock_func (gl_rwlock_t *lock); +extern int glthread_rwlock_destroy_func (gl_rwlock_t *lock); + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +/* The native Windows documentation says that CRITICAL_SECTION already + implements a recursive lock. But we need not rely on it: It's easy to + implement a recursive lock without this assumption. */ + +typedef struct + { + gl_spinlock_t guard; /* protects the initialization */ + DWORD owner; + unsigned long depth; + CRITICAL_SECTION lock; + } + gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME; +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer; +# define gl_recursive_lock_initializer \ + { { 0, -1 }, 0, 0 } +# define glthread_recursive_lock_init(LOCK) \ + (glthread_recursive_lock_init_func (LOCK), 0) +# define glthread_recursive_lock_lock(LOCK) \ + glthread_recursive_lock_lock_func (LOCK) +# define glthread_recursive_lock_unlock(LOCK) \ + glthread_recursive_lock_unlock_func (LOCK) +# define glthread_recursive_lock_destroy(LOCK) \ + glthread_recursive_lock_destroy_func (LOCK) +extern void glthread_recursive_lock_init_func (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock); +extern int glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock); + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef struct + { + volatile int inited; + volatile long started; + CRITICAL_SECTION lock; + } + gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_once_t NAME = { -1, -1 }; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (glthread_once_func (ONCE_CONTROL, INITFUNCTION), 0) +extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (void)); + +# ifdef __cplusplus +} +# endif + +#endif + +/* ========================================================================= */ + +#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS) + +/* Provide dummy implementation if threads are not supported. */ + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +typedef int gl_lock_t; +# define gl_lock_define(STORAGECLASS, NAME) +# define gl_lock_define_initialized(STORAGECLASS, NAME) +# define glthread_lock_init(NAME) 0 +# define glthread_lock_lock(NAME) 0 +# define glthread_lock_unlock(NAME) 0 +# define glthread_lock_destroy(NAME) 0 + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +typedef int gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) +# define glthread_rwlock_init(NAME) 0 +# define glthread_rwlock_rdlock(NAME) 0 +# define glthread_rwlock_wrlock(NAME) 0 +# define glthread_rwlock_unlock(NAME) 0 +# define glthread_rwlock_destroy(NAME) 0 + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +typedef int gl_recursive_lock_t; +# define gl_recursive_lock_define(STORAGECLASS, NAME) +# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) +# define glthread_recursive_lock_init(NAME) 0 +# define glthread_recursive_lock_lock(NAME) 0 +# define glthread_recursive_lock_unlock(NAME) 0 +# define glthread_recursive_lock_destroy(NAME) 0 + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef int gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_once_t NAME = 0; +# define glthread_once(ONCE_CONTROL, INITFUNCTION) \ + (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0) + +#endif + +/* ========================================================================= */ + +/* Macros with built-in error handling. */ + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +#define gl_lock_init(NAME) \ + do \ + { \ + if (glthread_lock_init (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_lock_lock(NAME) \ + do \ + { \ + if (glthread_lock_lock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_lock_unlock(NAME) \ + do \ + { \ + if (glthread_lock_unlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_lock_destroy(NAME) \ + do \ + { \ + if (glthread_lock_destroy (&NAME)) \ + abort (); \ + } \ + while (0) + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +#define gl_rwlock_init(NAME) \ + do \ + { \ + if (glthread_rwlock_init (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_rdlock(NAME) \ + do \ + { \ + if (glthread_rwlock_rdlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_wrlock(NAME) \ + do \ + { \ + if (glthread_rwlock_wrlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_unlock(NAME) \ + do \ + { \ + if (glthread_rwlock_unlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_rwlock_destroy(NAME) \ + do \ + { \ + if (glthread_rwlock_destroy (&NAME)) \ + abort (); \ + } \ + while (0) + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +#define gl_recursive_lock_init(NAME) \ + do \ + { \ + if (glthread_recursive_lock_init (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_recursive_lock_lock(NAME) \ + do \ + { \ + if (glthread_recursive_lock_lock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_recursive_lock_unlock(NAME) \ + do \ + { \ + if (glthread_recursive_lock_unlock (&NAME)) \ + abort (); \ + } \ + while (0) +#define gl_recursive_lock_destroy(NAME) \ + do \ + { \ + if (glthread_recursive_lock_destroy (&NAME)) \ + abort (); \ + } \ + while (0) + +/* -------------------------- gl_once_t datatype -------------------------- */ + +#define gl_once(NAME, INITFUNCTION) \ + do \ + { \ + if (glthread_once (&NAME, INITFUNCTION)) \ + abort (); \ + } \ + while (0) + +/* ========================================================================= */ + +#endif /* _LOCK_H */ diff --git a/grub-core/lib/gnulib/glthread/threadlib.c b/grub-core/lib/gnulib/glthread/threadlib.c new file mode 100644 index 0000000..a5ebd9b --- /dev/null +++ b/grub-core/lib/gnulib/glthread/threadlib.c @@ -0,0 +1,73 @@ +/* Multithreading primitives. + Copyright (C) 2005-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2005. */ + +#include <config.h> + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +/* Use the POSIX threads library. */ + +# include <pthread.h> +# include <stdlib.h> + +# if PTHREAD_IN_USE_DETECTION_HARD + +/* The function to be executed by a dummy thread. */ +static void * +dummy_thread_func (void *arg) +{ + return arg; +} + +int +glthread_in_use (void) +{ + static int tested; + static int result; /* 1: linked with -lpthread, 0: only with libc */ + + if (!tested) + { + pthread_t thread; + + if (pthread_create (&thread, NULL, dummy_thread_func, NULL) != 0) + /* Thread creation failed. */ + result = 0; + else + { + /* Thread creation works. */ + void *retval; + if (pthread_join (thread, &retval) != 0) + abort (); + result = 1; + } + tested = 1; + } + return result; +} + +# endif + +#endif + +/* ========================================================================= */ + +/* This declaration is solely to ensure that after preprocessing + this file is never empty. */ +typedef int dummy; diff --git a/grub-core/lib/gnulib/hard-locale.c b/grub-core/lib/gnulib/hard-locale.c new file mode 100644 index 0000000..dcfcad6 --- /dev/null +++ b/grub-core/lib/gnulib/hard-locale.c @@ -0,0 +1,72 @@ +/* hard-locale.c -- Determine whether a locale is hard. + + Copyright (C) 1997-1999, 2002-2004, 2006-2007, 2009-2019 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "hard-locale.h" + +#include <locale.h> +#include <stdlib.h> +#include <string.h> + +#ifdef __GLIBC__ +# define GLIBC_VERSION __GLIBC__ +#elif defined __UCLIBC__ +# define GLIBC_VERSION 2 +#else +# define GLIBC_VERSION 0 +#endif + +/* Return true if the current CATEGORY locale is hard, i.e. if you + can't get away with assuming traditional C or POSIX behavior. */ +bool +hard_locale (int category) +{ + bool hard = true; + char const *p = setlocale (category, NULL); + + if (p) + { + if (2 <= GLIBC_VERSION) + { + if (strcmp (p, "C") == 0 || strcmp (p, "POSIX") == 0) + hard = false; + } + else + { + char *locale = strdup (p); + if (locale) + { + /* Temporarily set the locale to the "C" and "POSIX" locales + to find their names, so that we can determine whether one + or the other is the caller's locale. */ + if (((p = setlocale (category, "C")) + && strcmp (p, locale) == 0) + || ((p = setlocale (category, "POSIX")) + && strcmp (p, locale) == 0)) + hard = false; + + /* Restore the caller's locale. */ + setlocale (category, locale); + free (locale); + } + } + } + + return hard; +} diff --git a/grub-core/lib/gnulib/hard-locale.h b/grub-core/lib/gnulib/hard-locale.h new file mode 100644 index 0000000..8f1da96 --- /dev/null +++ b/grub-core/lib/gnulib/hard-locale.h @@ -0,0 +1,25 @@ +/* Determine whether a locale is hard. + + Copyright (C) 1999, 2003-2004, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef HARD_LOCALE_H_ +# define HARD_LOCALE_H_ 1 + +# include <stdbool.h> + +bool hard_locale (int); + +#endif /* HARD_LOCALE_H_ */ diff --git a/grub-core/lib/gnulib/intprops.h b/grub-core/lib/gnulib/intprops.h new file mode 100644 index 0000000..1a44ae5 --- /dev/null +++ b/grub-core/lib/gnulib/intprops.h @@ -0,0 +1,455 @@ +/* intprops.h -- properties of integer types + + Copyright (C) 2001-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +#ifndef _GL_INTPROPS_H +#define _GL_INTPROPS_H + +#include <limits.h> + +/* Return a value with the common real type of E and V and the value of V. + Do not evaluate E. */ +#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v)) + +/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see + <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00406.html>. */ +#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v)) + +/* The extra casts in the following macros work around compiler bugs, + e.g., in Cray C 5.0.3.0. */ + +/* True if the arithmetic type T is an integer type. bool counts as + an integer. */ +#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) + +/* True if the real type T is signed. */ +#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) + +/* Return 1 if the real expression E, after promotion, has a + signed or floating type. Do not evaluate E. */ +#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0) + + +/* Minimum and maximum values for integer types and expressions. */ + +/* The width in bits of the integer type or expression T. + Do not evaluate T. + Padding bits are not supported; this is checked at compile-time below. */ +#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT) + +/* The maximum and minimum values for the integer type T. */ +#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t)) +#define TYPE_MAXIMUM(t) \ + ((t) (! TYPE_SIGNED (t) \ + ? (t) -1 \ + : ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1))) + +/* The maximum and minimum values for the type of the expression E, + after integer promotion. E is not evaluated. */ +#define _GL_INT_MINIMUM(e) \ + (EXPR_SIGNED (e) \ + ? ~ _GL_SIGNED_INT_MAXIMUM (e) \ + : _GL_INT_CONVERT (e, 0)) +#define _GL_INT_MAXIMUM(e) \ + (EXPR_SIGNED (e) \ + ? _GL_SIGNED_INT_MAXIMUM (e) \ + : _GL_INT_NEGATE_CONVERT (e, 1)) +#define _GL_SIGNED_INT_MAXIMUM(e) \ + (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH ((e) + 0) - 2)) - 1) * 2 + 1) + +/* Work around OpenVMS incompatibility with C99. */ +#if !defined LLONG_MAX && defined __INT64_MAX +# define LLONG_MAX __INT64_MAX +# define LLONG_MIN __INT64_MIN +#endif + +/* This include file assumes that signed types are two's complement without + padding bits; the above macros have undefined behavior otherwise. + If this is a problem for you, please let us know how to fix it for your host. + This assumption is tested by the intprops-tests module. */ + +/* Does the __typeof__ keyword work? This could be done by + 'configure', but for now it's easier to do it by hand. */ +#if (2 <= __GNUC__ \ + || (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \ + || (0x5110 <= __SUNPRO_C && !__STDC__)) +# define _GL_HAVE___TYPEOF__ 1 +#else +# define _GL_HAVE___TYPEOF__ 0 +#endif + +/* Return 1 if the integer type or expression T might be signed. Return 0 + if it is definitely unsigned. This macro does not evaluate its argument, + and expands to an integer constant expression. */ +#if _GL_HAVE___TYPEOF__ +# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t)) +#else +# define _GL_SIGNED_TYPE_OR_EXPR(t) 1 +#endif + +/* Bound on length of the string representing an unsigned integer + value representable in B bits. log10 (2.0) < 146/485. The + smallest value of B where this bound is not tight is 2621. */ +#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485) + +/* Bound on length of the string representing an integer type or expression T. + Subtract 1 for the sign bit if T is signed, and then add 1 more for + a minus sign if needed. + + Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 0 when its argument is + signed, this macro may overestimate the true bound by one byte when + applied to unsigned types of size 2, 4, 16, ... bytes. */ +#define INT_STRLEN_BOUND(t) \ + (INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \ + + _GL_SIGNED_TYPE_OR_EXPR (t)) + +/* Bound on buffer size needed to represent an integer type or expression T, + including the terminating null. */ +#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) + + +/* Range overflow checks. + + The INT_<op>_RANGE_OVERFLOW macros return 1 if the corresponding C + operators might not yield numerically correct answers due to + arithmetic overflow. They do not rely on undefined or + implementation-defined behavior. Their implementations are simple + and straightforward, but they are a bit harder to use than the + INT_<op>_OVERFLOW macros described below. + + Example usage: + + long int i = ...; + long int j = ...; + if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX)) + printf ("multiply would overflow"); + else + printf ("product is %ld", i * j); + + Restrictions on *_RANGE_OVERFLOW macros: + + These macros do not check for all possible numerical problems or + undefined or unspecified behavior: they do not check for division + by zero, for bad shift counts, or for shifting negative numbers. + + These macros may evaluate their arguments zero or multiple times, + so the arguments should not have side effects. The arithmetic + arguments (including the MIN and MAX arguments) must be of the same + integer type after the usual arithmetic conversions, and the type + must have minimum value MIN and maximum MAX. Unsigned types should + use a zero MIN of the proper type. + + These macros are tuned for constant MIN and MAX. For commutative + operations such as A + B, they are also tuned for constant B. */ + +/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (a) < (min) - (b) \ + : (max) - (b) < (a)) + +/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (max) + (b) < (a) \ + : (a) < (min) + (b)) + +/* Return 1 if - A would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \ + ((min) < 0 \ + ? (a) < - (max) \ + : 0 < (a)) + +/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Avoid && and || as they tickle + bugs in Sun C 5.11 2010/08/13 and other compilers; see + <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00401.html>. */ +#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? ((a) < 0 \ + ? (a) < (max) / (b) \ + : (b) == -1 \ + ? 0 \ + : (min) / (b) < (a)) \ + : (b) == 0 \ + ? 0 \ + : ((a) < 0 \ + ? (a) < (min) / (b) \ + : (max) / (b) < (a))) + +/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Do not check for division by zero. */ +#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max) \ + ((min) < 0 && (b) == -1 && (a) < - (max)) + +/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Do not check for division by zero. + Mathematically, % should never overflow, but on x86-like hosts + INT_MIN % -1 traps, and the C standard permits this, so treat this + as an overflow too. */ +#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max) \ + INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max) + +/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Here, MIN and MAX are for A only, and B need + not be of the same type as the other arguments. The C standard says that + behavior is undefined for shifts unless 0 <= B < wordwidth, and that when + A is negative then A << B has undefined behavior and A >> B has + implementation-defined behavior, but do not check these other + restrictions. */ +#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \ + ((a) < 0 \ + ? (a) < (min) >> (b) \ + : (max) >> (b) < (a)) + +/* True if __builtin_add_overflow (A, B, P) works when P is non-null. */ +#if 5 <= __GNUC__ && !defined __ICC +# define _GL_HAS_BUILTIN_OVERFLOW 1 +#else +# define _GL_HAS_BUILTIN_OVERFLOW 0 +#endif + +/* True if __builtin_add_overflow_p (A, B, C) works. */ +#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__) + +/* The _GL*_OVERFLOW macros have the same restrictions as the + *_RANGE_OVERFLOW macros, except that they do not assume that operands + (e.g., A and B) have the same type as MIN and MAX. Instead, they assume + that the result (e.g., A + B) has that type. */ +#if _GL_HAS_BUILTIN_OVERFLOW_P +# define _GL_ADD_OVERFLOW(a, b, min, max) \ + __builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0) +# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ + __builtin_sub_overflow_p (a, b, (__typeof__ ((a) - (b))) 0) +# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ + __builtin_mul_overflow_p (a, b, (__typeof__ ((a) * (b))) 0) +#else +# define _GL_ADD_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? (b) <= (a) + (b) \ + : (b) < 0 ? (a) <= (a) + (b) \ + : (a) + (b) < (b)) +# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? 1 \ + : (b) < 0 ? (a) - (b) <= (a) \ + : (a) < (b)) +# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ + (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \ + || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max)) +#endif +#define _GL_DIVIDE_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + : (a) < 0 ? (b) <= (a) + (b) - 1 \ + : (b) < 0 && (a) + (b) <= (a)) +#define _GL_REMAINDER_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + : (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \ + : (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max)) + +/* Return a nonzero value if A is a mathematical multiple of B, where + A is unsigned, B is negative, and MAX is the maximum value of A's + type. A's type must be the same as (A % B)'s type. Normally (A % + -B == 0) suffices, but things get tricky if -B would overflow. */ +#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max) \ + (((b) < -_GL_SIGNED_INT_MAXIMUM (b) \ + ? (_GL_SIGNED_INT_MAXIMUM (b) == (max) \ + ? (a) \ + : (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1)) \ + : (a) % - (b)) \ + == 0) + +/* Check for integer overflow, and report low order bits of answer. + + The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators + might not yield numerically correct answers due to arithmetic overflow. + The INT_<op>_WRAPV macros also store the low-order bits of the answer. + These macros work correctly on all known practical hosts, and do not rely + on undefined behavior due to signed arithmetic overflow. + + Example usage, assuming A and B are long int: + + if (INT_MULTIPLY_OVERFLOW (a, b)) + printf ("result would overflow\n"); + else + printf ("result is %ld (no overflow)\n", a * b); + + Example usage with WRAPV flavor: + + long int result; + bool overflow = INT_MULTIPLY_WRAPV (a, b, &result); + printf ("result is %ld (%s)\n", result, + overflow ? "after overflow" : "no overflow"); + + Restrictions on these macros: + + These macros do not check for all possible numerical problems or + undefined or unspecified behavior: they do not check for division + by zero, for bad shift counts, or for shifting negative numbers. + + These macros may evaluate their arguments zero or multiple times, so the + arguments should not have side effects. + + The WRAPV macros are not constant expressions. They support only + +, binary -, and *. The result type must be signed. + + These macros are tuned for their last argument being a constant. + + Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B, + A % B, and A << B would overflow, respectively. */ + +#define INT_ADD_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW) +#define INT_SUBTRACT_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW) +#if _GL_HAS_BUILTIN_OVERFLOW_P +# define INT_NEGATE_OVERFLOW(a) INT_SUBTRACT_OVERFLOW (0, a) +#else +# define INT_NEGATE_OVERFLOW(a) \ + INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) +#endif +#define INT_MULTIPLY_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) +#define INT_DIVIDE_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW) +#define INT_REMAINDER_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW) +#define INT_LEFT_SHIFT_OVERFLOW(a, b) \ + INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \ + _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) + +/* Return 1 if the expression A <op> B would overflow, + where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test, + assuming MIN and MAX are the minimum and maximum for the result type. + Arguments should be free of side effects. */ +#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \ + op_result_overflow (a, b, \ + _GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \ + _GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b))) + +/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R. + Return 1 if the result overflows. See above for restrictions. */ +#define INT_ADD_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, +, __builtin_add_overflow, INT_ADD_OVERFLOW) +#define INT_SUBTRACT_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, INT_SUBTRACT_OVERFLOW) +#define INT_MULTIPLY_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, *, __builtin_mul_overflow, INT_MULTIPLY_OVERFLOW) + +/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193 + https://llvm.org/bugs/show_bug.cgi?id=25390 + For now, assume all versions of GCC-like compilers generate bogus + warnings for _Generic. This matters only for older compilers that + lack __builtin_add_overflow. */ +#if __GNUC__ +# define _GL__GENERIC_BOGUS 1 +#else +# define _GL__GENERIC_BOGUS 0 +#endif + +/* Store the low-order bits of A <op> B into *R, where OP specifies + the operation. BUILTIN is the builtin operation, and OVERFLOW the + overflow predicate. Return 1 if the result overflows. See above + for restrictions. */ +#if _GL_HAS_BUILTIN_OVERFLOW +# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) builtin (a, b, r) +#elif 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS +# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \ + (_Generic \ + (*(r), \ + signed char: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + signed char, SCHAR_MIN, SCHAR_MAX), \ + short int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + short int, SHRT_MIN, SHRT_MAX), \ + int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + int, INT_MIN, INT_MAX), \ + long int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + long int, LONG_MIN, LONG_MAX), \ + long long int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ + long long int, LLONG_MIN, LLONG_MAX))) +#else +# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \ + (sizeof *(r) == sizeof (signed char) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + signed char, SCHAR_MIN, SCHAR_MAX) \ + : sizeof *(r) == sizeof (short int) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + short int, SHRT_MIN, SHRT_MAX) \ + : sizeof *(r) == sizeof (int) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + int, INT_MIN, INT_MAX) \ + : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow)) +# ifdef LLONG_MAX +# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ + (sizeof *(r) == sizeof (long int) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + long int, LONG_MIN, LONG_MAX) \ + : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ + long long int, LLONG_MIN, LLONG_MAX)) +# else +# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + long int, LONG_MIN, LONG_MAX) +# endif +#endif + +/* Store the low-order bits of A <op> B into *R, where the operation + is given by OP. Use the unsigned type UT for calculation to avoid + overflow problems. *R's type is T, with extrema TMIN and TMAX. + T must be a signed integer type. Return 1 if the result overflows. */ +#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \ + (sizeof ((a) op (b)) < sizeof (t) \ + ? _GL_INT_OP_CALC1 ((t) (a), (t) (b), r, op, overflow, ut, t, tmin, tmax) \ + : _GL_INT_OP_CALC1 (a, b, r, op, overflow, ut, t, tmin, tmax)) +#define _GL_INT_OP_CALC1(a, b, r, op, overflow, ut, t, tmin, tmax) \ + ((overflow (a, b) \ + || (EXPR_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \ + || (tmax) < ((a) op (b))) \ + ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \ + : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0)) + +/* Return the low-order bits of A <op> B, where the operation is given + by OP. Use the unsigned type UT for calculation to avoid undefined + behavior on signed integer overflow, and convert the result to type T. + UT is at least as wide as T and is no narrower than unsigned int, + T is two's complement, and there is no padding or trap representations. + Assume that converting UT to T yields the low-order bits, as is + done in all known two's-complement C compilers. E.g., see: + https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html + + According to the C standard, converting UT to T yields an + implementation-defined result or signal for values outside T's + range. However, code that works around this theoretical problem + runs afoul of a compiler bug in Oracle Studio 12.3 x86. See: + https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html + As the compiler bug is real, don't try to work around the + theoretical problem. */ + +#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \ + ((t) ((ut) (a) op (ut) (b))) + +#endif /* _GL_INTPROPS_H */ diff --git a/grub-core/lib/gnulib/itold.c b/grub-core/lib/gnulib/itold.c new file mode 100644 index 0000000..bca01eb --- /dev/null +++ b/grub-core/lib/gnulib/itold.c @@ -0,0 +1,28 @@ +/* Replacement for 'int' to 'long double' conversion routine. + Copyright (C) 2011-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <float.h> + +void +_Qp_itoq (long double *result, int a) +{ + /* Convert from 'int' to 'double', then from 'double' to 'long double'. */ + *result = (double) a; +} diff --git a/grub-core/lib/gnulib/langinfo.in.h b/grub-core/lib/gnulib/langinfo.in.h new file mode 100644 index 0000000..6d40635 --- /dev/null +++ b/grub-core/lib/gnulib/langinfo.in.h @@ -0,0 +1,222 @@ +/* Substitute for and wrapper around <langinfo.h>. + Copyright (C) 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* + * POSIX <langinfo.h> for platforms that lack it or have an incomplete one. + * <http://www.opengroup.org/onlinepubs/9699919799/basedefs/langinfo.h.html> + */ + +#ifndef _@GUARD_PREFIX@_LANGINFO_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_LANGINFO_H@ +# @INCLUDE_NEXT@ @NEXT_LANGINFO_H@ +#endif + +#ifndef _@GUARD_PREFIX@_LANGINFO_H +#define _@GUARD_PREFIX@_LANGINFO_H + + +#if !@HAVE_LANGINFO_H@ + +/* A platform that lacks <langinfo.h>. */ + +/* Assume that it also lacks <nl_types.h> and the nl_item type. */ +# if !GNULIB_defined_nl_item +typedef int nl_item; +# define GNULIB_defined_nl_item 1 +# endif + +/* nl_langinfo items of the LC_CTYPE category */ +# define CODESET 10000 +/* nl_langinfo items of the LC_NUMERIC category */ +# define RADIXCHAR 10001 +# define DECIMAL_POINT RADIXCHAR +# define THOUSEP 10002 +# define THOUSANDS_SEP THOUSEP +# define GROUPING 10114 +/* nl_langinfo items of the LC_TIME category */ +# define D_T_FMT 10003 +# define D_FMT 10004 +# define T_FMT 10005 +# define T_FMT_AMPM 10006 +# define AM_STR 10007 +# define PM_STR 10008 +# define DAY_1 10009 +# define DAY_2 (DAY_1 + 1) +# define DAY_3 (DAY_1 + 2) +# define DAY_4 (DAY_1 + 3) +# define DAY_5 (DAY_1 + 4) +# define DAY_6 (DAY_1 + 5) +# define DAY_7 (DAY_1 + 6) +# define ABDAY_1 10016 +# define ABDAY_2 (ABDAY_1 + 1) +# define ABDAY_3 (ABDAY_1 + 2) +# define ABDAY_4 (ABDAY_1 + 3) +# define ABDAY_5 (ABDAY_1 + 4) +# define ABDAY_6 (ABDAY_1 + 5) +# define ABDAY_7 (ABDAY_1 + 6) +# define MON_1 10023 +# define MON_2 (MON_1 + 1) +# define MON_3 (MON_1 + 2) +# define MON_4 (MON_1 + 3) +# define MON_5 (MON_1 + 4) +# define MON_6 (MON_1 + 5) +# define MON_7 (MON_1 + 6) +# define MON_8 (MON_1 + 7) +# define MON_9 (MON_1 + 8) +# define MON_10 (MON_1 + 9) +# define MON_11 (MON_1 + 10) +# define MON_12 (MON_1 + 11) +# define ALTMON_1 10200 +# define ALTMON_2 (ALTMON_1 + 1) +# define ALTMON_3 (ALTMON_1 + 2) +# define ALTMON_4 (ALTMON_1 + 3) +# define ALTMON_5 (ALTMON_1 + 4) +# define ALTMON_6 (ALTMON_1 + 5) +# define ALTMON_7 (ALTMON_1 + 6) +# define ALTMON_8 (ALTMON_1 + 7) +# define ALTMON_9 (ALTMON_1 + 8) +# define ALTMON_10 (ALTMON_1 + 9) +# define ALTMON_11 (ALTMON_1 + 10) +# define ALTMON_12 (ALTMON_1 + 11) +# define ABMON_1 10035 +# define ABMON_2 (ABMON_1 + 1) +# define ABMON_3 (ABMON_1 + 2) +# define ABMON_4 (ABMON_1 + 3) +# define ABMON_5 (ABMON_1 + 4) +# define ABMON_6 (ABMON_1 + 5) +# define ABMON_7 (ABMON_1 + 6) +# define ABMON_8 (ABMON_1 + 7) +# define ABMON_9 (ABMON_1 + 8) +# define ABMON_10 (ABMON_1 + 9) +# define ABMON_11 (ABMON_1 + 10) +# define ABMON_12 (ABMON_1 + 11) +# define ERA 10047 +# define ERA_D_FMT 10048 +# define ERA_D_T_FMT 10049 +# define ERA_T_FMT 10050 +# define ALT_DIGITS 10051 +/* nl_langinfo items of the LC_MONETARY category */ +# define CRNCYSTR 10052 +# define CURRENCY_SYMBOL CRNCYSTR +# define INT_CURR_SYMBOL 10100 +# define MON_DECIMAL_POINT 10101 +# define MON_THOUSANDS_SEP 10102 +# define MON_GROUPING 10103 +# define POSITIVE_SIGN 10104 +# define NEGATIVE_SIGN 10105 +# define FRAC_DIGITS 10106 +# define INT_FRAC_DIGITS 10107 +# define P_CS_PRECEDES 10108 +# define N_CS_PRECEDES 10109 +# define P_SEP_BY_SPACE 10110 +# define N_SEP_BY_SPACE 10111 +# define P_SIGN_POSN 10112 +# define N_SIGN_POSN 10113 +/* nl_langinfo items of the LC_MESSAGES category */ +# define YESEXPR 10053 +# define NOEXPR 10054 + +#else + +/* A platform that has <langinfo.h>. */ + +# if !@HAVE_LANGINFO_CODESET@ +# define CODESET 10000 +# define GNULIB_defined_CODESET 1 +# endif + +# if !@HAVE_LANGINFO_T_FMT_AMPM@ +# define T_FMT_AMPM 10006 +# define GNULIB_defined_T_FMT_AMPM 1 +# endif + +# if !@HAVE_LANGINFO_ALTMON@ +# define ALTMON_1 10200 +# define ALTMON_2 (ALTMON_1 + 1) +# define ALTMON_3 (ALTMON_1 + 2) +# define ALTMON_4 (ALTMON_1 + 3) +# define ALTMON_5 (ALTMON_1 + 4) +# define ALTMON_6 (ALTMON_1 + 5) +# define ALTMON_7 (ALTMON_1 + 6) +# define ALTMON_8 (ALTMON_1 + 7) +# define ALTMON_9 (ALTMON_1 + 8) +# define ALTMON_10 (ALTMON_1 + 9) +# define ALTMON_11 (ALTMON_1 + 10) +# define ALTMON_12 (ALTMON_1 + 11) +# define GNULIB_defined_ALTMON 1 +# endif + +# if !@HAVE_LANGINFO_ERA@ +# define ERA 10047 +# define ERA_D_FMT 10048 +# define ERA_D_T_FMT 10049 +# define ERA_T_FMT 10050 +# define ALT_DIGITS 10051 +# define GNULIB_defined_ERA 1 +# endif + +# if !@HAVE_LANGINFO_YESEXPR@ +# define YESEXPR 10053 +# define NOEXPR 10054 +# define GNULIB_defined_YESEXPR 1 +# endif + +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Declare overridden functions. */ + + +/* Return a piece of locale dependent information. + Note: The difference between nl_langinfo (CODESET) and locale_charset () + is that the latter normalizes the encoding names to GNU conventions. */ + +#if @GNULIB_NL_LANGINFO@ +# if @REPLACE_NL_LANGINFO@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef nl_langinfo +# define nl_langinfo rpl_nl_langinfo +# endif +_GL_FUNCDECL_RPL (nl_langinfo, char *, (nl_item item)); +_GL_CXXALIAS_RPL (nl_langinfo, char *, (nl_item item)); +# else +# if !@HAVE_NL_LANGINFO@ +_GL_FUNCDECL_SYS (nl_langinfo, char *, (nl_item item)); +# endif +_GL_CXXALIAS_SYS (nl_langinfo, char *, (nl_item item)); +# endif +_GL_CXXALIASWARN (nl_langinfo); +#elif defined GNULIB_POSIXCHECK +# undef nl_langinfo +# if HAVE_RAW_DECL_NL_LANGINFO +_GL_WARN_ON_USE (nl_langinfo, "nl_langinfo is not portable - " + "use gnulib module nl_langinfo for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_LANGINFO_H */ +#endif /* _@GUARD_PREFIX@_LANGINFO_H */ diff --git a/grub-core/lib/gnulib/libc-config.h b/grub-core/lib/gnulib/libc-config.h new file mode 100644 index 0000000..57c6966 --- /dev/null +++ b/grub-core/lib/gnulib/libc-config.h @@ -0,0 +1,174 @@ +/* System definitions for code taken from the GNU C Library + + Copyright 2017-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, see + <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +/* This is intended to be a good-enough substitute for glibc system + macros like those defined in <sys/cdefs.h>, so that Gnulib code + shared with glibc can do this as the first #include: + + #ifndef _LIBC + # include <libc-config.h> + #endif + + When compiled as part of glibc this is a no-op; when compiled as + part of Gnulib this includes Gnulib's <config.h> and defines macros + that glibc library code would normally assume. */ + +#include <config.h> + +/* On glibc this includes <features.h> and <sys/cdefs.h> and #defines + _FEATURES_H, __WORDSIZE, and __set_errno. On FreeBSD 11 it + includes <sys/cdefs.h> which defines __nonnull. Elsewhere it + is harmless. */ +#include <errno.h> + +/* From glibc <errno.h>. */ +#ifndef __set_errno +# define __set_errno(val) (errno = (val)) +#endif + +/* From glibc <features.h>. */ + +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_MINOR__ +# define __GNUC_PREREQ(maj, min) ((maj) < __GNUC__ + ((min) <= __GNUC_MINOR__)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + +#ifndef __glibc_clang_prereq +# if defined __clang_major__ && defined __clang_minor__ +# define __glibc_clang_prereq(maj, min) \ + ((maj) < __clang_major__ + ((min) <= __clang_minor__)) +# else +# define __glibc_clang_prereq(maj, min) 0 +# endif +#endif + + +/* Prepare to include <cdefs.h>, which is our copy of glibc + <sys/cdefs.h>. */ + +/* Define _FEATURES_H so that <cdefs.h> does not include <features.h>. */ +#ifndef _FEATURES_H +# define _FEATURES_H 1 +#endif +/* Define __WORDSIZE so that <cdefs.h> does not attempt to include + nonexistent files. Make it a syntax error, since Gnulib does not + use __WORDSIZE now, and if Gnulib uses it later the syntax error + will let us know that __WORDSIZE needs configuring. */ +#ifndef __WORDSIZE +# define __WORDSIZE %%% +#endif +/* Undef the macros unconditionally defined by our copy of glibc + <sys/cdefs.h>, so that they do not clash with any system-defined + versions. */ +#undef _SYS_CDEFS_H +#undef __ASMNAME +#undef __ASMNAME2 +#undef __BEGIN_DECLS +#undef __CONCAT +#undef __END_DECLS +#undef __HAVE_GENERIC_SELECTION +#undef __LDBL_COMPAT +#undef __LDBL_REDIR +#undef __LDBL_REDIR1 +#undef __LDBL_REDIR1_DECL +#undef __LDBL_REDIR1_NTH +#undef __LDBL_REDIR_DECL +#undef __LDBL_REDIR_NTH +#undef __LEAF +#undef __LEAF_ATTR +#undef __NTH +#undef __NTHNL +#undef __P +#undef __PMT +#undef __REDIRECT +#undef __REDIRECT_LDBL +#undef __REDIRECT_NTH +#undef __REDIRECT_NTHNL +#undef __REDIRECT_NTH_LDBL +#undef __STRING +#undef __THROW +#undef __THROWNL +#undef __always_inline +#undef __attribute__ +#undef __attribute_alloc_size__ +#undef __attribute_artificial__ +#undef __attribute_const__ +#undef __attribute_deprecated__ +#undef __attribute_deprecated_msg__ +#undef __attribute_format_arg__ +#undef __attribute_format_strfmon__ +#undef __attribute_malloc__ +#undef __attribute_noinline__ +#undef __attribute_nonstring__ +#undef __attribute_pure__ +#undef __attribute_used__ +#undef __attribute_warn_unused_result__ +#undef __bos +#undef __bos0 +#undef __errordecl +#undef __extension__ +#undef __extern_always_inline +#undef __extern_inline +#undef __flexarr +#undef __fortify_function +#undef __glibc_c99_flexarr_available +#undef __glibc_clang_has_extension +#undef __glibc_likely +#undef __glibc_macro_warning +#undef __glibc_macro_warning1 +#undef __glibc_unlikely +#undef __inline +#undef __ptr_t +#undef __restrict +#undef __restrict_arr +#undef __va_arg_pack +#undef __va_arg_pack_len +#undef __warnattr +#undef __warndecl + +/* Include our copy of glibc <sys/cdefs.h>. */ +#include <cdefs.h> + +/* <cdefs.h> __inline is too pessimistic for non-GCC. */ +#undef __inline +#ifndef HAVE___INLINE +# if 199901 <= __STDC_VERSION__ || defined inline +# define __inline inline +# else +# define __inline +# endif +#endif + + +/* A substitute for glibc <libc-symbols.h>, good enough for Gnulib. */ +#define attribute_hidden +#define libc_hidden_proto(name, ...) +#define libc_hidden_def(name) +#define libc_hidden_weak(name) +#define libc_hidden_ver(local, name) +#define strong_alias(name, aliasname) +#define weak_alias(name, aliasname) + +/* A substitute for glibc <shlib-compat.h>, good enough for Gnulib. */ +#define SHLIB_COMPAT(lib, introduced, obsoleted) 0 +#define versioned_symbol(lib, local, symbol, version) diff --git a/grub-core/lib/gnulib/limits.in.h b/grub-core/lib/gnulib/limits.in.h new file mode 100644 index 0000000..39750b3 --- /dev/null +++ b/grub-core/lib/gnulib/limits.in.h @@ -0,0 +1,104 @@ +/* A GNU-like <limits.h>. + + Copyright 2016-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 3, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _@GUARD_PREFIX@_LIMITS_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_LIMITS_H@ + +#ifndef _@GUARD_PREFIX@_LIMITS_H +#define _@GUARD_PREFIX@_LIMITS_H + +#ifndef LLONG_MIN +# if defined LONG_LONG_MIN /* HP-UX 11.31 */ +# define LLONG_MIN LONG_LONG_MIN +# elif defined LONGLONG_MIN /* IRIX 6.5 */ +# define LLONG_MIN LONGLONG_MIN +# elif defined __GNUC__ +# define LLONG_MIN (- __LONG_LONG_MAX__ - 1LL) +# endif +#endif +#ifndef LLONG_MAX +# if defined LONG_LONG_MAX /* HP-UX 11.31 */ +# define LLONG_MAX LONG_LONG_MAX +# elif defined LONGLONG_MAX /* IRIX 6.5 */ +# define LLONG_MAX LONGLONG_MAX +# elif defined __GNUC__ +# define LLONG_MAX __LONG_LONG_MAX__ +# endif +#endif +#ifndef ULLONG_MAX +# if defined ULONG_LONG_MAX /* HP-UX 11.31 */ +# define ULLONG_MAX ULONG_LONG_MAX +# elif defined ULONGLONG_MAX /* IRIX 6.5 */ +# define ULLONG_MAX ULONGLONG_MAX +# elif defined __GNUC__ +# define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1ULL) +# endif +#endif + +/* The number of usable bits in an unsigned or signed integer type + with minimum value MIN and maximum value MAX, as an int expression + suitable in #if. Cover all known practical hosts. This + implementation exploits the fact that MAX is 1 less than a power of + 2, and merely counts the number of 1 bits in MAX; "COBn" means + "count the number of 1 bits in the low-order n bits"). */ +#define _GL_INTEGER_WIDTH(min, max) (((min) < 0) + _GL_COB128 (max)) +#define _GL_COB128(n) (_GL_COB64 ((n) >> 31 >> 31 >> 2) + _GL_COB64 (n)) +#define _GL_COB64(n) (_GL_COB32 ((n) >> 31 >> 1) + _GL_COB32 (n)) +#define _GL_COB32(n) (_GL_COB16 ((n) >> 16) + _GL_COB16 (n)) +#define _GL_COB16(n) (_GL_COB8 ((n) >> 8) + _GL_COB8 (n)) +#define _GL_COB8(n) (_GL_COB4 ((n) >> 4) + _GL_COB4 (n)) +#define _GL_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + !!((n) & 1)) + +#ifndef WORD_BIT +/* Assume 'int' is 32 bits wide. */ +# define WORD_BIT 32 +#endif +#ifndef LONG_BIT +/* Assume 'long' is 32 or 64 bits wide. */ +# if LONG_MAX == INT_MAX +# define LONG_BIT 32 +# else +# define LONG_BIT 64 +# endif +#endif + +/* Macros specified by ISO/IEC TS 18661-1:2014. */ + +#if (! defined ULLONG_WIDTH \ + && (defined _GNU_SOURCE || defined __STDC_WANT_IEC_60559_BFP_EXT__)) +# define CHAR_WIDTH _GL_INTEGER_WIDTH (CHAR_MIN, CHAR_MAX) +# define SCHAR_WIDTH _GL_INTEGER_WIDTH (SCHAR_MIN, SCHAR_MAX) +# define UCHAR_WIDTH _GL_INTEGER_WIDTH (0, UCHAR_MAX) +# define SHRT_WIDTH _GL_INTEGER_WIDTH (SHRT_MIN, SHRT_MAX) +# define USHRT_WIDTH _GL_INTEGER_WIDTH (0, USHRT_MAX) +# define INT_WIDTH _GL_INTEGER_WIDTH (INT_MIN, INT_MAX) +# define UINT_WIDTH _GL_INTEGER_WIDTH (0, UINT_MAX) +# define LONG_WIDTH _GL_INTEGER_WIDTH (LONG_MIN, LONG_MAX) +# define ULONG_WIDTH _GL_INTEGER_WIDTH (0, ULONG_MAX) +# define LLONG_WIDTH _GL_INTEGER_WIDTH (LLONG_MIN, LLONG_MAX) +# define ULLONG_WIDTH _GL_INTEGER_WIDTH (0, ULLONG_MAX) +#endif /* !ULLONG_WIDTH && (_GNU_SOURCE || __STDC_WANT_IEC_60559_BFP_EXT__) */ + +#endif /* _@GUARD_PREFIX@_LIMITS_H */ +#endif /* _@GUARD_PREFIX@_LIMITS_H */ diff --git a/grub-core/lib/gnulib/localcharset.c b/grub-core/lib/gnulib/localcharset.c new file mode 100644 index 0000000..38e27e6 --- /dev/null +++ b/grub-core/lib/gnulib/localcharset.c @@ -0,0 +1,996 @@ +/* Determine a canonical name for the current locale's character encoding. + + Copyright (C) 2000-2006, 2008-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>. */ + +#include <config.h> + +/* Specification. */ +#include "localcharset.h" + +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#if defined __APPLE__ && defined __MACH__ && HAVE_LANGINFO_CODESET +# define DARWIN7 /* Darwin 7 or newer, i.e. Mac OS X 10.3 or newer */ +#endif + +#if defined _WIN32 && !defined __CYGWIN__ +# define WINDOWS_NATIVE +# include <locale.h> +#endif + +#if defined __EMX__ +/* Assume EMX program runs on OS/2, even if compiled under DOS. */ +# ifndef OS2 +# define OS2 +# endif +#endif + +#if !defined WINDOWS_NATIVE +# if HAVE_LANGINFO_CODESET +# include <langinfo.h> +# else +# if 0 /* see comment regarding use of setlocale(), below */ +# include <locale.h> +# endif +# endif +# ifdef __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# endif +#elif defined WINDOWS_NATIVE +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +#endif +#if defined OS2 +# define INCL_DOS +# include <os2.h> +#endif + +/* For MB_CUR_MAX_L */ +#if defined DARWIN7 +# include <xlocale.h> +#endif + + +#if HAVE_LANGINFO_CODESET || defined WINDOWS_NATIVE || defined OS2 + +/* On these platforms, we use a mapping from non-canonical encoding name + to GNU canonical encoding name. */ + +/* With glibc-2.1 or newer, we don't need any canonicalization, + because glibc has iconv and both glibc and libiconv support all + GNU canonical names directly. */ +# if !((defined __GNU_LIBRARY__ && __GLIBC__ >= 2) || defined __UCLIBC__) + +struct table_entry +{ + const char alias[11+1]; + const char canonical[11+1]; +}; + +/* Table of platform-dependent mappings, sorted in ascending order. */ +static const struct table_entry alias_table[] = + { +# if defined __FreeBSD__ /* FreeBSD */ + /*{ "ARMSCII-8", "ARMSCII-8" },*/ + { "Big5", "BIG5" }, + { "C", "ASCII" }, + /*{ "CP1131", "CP1131" },*/ + /*{ "CP1251", "CP1251" },*/ + /*{ "CP866", "CP866" },*/ + /*{ "GB18030", "GB18030" },*/ + /*{ "GB2312", "GB2312" },*/ + /*{ "GBK", "GBK" },*/ + /*{ "ISCII-DEV", "?" },*/ + { "ISO8859-1", "ISO-8859-1" }, + { "ISO8859-13", "ISO-8859-13" }, + { "ISO8859-15", "ISO-8859-15" }, + { "ISO8859-2", "ISO-8859-2" }, + { "ISO8859-5", "ISO-8859-5" }, + { "ISO8859-7", "ISO-8859-7" }, + { "ISO8859-9", "ISO-8859-9" }, + /*{ "KOI8-R", "KOI8-R" },*/ + /*{ "KOI8-U", "KOI8-U" },*/ + { "SJIS", "SHIFT_JIS" }, + { "US-ASCII", "ASCII" }, + { "eucCN", "GB2312" }, + { "eucJP", "EUC-JP" }, + { "eucKR", "EUC-KR" } +# define alias_table_defined +# endif +# if defined __NetBSD__ /* NetBSD */ + { "646", "ASCII" }, + /*{ "ARMSCII-8", "ARMSCII-8" },*/ + /*{ "BIG5", "BIG5" },*/ + { "Big5-HKSCS", "BIG5-HKSCS" }, + /*{ "CP1251", "CP1251" },*/ + /*{ "CP866", "CP866" },*/ + /*{ "GB18030", "GB18030" },*/ + /*{ "GB2312", "GB2312" },*/ + { "ISO8859-1", "ISO-8859-1" }, + { "ISO8859-13", "ISO-8859-13" }, + { "ISO8859-15", "ISO-8859-15" }, + { "ISO8859-2", "ISO-8859-2" }, + { "ISO8859-4", "ISO-8859-4" }, + { "ISO8859-5", "ISO-8859-5" }, + { "ISO8859-7", "ISO-8859-7" }, + /*{ "KOI8-R", "KOI8-R" },*/ + /*{ "KOI8-U", "KOI8-U" },*/ + /*{ "PT154", "PT154" },*/ + { "SJIS", "SHIFT_JIS" }, + { "eucCN", "GB2312" }, + { "eucJP", "EUC-JP" }, + { "eucKR", "EUC-KR" }, + { "eucTW", "EUC-TW" } +# define alias_table_defined +# endif +# if defined __OpenBSD__ /* OpenBSD */ + { "646", "ASCII" }, + { "ISO8859-1", "ISO-8859-1" }, + { "ISO8859-13", "ISO-8859-13" }, + { "ISO8859-15", "ISO-8859-15" }, + { "ISO8859-2", "ISO-8859-2" }, + { "ISO8859-4", "ISO-8859-4" }, + { "ISO8859-5", "ISO-8859-5" }, + { "ISO8859-7", "ISO-8859-7" } +# define alias_table_defined +# endif +# if defined __APPLE__ && defined __MACH__ /* Mac OS X */ + /* Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is + useless: + - It returns the empty string when LANG is set to a locale of the + form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8 + LC_CTYPE file. + - The environment variables LANG, LC_CTYPE, LC_ALL are not set by + the system; nl_langinfo(CODESET) returns "US-ASCII" in this case. + - The documentation says: + "... all code that calls BSD system routines should ensure + that the const *char parameters of these routines are in UTF-8 + encoding. All BSD system functions expect their string + parameters to be in UTF-8 encoding and nothing else." + It also says + "An additional caveat is that string parameters for files, + paths, and other file-system entities must be in canonical + UTF-8. In a canonical UTF-8 Unicode string, all decomposable + characters are decomposed ..." + but this is not true: You can pass non-decomposed UTF-8 strings + to file system functions, and it is the OS which will convert + them to decomposed UTF-8 before accessing the file system. + - The Apple Terminal application displays UTF-8 by default. + - However, other applications are free to use different encodings: + - xterm uses ISO-8859-1 by default. + - TextEdit uses MacRoman by default. + We prefer UTF-8 over decomposed UTF-8-MAC because one should + minimize the use of decomposed Unicode. Unfortunately, through the + Darwin file system, decomposed UTF-8 strings are leaked into user + space nevertheless. + Then there are also the locales with encodings other than US-ASCII + and UTF-8. These locales can be occasionally useful to users (e.g. + when grepping through ISO-8859-1 encoded text files), when all their + file names are in US-ASCII. + */ + { "ARMSCII-8", "ARMSCII-8" }, + { "Big5", "BIG5" }, + { "Big5HKSCS", "BIG5-HKSCS" }, + { "CP1131", "CP1131" }, + { "CP1251", "CP1251" }, + { "CP866", "CP866" }, + { "CP949", "CP949" }, + { "GB18030", "GB18030" }, + { "GB2312", "GB2312" }, + { "GBK", "GBK" }, + /*{ "ISCII-DEV", "?" },*/ + { "ISO8859-1", "ISO-8859-1" }, + { "ISO8859-13", "ISO-8859-13" }, + { "ISO8859-15", "ISO-8859-15" }, + { "ISO8859-2", "ISO-8859-2" }, + { "ISO8859-4", "ISO-8859-4" }, + { "ISO8859-5", "ISO-8859-5" }, + { "ISO8859-7", "ISO-8859-7" }, + { "ISO8859-9", "ISO-8859-9" }, + { "KOI8-R", "KOI8-R" }, + { "KOI8-U", "KOI8-U" }, + { "PT154", "PT154" }, + { "SJIS", "SHIFT_JIS" }, + { "eucCN", "GB2312" }, + { "eucJP", "EUC-JP" }, + { "eucKR", "EUC-KR" } +# define alias_table_defined +# endif +# if defined _AIX /* AIX */ + /*{ "GBK", "GBK" },*/ + { "IBM-1046", "CP1046" }, + { "IBM-1124", "CP1124" }, + { "IBM-1129", "CP1129" }, + { "IBM-1252", "CP1252" }, + { "IBM-850", "CP850" }, + { "IBM-856", "CP856" }, + { "IBM-921", "ISO-8859-13" }, + { "IBM-922", "CP922" }, + { "IBM-932", "CP932" }, + { "IBM-943", "CP943" }, + { "IBM-eucCN", "GB2312" }, + { "IBM-eucJP", "EUC-JP" }, + { "IBM-eucKR", "EUC-KR" }, + { "IBM-eucTW", "EUC-TW" }, + { "ISO8859-1", "ISO-8859-1" }, + { "ISO8859-15", "ISO-8859-15" }, + { "ISO8859-2", "ISO-8859-2" }, + { "ISO8859-5", "ISO-8859-5" }, + { "ISO8859-6", "ISO-8859-6" }, + { "ISO8859-7", "ISO-8859-7" }, + { "ISO8859-8", "ISO-8859-8" }, + { "ISO8859-9", "ISO-8859-9" }, + { "TIS-620", "TIS-620" }, + /*{ "UTF-8", "UTF-8" },*/ + { "big5", "BIG5" } +# define alias_table_defined +# endif +# if defined __hpux /* HP-UX */ + { "SJIS", "SHIFT_JIS" }, + { "arabic8", "HP-ARABIC8" }, + { "big5", "BIG5" }, + { "cp1251", "CP1251" }, + { "eucJP", "EUC-JP" }, + { "eucKR", "EUC-KR" }, + { "eucTW", "EUC-TW" }, + { "gb18030", "GB18030" }, + { "greek8", "HP-GREEK8" }, + { "hebrew8", "HP-HEBREW8" }, + { "hkbig5", "BIG5-HKSCS" }, + { "hp15CN", "GB2312" }, + { "iso88591", "ISO-8859-1" }, + { "iso885913", "ISO-8859-13" }, + { "iso885915", "ISO-8859-15" }, + { "iso88592", "ISO-8859-2" }, + { "iso88594", "ISO-8859-4" }, + { "iso88595", "ISO-8859-5" }, + { "iso88596", "ISO-8859-6" }, + { "iso88597", "ISO-8859-7" }, + { "iso88598", "ISO-8859-8" }, + { "iso88599", "ISO-8859-9" }, + { "kana8", "HP-KANA8" }, + { "koi8r", "KOI8-R" }, + { "roman8", "HP-ROMAN8" }, + { "tis620", "TIS-620" }, + { "turkish8", "HP-TURKISH8" }, + { "utf8", "UTF-8" } +# define alias_table_defined +# endif +# if defined __sgi /* IRIX */ + { "ISO8859-1", "ISO-8859-1" }, + { "ISO8859-15", "ISO-8859-15" }, + { "ISO8859-2", "ISO-8859-2" }, + { "ISO8859-5", "ISO-8859-5" }, + { "ISO8859-7", "ISO-8859-7" }, + { "ISO8859-9", "ISO-8859-9" }, + { "eucCN", "GB2312" }, + { "eucJP", "EUC-JP" }, + { "eucKR", "EUC-KR" }, + { "eucTW", "EUC-TW" } +# define alias_table_defined +# endif +# if defined __osf__ /* OSF/1 */ + /*{ "GBK", "GBK" },*/ + { "ISO8859-1", "ISO-8859-1" }, + { "ISO8859-15", "ISO-8859-15" }, + { "ISO8859-2", "ISO-8859-2" }, + { "ISO8859-4", "ISO-8859-4" }, + { "ISO8859-5", "ISO-8859-5" }, + { "ISO8859-7", "ISO-8859-7" }, + { "ISO8859-8", "ISO-8859-8" }, + { "ISO8859-9", "ISO-8859-9" }, + { "KSC5601", "CP949" }, + { "SJIS", "SHIFT_JIS" }, + { "TACTIS", "TIS-620" }, + /*{ "UTF-8", "UTF-8" },*/ + { "big5", "BIG5" }, + { "cp850", "CP850" }, + { "dechanyu", "DEC-HANYU" }, + { "dechanzi", "GB2312" }, + { "deckanji", "DEC-KANJI" }, + { "deckorean", "EUC-KR" }, + { "eucJP", "EUC-JP" }, + { "eucKR", "EUC-KR" }, + { "eucTW", "EUC-TW" }, + { "sdeckanji", "EUC-JP" } +# define alias_table_defined +# endif +# if defined __sun /* Solaris */ + { "5601", "EUC-KR" }, + { "646", "ASCII" }, + /*{ "BIG5", "BIG5" },*/ + { "Big5-HKSCS", "BIG5-HKSCS" }, + { "GB18030", "GB18030" }, + /*{ "GBK", "GBK" },*/ + { "ISO8859-1", "ISO-8859-1" }, + { "ISO8859-11", "TIS-620" }, + { "ISO8859-13", "ISO-8859-13" }, + { "ISO8859-15", "ISO-8859-15" }, + { "ISO8859-2", "ISO-8859-2" }, + { "ISO8859-3", "ISO-8859-3" }, + { "ISO8859-4", "ISO-8859-4" }, + { "ISO8859-5", "ISO-8859-5" }, + { "ISO8859-6", "ISO-8859-6" }, + { "ISO8859-7", "ISO-8859-7" }, + { "ISO8859-8", "ISO-8859-8" }, + { "ISO8859-9", "ISO-8859-9" }, + { "PCK", "SHIFT_JIS" }, + { "TIS620.2533", "TIS-620" }, + /*{ "UTF-8", "UTF-8" },*/ + { "ansi-1251", "CP1251" }, + { "cns11643", "EUC-TW" }, + { "eucJP", "EUC-JP" }, + { "gb2312", "GB2312" }, + { "koi8-r", "KOI8-R" } +# define alias_table_defined +# endif +# if defined __minix /* Minix */ + { "646", "ASCII" } +# define alias_table_defined +# endif +# if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Windows */ + { "CP1361", "JOHAB" }, + { "CP20127", "ASCII" }, + { "CP20866", "KOI8-R" }, + { "CP20936", "GB2312" }, + { "CP21866", "KOI8-RU" }, + { "CP28591", "ISO-8859-1" }, + { "CP28592", "ISO-8859-2" }, + { "CP28593", "ISO-8859-3" }, + { "CP28594", "ISO-8859-4" }, + { "CP28595", "ISO-8859-5" }, + { "CP28596", "ISO-8859-6" }, + { "CP28597", "ISO-8859-7" }, + { "CP28598", "ISO-8859-8" }, + { "CP28599", "ISO-8859-9" }, + { "CP28605", "ISO-8859-15" }, + { "CP38598", "ISO-8859-8" }, + { "CP51932", "EUC-JP" }, + { "CP51936", "GB2312" }, + { "CP51949", "EUC-KR" }, + { "CP51950", "EUC-TW" }, + { "CP54936", "GB18030" }, + { "CP65001", "UTF-8" }, + { "CP936", "GBK" } +# define alias_table_defined +# endif +# if defined OS2 /* OS/2 */ + /* The list of encodings is taken from "List of OS/2 Codepages" + by Alex Taylor: + <http://altsan.org/os2/toolkits/uls/index.html#codepages>. + See also "IBM Globalization - Code page identifiers": + <https://www-01.ibm.com/software/globalization/cp/cp_cpgid.html>. */ + { "CP1089", "ISO-8859-6" }, + { "CP1208", "UTF-8" }, + { "CP1381", "GB2312" }, + { "CP1386", "GBK" }, + { "CP3372", "EUC-JP" }, + { "CP813", "ISO-8859-7" }, + { "CP819", "ISO-8859-1" }, + { "CP878", "KOI8-R" }, + { "CP912", "ISO-8859-2" }, + { "CP913", "ISO-8859-3" }, + { "CP914", "ISO-8859-4" }, + { "CP915", "ISO-8859-5" }, + { "CP916", "ISO-8859-8" }, + { "CP920", "ISO-8859-9" }, + { "CP921", "ISO-8859-13" }, + { "CP923", "ISO-8859-15" }, + { "CP954", "EUC-JP" }, + { "CP964", "EUC-TW" }, + { "CP970", "EUC-KR" } +# define alias_table_defined +# endif +# if defined VMS /* OpenVMS */ + /* The list of encodings is taken from the OpenVMS 7.3-1 documentation + "Compaq C Run-Time Library Reference Manual for OpenVMS systems" + section 10.7 "Handling Different Character Sets". */ + { "DECHANYU", "DEC-HANYU" }, + { "DECHANZI", "GB2312" }, + { "DECKANJI", "DEC-KANJI" }, + { "DECKOREAN", "EUC-KR" }, + { "ISO8859-1", "ISO-8859-1" }, + { "ISO8859-2", "ISO-8859-2" }, + { "ISO8859-5", "ISO-8859-5" }, + { "ISO8859-7", "ISO-8859-7" }, + { "ISO8859-8", "ISO-8859-8" }, + { "ISO8859-9", "ISO-8859-9" }, + { "SDECKANJI", "EUC-JP" }, + { "SJIS", "SHIFT_JIS" }, + { "eucJP", "EUC-JP" }, + { "eucTW", "EUC-TW" } +# define alias_table_defined +# endif +# ifndef alias_table_defined + /* Just a dummy entry, to avoid a C syntax error. */ + { "", "" } +# endif + }; + +# endif + +#else + +/* On these platforms, we use a mapping from locale name to GNU canonical + encoding name. */ + +struct table_entry +{ + const char locale[17+1]; + const char canonical[11+1]; +}; + +/* Table of platform-dependent mappings, sorted in ascending order. */ +static const struct table_entry locale_table[] = + { +# if defined __FreeBSD__ /* FreeBSD 4.2 */ + { "cs_CZ.ISO_8859-2", "ISO-8859-2" }, + { "da_DK.DIS_8859-15", "ISO-8859-15" }, + { "da_DK.ISO_8859-1", "ISO-8859-1" }, + { "de_AT.DIS_8859-15", "ISO-8859-15" }, + { "de_AT.ISO_8859-1", "ISO-8859-1" }, + { "de_CH.DIS_8859-15", "ISO-8859-15" }, + { "de_CH.ISO_8859-1", "ISO-8859-1" }, + { "de_DE.DIS_8859-15", "ISO-8859-15" }, + { "de_DE.ISO_8859-1", "ISO-8859-1" }, + { "en_AU.DIS_8859-15", "ISO-8859-15" }, + { "en_AU.ISO_8859-1", "ISO-8859-1" }, + { "en_CA.DIS_8859-15", "ISO-8859-15" }, + { "en_CA.ISO_8859-1", "ISO-8859-1" }, + { "en_GB.DIS_8859-15", "ISO-8859-15" }, + { "en_GB.ISO_8859-1", "ISO-8859-1" }, + { "en_US.DIS_8859-15", "ISO-8859-15" }, + { "en_US.ISO_8859-1", "ISO-8859-1" }, + { "es_ES.DIS_8859-15", "ISO-8859-15" }, + { "es_ES.ISO_8859-1", "ISO-8859-1" }, + { "fi_FI.DIS_8859-15", "ISO-8859-15" }, + { "fi_FI.ISO_8859-1", "ISO-8859-1" }, + { "fr_BE.DIS_8859-15", "ISO-8859-15" }, + { "fr_BE.ISO_8859-1", "ISO-8859-1" }, + { "fr_CA.DIS_8859-15", "ISO-8859-15" }, + { "fr_CA.ISO_8859-1", "ISO-8859-1" }, + { "fr_CH.DIS_8859-15", "ISO-8859-15" }, + { "fr_CH.ISO_8859-1", "ISO-8859-1" }, + { "fr_FR.DIS_8859-15", "ISO-8859-15" }, + { "fr_FR.ISO_8859-1", "ISO-8859-1" }, + { "hr_HR.ISO_8859-2", "ISO-8859-2" }, + { "hu_HU.ISO_8859-2", "ISO-8859-2" }, + { "is_IS.DIS_8859-15", "ISO-8859-15" }, + { "is_IS.ISO_8859-1", "ISO-8859-1" }, + { "it_CH.DIS_8859-15", "ISO-8859-15" }, + { "it_CH.ISO_8859-1", "ISO-8859-1" }, + { "it_IT.DIS_8859-15", "ISO-8859-15" }, + { "it_IT.ISO_8859-1", "ISO-8859-1" }, + { "ja_JP.EUC", "EUC-JP" }, + { "ja_JP.SJIS", "SHIFT_JIS" }, + { "ja_JP.Shift_JIS", "SHIFT_JIS" }, + { "ko_KR.EUC", "EUC-KR" }, + { "la_LN.ASCII", "ASCII" }, + { "la_LN.DIS_8859-15", "ISO-8859-15" }, + { "la_LN.ISO_8859-1", "ISO-8859-1" }, + { "la_LN.ISO_8859-2", "ISO-8859-2" }, + { "la_LN.ISO_8859-4", "ISO-8859-4" }, + { "lt_LN.ASCII", "ASCII" }, + { "lt_LN.DIS_8859-15", "ISO-8859-15" }, + { "lt_LN.ISO_8859-1", "ISO-8859-1" }, + { "lt_LN.ISO_8859-2", "ISO-8859-2" }, + { "lt_LT.ISO_8859-4", "ISO-8859-4" }, + { "nl_BE.DIS_8859-15", "ISO-8859-15" }, + { "nl_BE.ISO_8859-1", "ISO-8859-1" }, + { "nl_NL.DIS_8859-15", "ISO-8859-15" }, + { "nl_NL.ISO_8859-1", "ISO-8859-1" }, + { "no_NO.DIS_8859-15", "ISO-8859-15" }, + { "no_NO.ISO_8859-1", "ISO-8859-1" }, + { "pl_PL.ISO_8859-2", "ISO-8859-2" }, + { "pt_PT.DIS_8859-15", "ISO-8859-15" }, + { "pt_PT.ISO_8859-1", "ISO-8859-1" }, + { "ru_RU.CP866", "CP866" }, + { "ru_RU.ISO_8859-5", "ISO-8859-5" }, + { "ru_RU.KOI8-R", "KOI8-R" }, + { "ru_SU.CP866", "CP866" }, + { "ru_SU.ISO_8859-5", "ISO-8859-5" }, + { "ru_SU.KOI8-R", "KOI8-R" }, + { "sl_SI.ISO_8859-2", "ISO-8859-2" }, + { "sv_SE.DIS_8859-15", "ISO-8859-15" }, + { "sv_SE.ISO_8859-1", "ISO-8859-1" }, + { "uk_UA.KOI8-U", "KOI8-U" }, + { "zh_CN.EUC", "GB2312" }, + { "zh_TW.BIG5", "BIG5" }, + { "zh_TW.Big5", "BIG5" } +# define locale_table_defined +# endif +# if defined __DJGPP__ /* DOS / DJGPP 2.03 */ + /* The encodings given here may not all be correct. + If you find that the encoding given for your language and + country is not the one your DOS machine actually uses, just + correct it in this file, and send a mail to + Juan Manuel Guerrero <juan.guerrero@gmx.de> + and <bug-gnulib@gnu.org>. */ + { "C", "ASCII" }, + { "ar", "CP864" }, + { "ar_AE", "CP864" }, + { "ar_DZ", "CP864" }, + { "ar_EG", "CP864" }, + { "ar_IQ", "CP864" }, + { "ar_IR", "CP864" }, + { "ar_JO", "CP864" }, + { "ar_KW", "CP864" }, + { "ar_MA", "CP864" }, + { "ar_OM", "CP864" }, + { "ar_QA", "CP864" }, + { "ar_SA", "CP864" }, + { "ar_SY", "CP864" }, + { "be", "CP866" }, + { "be_BE", "CP866" }, + { "bg", "CP866" }, /* not CP855 ?? */ + { "bg_BG", "CP866" }, /* not CP855 ?? */ + { "ca", "CP850" }, + { "ca_ES", "CP850" }, + { "cs", "CP852" }, + { "cs_CZ", "CP852" }, + { "da", "CP865" }, /* not CP850 ?? */ + { "da_DK", "CP865" }, /* not CP850 ?? */ + { "de", "CP850" }, + { "de_AT", "CP850" }, + { "de_CH", "CP850" }, + { "de_DE", "CP850" }, + { "el", "CP869" }, + { "el_GR", "CP869" }, + { "en", "CP850" }, + { "en_AU", "CP850" }, /* not CP437 ?? */ + { "en_CA", "CP850" }, + { "en_GB", "CP850" }, + { "en_NZ", "CP437" }, + { "en_US", "CP437" }, + { "en_ZA", "CP850" }, /* not CP437 ?? */ + { "eo", "CP850" }, + { "eo_EO", "CP850" }, + { "es", "CP850" }, + { "es_AR", "CP850" }, + { "es_BO", "CP850" }, + { "es_CL", "CP850" }, + { "es_CO", "CP850" }, + { "es_CR", "CP850" }, + { "es_CU", "CP850" }, + { "es_DO", "CP850" }, + { "es_EC", "CP850" }, + { "es_ES", "CP850" }, + { "es_GT", "CP850" }, + { "es_HN", "CP850" }, + { "es_MX", "CP850" }, + { "es_NI", "CP850" }, + { "es_PA", "CP850" }, + { "es_PE", "CP850" }, + { "es_PY", "CP850" }, + { "es_SV", "CP850" }, + { "es_UY", "CP850" }, + { "es_VE", "CP850" }, + { "et", "CP850" }, + { "et_EE", "CP850" }, + { "eu", "CP850" }, + { "eu_ES", "CP850" }, + { "fi", "CP850" }, + { "fi_FI", "CP850" }, + { "fr", "CP850" }, + { "fr_BE", "CP850" }, + { "fr_CA", "CP850" }, + { "fr_CH", "CP850" }, + { "fr_FR", "CP850" }, + { "ga", "CP850" }, + { "ga_IE", "CP850" }, + { "gd", "CP850" }, + { "gd_GB", "CP850" }, + { "gl", "CP850" }, + { "gl_ES", "CP850" }, + { "he", "CP862" }, + { "he_IL", "CP862" }, + { "hr", "CP852" }, + { "hr_HR", "CP852" }, + { "hu", "CP852" }, + { "hu_HU", "CP852" }, + { "id", "CP850" }, /* not CP437 ?? */ + { "id_ID", "CP850" }, /* not CP437 ?? */ + { "is", "CP861" }, /* not CP850 ?? */ + { "is_IS", "CP861" }, /* not CP850 ?? */ + { "it", "CP850" }, + { "it_CH", "CP850" }, + { "it_IT", "CP850" }, + { "ja", "CP932" }, + { "ja_JP", "CP932" }, + { "kr", "CP949" }, /* not CP934 ?? */ + { "kr_KR", "CP949" }, /* not CP934 ?? */ + { "lt", "CP775" }, + { "lt_LT", "CP775" }, + { "lv", "CP775" }, + { "lv_LV", "CP775" }, + { "mk", "CP866" }, /* not CP855 ?? */ + { "mk_MK", "CP866" }, /* not CP855 ?? */ + { "mt", "CP850" }, + { "mt_MT", "CP850" }, + { "nb", "CP865" }, /* not CP850 ?? */ + { "nb_NO", "CP865" }, /* not CP850 ?? */ + { "nl", "CP850" }, + { "nl_BE", "CP850" }, + { "nl_NL", "CP850" }, + { "nn", "CP865" }, /* not CP850 ?? */ + { "nn_NO", "CP865" }, /* not CP850 ?? */ + { "no", "CP865" }, /* not CP850 ?? */ + { "no_NO", "CP865" }, /* not CP850 ?? */ + { "pl", "CP852" }, + { "pl_PL", "CP852" }, + { "pt", "CP850" }, + { "pt_BR", "CP850" }, + { "pt_PT", "CP850" }, + { "ro", "CP852" }, + { "ro_RO", "CP852" }, + { "ru", "CP866" }, + { "ru_RU", "CP866" }, + { "sk", "CP852" }, + { "sk_SK", "CP852" }, + { "sl", "CP852" }, + { "sl_SI", "CP852" }, + { "sq", "CP852" }, + { "sq_AL", "CP852" }, + { "sr", "CP852" }, /* CP852 or CP866 or CP855 ?? */ + { "sr_CS", "CP852" }, /* CP852 or CP866 or CP855 ?? */ + { "sr_YU", "CP852" }, /* CP852 or CP866 or CP855 ?? */ + { "sv", "CP850" }, + { "sv_SE", "CP850" }, + { "th", "CP874" }, + { "th_TH", "CP874" }, + { "tr", "CP857" }, + { "tr_TR", "CP857" }, + { "uk", "CP1125" }, + { "uk_UA", "CP1125" }, + { "zh_CN", "GBK" }, + { "zh_TW", "CP950" } /* not CP938 ?? */ +# define locale_table_defined +# endif +# ifndef locale_table_defined + /* Just a dummy entry, to avoid a C syntax error. */ + { "", "" } +# endif + }; + +#endif + + +/* Determine the current locale's character encoding, and canonicalize it + into one of the canonical names listed in localcharset.h. + The result must not be freed; it is statically allocated. + If the canonical name cannot be determined, the result is a non-canonical + name. */ + +#ifdef STATIC +STATIC +#endif +const char * +locale_charset (void) +{ + const char *codeset; + +#if HAVE_LANGINFO_CODESET || defined WINDOWS_NATIVE || defined OS2 + +# if HAVE_LANGINFO_CODESET + + /* Most systems support nl_langinfo (CODESET) nowadays. */ + codeset = nl_langinfo (CODESET); + +# ifdef __CYGWIN__ + /* Cygwin < 1.7 does not have locales. nl_langinfo (CODESET) always + returns "US-ASCII". Return the suffix of the locale name from the + environment variables (if present) or the codepage as a number. */ + if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0) + { + const char *locale; + static char buf[2 + 10 + 1]; + + locale = getenv ("LC_ALL"); + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_CTYPE"); + if (locale == NULL || locale[0] == '\0') + locale = getenv ("LANG"); + } + if (locale != NULL && locale[0] != '\0') + { + /* If the locale name contains an encoding after the dot, return + it. */ + const char *dot = strchr (locale, '.'); + + if (dot != NULL) + { + const char *modifier; + + dot++; + /* Look for the possible @... trailer and remove it, if any. */ + modifier = strchr (dot, '@'); + if (modifier == NULL) + return dot; + if (modifier - dot < sizeof (buf)) + { + memcpy (buf, dot, modifier - dot); + buf [modifier - dot] = '\0'; + return buf; + } + } + } + + /* The Windows API has a function returning the locale's codepage as a + number: GetACP(). This encoding is used by Cygwin, unless the user + has set the environment variable CYGWIN=codepage:oem (which very few + people do). + Output directed to console windows needs to be converted (to + GetOEMCP() if the console is using a raster font, or to + GetConsoleOutputCP() if it is using a TrueType font). Cygwin does + this conversion transparently (see winsup/cygwin/fhandler_console.cc), + converting to GetConsoleOutputCP(). This leads to correct results, + except when SetConsoleOutputCP has been called and a raster font is + in use. */ + sprintf (buf, "CP%u", GetACP ()); + codeset = buf; + } +# endif + + if (codeset == NULL) + /* The canonical name cannot be determined. */ + codeset = ""; + +# elif defined WINDOWS_NATIVE + + static char buf[2 + 10 + 1]; + + /* The Windows API has a function returning the locale's codepage as + a number, but the value doesn't change according to what the + 'setlocale' call specified. So we use it as a last resort, in + case the string returned by 'setlocale' doesn't specify the + codepage. */ + char *current_locale = setlocale (LC_ALL, NULL); + char *pdot; + + /* If they set different locales for different categories, + 'setlocale' will return a semi-colon separated list of locale + values. To make sure we use the correct one, we choose LC_CTYPE. */ + if (strchr (current_locale, ';')) + current_locale = setlocale (LC_CTYPE, NULL); + + pdot = strrchr (current_locale, '.'); + if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf)) + sprintf (buf, "CP%s", pdot + 1); + else + { + /* The Windows API has a function returning the locale's codepage as a + number: GetACP(). + When the output goes to a console window, it needs to be provided in + GetOEMCP() encoding if the console is using a raster font, or in + GetConsoleOutputCP() encoding if it is using a TrueType font. + But in GUI programs and for output sent to files and pipes, GetACP() + encoding is the best bet. */ + sprintf (buf, "CP%u", GetACP ()); + } + codeset = buf; + +# elif defined OS2 + + const char *locale; + static char buf[2 + 10 + 1]; + ULONG cp[3]; + ULONG cplen; + + codeset = NULL; + + /* Allow user to override the codeset, as set in the operating system, + with standard language environment variables. */ + locale = getenv ("LC_ALL"); + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_CTYPE"); + if (locale == NULL || locale[0] == '\0') + locale = getenv ("LANG"); + } + if (locale != NULL && locale[0] != '\0') + { + /* If the locale name contains an encoding after the dot, return it. */ + const char *dot = strchr (locale, '.'); + + if (dot != NULL) + { + const char *modifier; + + dot++; + /* Look for the possible @... trailer and remove it, if any. */ + modifier = strchr (dot, '@'); + if (modifier == NULL) + return dot; + if (modifier - dot < sizeof (buf)) + { + memcpy (buf, dot, modifier - dot); + buf [modifier - dot] = '\0'; + return buf; + } + } + + /* For the POSIX locale, don't use the system's codepage. */ + if (strcmp (locale, "C") == 0 || strcmp (locale, "POSIX") == 0) + codeset = ""; + } + + if (codeset == NULL) + { + /* OS/2 has a function returning the locale's codepage as a number. */ + if (DosQueryCp (sizeof (cp), cp, &cplen)) + codeset = ""; + else + { + sprintf (buf, "CP%u", cp[0]); + codeset = buf; + } + } + +# else + +# error "Add code for other platforms here." + +# endif + + /* Resolve alias. */ + { +# ifdef alias_table_defined + /* On some platforms, UTF-8 locales are the most frequently used ones. + Speed up the common case and slow down the less common cases by + testing for this case first. */ +# if defined __OpenBSD__ || (defined __APPLE__ && defined __MACH__) || defined __sun || defined __CYGWIN__ + if (strcmp (codeset, "UTF-8") == 0) + goto done_table_lookup; + else +# endif + { + const struct table_entry * const table = alias_table; + size_t const table_size = + sizeof (alias_table) / sizeof (struct table_entry); + /* The table is sorted. Perform a binary search. */ + size_t hi = table_size; + size_t lo = 0; + while (lo < hi) + { + /* Invariant: + for i < lo, strcmp (table[i].alias, codeset) < 0, + for i >= hi, strcmp (table[i].alias, codeset) > 0. */ + size_t mid = (hi + lo) >> 1; /* >= lo, < hi */ + int cmp = strcmp (table[mid].alias, codeset); + if (cmp < 0) + lo = mid + 1; + else if (cmp > 0) + hi = mid; + else + { + /* Found an i with + strcmp (table[i].alias, codeset) == 0. */ + codeset = table[mid].canonical; + goto done_table_lookup; + } + } + } + if (0) + done_table_lookup: ; + else +# endif + { + /* Did not find it in the table. */ + /* On Mac OS X, all modern locales use the UTF-8 encoding. + BeOS and Haiku have a single locale, and it has UTF-8 encoding. */ +# if (defined __APPLE__ && defined __MACH__) || defined __BEOS__ || defined __HAIKU__ + codeset = "UTF-8"; +# else + /* Don't return an empty string. GNU libc and GNU libiconv interpret + the empty string as denoting "the locale's character encoding", + thus GNU libiconv would call this function a second time. */ + if (codeset[0] == '\0') + codeset = "ASCII"; +# endif + } + } + +#else + + /* On old systems which lack it, use setlocale or getenv. */ + const char *locale = NULL; + + /* But most old systems don't have a complete set of locales. Some + (like DJGPP) have only the C locale. Therefore we don't use setlocale + here; it would return "C" when it doesn't support the locale name the + user has set. */ +# if 0 + locale = setlocale (LC_CTYPE, NULL); +# endif + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_ALL"); + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_CTYPE"); + if (locale == NULL || locale[0] == '\0') + locale = getenv ("LANG"); + if (locale == NULL) + locale = ""; + } + } + + /* Map locale name to canonical encoding name. */ + { +# ifdef locale_table_defined + const struct table_entry * const table = locale_table; + size_t const table_size = + sizeof (locale_table) / sizeof (struct table_entry); + /* The table is sorted. Perform a binary search. */ + size_t hi = table_size; + size_t lo = 0; + while (lo < hi) + { + /* Invariant: + for i < lo, strcmp (table[i].locale, locale) < 0, + for i >= hi, strcmp (table[i].locale, locale) > 0. */ + size_t mid = (hi + lo) >> 1; /* >= lo, < hi */ + int cmp = strcmp (table[mid].locale, locale); + if (cmp < 0) + lo = mid + 1; + else if (cmp > 0) + hi = mid; + else + { + /* Found an i with + strcmp (table[i].locale, locale) == 0. */ + codeset = table[mid].canonical; + goto done_table_lookup; + } + } + if (0) + done_table_lookup: ; + else +# endif + { + /* Did not find it in the table. */ + /* On Mac OS X, all modern locales use the UTF-8 encoding. + BeOS and Haiku have a single locale, and it has UTF-8 encoding. */ +# if (defined __APPLE__ && defined __MACH__) || defined __BEOS__ || defined __HAIKU__ + codeset = "UTF-8"; +# else + /* The canonical name cannot be determined. */ + /* Don't return an empty string. GNU libc and GNU libiconv interpret + the empty string as denoting "the locale's character encoding", + thus GNU libiconv would call this function a second time. */ + codeset = "ASCII"; +# endif + } + } + +#endif + +#ifdef DARWIN7 + /* Mac OS X sets MB_CUR_MAX to 1 when LC_ALL=C, and "UTF-8" + (the default codeset) does not work when MB_CUR_MAX is 1. */ + if (strcmp (codeset, "UTF-8") == 0 && MB_CUR_MAX_L (uselocale (NULL)) <= 1) + codeset = "ASCII"; +#endif + + return codeset; +} diff --git a/grub-core/lib/gnulib/localcharset.h b/grub-core/lib/gnulib/localcharset.h new file mode 100644 index 0000000..7d0d771 --- /dev/null +++ b/grub-core/lib/gnulib/localcharset.h @@ -0,0 +1,134 @@ +/* Determine a canonical name for the current locale's character encoding. + Copyright (C) 2000-2003, 2009-2019 Free Software Foundation, Inc. + This file is part of the GNU CHARSET Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _LOCALCHARSET_H +#define _LOCALCHARSET_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Determine the current locale's character encoding, and canonicalize it + into one of the canonical names listed below. + The result must not be freed; it is statically allocated. + If the canonical name cannot be determined, the result is a non-canonical + name. */ +extern const char * locale_charset (void); + +/* About GNU canonical names for character encodings: + + Every canonical name must be supported by GNU libiconv. Support by GNU libc + is also desirable. + + The name is case insensitive. Usually an upper case MIME charset name is + preferred. + + The current list of these GNU canonical names is: + + name MIME? used by which systems + (darwin = Mac OS X, windows = native Windows) + + ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin minix cygwin + ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin + ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin + ISO-8859-3 Y glibc solaris cygwin + ISO-8859-4 Y hpux osf solaris freebsd netbsd openbsd darwin + ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin + ISO-8859-6 Y glibc aix hpux solaris cygwin + ISO-8859-7 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin + ISO-8859-8 Y glibc aix hpux osf solaris cygwin + ISO-8859-9 Y glibc aix hpux irix osf solaris freebsd darwin cygwin + ISO-8859-13 glibc hpux solaris freebsd netbsd openbsd darwin cygwin + ISO-8859-14 glibc cygwin + ISO-8859-15 glibc aix irix osf solaris freebsd netbsd openbsd darwin cygwin + KOI8-R Y glibc hpux solaris freebsd netbsd openbsd darwin + KOI8-U Y glibc freebsd netbsd openbsd darwin cygwin + KOI8-T glibc + CP437 dos + CP775 dos + CP850 aix osf dos + CP852 dos + CP855 dos + CP856 aix + CP857 dos + CP861 dos + CP862 dos + CP864 dos + CP865 dos + CP866 freebsd netbsd openbsd darwin dos + CP869 dos + CP874 windows dos + CP922 aix + CP932 aix cygwin windows dos + CP943 aix + CP949 osf darwin windows dos + CP950 windows dos + CP1046 aix + CP1124 aix + CP1125 dos + CP1129 aix + CP1131 freebsd darwin + CP1250 windows + CP1251 glibc hpux solaris freebsd netbsd openbsd darwin cygwin windows + CP1252 aix windows + CP1253 windows + CP1254 windows + CP1255 glibc windows + CP1256 windows + CP1257 windows + GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin cygwin + EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin + EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin + EUC-TW glibc aix hpux irix osf solaris netbsd + BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin + BIG5-HKSCS glibc hpux solaris netbsd darwin + GBK glibc aix osf solaris freebsd darwin cygwin windows dos + GB18030 glibc hpux solaris freebsd netbsd darwin + SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin + JOHAB glibc solaris windows + TIS-620 glibc aix hpux osf solaris cygwin + VISCII Y glibc + TCVN5712-1 glibc + ARMSCII-8 glibc freebsd netbsd darwin + GEORGIAN-PS glibc cygwin + PT154 glibc netbsd cygwin + HP-ROMAN8 hpux + HP-ARABIC8 hpux + HP-GREEK8 hpux + HP-HEBREW8 hpux + HP-TURKISH8 hpux + HP-KANA8 hpux + DEC-KANJI osf + DEC-HANYU osf + UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin + + Note: Names which are not marked as being a MIME name should not be used in + Internet protocols for information interchange (mail, news, etc.). + + Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications + must understand both names and treat them as equivalent. + */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _LOCALCHARSET_H */ diff --git a/grub-core/lib/gnulib/locale.in.h b/grub-core/lib/gnulib/locale.in.h new file mode 100644 index 0000000..5f33ed1 --- /dev/null +++ b/grub-core/lib/gnulib/locale.in.h @@ -0,0 +1,272 @@ +/* A POSIX <locale.h>. + Copyright (C) 2007-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if (defined _WIN32 && !defined __CYGWIN__ && defined __need_locale_t) \ + || defined _GL_ALREADY_INCLUDING_LOCALE_H + +/* Special invocation convention: + - Inside mingw header files, + - To handle Solaris header files (through Solaris 10) when combined + with gettext's libintl.h. */ + +#@INCLUDE_NEXT@ @NEXT_LOCALE_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_LOCALE_H + +#define _GL_ALREADY_INCLUDING_LOCALE_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_LOCALE_H@ + +#undef _GL_ALREADY_INCLUDING_LOCALE_H + +#ifndef _@GUARD_PREFIX@_LOCALE_H +#define _@GUARD_PREFIX@_LOCALE_H + +/* NetBSD 5.0 mis-defines NULL. */ +#include <stddef.h> + +/* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */ +#if @HAVE_XLOCALE_H@ +# include <xlocale.h> +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* The LC_MESSAGES locale category is specified in POSIX, but not in ISO C. + On systems that don't define it, use the same value as GNU libintl. */ +#if !defined LC_MESSAGES +# define LC_MESSAGES 1729 +#endif + +/* Bionic libc's 'struct lconv' is just a dummy. */ +#if @REPLACE_STRUCT_LCONV@ +# define lconv rpl_lconv +struct lconv +{ + /* All 'char *' are actually 'const char *'. */ + + /* Members that depend on the LC_NUMERIC category of the locale. See + <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_04> */ + + /* Symbol used as decimal point. */ + char *decimal_point; + /* Symbol used to separate groups of digits to the left of the decimal + point. */ + char *thousands_sep; + /* Definition of the size of groups of digits to the left of the decimal + point. */ + char *grouping; + + /* Members that depend on the LC_MONETARY category of the locale. See + <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_03> */ + + /* Symbol used as decimal point. */ + char *mon_decimal_point; + /* Symbol used to separate groups of digits to the left of the decimal + point. */ + char *mon_thousands_sep; + /* Definition of the size of groups of digits to the left of the decimal + point. */ + char *mon_grouping; + /* Sign used to indicate a value >= 0. */ + char *positive_sign; + /* Sign used to indicate a value < 0. */ + char *negative_sign; + + /* For formatting local currency. */ + /* Currency symbol (3 characters) followed by separator (1 character). */ + char *currency_symbol; + /* Number of digits after the decimal point. */ + char frac_digits; + /* For values >= 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char p_cs_precedes; + /* For values >= 0: Position of the sign. */ + char p_sign_posn; + /* For values >= 0: Placement of spaces between currency symbol, sign, and + number. */ + char p_sep_by_space; + /* For values < 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char n_cs_precedes; + /* For values < 0: Position of the sign. */ + char n_sign_posn; + /* For values < 0: Placement of spaces between currency symbol, sign, and + number. */ + char n_sep_by_space; + + /* For formatting international currency. */ + /* Currency symbol (3 characters) followed by separator (1 character). */ + char *int_curr_symbol; + /* Number of digits after the decimal point. */ + char int_frac_digits; + /* For values >= 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char int_p_cs_precedes; + /* For values >= 0: Position of the sign. */ + char int_p_sign_posn; + /* For values >= 0: Placement of spaces between currency symbol, sign, and + number. */ + char int_p_sep_by_space; + /* For values < 0: 1 if the currency symbol precedes the number, 0 if it + comes after the number. */ + char int_n_cs_precedes; + /* For values < 0: Position of the sign. */ + char int_n_sign_posn; + /* For values < 0: Placement of spaces between currency symbol, sign, and + number. */ + char int_n_sep_by_space; +}; +#endif + +#if @GNULIB_LOCALECONV@ +# if @REPLACE_LOCALECONV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef localeconv +# define localeconv rpl_localeconv +# endif +_GL_FUNCDECL_RPL (localeconv, struct lconv *, (void)); +_GL_CXXALIAS_RPL (localeconv, struct lconv *, (void)); +# else +_GL_CXXALIAS_SYS (localeconv, struct lconv *, (void)); +# endif +_GL_CXXALIASWARN (localeconv); +#elif @REPLACE_STRUCT_LCONV@ +# undef localeconv +# define localeconv localeconv_used_without_requesting_gnulib_module_localeconv +#elif defined GNULIB_POSIXCHECK +# undef localeconv +# if HAVE_RAW_DECL_LOCALECONV +_GL_WARN_ON_USE (localeconv, + "localeconv returns too few information on some platforms - " + "use gnulib module localeconv for portability"); +# endif +#endif + +#if @GNULIB_SETLOCALE@ +# if @REPLACE_SETLOCALE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef setlocale +# define setlocale rpl_setlocale +# define GNULIB_defined_setlocale 1 +# endif +_GL_FUNCDECL_RPL (setlocale, char *, (int category, const char *locale)); +_GL_CXXALIAS_RPL (setlocale, char *, (int category, const char *locale)); +# else +_GL_CXXALIAS_SYS (setlocale, char *, (int category, const char *locale)); +# endif +_GL_CXXALIASWARN (setlocale); +#elif defined GNULIB_POSIXCHECK +# undef setlocale +# if HAVE_RAW_DECL_SETLOCALE +_GL_WARN_ON_USE (setlocale, "setlocale works differently on native Windows - " + "use gnulib module setlocale for portability"); +# endif +#endif + +#if /*@GNULIB_NEWLOCALE@ ||*/ (@GNULIB_LOCALENAME@ && @HAVE_NEWLOCALE@) +# if @REPLACE_NEWLOCALE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef newlocale +# define newlocale rpl_newlocale +# define GNULIB_defined_newlocale 1 +# endif +_GL_FUNCDECL_RPL (newlocale, locale_t, + (int category_mask, const char *name, locale_t base) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (newlocale, locale_t, + (int category_mask, const char *name, locale_t base)); +# else +# if @HAVE_NEWLOCALE@ +_GL_CXXALIAS_SYS (newlocale, locale_t, + (int category_mask, const char *name, locale_t base)); +# endif +# endif +# if @HAVE_NEWLOCALE@ +_GL_CXXALIASWARN (newlocale); +# endif +#elif defined GNULIB_POSIXCHECK +# undef newlocale +# if HAVE_RAW_DECL_NEWLOCALE +_GL_WARN_ON_USE (newlocale, "newlocale is not portable"); +# endif +#endif + +#if @GNULIB_DUPLOCALE@ || (@GNULIB_LOCALENAME@ && @HAVE_DUPLOCALE@) +# if @REPLACE_DUPLOCALE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef duplocale +# define duplocale rpl_duplocale +# define GNULIB_defined_duplocale 1 +# endif +_GL_FUNCDECL_RPL (duplocale, locale_t, (locale_t locale) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (duplocale, locale_t, (locale_t locale)); +# else +# if @HAVE_DUPLOCALE@ +_GL_CXXALIAS_SYS (duplocale, locale_t, (locale_t locale)); +# endif +# endif +# if @HAVE_DUPLOCALE@ +_GL_CXXALIASWARN (duplocale); +# endif +#elif defined GNULIB_POSIXCHECK +# undef duplocale +# if HAVE_RAW_DECL_DUPLOCALE +_GL_WARN_ON_USE (duplocale, "duplocale is buggy on some glibc systems - " + "use gnulib module duplocale for portability"); +# endif +#endif + +#if /*@GNULIB_FREELOCALE@ ||*/ (@GNULIB_LOCALENAME@ && @HAVE_FREELOCALE@) +# if @REPLACE_FREELOCALE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef freelocale +# define freelocale rpl_freelocale +# define GNULIB_defined_freelocale 1 +# endif +_GL_FUNCDECL_RPL (freelocale, void, (locale_t locale) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (freelocale, void, (locale_t locale)); +# else +# if @HAVE_FREELOCALE@ +_GL_CXXALIAS_SYS (freelocale, void, (locale_t locale)); +# endif +# endif +# if @HAVE_FREELOCALE@ +_GL_CXXALIASWARN (freelocale); +# endif +#elif defined GNULIB_POSIXCHECK +# undef freelocale +# if HAVE_RAW_DECL_FREELOCALE +_GL_WARN_ON_USE (freelocale, "freelocale is not portable"); +# endif +#endif + +#endif /* _@GUARD_PREFIX@_LOCALE_H */ +#endif /* _@GUARD_PREFIX@_LOCALE_H */ +#endif /* !(__need_locale_t || _GL_ALREADY_INCLUDING_LOCALE_H) */ diff --git a/grub-core/lib/gnulib/localeconv.c b/grub-core/lib/gnulib/localeconv.c new file mode 100644 index 0000000..b5a965f --- /dev/null +++ b/grub-core/lib/gnulib/localeconv.c @@ -0,0 +1,103 @@ +/* Query locale dependent information for formatting numbers. + Copyright (C) 2012-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <locale.h> + +#if HAVE_STRUCT_LCONV_DECIMAL_POINT + +/* Override for platforms where 'struct lconv' lacks the int_p_*, int_n_* + members. */ + +struct lconv * +localeconv (void) +{ + static struct lconv result; +# undef lconv +# undef localeconv + struct lconv *sys_result = localeconv (); + + result.decimal_point = sys_result->decimal_point; + result.thousands_sep = sys_result->thousands_sep; + result.grouping = sys_result->grouping; + result.mon_decimal_point = sys_result->mon_decimal_point; + result.mon_thousands_sep = sys_result->mon_thousands_sep; + result.mon_grouping = sys_result->mon_grouping; + result.positive_sign = sys_result->positive_sign; + result.negative_sign = sys_result->negative_sign; + result.currency_symbol = sys_result->currency_symbol; + result.frac_digits = sys_result->frac_digits; + result.p_cs_precedes = sys_result->p_cs_precedes; + result.p_sign_posn = sys_result->p_sign_posn; + result.p_sep_by_space = sys_result->p_sep_by_space; + result.n_cs_precedes = sys_result->n_cs_precedes; + result.n_sign_posn = sys_result->n_sign_posn; + result.n_sep_by_space = sys_result->n_sep_by_space; + result.int_curr_symbol = sys_result->int_curr_symbol; + result.int_frac_digits = sys_result->int_frac_digits; + result.int_p_cs_precedes = sys_result->p_cs_precedes; + result.int_p_sign_posn = sys_result->p_sign_posn; + result.int_p_sep_by_space = sys_result->p_sep_by_space; + result.int_n_cs_precedes = sys_result->n_cs_precedes; + result.int_n_sign_posn = sys_result->n_sign_posn; + result.int_n_sep_by_space = sys_result->n_sep_by_space; + + return &result; +} + +#else + +/* Override for platforms where 'struct lconv' is a dummy. */ + +# include <limits.h> + +struct lconv * +localeconv (void) +{ + static /*const*/ struct lconv result = + { + /* decimal_point */ ".", + /* thousands_sep */ "", + /* grouping */ "", + /* mon_decimal_point */ "", + /* mon_thousands_sep */ "", + /* mon_grouping */ "", + /* positive_sign */ "", + /* negative_sign */ "", + /* currency_symbol */ "", + /* frac_digits */ CHAR_MAX, + /* p_cs_precedes */ CHAR_MAX, + /* p_sign_posn */ CHAR_MAX, + /* p_sep_by_space */ CHAR_MAX, + /* n_cs_precedes */ CHAR_MAX, + /* n_sign_posn */ CHAR_MAX, + /* n_sep_by_space */ CHAR_MAX, + /* int_curr_symbol */ "", + /* int_frac_digits */ CHAR_MAX, + /* int_p_cs_precedes */ CHAR_MAX, + /* int_p_sign_posn */ CHAR_MAX, + /* int_p_sep_by_space */ CHAR_MAX, + /* int_n_cs_precedes */ CHAR_MAX, + /* int_n_sign_posn */ CHAR_MAX, + /* int_n_sep_by_space */ CHAR_MAX + }; + + return &result; +} + +#endif diff --git a/grub-core/lib/gnulib/malloc.c b/grub-core/lib/gnulib/malloc.c new file mode 100644 index 0000000..76e6ff7 --- /dev/null +++ b/grub-core/lib/gnulib/malloc.c @@ -0,0 +1,56 @@ +/* malloc() function that is glibc compatible. + + Copyright (C) 1997-1998, 2006-2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* written by Jim Meyering and Bruno Haible */ + +#define _GL_USE_STDLIB_ALLOC 1 +#include <config.h> +/* Only the AC_FUNC_MALLOC macro defines 'malloc' already in config.h. */ +#ifdef malloc +# define NEED_MALLOC_GNU 1 +# undef malloc +/* Whereas the gnulib module 'malloc-gnu' defines HAVE_MALLOC_GNU. */ +#elif GNULIB_MALLOC_GNU && !HAVE_MALLOC_GNU +# define NEED_MALLOC_GNU 1 +#endif + +#include <stdlib.h> + +#include <errno.h> + +/* Allocate an N-byte block of memory from the heap. + If N is zero, allocate a 1-byte block. */ + +void * +rpl_malloc (size_t n) +{ + void *result; + +#if NEED_MALLOC_GNU + if (n == 0) + n = 1; +#endif + + result = malloc (n); + +#if !HAVE_MALLOC_POSIX + if (result == NULL) + errno = ENOMEM; +#endif + + return result; +} diff --git a/grub-core/lib/gnulib/malloca.c b/grub-core/lib/gnulib/malloca.c new file mode 100644 index 0000000..f60c5fb --- /dev/null +++ b/grub-core/lib/gnulib/malloca.c @@ -0,0 +1,105 @@ +/* Safe automatic memory allocation. + Copyright (C) 2003, 2006-2007, 2009-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2003, 2018. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#define _GL_USE_STDLIB_ALLOC 1 +#include <config.h> + +/* Specification. */ +#include "malloca.h" + +#include "verify.h" + +/* The speed critical point in this file is freea() applied to an alloca() + result: it must be fast, to match the speed of alloca(). The speed of + mmalloca() and freea() in the other case are not critical, because they + are only invoked for big memory sizes. + Here we use a bit in the address as an indicator, an idea by OndÅ™ej BÃlka. + malloca() can return three types of pointers: + - Pointers ≡ 0 mod 2*sa_alignment_max come from stack allocation. + - Pointers ≡ sa_alignment_max mod 2*sa_alignment_max come from heap + allocation. + - NULL comes from a failed heap allocation. */ + +/* Type for holding very small pointer differences. */ +typedef unsigned char small_t; +/* Verify that it is wide enough. */ +verify (2 * sa_alignment_max - 1 <= (small_t) -1); + +void * +mmalloca (size_t n) +{ +#if HAVE_ALLOCA + /* Allocate one more word, used to determine the address to pass to freea(), + and room for the alignment ≡ sa_alignment_max mod 2*sa_alignment_max. */ + size_t nplus = n + sizeof (small_t) + 2 * sa_alignment_max - 1; + + if (nplus >= n) + { + char *mem = (char *) malloc (nplus); + + if (mem != NULL) + { + char *p = + (char *)((((uintptr_t)mem + sizeof (small_t) + sa_alignment_max - 1) + & ~(uintptr_t)(2 * sa_alignment_max - 1)) + + sa_alignment_max); + /* Here p >= mem + sizeof (small_t), + and p <= mem + sizeof (small_t) + 2 * sa_alignment_max - 1 + hence p + n <= mem + nplus. + So, the memory range [p, p+n) lies in the allocated memory range + [mem, mem + nplus). */ + ((small_t *) p)[-1] = p - mem; + /* p ≡ sa_alignment_max mod 2*sa_alignment_max. */ + return p; + } + } + /* Out of memory. */ + return NULL; +#else +# if !MALLOC_0_IS_NONNULL + if (n == 0) + n = 1; +# endif + return malloc (n); +#endif +} + +#if HAVE_ALLOCA +void +freea (void *p) +{ + /* Check argument. */ + if ((uintptr_t) p & (sa_alignment_max - 1)) + { + /* p was not the result of a malloca() call. Invalid argument. */ + abort (); + } + /* Determine whether p was a non-NULL pointer returned by mmalloca(). */ + if ((uintptr_t) p & sa_alignment_max) + { + void *mem = (char *) p - ((small_t *) p)[-1]; + free (mem); + } +} +#endif + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/grub-core/lib/gnulib/malloca.h b/grub-core/lib/gnulib/malloca.h new file mode 100644 index 0000000..d80c316 --- /dev/null +++ b/grub-core/lib/gnulib/malloca.h @@ -0,0 +1,127 @@ +/* Safe automatic memory allocation. + Copyright (C) 2003-2007, 2009-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2003. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _MALLOCA_H +#define _MALLOCA_H + +#include <alloca.h> +#include <stddef.h> +#include <stdlib.h> +#include <stdint.h> + +#include "xalloc-oversized.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* safe_alloca(N) is equivalent to alloca(N) when it is safe to call + alloca(N); otherwise it returns NULL. It either returns N bytes of + memory allocated on the stack, that lasts until the function returns, + or NULL. + Use of safe_alloca should be avoided: + - inside arguments of function calls - undefined behaviour, + - in inline functions - the allocation may actually last until the + calling function returns. +*/ +#if HAVE_ALLOCA +/* The OS usually guarantees only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + allocate anything larger than 4096 bytes. Also care for the possibility + of a few compiler-allocated temporary stack slots. + This must be a macro, not a function. */ +# define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL) +#else +# define safe_alloca(N) ((void) (N), NULL) +#endif + +/* malloca(N) is a safe variant of alloca(N). It allocates N bytes of + memory allocated on the stack, that must be freed using freea() before + the function returns. Upon failure, it returns NULL. */ +#if HAVE_ALLOCA +# define malloca(N) \ + ((N) < 4032 - (2 * sa_alignment_max - 1) \ + ? (void *) (((uintptr_t) (char *) alloca ((N) + 2 * sa_alignment_max - 1) \ + + (2 * sa_alignment_max - 1)) \ + & ~(uintptr_t)(2 * sa_alignment_max - 1)) \ + : mmalloca (N)) +#else +# define malloca(N) \ + mmalloca (N) +#endif +extern void * mmalloca (size_t n); + +/* Free a block of memory allocated through malloca(). */ +#if HAVE_ALLOCA +extern void freea (void *p); +#else +# define freea free +#endif + +/* nmalloca(N,S) is an overflow-safe variant of malloca (N * S). + It allocates an array of N objects, each with S bytes of memory, + on the stack. S must be positive and N must be nonnegative. + The array must be freed using freea() before the function returns. */ +#define nmalloca(n, s) (xalloc_oversized (n, s) ? NULL : malloca ((n) * (s))) + + +#ifdef __cplusplus +} +#endif + + +/* ------------------- Auxiliary, non-public definitions ------------------- */ + +/* Determine the alignment of a type at compile time. */ +#if defined __GNUC__ || defined __IBM__ALIGNOF__ +# define sa_alignof __alignof__ +#elif defined __cplusplus + template <class type> struct sa_alignof_helper { char __slot1; type __slot2; }; +# define sa_alignof(type) offsetof (sa_alignof_helper<type>, __slot2) +#elif defined __hpux + /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof + values. */ +# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8) +#elif defined _AIX + /* Work around an AIX 3.2.5 xlc bug with enums constants defined as offsetof + values. */ +# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8) +#else +# define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2) +#endif + +enum +{ +/* The desired alignment of memory allocations is the maximum alignment + among all elementary types. */ + sa_alignment_long = sa_alignof (long), + sa_alignment_double = sa_alignof (double), +#if HAVE_LONG_LONG_INT + sa_alignment_longlong = sa_alignof (long long), +#endif + sa_alignment_longdouble = sa_alignof (long double), + sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1) +#if HAVE_LONG_LONG_INT + | (sa_alignment_longlong - 1) +#endif + | (sa_alignment_longdouble - 1) + ) + 1 +}; + +#endif /* _MALLOCA_H */ diff --git a/grub-core/lib/gnulib/mbrtowc.c b/grub-core/lib/gnulib/mbrtowc.c new file mode 100644 index 0000000..bbe3f7a --- /dev/null +++ b/grub-core/lib/gnulib/mbrtowc.c @@ -0,0 +1,458 @@ +/* Convert multibyte character to wide character. + Copyright (C) 1999-2002, 2005-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <wchar.h> + +#if C_LOCALE_MAYBE_EILSEQ +# include "hard-locale.h" +# include <locale.h> +#endif + +#if GNULIB_defined_mbstate_t +/* Implement mbrtowc() on top of mbtowc(). */ + +# include <errno.h> +# include <stdlib.h> + +# include "localcharset.h" +# include "streq.h" +# include "verify.h" + +# ifndef FALLTHROUGH +# if __GNUC__ < 7 +# define FALLTHROUGH ((void) 0) +# else +# define FALLTHROUGH __attribute__ ((__fallthrough__)) +# endif +# endif + +/* Returns a classification of special values of the encoding of the current + locale. */ +typedef enum { + enc_other, /* other */ + enc_utf8, /* UTF-8 */ + enc_eucjp, /* EUC-JP */ + enc_94, /* EUC-KR, GB2312, BIG5 */ + enc_euctw, /* EUC-TW */ + enc_gb18030, /* GB18030 */ + enc_sjis /* SJIS */ +} enc_t; +static inline enc_t +locale_enc (void) +{ + const char *encoding = locale_charset (); + if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0)) + return enc_utf8; + if (STREQ_OPT (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0)) + return enc_eucjp; + if (STREQ_OPT (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) + || STREQ_OPT (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0) + || STREQ_OPT (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0)) + return enc_94; + if (STREQ_OPT (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0)) + return enc_euctw; + if (STREQ_OPT (encoding, "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0)) + return enc_gb18030; + if (STREQ_OPT (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0)) + return enc_sjis; + return enc_other; +} + +#if GNULIB_WCHAR_SINGLE +/* When we know that the locale does not change, provide a speedup by + caching the value of locale_enc. */ +static int cached_locale_enc = -1; +static inline enc_t +locale_enc_cached (void) +{ + if (cached_locale_enc < 0) + cached_locale_enc = locale_enc (); + return cached_locale_enc; +} +#else +/* By default, don't make assumptions, hence no caching. */ +# define locale_enc_cached locale_enc +#endif + +verify (sizeof (mbstate_t) >= 4); + +static char internal_state[4]; + +size_t +mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) +{ + char *pstate = (char *)ps; + + if (s == NULL) + { + pwc = NULL; + s = ""; + n = 1; + } + + if (n == 0) + return (size_t)(-2); + + /* Here n > 0. */ + + if (pstate == NULL) + pstate = internal_state; + + { + size_t nstate = pstate[0]; + char buf[4]; + const char *p; + size_t m; + + switch (nstate) + { + case 0: + p = s; + m = n; + break; + case 3: + buf[2] = pstate[3]; + FALLTHROUGH; + case 2: + buf[1] = pstate[2]; + FALLTHROUGH; + case 1: + buf[0] = pstate[1]; + p = buf; + m = nstate; + buf[m++] = s[0]; + if (n >= 2 && m < 4) + { + buf[m++] = s[1]; + if (n >= 3 && m < 4) + buf[m++] = s[2]; + } + break; + default: + errno = EINVAL; + return (size_t)(-1); + } + + /* Here m > 0. */ + +# if __GLIBC__ || defined __UCLIBC__ + /* Work around bug <https://sourceware.org/bugzilla/show_bug.cgi?id=9674> */ + mbtowc (NULL, NULL, 0); +# endif + { + int res = mbtowc (pwc, p, m); + + if (res >= 0) + { + if (pwc != NULL && ((*pwc == 0) != (res == 0))) + abort (); + if (nstate >= (res > 0 ? res : 1)) + abort (); + res -= nstate; + pstate[0] = 0; + return res; + } + + /* mbtowc does not distinguish between invalid and incomplete multibyte + sequences. But mbrtowc needs to make this distinction. + There are two possible approaches: + - Use iconv() and its return value. + - Use built-in knowledge about the possible encodings. + Given the low quality of implementation of iconv() on the systems that + lack mbrtowc(), we use the second approach. + The possible encodings are: + - 8-bit encodings, + - EUC-JP, EUC-KR, GB2312, EUC-TW, BIG5, GB18030, SJIS, + - UTF-8. + Use specialized code for each. */ + if (m >= 4 || m >= MB_CUR_MAX) + goto invalid; + /* Here MB_CUR_MAX > 1 and 0 < m < 4. */ + switch (locale_enc_cached ()) + { + case enc_utf8: /* UTF-8 */ + { + /* Cf. unistr/u8-mblen.c. */ + unsigned char c = (unsigned char) p[0]; + + if (c >= 0xc2) + { + if (c < 0xe0) + { + if (m == 1) + goto incomplete; + } + else if (c < 0xf0) + { + if (m == 1) + goto incomplete; + if (m == 2) + { + unsigned char c2 = (unsigned char) p[1]; + + if ((c2 ^ 0x80) < 0x40 + && (c >= 0xe1 || c2 >= 0xa0) + && (c != 0xed || c2 < 0xa0)) + goto incomplete; + } + } + else if (c <= 0xf4) + { + if (m == 1) + goto incomplete; + else /* m == 2 || m == 3 */ + { + unsigned char c2 = (unsigned char) p[1]; + + if ((c2 ^ 0x80) < 0x40 + && (c >= 0xf1 || c2 >= 0x90) + && (c < 0xf4 || (c == 0xf4 && c2 < 0x90))) + { + if (m == 2) + goto incomplete; + else /* m == 3 */ + { + unsigned char c3 = (unsigned char) p[2]; + + if ((c3 ^ 0x80) < 0x40) + goto incomplete; + } + } + } + } + } + goto invalid; + } + + /* As a reference for this code, you can use the GNU libiconv + implementation. Look for uses of the RET_TOOFEW macro. */ + + case enc_eucjp: /* EUC-JP */ + { + if (m == 1) + { + unsigned char c = (unsigned char) p[0]; + + if ((c >= 0xa1 && c < 0xff) || c == 0x8e || c == 0x8f) + goto incomplete; + } + if (m == 2) + { + unsigned char c = (unsigned char) p[0]; + + if (c == 0x8f) + { + unsigned char c2 = (unsigned char) p[1]; + + if (c2 >= 0xa1 && c2 < 0xff) + goto incomplete; + } + } + goto invalid; + } + + case enc_94: /* EUC-KR, GB2312, BIG5 */ + { + if (m == 1) + { + unsigned char c = (unsigned char) p[0]; + + if (c >= 0xa1 && c < 0xff) + goto incomplete; + } + goto invalid; + } + + case enc_euctw: /* EUC-TW */ + { + if (m == 1) + { + unsigned char c = (unsigned char) p[0]; + + if ((c >= 0xa1 && c < 0xff) || c == 0x8e) + goto incomplete; + } + else /* m == 2 || m == 3 */ + { + unsigned char c = (unsigned char) p[0]; + + if (c == 0x8e) + goto incomplete; + } + goto invalid; + } + + case enc_gb18030: /* GB18030 */ + { + if (m == 1) + { + unsigned char c = (unsigned char) p[0]; + + if ((c >= 0x90 && c <= 0xe3) || (c >= 0xf8 && c <= 0xfe)) + goto incomplete; + } + else /* m == 2 || m == 3 */ + { + unsigned char c = (unsigned char) p[0]; + + if (c >= 0x90 && c <= 0xe3) + { + unsigned char c2 = (unsigned char) p[1]; + + if (c2 >= 0x30 && c2 <= 0x39) + { + if (m == 2) + goto incomplete; + else /* m == 3 */ + { + unsigned char c3 = (unsigned char) p[2]; + + if (c3 >= 0x81 && c3 <= 0xfe) + goto incomplete; + } + } + } + } + goto invalid; + } + + case enc_sjis: /* SJIS */ + { + if (m == 1) + { + unsigned char c = (unsigned char) p[0]; + + if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea) + || (c >= 0xf0 && c <= 0xf9)) + goto incomplete; + } + goto invalid; + } + + default: + /* An unknown multibyte encoding. */ + goto incomplete; + } + + incomplete: + { + size_t k = nstate; + /* Here 0 <= k < m < 4. */ + pstate[++k] = s[0]; + if (k < m) + { + pstate[++k] = s[1]; + if (k < m) + pstate[++k] = s[2]; + } + if (k != m) + abort (); + } + pstate[0] = m; + return (size_t)(-2); + + invalid: + errno = EILSEQ; + /* The conversion state is undefined, says POSIX. */ + return (size_t)(-1); + } + } +} + +#else +/* Override the system's mbrtowc() function. */ + +# undef mbrtowc + +size_t +rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) +{ + size_t ret; + wchar_t wc; + +# if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG || MBRTOWC_EMPTY_INPUT_BUG + if (s == NULL) + { + pwc = NULL; + s = ""; + n = 1; + } +# endif + +# if MBRTOWC_EMPTY_INPUT_BUG + if (n == 0) + return (size_t) -2; +# endif + + if (! pwc) + pwc = &wc; + +# if MBRTOWC_RETVAL_BUG + { + static mbstate_t internal_state; + + /* Override mbrtowc's internal state. We cannot call mbsinit() on the + hidden internal state, but we can call it on our variable. */ + if (ps == NULL) + ps = &internal_state; + + if (!mbsinit (ps)) + { + /* Parse the rest of the multibyte character byte for byte. */ + size_t count = 0; + for (; n > 0; s++, n--) + { + ret = mbrtowc (&wc, s, 1, ps); + + if (ret == (size_t)(-1)) + return (size_t)(-1); + count++; + if (ret != (size_t)(-2)) + { + /* The multibyte character has been completed. */ + *pwc = wc; + return (wc == 0 ? 0 : count); + } + } + return (size_t)(-2); + } + } +# endif + + ret = mbrtowc (pwc, s, n, ps); + +# if MBRTOWC_NUL_RETVAL_BUG + if (ret < (size_t) -2 && !*pwc) + return 0; +# endif + +# if C_LOCALE_MAYBE_EILSEQ + if ((size_t) -2 <= ret && n != 0 && ! hard_locale (LC_CTYPE)) + { + unsigned char uc = *s; + *pwc = uc; + return 1; + } +# endif + + return ret; +} + +#endif diff --git a/grub-core/lib/gnulib/mbsinit.c b/grub-core/lib/gnulib/mbsinit.c new file mode 100644 index 0000000..5ecaef7 --- /dev/null +++ b/grub-core/lib/gnulib/mbsinit.c @@ -0,0 +1,73 @@ +/* Test for initial conversion state. + Copyright (C) 2008-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <wchar.h> + +#include "verify.h" + +#if GNULIB_defined_mbstate_t + +/* Platforms that lack mbsinit() also lack mbrlen(), mbrtowc(), mbsrtowcs() + and wcrtomb(), wcsrtombs(). + We assume that + - sizeof (mbstate_t) >= 4, + - only stateless encodings are supported (such as UTF-8 and EUC-JP, but + not ISO-2022 variants), + - for each encoding, the number of bytes for a wide character is <= 4. + (This maximum is attained for UTF-8, GB18030, EUC-TW.) + We define the meaning of mbstate_t as follows: + - In mb -> wc direction, mbstate_t's first byte contains the number of + buffered bytes (in the range 0..3), followed by up to 3 buffered bytes. + See mbrtowc.c. + - In wc -> mb direction, mbstate_t contains no information. In other + words, it is always in the initial state. */ + +verify (sizeof (mbstate_t) >= 4); + +int +mbsinit (const mbstate_t *ps) +{ + const char *pstate = (const char *)ps; + + return pstate == NULL || pstate[0] == 0; +} + +#else + +int +mbsinit (const mbstate_t *ps) +{ +# if defined _WIN32 && !defined __CYGWIN__ + /* Native Windows. */ +# ifdef __MINGW32__ + /* On mingw, 'mbstate_t' is defined as 'int'. */ + return ps == NULL || *ps == 0; +# else + /* MSVC defines 'mbstate_t' as an 8-byte struct; the first 4-bytes matter. */ + return ps == NULL || *(const unsigned int *)ps == 0; +# endif +# else + /* Minix, HP-UX 11.00, Solaris 2.6, Interix, ... */ + /* Maybe this definition works, maybe not... */ + return ps == NULL || *(const char *)ps == 0; +# endif +} + +#endif diff --git a/grub-core/lib/gnulib/mbsrtowcs-impl.h b/grub-core/lib/gnulib/mbsrtowcs-impl.h new file mode 100644 index 0000000..110d692 --- /dev/null +++ b/grub-core/lib/gnulib/mbsrtowcs-impl.h @@ -0,0 +1,122 @@ +/* Convert string to wide string. + Copyright (C) 2008-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +size_t +mbsrtowcs (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps) +{ + if (ps == NULL) + ps = &_gl_mbsrtowcs_state; + { + const char *src = *srcp; + + if (dest != NULL) + { + wchar_t *destptr = dest; + + for (; len > 0; destptr++, len--) + { + size_t src_avail; + size_t ret; + + /* An optimized variant of + src_avail = strnlen1 (src, MB_LEN_MAX); */ + if (src[0] == '\0') + src_avail = 1; + else if (src[1] == '\0') + src_avail = 2; + else if (src[2] == '\0') + src_avail = 3; + else if (MB_LEN_MAX <= 4 || src[3] == '\0') + src_avail = 4; + else + src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4); + + /* Parse the next multibyte character. */ + ret = mbrtowc (destptr, src, src_avail, ps); + + if (ret == (size_t)(-2)) + /* Encountered a multibyte character that extends past a '\0' byte + or that is longer than MB_LEN_MAX bytes. Cannot happen. */ + abort (); + + if (ret == (size_t)(-1)) + goto bad_input; + if (ret == 0) + { + src = NULL; + /* Here mbsinit (ps). */ + break; + } + src += ret; + } + + *srcp = src; + return destptr - dest; + } + else + { + /* Ignore dest and len, don't store *srcp at the end, and + don't clobber *ps. */ + mbstate_t state = *ps; + size_t totalcount = 0; + + for (;; totalcount++) + { + size_t src_avail; + size_t ret; + + /* An optimized variant of + src_avail = strnlen1 (src, MB_LEN_MAX); */ + if (src[0] == '\0') + src_avail = 1; + else if (src[1] == '\0') + src_avail = 2; + else if (src[2] == '\0') + src_avail = 3; + else if (MB_LEN_MAX <= 4 || src[3] == '\0') + src_avail = 4; + else + src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4); + + /* Parse the next multibyte character. */ + ret = mbrtowc (NULL, src, src_avail, &state); + + if (ret == (size_t)(-2)) + /* Encountered a multibyte character that extends past a '\0' byte + or that is longer than MB_LEN_MAX bytes. Cannot happen. */ + abort (); + + if (ret == (size_t)(-1)) + goto bad_input2; + if (ret == 0) + { + /* Here mbsinit (&state). */ + break; + } + src += ret; + } + + return totalcount; + } + + bad_input: + *srcp = src; + bad_input2: + errno = EILSEQ; + return (size_t)(-1); + } +} diff --git a/grub-core/lib/gnulib/mbsrtowcs-state.c b/grub-core/lib/gnulib/mbsrtowcs-state.c new file mode 100644 index 0000000..59525e7 --- /dev/null +++ b/grub-core/lib/gnulib/mbsrtowcs-state.c @@ -0,0 +1,37 @@ +/* Convert string to wide string. + Copyright (C) 2008-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include <wchar.h> + +/* Internal state used by the functions mbsrtowcs() and mbsnrtowcs(). */ +mbstate_t _gl_mbsrtowcs_state +/* The state must initially be in the "initial state"; so, zero-initialize it. + On most systems, putting it into BSS is sufficient. Not so on Mac OS X 10.3, + see <https://lists.gnu.org/r/bug-gnulib/2009-01/msg00329.html>. + When it needs an initializer, use 0 or {0} as initializer? 0 only works + when mbstate_t is a scalar type (such as when gnulib defines it, or on + AIX, IRIX, mingw). {0} works as an initializer in all cases: for a struct + or union type, but also for a scalar type (ISO C 99, 6.7.8.(11)). */ +#if defined __ELF__ + /* On ELF systems, variables in BSS behave well. */ +#else + /* Use braces, to be on the safe side. */ + = { 0 } +#endif + ; diff --git a/grub-core/lib/gnulib/mbsrtowcs.c b/grub-core/lib/gnulib/mbsrtowcs.c new file mode 100644 index 0000000..14f241e --- /dev/null +++ b/grub-core/lib/gnulib/mbsrtowcs.c @@ -0,0 +1,32 @@ +/* Convert string to wide string. + Copyright (C) 2008-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <wchar.h> + +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +#include "strnlen1.h" + + +extern mbstate_t _gl_mbsrtowcs_state; + +#include "mbsrtowcs-impl.h" diff --git a/grub-core/lib/gnulib/mbswidth.c b/grub-core/lib/gnulib/mbswidth.c new file mode 100644 index 0000000..b3fb7f8 --- /dev/null +++ b/grub-core/lib/gnulib/mbswidth.c @@ -0,0 +1,208 @@ +/* Determine the number of screen columns needed for a string. + Copyright (C) 2000-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <haible@clisp.cons.org>. */ + +#include <config.h> + +/* Specification. */ +#include "mbswidth.h" + +/* Get MB_CUR_MAX. */ +#include <stdlib.h> + +#include <string.h> + +/* Get isprint(). */ +#include <ctype.h> + +/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */ +#include <wchar.h> + +/* Get iswcntrl(). */ +#include <wctype.h> + +/* Get INT_MAX. */ +#include <limits.h> + +#ifndef FALLTHROUGH +# if __GNUC__ < 7 +# define FALLTHROUGH ((void) 0) +# else +# define FALLTHROUGH __attribute__ ((__fallthrough__)) +# endif +#endif + +/* Returns the number of columns needed to represent the multibyte + character string pointed to by STRING. If a non-printable character + occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned. + With flags = MBSW_REJECT_INVALID | MBSW_REJECT_UNPRINTABLE, this is + the multibyte analogue of the wcswidth function. */ +int +mbswidth (const char *string, int flags) +{ + return mbsnwidth (string, strlen (string), flags); +} + +/* Returns the number of columns needed to represent the multibyte + character string pointed to by STRING of length NBYTES. If a + non-printable character occurs, and MBSW_REJECT_UNPRINTABLE is + specified, -1 is returned. */ +int +mbsnwidth (const char *string, size_t nbytes, int flags) +{ + const char *p = string; + const char *plimit = p + nbytes; + int width; + + width = 0; + if (MB_CUR_MAX > 1) + { + while (p < plimit) + switch (*p) + { + case ' ': case '!': case '"': case '#': case '%': + case '&': case '\'': case '(': case ')': case '*': + case '+': case ',': case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case ':': case ';': case '<': case '=': case '>': + case '?': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '[': case '\\': case ']': case '^': case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': case '{': case '|': case '}': case '~': + /* These characters are printable ASCII characters. */ + p++; + width++; + break; + case '\0': + if (flags & MBSW_STOP_AT_NUL) + return width; + FALLTHROUGH; + default: + /* If we have a multibyte sequence, scan it up to its end. */ + { + mbstate_t mbstate; + memset (&mbstate, 0, sizeof mbstate); + do + { + wchar_t wc; + size_t bytes; + int w; + + bytes = mbrtowc (&wc, p, plimit - p, &mbstate); + + if (bytes == (size_t) -1) + /* An invalid multibyte sequence was encountered. */ + { + if (!(flags & MBSW_REJECT_INVALID)) + { + p++; + width++; + break; + } + else + return -1; + } + + if (bytes == (size_t) -2) + /* An incomplete multibyte character at the end. */ + { + if (!(flags & MBSW_REJECT_INVALID)) + { + p = plimit; + width++; + break; + } + else + return -1; + } + + if (bytes == 0) + /* A null wide character was encountered. */ + bytes = 1; + + w = wcwidth (wc); + if (w >= 0) + /* A printable multibyte character. */ + { + if (w > INT_MAX - width) + goto overflow; + width += w; + } + else + /* An unprintable multibyte character. */ + if (!(flags & MBSW_REJECT_UNPRINTABLE)) + { + if (!iswcntrl (wc)) + { + if (width == INT_MAX) + goto overflow; + width++; + } + } + else + return -1; + + p += bytes; + } + while (! mbsinit (&mbstate)); + } + break; + } + return width; + } + + while (p < plimit) + { + unsigned char c = (unsigned char) *p++; + + if (c == 0 && (flags & MBSW_STOP_AT_NUL)) + return width; + + if (isprint (c)) + { + if (width == INT_MAX) + goto overflow; + width++; + } + else if (!(flags & MBSW_REJECT_UNPRINTABLE)) + { + if (!iscntrl (c)) + { + if (width == INT_MAX) + goto overflow; + width++; + } + } + else + return -1; + } + return width; + + overflow: + return INT_MAX; +} diff --git a/grub-core/lib/gnulib/mbswidth.h b/grub-core/lib/gnulib/mbswidth.h new file mode 100644 index 0000000..45a123e --- /dev/null +++ b/grub-core/lib/gnulib/mbswidth.h @@ -0,0 +1,64 @@ +/* Determine the number of screen columns needed for a string. + Copyright (C) 2000-2004, 2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <stddef.h> + +/* Avoid a clash of our mbswidth() with a function of the same name defined + in UnixWare 7.1.1 <wchar.h>. We need this #include before the #define + below. + However, we don't want to #include <wchar.h> on all platforms because + - Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before + <wchar.h>. + - BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before + <wchar.h>. */ +#if HAVE_DECL_MBSWIDTH_IN_WCHAR_H +# include <wchar.h> +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Optional flags to influence mbswidth/mbsnwidth behavior. */ + +/* If this bit is set, return -1 upon finding an invalid or incomplete + character. Otherwise, assume invalid characters have width 1. */ +#define MBSW_REJECT_INVALID 1 + +/* If this bit is set, return -1 upon finding a non-printable character. + Otherwise, assume unprintable characters have width 0 if they are + control characters and 1 otherwise. */ +#define MBSW_REJECT_UNPRINTABLE 2 + +/* If this bit is set \0 is treated as the end of string. + Otherwise it's treated as a normal one column width character. */ +#define MBSW_STOP_AT_NUL 4 + + +/* Returns the number of screen columns needed for STRING. */ +#define mbswidth gnu_mbswidth /* avoid clash with UnixWare 7.1.1 function */ +extern int mbswidth (const char *string, int flags); + +/* Returns the number of screen columns needed for the NBYTES bytes + starting at BUF. */ +extern int mbsnwidth (const char *buf, size_t nbytes, int flags); + + +#ifdef __cplusplus +} +#endif diff --git a/grub-core/lib/gnulib/mbtowc-impl.h b/grub-core/lib/gnulib/mbtowc-impl.h new file mode 100644 index 0000000..f4ab981 --- /dev/null +++ b/grub-core/lib/gnulib/mbtowc-impl.h @@ -0,0 +1,44 @@ +/* Convert multibyte character to wide character. + Copyright (C) 2011-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* We don't need a static internal state, because the encoding is not state + dependent, and when mbrtowc returns (size_t)(-2). we throw the result + away. */ + +int +mbtowc (wchar_t *pwc, const char *s, size_t n) +{ + if (s == NULL) + return 0; + else + { + mbstate_t state; + wchar_t wc; + size_t result; + + memset (&state, 0, sizeof (mbstate_t)); + result = mbrtowc (&wc, s, n, &state); + if (result == (size_t)-1 || result == (size_t)-2) + { + errno = EILSEQ; + return -1; + } + if (pwc != NULL) + *pwc = wc; + return (wc == 0 ? 0 : result); + } +} diff --git a/grub-core/lib/gnulib/mbtowc.c b/grub-core/lib/gnulib/mbtowc.c new file mode 100644 index 0000000..77a8472 --- /dev/null +++ b/grub-core/lib/gnulib/mbtowc.c @@ -0,0 +1,26 @@ +/* Convert multibyte character to wide character. + Copyright (C) 2011-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2011. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include <stdlib.h> + +#include <errno.h> +#include <string.h> +#include <wchar.h> + +#include "mbtowc-impl.h" diff --git a/grub-core/lib/gnulib/memchr.c b/grub-core/lib/gnulib/memchr.c new file mode 100644 index 0000000..4e0c5f9 --- /dev/null +++ b/grub-core/lib/gnulib/memchr.c @@ -0,0 +1,172 @@ +/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2019 + Free Software Foundation, Inc. + + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + +NOTE: The canonical source of this file is maintained with the GNU C Library. +Bugs can be reported to bug-glibc@prep.ai.mit.edu. + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _LIBC +# include <config.h> +#endif + +#include <string.h> + +#include <stddef.h> + +#if defined _LIBC +# include <memcopy.h> +#else +# define reg_char char +#endif + +#include <limits.h> + +#if HAVE_BP_SYM_H || defined _LIBC +# include <bp-sym.h> +#else +# define BP_SYM(sym) sym +#endif + +#undef __memchr +#ifdef _LIBC +# undef memchr +#endif + +#ifndef weak_alias +# define __memchr memchr +#endif + +/* Search no more than N bytes of S for C. */ +void * +__memchr (void const *s, int c_in, size_t n) +{ + /* On 32-bit hardware, choosing longword to be a 32-bit unsigned + long instead of a 64-bit uintmax_t tends to give better + performance. On 64-bit hardware, unsigned long is generally 64 + bits already. Change this typedef to experiment with + performance. */ + typedef unsigned long int longword; + + const unsigned char *char_ptr; + const longword *longword_ptr; + longword repeated_one; + longword repeated_c; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the first few bytes by reading one byte at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + n > 0 && (size_t) char_ptr % sizeof (longword) != 0; + --n, ++char_ptr) + if (*char_ptr == c) + return (void *) char_ptr; + + longword_ptr = (const longword *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to any size longwords. */ + + /* Compute auxiliary longword values: + repeated_one is a value which has a 1 in every byte. + repeated_c has c in every byte. */ + repeated_one = 0x01010101; + repeated_c = c | (c << 8); + repeated_c |= repeated_c << 16; + if (0xffffffffU < (longword) -1) + { + repeated_one |= repeated_one << 31 << 1; + repeated_c |= repeated_c << 31 << 1; + if (8 < sizeof (longword)) + { + size_t i; + + for (i = 64; i < sizeof (longword) * 8; i *= 2) + { + repeated_one |= repeated_one << i; + repeated_c |= repeated_c << i; + } + } + } + + /* Instead of the traditional loop which tests each byte, we will test a + longword at a time. The tricky part is testing if *any of the four* + bytes in the longword in question are equal to c. We first use an xor + with repeated_c. This reduces the task to testing whether *any of the + four* bytes in longword1 is zero. + + We compute tmp = + ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). + That is, we perform the following operations: + 1. Subtract repeated_one. + 2. & ~longword1. + 3. & a mask consisting of 0x80 in every byte. + Consider what happens in each byte: + - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, + and step 3 transforms it into 0x80. A carry can also be propagated + to more significant bytes. + - If a byte of longword1 is nonzero, let its lowest 1 bit be at + position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, + the byte ends in a single bit of value 0 and k bits of value 1. + After step 2, the result is just k bits of value 1: 2^k - 1. After + step 3, the result is 0. And no carry is produced. + So, if longword1 has only non-zero bytes, tmp is zero. + Whereas if longword1 has a zero byte, call j the position of the least + significant zero byte. Then the result has a zero at positions 0, ..., + j-1 and a 0x80 at position j. We cannot predict the result at the more + significant bytes (positions j+1..3), but it does not matter since we + already have a non-zero bit at position 8*j+7. + + So, the test whether any byte in longword1 is zero is equivalent to + testing whether tmp is nonzero. */ + + while (n >= sizeof (longword)) + { + longword longword1 = *longword_ptr ^ repeated_c; + + if ((((longword1 - repeated_one) & ~longword1) + & (repeated_one << 7)) != 0) + break; + longword_ptr++; + n -= sizeof (longword); + } + + char_ptr = (const unsigned char *) longword_ptr; + + /* At this point, we know that either n < sizeof (longword), or one of the + sizeof (longword) bytes starting at char_ptr is == c. On little-endian + machines, we could determine the first such byte without any further + memory accesses, just by looking at the tmp result from the last loop + iteration. But this does not work on big-endian machines. Choose code + that works in both cases. */ + + for (; n > 0; --n, ++char_ptr) + { + if (*char_ptr == c) + return (void *) char_ptr; + } + + return NULL; +} +#ifdef weak_alias +weak_alias (__memchr, BP_SYM (memchr)) +#endif diff --git a/grub-core/lib/gnulib/memchr.valgrind b/grub-core/lib/gnulib/memchr.valgrind new file mode 100644 index 0000000..60f247e --- /dev/null +++ b/grub-core/lib/gnulib/memchr.valgrind @@ -0,0 +1,14 @@ +# Suppress a valgrind message about use of uninitialized memory in memchr(). +# POSIX states that when the character is found, memchr must not read extra +# bytes in an overestimated length (for example, where memchr is used to +# implement strnlen). However, we use a safe word read to provide a speedup. +{ + memchr-value4 + Memcheck:Value4 + fun:rpl_memchr +} +{ + memchr-value8 + Memcheck:Value8 + fun:rpl_memchr +} diff --git a/grub-core/lib/gnulib/mempcpy.c b/grub-core/lib/gnulib/mempcpy.c new file mode 100644 index 0000000..d0220e1 --- /dev/null +++ b/grub-core/lib/gnulib/mempcpy.c @@ -0,0 +1,28 @@ +/* Copy memory area and return pointer after last written byte. + Copyright (C) 2003, 2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <string.h> + +/* Copy N bytes of SRC to DEST, return pointer to bytes after the + last written byte. */ +void * +mempcpy (void *dest, const void *src, size_t n) +{ + return (char *) memcpy (dest, src, n) + n; +} diff --git a/grub-core/lib/gnulib/memrchr.c b/grub-core/lib/gnulib/memrchr.c new file mode 100644 index 0000000..9602283 --- /dev/null +++ b/grub-core/lib/gnulib/memrchr.c @@ -0,0 +1,161 @@ +/* memrchr -- find the last occurrence of a byte in a memory block + + Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2019 Free Software + Foundation, Inc. + + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#if defined _LIBC +# include <memcopy.h> +#else +# include <config.h> +# define reg_char char +#endif + +#include <string.h> +#include <limits.h> + +#undef __memrchr +#ifdef _LIBC +# undef memrchr +#endif + +#ifndef weak_alias +# define __memrchr memrchr +#endif + +/* Search no more than N bytes of S for C. */ +void * +__memrchr (void const *s, int c_in, size_t n) +{ + /* On 32-bit hardware, choosing longword to be a 32-bit unsigned + long instead of a 64-bit uintmax_t tends to give better + performance. On 64-bit hardware, unsigned long is generally 64 + bits already. Change this typedef to experiment with + performance. */ + typedef unsigned long int longword; + + const unsigned char *char_ptr; + const longword *longword_ptr; + longword repeated_one; + longword repeated_c; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the last few bytes by reading one byte at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s + n; + n > 0 && (size_t) char_ptr % sizeof (longword) != 0; + --n) + if (*--char_ptr == c) + return (void *) char_ptr; + + longword_ptr = (const void *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to any size longwords. */ + + /* Compute auxiliary longword values: + repeated_one is a value which has a 1 in every byte. + repeated_c has c in every byte. */ + repeated_one = 0x01010101; + repeated_c = c | (c << 8); + repeated_c |= repeated_c << 16; + if (0xffffffffU < (longword) -1) + { + repeated_one |= repeated_one << 31 << 1; + repeated_c |= repeated_c << 31 << 1; + if (8 < sizeof (longword)) + { + size_t i; + + for (i = 64; i < sizeof (longword) * 8; i *= 2) + { + repeated_one |= repeated_one << i; + repeated_c |= repeated_c << i; + } + } + } + + /* Instead of the traditional loop which tests each byte, we will test a + longword at a time. The tricky part is testing if *any of the four* + bytes in the longword in question are equal to c. We first use an xor + with repeated_c. This reduces the task to testing whether *any of the + four* bytes in longword1 is zero. + + We compute tmp = + ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). + That is, we perform the following operations: + 1. Subtract repeated_one. + 2. & ~longword1. + 3. & a mask consisting of 0x80 in every byte. + Consider what happens in each byte: + - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, + and step 3 transforms it into 0x80. A carry can also be propagated + to more significant bytes. + - If a byte of longword1 is nonzero, let its lowest 1 bit be at + position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, + the byte ends in a single bit of value 0 and k bits of value 1. + After step 2, the result is just k bits of value 1: 2^k - 1. After + step 3, the result is 0. And no carry is produced. + So, if longword1 has only non-zero bytes, tmp is zero. + Whereas if longword1 has a zero byte, call j the position of the least + significant zero byte. Then the result has a zero at positions 0, ..., + j-1 and a 0x80 at position j. We cannot predict the result at the more + significant bytes (positions j+1..3), but it does not matter since we + already have a non-zero bit at position 8*j+7. + + So, the test whether any byte in longword1 is zero is equivalent to + testing whether tmp is nonzero. */ + + while (n >= sizeof (longword)) + { + longword longword1 = *--longword_ptr ^ repeated_c; + + if ((((longword1 - repeated_one) & ~longword1) + & (repeated_one << 7)) != 0) + { + longword_ptr++; + break; + } + n -= sizeof (longword); + } + + char_ptr = (const unsigned char *) longword_ptr; + + /* At this point, we know that either n < sizeof (longword), or one of the + sizeof (longword) bytes starting at char_ptr is == c. On little-endian + machines, we could determine the first such byte without any further + memory accesses, just by looking at the tmp result from the last loop + iteration. But this does not work on big-endian machines. Choose code + that works in both cases. */ + + while (n-- > 0) + { + if (*--char_ptr == c) + return (void *) char_ptr; + } + + return NULL; +} +#ifdef weak_alias +weak_alias (__memrchr, memrchr) +#endif diff --git a/grub-core/lib/gnulib/msvc-inval.c b/grub-core/lib/gnulib/msvc-inval.c new file mode 100644 index 0000000..75b5a07 --- /dev/null +++ b/grub-core/lib/gnulib/msvc-inval.c @@ -0,0 +1,129 @@ +/* Invalid parameter handler for MSVC runtime libraries. + Copyright (C) 2011-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "msvc-inval.h" + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ + && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) + +/* Get _invalid_parameter_handler type and _set_invalid_parameter_handler + declaration. */ +# include <stdlib.h> + +# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING + +static void __cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ +} + +# else + +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> + +# if defined _MSC_VER + +static void __cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ + RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); +} + +# else + +/* An index to thread-local storage. */ +static DWORD tls_index; +static int tls_initialized /* = 0 */; + +/* Used as a fallback only. */ +static struct gl_msvc_inval_per_thread not_per_thread; + +struct gl_msvc_inval_per_thread * +gl_msvc_inval_current (void) +{ + if (!tls_initialized) + { + tls_index = TlsAlloc (); + tls_initialized = 1; + } + if (tls_index == TLS_OUT_OF_INDEXES) + /* TlsAlloc had failed. */ + return ¬_per_thread; + else + { + struct gl_msvc_inval_per_thread *pointer = + (struct gl_msvc_inval_per_thread *) TlsGetValue (tls_index); + if (pointer == NULL) + { + /* First call. Allocate a new 'struct gl_msvc_inval_per_thread'. */ + pointer = + (struct gl_msvc_inval_per_thread *) + malloc (sizeof (struct gl_msvc_inval_per_thread)); + if (pointer == NULL) + /* Could not allocate memory. Use the global storage. */ + pointer = ¬_per_thread; + TlsSetValue (tls_index, pointer); + } + return pointer; + } +} + +static void __cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ + struct gl_msvc_inval_per_thread *current = gl_msvc_inval_current (); + if (current->restart_valid) + longjmp (current->restart, 1); + else + /* An invalid parameter notification from outside the gnulib code. + Give the caller a chance to intervene. */ + RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); +} + +# endif + +# endif + +static int gl_msvc_inval_initialized /* = 0 */; + +void +gl_msvc_inval_ensure_handler (void) +{ + if (gl_msvc_inval_initialized == 0) + { + _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler); + gl_msvc_inval_initialized = 1; + } +} + +#endif diff --git a/grub-core/lib/gnulib/msvc-inval.h b/grub-core/lib/gnulib/msvc-inval.h new file mode 100644 index 0000000..e31cf65 --- /dev/null +++ b/grub-core/lib/gnulib/msvc-inval.h @@ -0,0 +1,222 @@ +/* Invalid parameter handler for MSVC runtime libraries. + Copyright (C) 2011-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _MSVC_INVAL_H +#define _MSVC_INVAL_H + +/* With MSVC runtime libraries with the "invalid parameter handler" concept, + functions like fprintf(), dup2(), or close() crash when the caller passes + an invalid argument. But POSIX wants error codes (such as EINVAL or EBADF) + instead. + This file defines macros that turn such an invalid parameter notification + into a non-local exit. An error code can then be produced at the target + of this exit. You can thus write code like + + TRY_MSVC_INVAL + { + <Code that can trigger an invalid parameter notification + but does not do 'return', 'break', 'continue', nor 'goto'.> + } + CATCH_MSVC_INVAL + { + <Code that handles an invalid parameter notification + but does not do 'return', 'break', 'continue', nor 'goto'.> + } + DONE_MSVC_INVAL; + + This entire block expands to a single statement. + + The handling of invalid parameters can be done in three ways: + + * The default way, which is reasonable for programs (not libraries): + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [DEFAULT_HANDLING]) + + * The way for libraries that make "hairy" calls (like close(-1), or + fclose(fp) where fileno(fp) is closed, or simply getdtablesize()): + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [HAIRY_LIBRARY_HANDLING]) + + * The way for libraries that make no "hairy" calls: + AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [SANE_LIBRARY_HANDLING]) + */ + +#define DEFAULT_HANDLING 0 +#define HAIRY_LIBRARY_HANDLING 1 +#define SANE_LIBRARY_HANDLING 2 + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ + && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) +/* A native Windows platform with the "invalid parameter handler" concept, + and either DEFAULT_HANDLING or HAIRY_LIBRARY_HANDLING. */ + +# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING +/* Default handling. */ + +# ifdef __cplusplus +extern "C" { +# endif + +/* Ensure that the invalid parameter handler in installed that just returns. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + gl_msvc_inval_ensure_handler (); \ + if (1) +# define CATCH_MSVC_INVAL \ + else +# define DONE_MSVC_INVAL \ + } \ + while (0) + +# else +/* Handling for hairy libraries. */ + +# include <excpt.h> + +/* Gnulib can define its own status codes, as described in the page + "Raising Software Exceptions" on microsoft.com + <https://msdn.microsoft.com/en-us/library/het71c37.aspx>. + Our status codes are composed of + - 0xE0000000, mandatory for all user-defined status codes, + - 0x474E550, a API identifier ("GNU"), + - 0, 1, 2, ..., used to distinguish different status codes from the + same API. */ +# define STATUS_GNULIB_INVALID_PARAMETER (0xE0000000 + 0x474E550 + 0) + +# if defined _MSC_VER +/* A compiler that supports __try/__except, as described in the page + "try-except statement" on microsoft.com + <https://msdn.microsoft.com/en-us/library/s58ftw19.aspx>. + With __try/__except, we can use the multithread-safe exception handling. */ + +# ifdef __cplusplus +extern "C" { +# endif + +/* Ensure that the invalid parameter handler in installed that raises a + software exception with code STATUS_GNULIB_INVALID_PARAMETER. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + gl_msvc_inval_ensure_handler (); \ + __try +# define CATCH_MSVC_INVAL \ + __except (GetExceptionCode () == STATUS_GNULIB_INVALID_PARAMETER \ + ? EXCEPTION_EXECUTE_HANDLER \ + : EXCEPTION_CONTINUE_SEARCH) +# define DONE_MSVC_INVAL \ + } \ + while (0) + +# else +/* Any compiler. + We can only use setjmp/longjmp. */ + +# include <setjmp.h> + +# ifdef __cplusplus +extern "C" { +# endif + +struct gl_msvc_inval_per_thread +{ + /* The restart that will resume execution at the code between + CATCH_MSVC_INVAL and DONE_MSVC_INVAL. It is enabled only between + TRY_MSVC_INVAL and CATCH_MSVC_INVAL. */ + jmp_buf restart; + + /* Tells whether the contents of restart is valid. */ + int restart_valid; +}; + +/* Ensure that the invalid parameter handler in installed that passes + control to the gl_msvc_inval_restart if it is valid, or raises a + software exception with code STATUS_GNULIB_INVALID_PARAMETER otherwise. + Because we assume no other part of the program installs a different + invalid parameter handler, this solution is multithread-safe. */ +extern void gl_msvc_inval_ensure_handler (void); + +/* Return a pointer to the per-thread data for the current thread. */ +extern struct gl_msvc_inval_per_thread *gl_msvc_inval_current (void); + +# ifdef __cplusplus +} +# endif + +# define TRY_MSVC_INVAL \ + do \ + { \ + struct gl_msvc_inval_per_thread *msvc_inval_current; \ + gl_msvc_inval_ensure_handler (); \ + msvc_inval_current = gl_msvc_inval_current (); \ + /* First, initialize gl_msvc_inval_restart. */ \ + if (setjmp (msvc_inval_current->restart) == 0) \ + { \ + /* Then, mark it as valid. */ \ + msvc_inval_current->restart_valid = 1; +# define CATCH_MSVC_INVAL \ + /* Execution completed. \ + Mark gl_msvc_inval_restart as invalid. */ \ + msvc_inval_current->restart_valid = 0; \ + } \ + else \ + { \ + /* Execution triggered an invalid parameter notification. \ + Mark gl_msvc_inval_restart as invalid. */ \ + msvc_inval_current->restart_valid = 0; +# define DONE_MSVC_INVAL \ + } \ + } \ + while (0) + +# endif + +# endif + +#else +/* A platform that does not need to the invalid parameter handler, + or when SANE_LIBRARY_HANDLING is desired. */ + +/* The braces here avoid GCC warnings like + "warning: suggest explicit braces to avoid ambiguous 'else'". */ +# define TRY_MSVC_INVAL \ + do \ + { \ + if (1) +# define CATCH_MSVC_INVAL \ + else +# define DONE_MSVC_INVAL \ + } \ + while (0) + +#endif + +#endif /* _MSVC_INVAL_H */ diff --git a/grub-core/lib/gnulib/msvc-nothrow.c b/grub-core/lib/gnulib/msvc-nothrow.c new file mode 100644 index 0000000..49b709c --- /dev/null +++ b/grub-core/lib/gnulib/msvc-nothrow.c @@ -0,0 +1,51 @@ +/* Wrappers that don't throw invalid parameter notifications + with MSVC runtime libraries. + Copyright (C) 2011-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "msvc-nothrow.h" + +/* Get declarations of the native Windows API functions. */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +#endif + +#undef _get_osfhandle + +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +intptr_t +_gl_nothrow_get_osfhandle (int fd) +{ + intptr_t result; + + TRY_MSVC_INVAL + { + result = _get_osfhandle (fd); + } + CATCH_MSVC_INVAL + { + result = (intptr_t) INVALID_HANDLE_VALUE; + } + DONE_MSVC_INVAL; + + return result; +} +#endif diff --git a/grub-core/lib/gnulib/msvc-nothrow.h b/grub-core/lib/gnulib/msvc-nothrow.h new file mode 100644 index 0000000..8d3ca78 --- /dev/null +++ b/grub-core/lib/gnulib/msvc-nothrow.h @@ -0,0 +1,43 @@ +/* Wrappers that don't throw invalid parameter notifications + with MSVC runtime libraries. + Copyright (C) 2011-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _MSVC_NOTHROW_H +#define _MSVC_NOTHROW_H + +/* With MSVC runtime libraries with the "invalid parameter handler" concept, + functions like fprintf(), dup2(), or close() crash when the caller passes + an invalid argument. But POSIX wants error codes (such as EINVAL or EBADF) + instead. + This file defines wrappers that turn such an invalid parameter notification + into an error code. */ + +#if defined _WIN32 && ! defined __CYGWIN__ + +/* Get original declaration of _get_osfhandle. */ +# include <io.h> + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER + +/* Override _get_osfhandle. */ +extern intptr_t _gl_nothrow_get_osfhandle (int fd); +# define _get_osfhandle _gl_nothrow_get_osfhandle + +# endif + +#endif + +#endif /* _MSVC_NOTHROW_H */ diff --git a/grub-core/lib/gnulib/nl_langinfo.c b/grub-core/lib/gnulib/nl_langinfo.c new file mode 100644 index 0000000..e8a5595 --- /dev/null +++ b/grub-core/lib/gnulib/nl_langinfo.c @@ -0,0 +1,366 @@ +/* nl_langinfo() replacement: query locale dependent information. + + Copyright (C) 2007-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <langinfo.h> + +#include <locale.h> +#include <string.h> +#if defined _WIN32 && ! defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include <windows.h> +# include <stdio.h> +#endif + +#if !REPLACE_NL_LANGINFO || GNULIB_defined_CODESET +/* Return the codeset of the current locale, if this is easily deducible. + Otherwise, return "". */ +static char * +ctype_codeset (void) +{ + static char buf[2 + 10 + 1]; + char const *locale = setlocale (LC_CTYPE, NULL); + char *codeset = buf; + size_t codesetlen; + codeset[0] = '\0'; + + if (locale && locale[0]) + { + /* If the locale name contains an encoding after the dot, return it. */ + char *dot = strchr (locale, '.'); + + if (dot) + { + /* Look for the possible @... trailer and remove it, if any. */ + char *codeset_start = dot + 1; + char const *modifier = strchr (codeset_start, '@'); + + if (! modifier) + codeset = codeset_start; + else + { + codesetlen = modifier - codeset_start; + if (codesetlen < sizeof buf) + { + codeset = memcpy (buf, codeset_start, codesetlen); + codeset[codesetlen] = '\0'; + } + } + } + } + +# if defined _WIN32 && ! defined __CYGWIN__ + /* If setlocale is successful, it returns the number of the + codepage, as a string. Otherwise, fall back on Windows API + GetACP, which returns the locale's codepage as a number (although + this doesn't change according to what the 'setlocale' call specified). + Either way, prepend "CP" to make it a valid codeset name. */ + codesetlen = strlen (codeset); + if (0 < codesetlen && codesetlen < sizeof buf - 2) + memmove (buf + 2, codeset, codesetlen + 1); + else + sprintf (buf + 2, "%u", GetACP ()); + codeset = memcpy (buf, "CP", 2); +# endif + return codeset; +} +#endif + + +#if REPLACE_NL_LANGINFO + +/* Override nl_langinfo with support for added nl_item values. */ + +# undef nl_langinfo + +char * +rpl_nl_langinfo (nl_item item) +{ + switch (item) + { +# if GNULIB_defined_CODESET + case CODESET: + return ctype_codeset (); +# endif +# if GNULIB_defined_T_FMT_AMPM + case T_FMT_AMPM: + return (char *) "%I:%M:%S %p"; +# endif +# if GNULIB_defined_ALTMON + case ALTMON_1: + case ALTMON_2: + case ALTMON_3: + case ALTMON_4: + case ALTMON_5: + case ALTMON_6: + case ALTMON_7: + case ALTMON_8: + case ALTMON_9: + case ALTMON_10: + case ALTMON_11: + case ALTMON_12: + /* We don't ship the appropriate localizations with gnulib. Therefore, + treat ALTMON_i like MON_i. */ + item = item - ALTMON_1 + MON_1; + break; +# endif +# if GNULIB_defined_ERA + case ERA: + /* The format is not standardized. In glibc it is a sequence of strings + of the form "direction:offset:start_date:end_date:era_name:era_format" + with an empty string at the end. */ + return (char *) ""; + case ERA_D_FMT: + /* The %Ex conversion in strftime behaves like %x if the locale does not + have an alternative time format. */ + item = D_FMT; + break; + case ERA_D_T_FMT: + /* The %Ec conversion in strftime behaves like %c if the locale does not + have an alternative time format. */ + item = D_T_FMT; + break; + case ERA_T_FMT: + /* The %EX conversion in strftime behaves like %X if the locale does not + have an alternative time format. */ + item = T_FMT; + break; + case ALT_DIGITS: + /* The format is not standardized. In glibc it is a sequence of 10 + strings, appended in memory. */ + return (char *) "\0\0\0\0\0\0\0\0\0\0"; +# endif +# if GNULIB_defined_YESEXPR || !FUNC_NL_LANGINFO_YESEXPR_WORKS + case YESEXPR: + return (char *) "^[yY]"; + case NOEXPR: + return (char *) "^[nN]"; +# endif + default: + break; + } + return nl_langinfo (item); +} + +#else + +/* Provide nl_langinfo from scratch, either for native MS-Windows, or + for old Unix platforms without locales, such as Linux libc5 or + BeOS. */ + +# include <time.h> + +char * +nl_langinfo (nl_item item) +{ + static char nlbuf[100]; + struct tm tmm = { 0 }; + + switch (item) + { + /* nl_langinfo items of the LC_CTYPE category */ + case CODESET: + { + char *codeset = ctype_codeset (); + if (*codeset) + return codeset; + } +# ifdef __BEOS__ + return (char *) "UTF-8"; +# else + return (char *) "ISO-8859-1"; +# endif + /* nl_langinfo items of the LC_NUMERIC category */ + case RADIXCHAR: + return localeconv () ->decimal_point; + case THOUSEP: + return localeconv () ->thousands_sep; +# ifdef GROUPING + case GROUPING: + return localeconv () ->grouping; +# endif + /* nl_langinfo items of the LC_TIME category. + TODO: Really use the locale. */ + case D_T_FMT: + case ERA_D_T_FMT: + return (char *) "%a %b %e %H:%M:%S %Y"; + case D_FMT: + case ERA_D_FMT: + return (char *) "%m/%d/%y"; + case T_FMT: + case ERA_T_FMT: + return (char *) "%H:%M:%S"; + case T_FMT_AMPM: + return (char *) "%I:%M:%S %p"; + case AM_STR: + if (!strftime (nlbuf, sizeof nlbuf, "%p", &tmm)) + return (char *) "AM"; + return nlbuf; + case PM_STR: + tmm.tm_hour = 12; + if (!strftime (nlbuf, sizeof nlbuf, "%p", &tmm)) + return (char *) "PM"; + return nlbuf; + case DAY_1: + case DAY_2: + case DAY_3: + case DAY_4: + case DAY_5: + case DAY_6: + case DAY_7: + { + static char const days[][sizeof "Wednesday"] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday" + }; + tmm.tm_wday = item - DAY_1; + if (!strftime (nlbuf, sizeof nlbuf, "%A", &tmm)) + return (char *) days[item - DAY_1]; + return nlbuf; + } + case ABDAY_1: + case ABDAY_2: + case ABDAY_3: + case ABDAY_4: + case ABDAY_5: + case ABDAY_6: + case ABDAY_7: + { + static char const abdays[][sizeof "Sun"] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + tmm.tm_wday = item - ABDAY_1; + if (!strftime (nlbuf, sizeof nlbuf, "%a", &tmm)) + return (char *) abdays[item - ABDAY_1]; + return nlbuf; + } + { + static char const months[][sizeof "September"] = { + "January", "February", "March", "April", "May", "June", "July", + "September", "October", "November", "December" + }; + case MON_1: + case MON_2: + case MON_3: + case MON_4: + case MON_5: + case MON_6: + case MON_7: + case MON_8: + case MON_9: + case MON_10: + case MON_11: + case MON_12: + tmm.tm_mon = item - MON_1; + if (!strftime (nlbuf, sizeof nlbuf, "%B", &tmm)) + return (char *) months[item - MON_1]; + return nlbuf; + case ALTMON_1: + case ALTMON_2: + case ALTMON_3: + case ALTMON_4: + case ALTMON_5: + case ALTMON_6: + case ALTMON_7: + case ALTMON_8: + case ALTMON_9: + case ALTMON_10: + case ALTMON_11: + case ALTMON_12: + tmm.tm_mon = item - ALTMON_1; + /* The platforms without nl_langinfo() don't support strftime with %OB. + We don't even need to try. */ + #if 0 + if (!strftime (nlbuf, sizeof nlbuf, "%OB", &tmm)) + #endif + if (!strftime (nlbuf, sizeof nlbuf, "%B", &tmm)) + return (char *) months[item - ALTMON_1]; + return nlbuf; + } + case ABMON_1: + case ABMON_2: + case ABMON_3: + case ABMON_4: + case ABMON_5: + case ABMON_6: + case ABMON_7: + case ABMON_8: + case ABMON_9: + case ABMON_10: + case ABMON_11: + case ABMON_12: + { + static char const abmonths[][sizeof "Jan"] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Sep", "Oct", "Nov", "Dec" + }; + tmm.tm_mon = item - ABMON_1; + if (!strftime (nlbuf, sizeof nlbuf, "%b", &tmm)) + return (char *) abmonths[item - ABMON_1]; + return nlbuf; + } + case ERA: + return (char *) ""; + case ALT_DIGITS: + return (char *) "\0\0\0\0\0\0\0\0\0\0"; + /* nl_langinfo items of the LC_MONETARY category. */ + case CRNCYSTR: + return localeconv () ->currency_symbol; +# ifdef INT_CURR_SYMBOL + case INT_CURR_SYMBOL: + return localeconv () ->int_curr_symbol; + case MON_DECIMAL_POINT: + return localeconv () ->mon_decimal_point; + case MON_THOUSANDS_SEP: + return localeconv () ->mon_thousands_sep; + case MON_GROUPING: + return localeconv () ->mon_grouping; + case POSITIVE_SIGN: + return localeconv () ->positive_sign; + case NEGATIVE_SIGN: + return localeconv () ->negative_sign; + case FRAC_DIGITS: + return & localeconv () ->frac_digits; + case INT_FRAC_DIGITS: + return & localeconv () ->int_frac_digits; + case P_CS_PRECEDES: + return & localeconv () ->p_cs_precedes; + case N_CS_PRECEDES: + return & localeconv () ->n_cs_precedes; + case P_SEP_BY_SPACE: + return & localeconv () ->p_sep_by_space; + case N_SEP_BY_SPACE: + return & localeconv () ->n_sep_by_space; + case P_SIGN_POSN: + return & localeconv () ->p_sign_posn; + case N_SIGN_POSN: + return & localeconv () ->n_sign_posn; +# endif + /* nl_langinfo items of the LC_MESSAGES category + TODO: Really use the locale. */ + case YESEXPR: + return (char *) "^[yY]"; + case NOEXPR: + return (char *) "^[nN]"; + default: + return (char *) ""; + } +} + +#endif diff --git a/grub-core/lib/gnulib/open.c b/grub-core/lib/gnulib/open.c new file mode 100644 index 0000000..6552605 --- /dev/null +++ b/grub-core/lib/gnulib/open.c @@ -0,0 +1,208 @@ +/* Open a descriptor to a file. + Copyright (C) 2007-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2007. */ + +/* If the user's config.h happens to include <fcntl.h>, let it include only + the system's <fcntl.h> here, so that orig_open doesn't recurse to + rpl_open. */ +#define __need_system_fcntl_h +#include <config.h> + +/* Get the original definition of open. It might be defined as a macro. */ +#include <fcntl.h> +#include <sys/types.h> +#undef __need_system_fcntl_h + +static int +orig_open (const char *filename, int flags, mode_t mode) +{ + return open (filename, flags, mode); +} + +/* Specification. */ +/* Write "fcntl.h" here, not <fcntl.h>, otherwise OSF/1 5.1 DTK cc eliminates + this include because of the preliminary #include <fcntl.h> above. */ +#include "fcntl.h" + +#include "cloexec.h" + +#include <errno.h> +#include <stdarg.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#ifndef REPLACE_OPEN_DIRECTORY +# define REPLACE_OPEN_DIRECTORY 0 +#endif + +int +open (const char *filename, int flags, ...) +{ + /* 0 = unknown, 1 = yes, -1 = no. */ +#if GNULIB_defined_O_CLOEXEC + int have_cloexec = -1; +#else + static int have_cloexec; +#endif + + mode_t mode; + int fd; + + mode = 0; + if (flags & O_CREAT) + { + va_list arg; + va_start (arg, flags); + + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (arg, PROMOTED_MODE_T); + + va_end (arg); + } + +#if GNULIB_defined_O_NONBLOCK + /* The only known platform that lacks O_NONBLOCK is mingw, but it + also lacks named pipes and Unix sockets, which are the only two + file types that require non-blocking handling in open(). + Therefore, it is safe to ignore O_NONBLOCK here. It is handy + that mingw also lacks openat(), so that is also covered here. */ + flags &= ~O_NONBLOCK; +#endif + +#if defined _WIN32 && ! defined __CYGWIN__ + if (strcmp (filename, "/dev/null") == 0) + filename = "NUL"; +#endif + +#if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR + is specified, then fail. + Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file already exists as a directory, then + - if O_CREAT is specified, open() must fail because of the semantics + of O_CREAT, + - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX + <http://www.opengroup.org/susv3/functions/open.html> says that it + fails with errno = EISDIR in this case. + If the named file does not exist or does not name a directory, then + - if O_CREAT is specified, open() must fail since open() cannot create + directories, + - if O_WRONLY or O_RDWR is specified, open() must fail because the + file does not contain a '.' directory. */ + if (flags & (O_CREAT | O_WRONLY | O_RDWR)) + { + size_t len = strlen (filename); + if (len > 0 && filename[len - 1] == '/') + { + errno = EISDIR; + return -1; + } + } +#endif + + fd = orig_open (filename, + flags & ~(have_cloexec <= 0 ? O_CLOEXEC : 0), mode); + + if (flags & O_CLOEXEC) + { + if (! have_cloexec) + { + if (0 <= fd) + have_cloexec = 1; + else if (errno == EINVAL) + { + fd = orig_open (filename, flags & ~O_CLOEXEC, mode); + have_cloexec = -1; + } + } + if (have_cloexec < 0 && 0 <= fd) + set_cloexec_flag (fd, true); + } + + +#if REPLACE_FCHDIR + /* Implementing fchdir and fdopendir requires the ability to open a + directory file descriptor. If open doesn't support that (as on + mingw), we use a dummy file that behaves the same as directories + on Linux (ie. always reports EOF on attempts to read()), and + override fstat() in fchdir.c to hide the fact that we have a + dummy. */ + if (REPLACE_OPEN_DIRECTORY && fd < 0 && errno == EACCES + && ((flags & O_ACCMODE) == O_RDONLY + || (O_SEARCH != O_RDONLY && (flags & O_ACCMODE) == O_SEARCH))) + { + struct stat statbuf; + if (stat (filename, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) + { + /* Maximum recursion depth of 1. */ + fd = open ("/dev/null", flags, mode); + if (0 <= fd) + fd = _gl_register_fd (fd, filename); + } + else + errno = EACCES; + } +#endif + +#if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and fd does not refer to a directory, + then fail. + Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file without the slash is not a directory, open() must fail + with ENOTDIR. */ + if (fd >= 0) + { + /* We know len is positive, since open did not fail with ENOENT. */ + size_t len = strlen (filename); + if (filename[len - 1] == '/') + { + struct stat statbuf; + + if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) + { + close (fd); + errno = ENOTDIR; + return -1; + } + } + } +#endif + +#if REPLACE_FCHDIR + if (!REPLACE_OPEN_DIRECTORY && 0 <= fd) + fd = _gl_register_fd (fd, filename); +#endif + + return fd; +} diff --git a/grub-core/lib/gnulib/openat-die.c b/grub-core/lib/gnulib/openat-die.c new file mode 100644 index 0000000..690c447 --- /dev/null +++ b/grub-core/lib/gnulib/openat-die.c @@ -0,0 +1,62 @@ +/* Report a save- or restore-cwd failure in our openat replacement and then exit. + + Copyright (C) 2005-2006, 2008-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "openat.h" + +#include <stdlib.h> + +#ifndef GNULIB_LIBPOSIX +# include "error.h" +#endif + +#include "exitfail.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +_Noreturn void +openat_save_fail (int errnum) +{ +#ifndef GNULIB_LIBPOSIX + error (exit_failure, errnum, + _("unable to record current working directory")); +#endif + /* _Noreturn cannot be applied to error, since it returns + when its first argument is 0. To help compilers understand that this + function does not return, call abort. Also, the abort is a + safety feature if exit_failure is 0 (which shouldn't happen). */ + abort (); +} + + +/* Exit with an error about failure to restore the working directory + during an openat emulation. The caller must ensure that fd 2 is + not a just-opened fd, even when openat_safer is not in use. */ + +_Noreturn void +openat_restore_fail (int errnum) +{ +#ifndef GNULIB_LIBPOSIX + error (exit_failure, errnum, + _("failed to return to initial working directory")); +#endif + + /* As above. */ + abort (); +} diff --git a/grub-core/lib/gnulib/openat-priv.h b/grub-core/lib/gnulib/openat-priv.h new file mode 100644 index 0000000..7b90eef --- /dev/null +++ b/grub-core/lib/gnulib/openat-priv.h @@ -0,0 +1,64 @@ +/* Internals for openat-like functions. + + Copyright (C) 2005-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* written by Jim Meyering */ + +#ifndef _GL_HEADER_OPENAT_PRIV +#define _GL_HEADER_OPENAT_PRIV + +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +/* Maximum number of bytes that it is safe to allocate as a single + array on the stack, and that is known as a compile-time constant. + The assumption is that we'll touch the array very quickly, or a + temporary very near the array, provoking an out-of-memory trap. On + some operating systems, there is only one guard page for the stack, + and a page size can be as small as 4096 bytes. Subtract 64 in the + hope that this will let the compiler touch a nearby temporary and + provoke a trap. */ +#define SAFER_ALLOCA_MAX (4096 - 64) + +#define SAFER_ALLOCA(m) ((m) < SAFER_ALLOCA_MAX ? (m) : SAFER_ALLOCA_MAX) + +#if defined PATH_MAX +# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (PATH_MAX) +#elif defined _XOPEN_PATH_MAX +# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (_XOPEN_PATH_MAX) +#else +# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (1024) +#endif + +char *openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file); + +/* Trying to access a BUILD_PROC_NAME file will fail on systems without + /proc support, and even on systems *with* ProcFS support. Return + nonzero if the failure may be legitimate, e.g., because /proc is not + readable, or the particular .../fd/N directory is not present. */ +#define EXPECTED_ERRNO(Errno) \ + ((Errno) == ENOTDIR || (Errno) == ENOENT \ + || (Errno) == EPERM || (Errno) == EACCES \ + || (Errno) == ENOSYS /* Solaris 8 */ \ + || (Errno) == EOPNOTSUPP /* FreeBSD */) + +/* Wrapper function shared among linkat and renameat. */ +int at_func2 (int fd1, char const *file1, + int fd2, char const *file2, + int (*func) (char const *file1, char const *file2)); + +#endif /* _GL_HEADER_OPENAT_PRIV */ diff --git a/grub-core/lib/gnulib/openat-proc.c b/grub-core/lib/gnulib/openat-proc.c new file mode 100644 index 0000000..da76e2b --- /dev/null +++ b/grub-core/lib/gnulib/openat-proc.c @@ -0,0 +1,134 @@ +/* Create /proc/self/fd-related names for subfiles of open directories. + + Copyright (C) 2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +#include <config.h> + +#include "openat-priv.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef __KLIBC__ +# include <InnoTekLIBC/backend.h> +#endif + +#include "intprops.h" + +/* Set BUF to the name of the subfile of the directory identified by + FD, where the subfile is named FILE. If successful, return BUF if + the result fits in BUF, dynamically allocated memory otherwise. + Return NULL (setting errno) on error. */ +char * +openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file) +{ + char *result = buf; + int dirlen; + + /* Make sure the caller gets ENOENT when appropriate. */ + if (!*file) + { + buf[0] = '\0'; + return buf; + } + +#ifndef __KLIBC__ +# define PROC_SELF_FD_FORMAT "/proc/self/fd/%d/" + { + enum { + PROC_SELF_FD_DIR_SIZE_BOUND + = (sizeof PROC_SELF_FD_FORMAT - (sizeof "%d" - 1) + + INT_STRLEN_BOUND (int)) + }; + + static int proc_status = 0; + if (! proc_status) + { + /* Set PROC_STATUS to a positive value if /proc/self/fd is + reliable, and a negative value otherwise. Solaris 10 + /proc/self/fd mishandles "..", and any file name might expand + to ".." after symbolic link expansion, so avoid /proc/self/fd + if it mishandles "..". Solaris 10 has openat, but this + problem is exhibited on code that built on Solaris 8 and + running on Solaris 10. */ + + int proc_self_fd = open ("/proc/self/fd", + O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK); + if (proc_self_fd < 0) + proc_status = -1; + else + { + /* Detect whether /proc/self/fd/%i/../fd exists, where %i is the + number of a file descriptor open on /proc/self/fd. On Linux, + that name resolves to /proc/self/fd, which was opened above. + However, on Solaris, it may resolve to /proc/self/fd/fd, which + cannot exist, since all names in /proc/self/fd are numeric. */ + char dotdot_buf[PROC_SELF_FD_DIR_SIZE_BOUND + sizeof "../fd" - 1]; + sprintf (dotdot_buf, PROC_SELF_FD_FORMAT "../fd", proc_self_fd); + proc_status = access (dotdot_buf, F_OK) ? -1 : 1; + close (proc_self_fd); + } + } + + if (proc_status < 0) + return NULL; + else + { + size_t bufsize = PROC_SELF_FD_DIR_SIZE_BOUND + strlen (file); + if (OPENAT_BUFFER_SIZE < bufsize) + { + result = malloc (bufsize); + if (! result) + return NULL; + } + + dirlen = sprintf (result, PROC_SELF_FD_FORMAT, fd); + } + } +#else + /* OS/2 kLIBC provides a function to retrieve a path from a fd. */ + { + char dir[_MAX_PATH]; + size_t bufsize; + + if (__libc_Back_ioFHToPath (fd, dir, sizeof dir)) + return NULL; + + dirlen = strlen (dir); + bufsize = dirlen + 1 + strlen (file) + 1; /* 1 for '/', 1 for null */ + if (OPENAT_BUFFER_SIZE < bufsize) + { + result = malloc (bufsize); + if (! result) + return NULL; + } + + strcpy (result, dir); + result[dirlen++] = '/'; + } +#endif + + strcpy (result + dirlen, file); + return result; +} diff --git a/grub-core/lib/gnulib/openat.c b/grub-core/lib/gnulib/openat.c new file mode 100644 index 0000000..4ab4a31 --- /dev/null +++ b/grub-core/lib/gnulib/openat.c @@ -0,0 +1,314 @@ +/* provide a replacement openat function + Copyright (C) 2004-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* written by Jim Meyering */ + +/* If the user's config.h happens to include <fcntl.h>, let it include only + the system's <fcntl.h> here, so that orig_openat doesn't recurse to + rpl_openat. */ +#define __need_system_fcntl_h +#include <config.h> + +/* Get the original definition of open. It might be defined as a macro. */ +#include <fcntl.h> +#include <sys/types.h> +#undef __need_system_fcntl_h + +#if HAVE_OPENAT +static int +orig_openat (int fd, char const *filename, int flags, mode_t mode) +{ + return openat (fd, filename, flags, mode); +} +#endif + +/* Write "fcntl.h" here, not <fcntl.h>, otherwise OSF/1 5.1 DTK cc eliminates + this include because of the preliminary #include <fcntl.h> above. */ +#include "fcntl.h" + +#include "openat.h" + +#include "cloexec.h" + +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <string.h> +#include <sys/stat.h> +#include <errno.h> + +#if HAVE_OPENAT + +/* Like openat, but support O_CLOEXEC and work around Solaris 9 bugs + with trailing slash. */ +int +rpl_openat (int dfd, char const *filename, int flags, ...) +{ + /* 0 = unknown, 1 = yes, -1 = no. */ +#if GNULIB_defined_O_CLOEXEC + int have_cloexec = -1; +#else + static int have_cloexec; +#endif + + mode_t mode; + int fd; + + mode = 0; + if (flags & O_CREAT) + { + va_list arg; + va_start (arg, flags); + + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (arg, PROMOTED_MODE_T); + + va_end (arg); + } + +# if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR + is specified, then fail. + Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file already exists as a directory, then + - if O_CREAT is specified, open() must fail because of the semantics + of O_CREAT, + - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX + <http://www.opengroup.org/susv3/functions/open.html> says that it + fails with errno = EISDIR in this case. + If the named file does not exist or does not name a directory, then + - if O_CREAT is specified, open() must fail since open() cannot create + directories, + - if O_WRONLY or O_RDWR is specified, open() must fail because the + file does not contain a '.' directory. */ + if (flags & (O_CREAT | O_WRONLY | O_RDWR)) + { + size_t len = strlen (filename); + if (len > 0 && filename[len - 1] == '/') + { + errno = EISDIR; + return -1; + } + } +# endif + + fd = orig_openat (dfd, filename, + flags & ~(have_cloexec <= 0 ? O_CLOEXEC : 0), mode); + + if (flags & O_CLOEXEC) + { + if (! have_cloexec) + { + if (0 <= fd) + have_cloexec = 1; + else if (errno == EINVAL) + { + fd = orig_openat (dfd, filename, flags & ~O_CLOEXEC, mode); + have_cloexec = -1; + } + } + if (have_cloexec < 0 && 0 <= fd) + set_cloexec_flag (fd, true); + } + + +# if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and fd does not refer to a directory, + then fail. + Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file without the slash is not a directory, open() must fail + with ENOTDIR. */ + if (fd >= 0) + { + /* We know len is positive, since open did not fail with ENOENT. */ + size_t len = strlen (filename); + if (filename[len - 1] == '/') + { + struct stat statbuf; + + if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) + { + close (fd); + errno = ENOTDIR; + return -1; + } + } + } +# endif + + return fd; +} + +#else /* !HAVE_OPENAT */ + +# include "dosname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ +# include "openat-priv.h" +# include "save-cwd.h" + +/* Replacement for Solaris' openat function. + <https://www.google.com/search?q=openat+site:docs.oracle.com> + First, try to simulate it via open ("/proc/self/fd/FD/FILE"). + Failing that, simulate it by doing save_cwd/fchdir/open/restore_cwd. + If either the save_cwd or the restore_cwd fails (relatively unlikely), + then give a diagnostic and exit nonzero. + Otherwise, upon failure, set errno and return -1, as openat does. + Upon successful completion, return a file descriptor. */ +int +openat (int fd, char const *file, int flags, ...) +{ + mode_t mode = 0; + + if (flags & O_CREAT) + { + va_list arg; + va_start (arg, flags); + + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (arg, PROMOTED_MODE_T); + + va_end (arg); + } + + return openat_permissive (fd, file, flags, mode, NULL); +} + +/* Like openat (FD, FILE, FLAGS, MODE), but if CWD_ERRNO is + nonnull, set *CWD_ERRNO to an errno value if unable to save + or restore the initial working directory. This is needed only + the first time remove.c's remove_dir opens a command-line + directory argument. + + If a previous attempt to restore the current working directory + failed, then we must not even try to access a '.'-relative name. + It is the caller's responsibility not to call this function + in that case. */ + +int +openat_permissive (int fd, char const *file, int flags, mode_t mode, + int *cwd_errno) +{ + struct saved_cwd saved_cwd; + int saved_errno; + int err; + bool save_ok; + + if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) + return open (file, flags, mode); + + { + char buf[OPENAT_BUFFER_SIZE]; + char *proc_file = openat_proc_name (buf, fd, file); + if (proc_file) + { + int open_result = open (proc_file, flags, mode); + int open_errno = errno; + if (proc_file != buf) + free (proc_file); + /* If the syscall succeeds, or if it fails with an unexpected + errno value, then return right away. Otherwise, fall through + and resort to using save_cwd/restore_cwd. */ + if (0 <= open_result || ! EXPECTED_ERRNO (open_errno)) + { + errno = open_errno; + return open_result; + } + } + } + + save_ok = (save_cwd (&saved_cwd) == 0); + if (! save_ok) + { + if (! cwd_errno) + openat_save_fail (errno); + *cwd_errno = errno; + } + if (0 <= fd && fd == saved_cwd.desc) + { + /* If saving the working directory collides with the user's + requested fd, then the user's fd must have been closed to + begin with. */ + free_cwd (&saved_cwd); + errno = EBADF; + return -1; + } + + err = fchdir (fd); + saved_errno = errno; + + if (! err) + { + err = open (file, flags, mode); + saved_errno = errno; + if (save_ok && restore_cwd (&saved_cwd) != 0) + { + if (! cwd_errno) + { + /* Don't write a message to just-created fd 2. */ + saved_errno = errno; + if (err == STDERR_FILENO) + close (err); + openat_restore_fail (saved_errno); + } + *cwd_errno = errno; + } + } + + free_cwd (&saved_cwd); + errno = saved_errno; + return err; +} + +/* Return true if our openat implementation must resort to + using save_cwd and restore_cwd. */ +bool +openat_needs_fchdir (void) +{ + bool needs_fchdir = true; + int fd = open ("/", O_SEARCH); + + if (0 <= fd) + { + char buf[OPENAT_BUFFER_SIZE]; + char *proc_file = openat_proc_name (buf, fd, "."); + if (proc_file) + { + needs_fchdir = false; + if (proc_file != buf) + free (proc_file); + } + close (fd); + } + + return needs_fchdir; +} + +#endif /* !HAVE_OPENAT */ diff --git a/grub-core/lib/gnulib/openat.h b/grub-core/lib/gnulib/openat.h new file mode 100644 index 0000000..f23b371 --- /dev/null +++ b/grub-core/lib/gnulib/openat.h @@ -0,0 +1,123 @@ +/* provide a replacement openat function + Copyright (C) 2004-2006, 2008-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* written by Jim Meyering */ + +#ifndef _GL_HEADER_OPENAT +#define _GL_HEADER_OPENAT + +#include <fcntl.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdbool.h> + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN + +#if !HAVE_OPENAT + +int openat_permissive (int fd, char const *file, int flags, mode_t mode, + int *cwd_errno); +bool openat_needs_fchdir (void); + +#else + +# define openat_permissive(Fd, File, Flags, Mode, Cwd_errno) \ + openat (Fd, File, Flags, Mode) +# define openat_needs_fchdir() false + +#endif + +_Noreturn void openat_restore_fail (int); +_Noreturn void openat_save_fail (int); + +/* Using these function names makes application code + slightly more readable than it would be with + fchownat (..., 0) or fchownat (..., AT_SYMLINK_NOFOLLOW). */ + +#if GNULIB_FCHOWNAT + +# ifndef FCHOWNAT_INLINE +# define FCHOWNAT_INLINE _GL_INLINE +# endif + +FCHOWNAT_INLINE int +chownat (int fd, char const *file, uid_t owner, gid_t group) +{ + return fchownat (fd, file, owner, group, 0); +} + +FCHOWNAT_INLINE int +lchownat (int fd, char const *file, uid_t owner, gid_t group) +{ + return fchownat (fd, file, owner, group, AT_SYMLINK_NOFOLLOW); +} + +#endif + +#if GNULIB_FCHMODAT + +# ifndef FCHMODAT_INLINE +# define FCHMODAT_INLINE _GL_INLINE +# endif + +FCHMODAT_INLINE int +chmodat (int fd, char const *file, mode_t mode) +{ + return fchmodat (fd, file, mode, 0); +} + +FCHMODAT_INLINE int +lchmodat (int fd, char const *file, mode_t mode) +{ + return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW); +} + +#endif + +#if GNULIB_STATAT + +# ifndef STATAT_INLINE +# define STATAT_INLINE _GL_INLINE +# endif + +STATAT_INLINE int +statat (int fd, char const *name, struct stat *st) +{ + return fstatat (fd, name, st, 0); +} + +STATAT_INLINE int +lstatat (int fd, char const *name, struct stat *st) +{ + return fstatat (fd, name, st, AT_SYMLINK_NOFOLLOW); +} + +#endif + +/* For now, there are no wrappers named laccessat or leuidaccessat, + since gnulib doesn't support faccessat(,AT_SYMLINK_NOFOLLOW) and + since access rights on symlinks are of limited utility. Likewise, + wrappers are not provided for accessat or euidaccessat, so as to + avoid dragging in -lgen on some platforms. */ + +_GL_INLINE_HEADER_END + +#endif /* _GL_HEADER_OPENAT */ diff --git a/grub-core/lib/gnulib/pathmax.h b/grub-core/lib/gnulib/pathmax.h new file mode 100644 index 0000000..83b9491 --- /dev/null +++ b/grub-core/lib/gnulib/pathmax.h @@ -0,0 +1,83 @@ +/* Define PATH_MAX somehow. Requires sys/types.h. + Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2019 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _PATHMAX_H +# define _PATHMAX_H + +/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename, + including the terminating NUL byte. + <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html> + PATH_MAX is not defined on systems which have no limit on filename length, + such as GNU/Hurd. + + This file does *not* define PATH_MAX always. Programs that use this file + can handle the GNU/Hurd case in several ways: + - Either with a package-wide handling, or with a per-file handling, + - Either through a + #ifdef PATH_MAX + or through a fallback like + #ifndef PATH_MAX + # define PATH_MAX 8192 + #endif + or through a fallback like + #ifndef PATH_MAX + # define PATH_MAX pathconf ("/", _PC_PATH_MAX) + #endif + */ + +# include <unistd.h> + +# include <limits.h> + +# ifndef _POSIX_PATH_MAX +# define _POSIX_PATH_MAX 256 +# endif + +/* Don't include sys/param.h if it already has been. */ +# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN +# include <sys/param.h> +# endif + +# if !defined PATH_MAX && defined MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# endif + +# ifdef __hpux +/* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename, + *not* including the terminating NUL byte, and is set to 1023. + Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is + not defined at all any more. */ +# undef PATH_MAX +# define PATH_MAX 1024 +# endif + +# if defined _WIN32 && ! defined __CYGWIN__ +/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com, + section "Maximum Path Length Limitation", + <https://msdn.microsoft.com/en-us/library/aa365247.aspx#maxpath> + explains that the maximum size of a filename, including the terminating + NUL byte, is 260 = 3 + 256 + 1. + This is the same value as + - FILENAME_MAX in <stdio.h>, + - _MAX_PATH in <stdlib.h>, + - MAX_PATH in <windef.h>. + Undefine the original value, because mingw's <limits.h> gets it wrong. */ +# undef PATH_MAX +# define PATH_MAX 260 +# endif + +#endif /* _PATHMAX_H */ diff --git a/grub-core/lib/gnulib/pipe-safer.c b/grub-core/lib/gnulib/pipe-safer.c new file mode 100644 index 0000000..6201739 --- /dev/null +++ b/grub-core/lib/gnulib/pipe-safer.c @@ -0,0 +1,56 @@ +/* Invoke pipe, but avoid some glitches. + Copyright (C) 2005-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Jim Meyering. */ + +#include <config.h> + +#include "unistd-safer.h" + +#include <unistd.h> +#include <errno.h> + +/* Like pipe, but ensure that neither of the file descriptors is + STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO. Fail with ENOSYS on + platforms that lack pipe. */ + +int +pipe_safer (int fd[2]) +{ +#if HAVE_PIPE + if (pipe (fd) == 0) + { + int i; + for (i = 0; i < 2; i++) + { + fd[i] = fd_safer (fd[i]); + if (fd[i] < 0) + { + int e = errno; + close (fd[1 - i]); + errno = e; + return -1; + } + } + + return 0; + } +#else + errno = ENOSYS; +#endif + + return -1; +} diff --git a/grub-core/lib/gnulib/printf-args.c b/grub-core/lib/gnulib/printf-args.c new file mode 100644 index 0000000..e45cfbe --- /dev/null +++ b/grub-core/lib/gnulib/printf-args.c @@ -0,0 +1,187 @@ +/* Decomposed printf argument list. + Copyright (C) 1999, 2002-2003, 2005-2007, 2009-2019 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* This file can be parametrized with the following macros: + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. + PRINTF_FETCHARGS Name of the function to be defined. + STATIC Set to 'static' to declare the function static. */ + +#ifndef PRINTF_FETCHARGS +# include <config.h> +#endif + +/* Specification. */ +#ifndef PRINTF_FETCHARGS +# include "printf-args.h" +#endif + +#ifdef STATIC +STATIC +#endif +int +PRINTF_FETCHARGS (va_list args, arguments *a) +{ + size_t i; + argument *ap; + + for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++) + switch (ap->type) + { + case TYPE_SCHAR: + ap->a.a_schar = va_arg (args, /*signed char*/ int); + break; + case TYPE_UCHAR: + ap->a.a_uchar = va_arg (args, /*unsigned char*/ int); + break; + case TYPE_SHORT: + ap->a.a_short = va_arg (args, /*short*/ int); + break; + case TYPE_USHORT: + ap->a.a_ushort = va_arg (args, /*unsigned short*/ int); + break; + case TYPE_INT: + ap->a.a_int = va_arg (args, int); + break; + case TYPE_UINT: + ap->a.a_uint = va_arg (args, unsigned int); + break; + case TYPE_LONGINT: + ap->a.a_longint = va_arg (args, long int); + break; + case TYPE_ULONGINT: + ap->a.a_ulongint = va_arg (args, unsigned long int); + break; +#if HAVE_LONG_LONG_INT + case TYPE_LONGLONGINT: + ap->a.a_longlongint = va_arg (args, long long int); + break; + case TYPE_ULONGLONGINT: + ap->a.a_ulonglongint = va_arg (args, unsigned long long int); + break; +#endif + case TYPE_DOUBLE: + ap->a.a_double = va_arg (args, double); + break; + case TYPE_LONGDOUBLE: + ap->a.a_longdouble = va_arg (args, long double); + break; + case TYPE_CHAR: + ap->a.a_char = va_arg (args, int); + break; +#if HAVE_WINT_T + case TYPE_WIDE_CHAR: + /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by + default argument promotions", this is not the case in mingw32, + where wint_t is 'unsigned short'. */ + ap->a.a_wide_char = + (sizeof (wint_t) < sizeof (int) + ? (wint_t) va_arg (args, int) + : va_arg (args, wint_t)); + break; +#endif + case TYPE_STRING: + ap->a.a_string = va_arg (args, const char *); + /* A null pointer is an invalid argument for "%s", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_string == NULL) + ap->a.a_string = "(NULL)"; + break; +#if HAVE_WCHAR_T + case TYPE_WIDE_STRING: + ap->a.a_wide_string = va_arg (args, const wchar_t *); + /* A null pointer is an invalid argument for "%ls", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_wide_string == NULL) + { + static const wchar_t wide_null_string[] = + { + (wchar_t)'(', + (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L', + (wchar_t)')', + (wchar_t)0 + }; + ap->a.a_wide_string = wide_null_string; + } + break; +#endif + case TYPE_POINTER: + ap->a.a_pointer = va_arg (args, void *); + break; + case TYPE_COUNT_SCHAR_POINTER: + ap->a.a_count_schar_pointer = va_arg (args, signed char *); + break; + case TYPE_COUNT_SHORT_POINTER: + ap->a.a_count_short_pointer = va_arg (args, short *); + break; + case TYPE_COUNT_INT_POINTER: + ap->a.a_count_int_pointer = va_arg (args, int *); + break; + case TYPE_COUNT_LONGINT_POINTER: + ap->a.a_count_longint_pointer = va_arg (args, long int *); + break; +#if HAVE_LONG_LONG_INT + case TYPE_COUNT_LONGLONGINT_POINTER: + ap->a.a_count_longlongint_pointer = va_arg (args, long long int *); + break; +#endif +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + case TYPE_U8_STRING: + ap->a.a_u8_string = va_arg (args, const uint8_t *); + /* A null pointer is an invalid argument for "%U", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_u8_string == NULL) + { + static const uint8_t u8_null_string[] = + { '(', 'N', 'U', 'L', 'L', ')', 0 }; + ap->a.a_u8_string = u8_null_string; + } + break; + case TYPE_U16_STRING: + ap->a.a_u16_string = va_arg (args, const uint16_t *); + /* A null pointer is an invalid argument for "%lU", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_u16_string == NULL) + { + static const uint16_t u16_null_string[] = + { '(', 'N', 'U', 'L', 'L', ')', 0 }; + ap->a.a_u16_string = u16_null_string; + } + break; + case TYPE_U32_STRING: + ap->a.a_u32_string = va_arg (args, const uint32_t *); + /* A null pointer is an invalid argument for "%llU", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_u32_string == NULL) + { + static const uint32_t u32_null_string[] = + { '(', 'N', 'U', 'L', 'L', ')', 0 }; + ap->a.a_u32_string = u32_null_string; + } + break; +#endif + default: + /* Unknown type. */ + return -1; + } + return 0; +} diff --git a/grub-core/lib/gnulib/printf-args.h b/grub-core/lib/gnulib/printf-args.h new file mode 100644 index 0000000..866cba0 --- /dev/null +++ b/grub-core/lib/gnulib/printf-args.h @@ -0,0 +1,158 @@ +/* Decomposed printf argument list. + Copyright (C) 1999, 2002-2003, 2006-2007, 2011-2019 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _PRINTF_ARGS_H +#define _PRINTF_ARGS_H + +/* This file can be parametrized with the following macros: + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. + PRINTF_FETCHARGS Name of the function to be declared. + STATIC Set to 'static' to declare the function static. */ + +/* Default parameters. */ +#ifndef PRINTF_FETCHARGS +# define PRINTF_FETCHARGS printf_fetchargs +#endif + +/* Get size_t. */ +#include <stddef.h> + +/* Get wchar_t. */ +#if HAVE_WCHAR_T +# include <stddef.h> +#endif + +/* Get wint_t. */ +#if HAVE_WINT_T +# include <wchar.h> +#endif + +/* Get va_list. */ +#include <stdarg.h> + + +/* Argument types */ +typedef enum +{ + TYPE_NONE, + TYPE_SCHAR, + TYPE_UCHAR, + TYPE_SHORT, + TYPE_USHORT, + TYPE_INT, + TYPE_UINT, + TYPE_LONGINT, + TYPE_ULONGINT, +#if HAVE_LONG_LONG_INT + TYPE_LONGLONGINT, + TYPE_ULONGLONGINT, +#endif + TYPE_DOUBLE, + TYPE_LONGDOUBLE, + TYPE_CHAR, +#if HAVE_WINT_T + TYPE_WIDE_CHAR, +#endif + TYPE_STRING, +#if HAVE_WCHAR_T + TYPE_WIDE_STRING, +#endif + TYPE_POINTER, + TYPE_COUNT_SCHAR_POINTER, + TYPE_COUNT_SHORT_POINTER, + TYPE_COUNT_INT_POINTER, + TYPE_COUNT_LONGINT_POINTER +#if HAVE_LONG_LONG_INT +, TYPE_COUNT_LONGLONGINT_POINTER +#endif +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ +, TYPE_U8_STRING +, TYPE_U16_STRING +, TYPE_U32_STRING +#endif +} arg_type; + +/* Polymorphic argument */ +typedef struct +{ + arg_type type; + union + { + signed char a_schar; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long int a_longint; + unsigned long int a_ulongint; +#if HAVE_LONG_LONG_INT + long long int a_longlongint; + unsigned long long int a_ulonglongint; +#endif + float a_float; + double a_double; + long double a_longdouble; + int a_char; +#if HAVE_WINT_T + wint_t a_wide_char; +#endif + const char* a_string; +#if HAVE_WCHAR_T + const wchar_t* a_wide_string; +#endif + void* a_pointer; + signed char * a_count_schar_pointer; + short * a_count_short_pointer; + int * a_count_int_pointer; + long int * a_count_longint_pointer; +#if HAVE_LONG_LONG_INT + long long int * a_count_longlongint_pointer; +#endif +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + const uint8_t * a_u8_string; + const uint16_t * a_u16_string; + const uint32_t * a_u32_string; +#endif + } + a; +} +argument; + +/* Number of directly allocated arguments (no malloc() needed). */ +#define N_DIRECT_ALLOC_ARGUMENTS 7 + +typedef struct +{ + size_t count; + argument *arg; + argument direct_alloc_arg[N_DIRECT_ALLOC_ARGUMENTS]; +} +arguments; + + +/* Fetch the arguments, putting them into a. */ +#ifdef STATIC +STATIC +#else +extern +#endif +int PRINTF_FETCHARGS (va_list args, arguments *a); + +#endif /* _PRINTF_ARGS_H */ diff --git a/grub-core/lib/gnulib/printf-parse.c b/grub-core/lib/gnulib/printf-parse.c new file mode 100644 index 0000000..8596fd5 --- /dev/null +++ b/grub-core/lib/gnulib/printf-parse.c @@ -0,0 +1,638 @@ +/* Formatted output to strings. + Copyright (C) 1999-2000, 2002-2003, 2006-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* This file can be parametrized with the following macros: + CHAR_T The element type of the format string. + CHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters + in the format string are ASCII. + DIRECTIVE Structure denoting a format directive. + Depends on CHAR_T. + DIRECTIVES Structure denoting the set of format directives of a + format string. Depends on CHAR_T. + PRINTF_PARSE Function that parses a format string. + Depends on CHAR_T. + STATIC Set to 'static' to declare the function static. + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. */ + +#ifndef PRINTF_PARSE +# include <config.h> +#endif + +/* Specification. */ +#ifndef PRINTF_PARSE +# include "printf-parse.h" +#endif + +/* Default parameters. */ +#ifndef PRINTF_PARSE +# define PRINTF_PARSE printf_parse +# define CHAR_T char +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +#endif + +/* Get size_t, NULL. */ +#include <stddef.h> + +/* Get intmax_t. */ +#if defined IN_LIBINTL || defined IN_LIBASPRINTF +# if HAVE_STDINT_H_WITH_UINTMAX +# include <stdint.h> +# endif +# if HAVE_INTTYPES_H_WITH_UINTMAX +# include <inttypes.h> +# endif +#else +# include <stdint.h> +#endif + +/* malloc(), realloc(), free(). */ +#include <stdlib.h> + +/* memcpy(). */ +#include <string.h> + +/* errno. */ +#include <errno.h> + +/* Checked size_t computations. */ +#include "xsize.h" + +#if CHAR_T_ONLY_ASCII +/* c_isascii(). */ +# include "c-ctype.h" +#endif + +#ifdef STATIC +STATIC +#endif +int +PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) +{ + const CHAR_T *cp = format; /* pointer into format */ + size_t arg_posn = 0; /* number of regular arguments consumed */ + size_t d_allocated; /* allocated elements of d->dir */ + size_t a_allocated; /* allocated elements of a->arg */ + size_t max_width_length = 0; + size_t max_precision_length = 0; + + d->count = 0; + d_allocated = N_DIRECT_ALLOC_DIRECTIVES; + d->dir = d->direct_alloc_dir; + + a->count = 0; + a_allocated = N_DIRECT_ALLOC_ARGUMENTS; + a->arg = a->direct_alloc_arg; + +#define REGISTER_ARG(_index_,_type_) \ + { \ + size_t n = (_index_); \ + if (n >= a_allocated) \ + { \ + size_t memory_size; \ + argument *memory; \ + \ + a_allocated = xtimes (a_allocated, 2); \ + if (a_allocated <= n) \ + a_allocated = xsum (n, 1); \ + memory_size = xtimes (a_allocated, sizeof (argument)); \ + if (size_overflow_p (memory_size)) \ + /* Overflow, would lead to out of memory. */ \ + goto out_of_memory; \ + memory = (argument *) (a->arg != a->direct_alloc_arg \ + ? realloc (a->arg, memory_size) \ + : malloc (memory_size)); \ + if (memory == NULL) \ + /* Out of memory. */ \ + goto out_of_memory; \ + if (a->arg == a->direct_alloc_arg) \ + memcpy (memory, a->arg, a->count * sizeof (argument)); \ + a->arg = memory; \ + } \ + while (a->count <= n) \ + a->arg[a->count++].type = TYPE_NONE; \ + if (a->arg[n].type == TYPE_NONE) \ + a->arg[n].type = (_type_); \ + else if (a->arg[n].type != (_type_)) \ + /* Ambiguous type for positional argument. */ \ + goto error; \ + } + + while (*cp != '\0') + { + CHAR_T c = *cp++; + if (c == '%') + { + size_t arg_index = ARG_NONE; + DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */ + + /* Initialize the next directive. */ + dp->dir_start = cp - 1; + dp->flags = 0; + dp->width_start = NULL; + dp->width_end = NULL; + dp->width_arg_index = ARG_NONE; + dp->precision_start = NULL; + dp->precision_end = NULL; + dp->precision_arg_index = ARG_NONE; + dp->arg_index = ARG_NONE; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory later. */ + goto error; + arg_index = n - 1; + cp = np + 1; + } + } + + /* Read the flags. */ + for (;;) + { + if (*cp == '\'') + { + dp->flags |= FLAG_GROUP; + cp++; + } + else if (*cp == '-') + { + dp->flags |= FLAG_LEFT; + cp++; + } + else if (*cp == '+') + { + dp->flags |= FLAG_SHOWSIGN; + cp++; + } + else if (*cp == ' ') + { + dp->flags |= FLAG_SPACE; + cp++; + } + else if (*cp == '#') + { + dp->flags |= FLAG_ALT; + cp++; + } + else if (*cp == '0') + { + dp->flags |= FLAG_ZERO; + cp++; + } +#if __GLIBC__ >= 2 && !defined __UCLIBC__ + else if (*cp == 'I') + { + dp->flags |= FLAG_LOCALIZED; + cp++; + } +#endif + else + break; + } + + /* Parse the field width. */ + if (*cp == '*') + { + dp->width_start = cp; + cp++; + dp->width_end = cp; + if (max_width_length < 1) + max_width_length = 1; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory later. */ + goto error; + dp->width_arg_index = n - 1; + cp = np + 1; + } + } + if (dp->width_arg_index == ARG_NONE) + { + dp->width_arg_index = arg_posn++; + if (dp->width_arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->width_arg_index, TYPE_INT); + } + else if (*cp >= '0' && *cp <= '9') + { + size_t width_length; + + dp->width_start = cp; + for (; *cp >= '0' && *cp <= '9'; cp++) + ; + dp->width_end = cp; + width_length = dp->width_end - dp->width_start; + if (max_width_length < width_length) + max_width_length = width_length; + } + + /* Parse the precision. */ + if (*cp == '.') + { + cp++; + if (*cp == '*') + { + dp->precision_start = cp - 1; + cp++; + dp->precision_end = cp; + if (max_precision_length < 2) + max_precision_length = 2; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory + later. */ + goto error; + dp->precision_arg_index = n - 1; + cp = np + 1; + } + } + if (dp->precision_arg_index == ARG_NONE) + { + dp->precision_arg_index = arg_posn++; + if (dp->precision_arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->precision_arg_index, TYPE_INT); + } + else + { + size_t precision_length; + + dp->precision_start = cp - 1; + for (; *cp >= '0' && *cp <= '9'; cp++) + ; + dp->precision_end = cp; + precision_length = dp->precision_end - dp->precision_start; + if (max_precision_length < precision_length) + max_precision_length = precision_length; + } + } + + { + arg_type type; + + /* Parse argument type/size specifiers. */ + { + int flags = 0; + + for (;;) + { + if (*cp == 'h') + { + flags |= (1 << (flags & 1)); + cp++; + } + else if (*cp == 'L') + { + flags |= 4; + cp++; + } + else if (*cp == 'l') + { + flags += 8; + cp++; + } + else if (*cp == 'j') + { + if (sizeof (intmax_t) > sizeof (long)) + { + /* intmax_t = long long */ + flags += 16; + } + else if (sizeof (intmax_t) > sizeof (int)) + { + /* intmax_t = long */ + flags += 8; + } + cp++; + } + else if (*cp == 'z' || *cp == 'Z') + { + /* 'z' is standardized in ISO C 99, but glibc uses 'Z' + because the warning facility in gcc-2.95.2 understands + only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ + if (sizeof (size_t) > sizeof (long)) + { + /* size_t = long long */ + flags += 16; + } + else if (sizeof (size_t) > sizeof (int)) + { + /* size_t = long */ + flags += 8; + } + cp++; + } + else if (*cp == 't') + { + if (sizeof (ptrdiff_t) > sizeof (long)) + { + /* ptrdiff_t = long long */ + flags += 16; + } + else if (sizeof (ptrdiff_t) > sizeof (int)) + { + /* ptrdiff_t = long */ + flags += 8; + } + cp++; + } +#if defined __APPLE__ && defined __MACH__ + /* On Mac OS X 10.3, PRIdMAX is defined as "qd". + We cannot change it to "lld" because PRIdMAX must also + be understood by the system's printf routines. */ + else if (*cp == 'q') + { + if (64 / 8 > sizeof (long)) + { + /* int64_t = long long */ + flags += 16; + } + else + { + /* int64_t = long */ + flags += 8; + } + cp++; + } +#endif +#if defined _WIN32 && ! defined __CYGWIN__ + /* On native Windows, PRIdMAX is defined as "I64d". + We cannot change it to "lld" because PRIdMAX must also + be understood by the system's printf routines. */ + else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4') + { + if (64 / 8 > sizeof (long)) + { + /* __int64 = long long */ + flags += 16; + } + else + { + /* __int64 = long */ + flags += 8; + } + cp += 3; + } +#endif + else + break; + } + + /* Read the conversion character. */ + c = *cp++; + switch (c) + { + case 'd': case 'i': +#if HAVE_LONG_LONG_INT + /* If 'long long' exists and is larger than 'long': */ + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGLONGINT; + else +#endif + /* If 'long long' exists and is the same as 'long', we parse + "lld" into TYPE_LONGINT. */ + if (flags >= 8) + type = TYPE_LONGINT; + else if (flags & 2) + type = TYPE_SCHAR; + else if (flags & 1) + type = TYPE_SHORT; + else + type = TYPE_INT; + break; + case 'o': case 'u': case 'x': case 'X': +#if HAVE_LONG_LONG_INT + /* If 'long long' exists and is larger than 'long': */ + if (flags >= 16 || (flags & 4)) + type = TYPE_ULONGLONGINT; + else +#endif + /* If 'unsigned long long' exists and is the same as + 'unsigned long', we parse "llu" into TYPE_ULONGINT. */ + if (flags >= 8) + type = TYPE_ULONGINT; + else if (flags & 2) + type = TYPE_UCHAR; + else if (flags & 1) + type = TYPE_USHORT; + else + type = TYPE_UINT; + break; + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': + case 'a': case 'A': + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGDOUBLE; + else + type = TYPE_DOUBLE; + break; + case 'c': + if (flags >= 8) +#if HAVE_WINT_T + type = TYPE_WIDE_CHAR; +#else + goto error; +#endif + else + type = TYPE_CHAR; + break; +#if HAVE_WINT_T + case 'C': + type = TYPE_WIDE_CHAR; + c = 'c'; + break; +#endif + case 's': + if (flags >= 8) +#if HAVE_WCHAR_T + type = TYPE_WIDE_STRING; +#else + goto error; +#endif + else + type = TYPE_STRING; + break; +#if HAVE_WCHAR_T + case 'S': + type = TYPE_WIDE_STRING; + c = 's'; + break; +#endif + case 'p': + type = TYPE_POINTER; + break; + case 'n': +#if HAVE_LONG_LONG_INT + /* If 'long long' exists and is larger than 'long': */ + if (flags >= 16 || (flags & 4)) + type = TYPE_COUNT_LONGLONGINT_POINTER; + else +#endif + /* If 'long long' exists and is the same as 'long', we parse + "lln" into TYPE_COUNT_LONGINT_POINTER. */ + if (flags >= 8) + type = TYPE_COUNT_LONGINT_POINTER; + else if (flags & 2) + type = TYPE_COUNT_SCHAR_POINTER; + else if (flags & 1) + type = TYPE_COUNT_SHORT_POINTER; + else + type = TYPE_COUNT_INT_POINTER; + break; +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + case 'U': + if (flags >= 16) + type = TYPE_U32_STRING; + else if (flags >= 8) + type = TYPE_U16_STRING; + else + type = TYPE_U8_STRING; + break; +#endif + case '%': + type = TYPE_NONE; + break; + default: + /* Unknown conversion character. */ + goto error; + } + } + + if (type != TYPE_NONE) + { + dp->arg_index = arg_index; + if (dp->arg_index == ARG_NONE) + { + dp->arg_index = arg_posn++; + if (dp->arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->arg_index, type); + } + dp->conversion = c; + dp->dir_end = cp; + } + + d->count++; + if (d->count >= d_allocated) + { + size_t memory_size; + DIRECTIVE *memory; + + d_allocated = xtimes (d_allocated, 2); + memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); + if (size_overflow_p (memory_size)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir + ? realloc (d->dir, memory_size) + : malloc (memory_size)); + if (memory == NULL) + /* Out of memory. */ + goto out_of_memory; + if (d->dir == d->direct_alloc_dir) + memcpy (memory, d->dir, d->count * sizeof (DIRECTIVE)); + d->dir = memory; + } + } +#if CHAR_T_ONLY_ASCII + else if (!c_isascii (c)) + { + /* Non-ASCII character. Not supported. */ + goto error; + } +#endif + } + d->dir[d->count].dir_start = cp; + + d->max_width_length = max_width_length; + d->max_precision_length = max_precision_length; + return 0; + +error: + if (a->arg != a->direct_alloc_arg) + free (a->arg); + if (d->dir != d->direct_alloc_dir) + free (d->dir); + errno = EINVAL; + return -1; + +out_of_memory: + if (a->arg != a->direct_alloc_arg) + free (a->arg); + if (d->dir != d->direct_alloc_dir) + free (d->dir); + errno = ENOMEM; + return -1; +} + +#undef PRINTF_PARSE +#undef DIRECTIVES +#undef DIRECTIVE +#undef CHAR_T_ONLY_ASCII +#undef CHAR_T diff --git a/grub-core/lib/gnulib/printf-parse.h b/grub-core/lib/gnulib/printf-parse.h new file mode 100644 index 0000000..746bb3f --- /dev/null +++ b/grub-core/lib/gnulib/printf-parse.h @@ -0,0 +1,193 @@ +/* Parse printf format string. + Copyright (C) 1999, 2002-2003, 2005, 2007, 2010-2019 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _PRINTF_PARSE_H +#define _PRINTF_PARSE_H + +/* This file can be parametrized with the following macros: + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. + STATIC Set to 'static' to declare the function static. */ + +#if HAVE_FEATURES_H +# include <features.h> /* for __GLIBC__, __UCLIBC__ */ +#endif + +#include "printf-args.h" + + +/* Flags */ +#define FLAG_GROUP 1 /* ' flag */ +#define FLAG_LEFT 2 /* - flag */ +#define FLAG_SHOWSIGN 4 /* + flag */ +#define FLAG_SPACE 8 /* space flag */ +#define FLAG_ALT 16 /* # flag */ +#define FLAG_ZERO 32 +#if __GLIBC__ >= 2 && !defined __UCLIBC__ +# define FLAG_LOCALIZED 64 /* I flag, uses localized digits */ +#endif + +/* arg_index value indicating that no argument is consumed. */ +#define ARG_NONE (~(size_t)0) + +/* xxx_directive: A parsed directive. + xxx_directives: A parsed format string. */ + +/* Number of directly allocated directives (no malloc() needed). */ +#define N_DIRECT_ALLOC_DIRECTIVES 7 + +/* A parsed directive. */ +typedef struct +{ + const char* dir_start; + const char* dir_end; + int flags; + const char* width_start; + const char* width_end; + size_t width_arg_index; + const char* precision_start; + const char* precision_end; + size_t precision_arg_index; + char conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ + size_t arg_index; +} +char_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + char_directive *dir; + size_t max_width_length; + size_t max_precision_length; + char_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; +} +char_directives; + +#if ENABLE_UNISTDIO + +/* A parsed directive. */ +typedef struct +{ + const uint8_t* dir_start; + const uint8_t* dir_end; + int flags; + const uint8_t* width_start; + const uint8_t* width_end; + size_t width_arg_index; + const uint8_t* precision_start; + const uint8_t* precision_end; + size_t precision_arg_index; + uint8_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ + size_t arg_index; +} +u8_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + u8_directive *dir; + size_t max_width_length; + size_t max_precision_length; + u8_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; +} +u8_directives; + +/* A parsed directive. */ +typedef struct +{ + const uint16_t* dir_start; + const uint16_t* dir_end; + int flags; + const uint16_t* width_start; + const uint16_t* width_end; + size_t width_arg_index; + const uint16_t* precision_start; + const uint16_t* precision_end; + size_t precision_arg_index; + uint16_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ + size_t arg_index; +} +u16_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + u16_directive *dir; + size_t max_width_length; + size_t max_precision_length; + u16_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; +} +u16_directives; + +/* A parsed directive. */ +typedef struct +{ + const uint32_t* dir_start; + const uint32_t* dir_end; + int flags; + const uint32_t* width_start; + const uint32_t* width_end; + size_t width_arg_index; + const uint32_t* precision_start; + const uint32_t* precision_end; + size_t precision_arg_index; + uint32_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ + size_t arg_index; +} +u32_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + u32_directive *dir; + size_t max_width_length; + size_t max_precision_length; + u32_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES]; +} +u32_directives; + +#endif + + +/* Parses the format string. Fills in the number N of directives, and fills + in directives[0], ..., directives[N-1], and sets directives[N].dir_start + to the end of the format string. Also fills in the arg_type fields of the + arguments and the needed count of arguments. */ +#if ENABLE_UNISTDIO +extern int + ulc_printf_parse (const char *format, char_directives *d, arguments *a); +extern int + u8_printf_parse (const uint8_t *format, u8_directives *d, arguments *a); +extern int + u16_printf_parse (const uint16_t *format, u16_directives *d, + arguments *a); +extern int + u32_printf_parse (const uint32_t *format, u32_directives *d, + arguments *a); +#else +# ifdef STATIC +STATIC +# else +extern +# endif +int printf_parse (const char *format, char_directives *d, arguments *a); +#endif + +#endif /* _PRINTF_PARSE_H */ diff --git a/grub-core/lib/gnulib/progname.c b/grub-core/lib/gnulib/progname.c new file mode 100644 index 0000000..a42b7fa --- /dev/null +++ b/grub-core/lib/gnulib/progname.c @@ -0,0 +1,92 @@ +/* Program name management. + Copyright (C) 2001-2003, 2005-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + + +#include <config.h> + +/* Specification. */ +#undef ENABLE_RELOCATABLE /* avoid defining set_program_name as a macro */ +#include "progname.h" + +#include <errno.h> /* get program_invocation_name declaration */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +/* String containing name the program is called with. + To be initialized by main(). */ +const char *program_name = NULL; + +/* Set program_name, based on argv[0]. + argv0 must be a string allocated with indefinite extent, and must not be + modified after this call. */ +void +set_program_name (const char *argv0) +{ + /* libtool creates a temporary executable whose name is sometimes prefixed + with "lt-" (depends on the platform). It also makes argv[0] absolute. + But the name of the temporary executable is a detail that should not be + visible to the end user and to the test suite. + Remove this "<dirname>/.libs/" or "<dirname>/.libs/lt-" prefix here. */ + const char *slash; + const char *base; + + /* Sanity check. POSIX requires the invoking process to pass a non-NULL + argv[0]. */ + if (argv0 == NULL) + { + /* It's a bug in the invoking program. Help diagnosing it. */ + fputs ("A NULL argv[0] was passed through an exec system call.\n", + stderr); + abort (); + } + + slash = strrchr (argv0, '/'); + base = (slash != NULL ? slash + 1 : argv0); + if (base - argv0 >= 7 && strncmp (base - 7, "/.libs/", 7) == 0) + { + argv0 = base; + if (strncmp (base, "lt-", 3) == 0) + { + argv0 = base + 3; + /* On glibc systems, remove the "lt-" prefix from the variable + program_invocation_short_name. */ +#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME + program_invocation_short_name = (char *) argv0; +#endif + } + } + + /* But don't strip off a leading <dirname>/ in general, because when the user + runs + /some/hidden/place/bin/cp foo foo + he should get the error message + /some/hidden/place/bin/cp: `foo' and `foo' are the same file + not + cp: `foo' and `foo' are the same file + */ + + program_name = argv0; + + /* On glibc systems, the error() function comes from libc and uses the + variable program_invocation_name, not program_name. So set this variable + as well. */ +#if HAVE_DECL_PROGRAM_INVOCATION_NAME + program_invocation_name = (char *) argv0; +#endif +} diff --git a/grub-core/lib/gnulib/progname.h b/grub-core/lib/gnulib/progname.h new file mode 100644 index 0000000..c726e97 --- /dev/null +++ b/grub-core/lib/gnulib/progname.h @@ -0,0 +1,62 @@ +/* Program name management. + Copyright (C) 2001-2004, 2006, 2009-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _PROGNAME_H +#define _PROGNAME_H + +/* Programs using this file should do the following in main(): + set_program_name (argv[0]); + */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* String containing name the program is called with. */ +extern const char *program_name; + +/* Set program_name, based on argv[0]. + argv0 must be a string allocated with indefinite extent, and must not be + modified after this call. */ +extern void set_program_name (const char *argv0); + +#if ENABLE_RELOCATABLE + +/* Set program_name, based on argv[0], and original installation prefix and + directory, for relocatability. */ +extern void set_program_name_and_installdir (const char *argv0, + const char *orig_installprefix, + const char *orig_installdir); +#undef set_program_name +#define set_program_name(ARG0) \ + set_program_name_and_installdir (ARG0, INSTALLPREFIX, INSTALLDIR) + +/* Return the full pathname of the current executable, based on the earlier + call to set_program_name_and_installdir. Return NULL if unknown. */ +extern char *get_full_program_name (void); + +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* _PROGNAME_H */ diff --git a/grub-core/lib/gnulib/rawmemchr.c b/grub-core/lib/gnulib/rawmemchr.c new file mode 100644 index 0000000..7df6151 --- /dev/null +++ b/grub-core/lib/gnulib/rawmemchr.c @@ -0,0 +1,136 @@ +/* Searching in a string. + Copyright (C) 2008-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <string.h> + +/* Find the first occurrence of C in S. */ +void * +rawmemchr (const void *s, int c_in) +{ + /* On 32-bit hardware, choosing longword to be a 32-bit unsigned + long instead of a 64-bit uintmax_t tends to give better + performance. On 64-bit hardware, unsigned long is generally 64 + bits already. Change this typedef to experiment with + performance. */ + typedef unsigned long int longword; + + const unsigned char *char_ptr; + const longword *longword_ptr; + longword repeated_one; + longword repeated_c; + unsigned char c; + + c = (unsigned char) c_in; + + /* Handle the first few bytes by reading one byte at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + (size_t) char_ptr % sizeof (longword) != 0; + ++char_ptr) + if (*char_ptr == c) + return (void *) char_ptr; + + longword_ptr = (const longword *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to any size longwords. */ + + /* Compute auxiliary longword values: + repeated_one is a value which has a 1 in every byte. + repeated_c has c in every byte. */ + repeated_one = 0x01010101; + repeated_c = c | (c << 8); + repeated_c |= repeated_c << 16; + if (0xffffffffU < (longword) -1) + { + repeated_one |= repeated_one << 31 << 1; + repeated_c |= repeated_c << 31 << 1; + if (8 < sizeof (longword)) + { + size_t i; + + for (i = 64; i < sizeof (longword) * 8; i *= 2) + { + repeated_one |= repeated_one << i; + repeated_c |= repeated_c << i; + } + } + } + + /* Instead of the traditional loop which tests each byte, we will + test a longword at a time. The tricky part is testing if *any of + the four* bytes in the longword in question are equal to NUL or + c. We first use an xor with repeated_c. This reduces the task + to testing whether *any of the four* bytes in longword1 is zero. + + We compute tmp = + ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). + That is, we perform the following operations: + 1. Subtract repeated_one. + 2. & ~longword1. + 3. & a mask consisting of 0x80 in every byte. + Consider what happens in each byte: + - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, + and step 3 transforms it into 0x80. A carry can also be propagated + to more significant bytes. + - If a byte of longword1 is nonzero, let its lowest 1 bit be at + position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, + the byte ends in a single bit of value 0 and k bits of value 1. + After step 2, the result is just k bits of value 1: 2^k - 1. After + step 3, the result is 0. And no carry is produced. + So, if longword1 has only non-zero bytes, tmp is zero. + Whereas if longword1 has a zero byte, call j the position of the least + significant zero byte. Then the result has a zero at positions 0, ..., + j-1 and a 0x80 at position j. We cannot predict the result at the more + significant bytes (positions j+1..3), but it does not matter since we + already have a non-zero bit at position 8*j+7. + + The test whether any byte in longword1 is zero is equivalent + to testing whether tmp is nonzero. + + This test can read beyond the end of a string, depending on where + C_IN is encountered. However, this is considered safe since the + initialization phase ensured that the read will be aligned, + therefore, the read will not cross page boundaries and will not + cause a fault. */ + + while (1) + { + longword longword1 = *longword_ptr ^ repeated_c; + + if ((((longword1 - repeated_one) & ~longword1) + & (repeated_one << 7)) != 0) + break; + longword_ptr++; + } + + char_ptr = (const unsigned char *) longword_ptr; + + /* At this point, we know that one of the sizeof (longword) bytes + starting at char_ptr is == c. On little-endian machines, we + could determine the first such byte without any further memory + accesses, just by looking at the tmp result from the last loop + iteration. But this does not work on big-endian machines. + Choose code that works in both cases. */ + + char_ptr = (unsigned char *) longword_ptr; + while (*char_ptr != c) + char_ptr++; + return (void *) char_ptr; +} diff --git a/grub-core/lib/gnulib/rawmemchr.valgrind b/grub-core/lib/gnulib/rawmemchr.valgrind new file mode 100644 index 0000000..6363923 --- /dev/null +++ b/grub-core/lib/gnulib/rawmemchr.valgrind @@ -0,0 +1,12 @@ +# Suppress a valgrind message about use of uninitialized memory in rawmemchr(). +# This use is OK because it provides only a speedup. +{ + rawmemchr-value4 + Memcheck:Value4 + fun:rawmemchr +} +{ + rawmemchr-value8 + Memcheck:Value8 + fun:rawmemchr +} diff --git a/grub-core/lib/gnulib/realloc.c b/grub-core/lib/gnulib/realloc.c new file mode 100644 index 0000000..a81ce3b --- /dev/null +++ b/grub-core/lib/gnulib/realloc.c @@ -0,0 +1,79 @@ +/* realloc() function that is glibc compatible. + + Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2019 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* written by Jim Meyering and Bruno Haible */ + +#define _GL_USE_STDLIB_ALLOC 1 +#include <config.h> + +/* Only the AC_FUNC_REALLOC macro defines 'realloc' already in config.h. */ +#ifdef realloc +# define NEED_REALLOC_GNU 1 +/* Whereas the gnulib module 'realloc-gnu' defines HAVE_REALLOC_GNU. */ +#elif GNULIB_REALLOC_GNU && !HAVE_REALLOC_GNU +# define NEED_REALLOC_GNU 1 +#endif + +/* Infer the properties of the system's malloc function. + The gnulib module 'malloc-gnu' defines HAVE_MALLOC_GNU. */ +#if GNULIB_MALLOC_GNU && HAVE_MALLOC_GNU +# define SYSTEM_MALLOC_GLIBC_COMPATIBLE 1 +#endif + +#include <stdlib.h> + +#include <errno.h> + +/* Change the size of an allocated block of memory P to N bytes, + with error checking. If N is zero, change it to 1. If P is NULL, + use malloc. */ + +void * +rpl_realloc (void *p, size_t n) +{ + void *result; + +#if NEED_REALLOC_GNU + if (n == 0) + { + n = 1; + + /* In theory realloc might fail, so don't rely on it to free. */ + free (p); + p = NULL; + } +#endif + + if (p == NULL) + { +#if GNULIB_REALLOC_GNU && !NEED_REALLOC_GNU && !SYSTEM_MALLOC_GLIBC_COMPATIBLE + if (n == 0) + n = 1; +#endif + result = malloc (n); + } + else + result = realloc (p, n); + +#if !HAVE_REALLOC_POSIX + if (result == NULL) + errno = ENOMEM; +#endif + + return result; +} diff --git a/grub-core/lib/gnulib/regcomp.c b/grub-core/lib/gnulib/regcomp.c new file mode 100644 index 0000000..64a4fa7 --- /dev/null +++ b/grub-core/lib/gnulib/regcomp.c @@ -0,0 +1,3930 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifdef _LIBC +# include <locale/weight.h> +#endif + +static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, + size_t length, reg_syntax_t syntax); +static void re_compile_fastmap_iter (regex_t *bufp, + const re_dfastate_t *init_state, + char *fastmap); +static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); +#ifdef RE_ENABLE_I18N +static void free_charset (re_charset_t *cset); +#endif /* RE_ENABLE_I18N */ +static void free_workarea_compile (regex_t *preg); +static reg_errcode_t create_initial_state (re_dfa_t *dfa); +#ifdef RE_ENABLE_I18N +static void optimize_utf8 (re_dfa_t *dfa); +#endif +static reg_errcode_t analyze (regex_t *preg); +static reg_errcode_t preorder (bin_tree_t *root, + reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra); +static reg_errcode_t postorder (bin_tree_t *root, + reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra); +static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node); +static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node); +static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg, + bin_tree_t *node); +static reg_errcode_t calc_first (void *extra, bin_tree_t *node); +static reg_errcode_t calc_next (void *extra, bin_tree_t *node); +static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node); +static Idx duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint); +static Idx search_duplicated_node (const re_dfa_t *dfa, Idx org_node, + unsigned int constraint); +static reg_errcode_t calc_eclosure (re_dfa_t *dfa); +static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, + Idx node, bool root); +static reg_errcode_t calc_inveclosure (re_dfa_t *dfa); +static Idx fetch_number (re_string_t *input, re_token_t *token, + reg_syntax_t syntax); +static int peek_token (re_token_t *token, re_string_t *input, + reg_syntax_t syntax); +static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, + reg_syntax_t syntax, reg_errcode_t *err); +static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + Idx nest, reg_errcode_t *err); +static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + Idx nest, reg_errcode_t *err); +static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + Idx nest, reg_errcode_t *err); +static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + Idx nest, reg_errcode_t *err); +static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, + re_dfa_t *dfa, re_token_t *token, + reg_syntax_t syntax, reg_errcode_t *err); +static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, + re_token_t *token, reg_syntax_t syntax, + reg_errcode_t *err); +static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, + re_string_t *regexp, + re_token_t *token, int token_len, + re_dfa_t *dfa, + reg_syntax_t syntax, + bool accept_hyphen); +static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, + re_string_t *regexp, + re_token_t *token); +#ifdef RE_ENABLE_I18N +static reg_errcode_t build_equiv_class (bitset_t sbcset, + re_charset_t *mbcset, + Idx *equiv_class_alloc, + const unsigned char *name); +static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, + bitset_t sbcset, + re_charset_t *mbcset, + Idx *char_class_alloc, + const char *class_name, + reg_syntax_t syntax); +#else /* not RE_ENABLE_I18N */ +static reg_errcode_t build_equiv_class (bitset_t sbcset, + const unsigned char *name); +static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, + bitset_t sbcset, + const char *class_name, + reg_syntax_t syntax); +#endif /* not RE_ENABLE_I18N */ +static bin_tree_t *build_charclass_op (re_dfa_t *dfa, + RE_TRANSLATE_TYPE trans, + const char *class_name, + const char *extra, + bool non_match, reg_errcode_t *err); +static bin_tree_t *create_tree (re_dfa_t *dfa, + bin_tree_t *left, bin_tree_t *right, + re_token_type_t type); +static bin_tree_t *create_token_tree (re_dfa_t *dfa, + bin_tree_t *left, bin_tree_t *right, + const re_token_t *token); +static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); +static void free_token (re_token_t *node); +static reg_errcode_t free_tree (void *extra, bin_tree_t *node); +static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); + +/* This table gives an error message for each of the error codes listed + in regex.h. Obviously the order here has to be same as there. + POSIX doesn't require that we do anything for REG_NOERROR, + but why not be nice? */ + +static const char __re_error_msgid[] = + { +#define REG_NOERROR_IDX 0 + gettext_noop ("Success") /* REG_NOERROR */ + "\0" +#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") + gettext_noop ("No match") /* REG_NOMATCH */ + "\0" +#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") + gettext_noop ("Invalid regular expression") /* REG_BADPAT */ + "\0" +#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") + gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ + "\0" +#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") + gettext_noop ("Invalid character class name") /* REG_ECTYPE */ + "\0" +#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") + gettext_noop ("Trailing backslash") /* REG_EESCAPE */ + "\0" +#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") + gettext_noop ("Invalid back reference") /* REG_ESUBREG */ + "\0" +#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") + gettext_noop ("Unmatched [, [^, [:, [., or [=") /* REG_EBRACK */ + "\0" +#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [, [^, [:, [., or [=") + gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ + "\0" +#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") + gettext_noop ("Unmatched \\{") /* REG_EBRACE */ + "\0" +#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") + gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ + "\0" +#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") + gettext_noop ("Invalid range end") /* REG_ERANGE */ + "\0" +#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") + gettext_noop ("Memory exhausted") /* REG_ESPACE */ + "\0" +#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") + gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ + "\0" +#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") + gettext_noop ("Premature end of regular expression") /* REG_EEND */ + "\0" +#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") + gettext_noop ("Regular expression too big") /* REG_ESIZE */ + "\0" +#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") + gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ + }; + +static const size_t __re_error_msgid_idx[] = + { + REG_NOERROR_IDX, + REG_NOMATCH_IDX, + REG_BADPAT_IDX, + REG_ECOLLATE_IDX, + REG_ECTYPE_IDX, + REG_EESCAPE_IDX, + REG_ESUBREG_IDX, + REG_EBRACK_IDX, + REG_EPAREN_IDX, + REG_EBRACE_IDX, + REG_BADBR_IDX, + REG_ERANGE_IDX, + REG_ESPACE_IDX, + REG_BADRPT_IDX, + REG_EEND_IDX, + REG_ESIZE_IDX, + REG_ERPAREN_IDX + }; + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length LENGTH) and puts the result in BUFP. + Returns 0 if the pattern was valid, otherwise an error string. + + Assumes the 'allocated' (and perhaps 'buffer') and 'translate' fields + are set in BUFP on entry. */ + +const char * +re_compile_pattern (const char *pattern, size_t length, + struct re_pattern_buffer *bufp) +{ + reg_errcode_t ret; + + /* And GNU code determines whether or not to get register information + by passing null for the REGS argument to re_match, etc., not by + setting no_sub, unless RE_NO_SUB is set. */ + bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + + ret = re_compile_internal (bufp, pattern, length, re_syntax_options); + + if (!ret) + return NULL; + return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); +} +weak_alias (__re_compile_pattern, re_compile_pattern) + +/* Set by 're_set_syntax' to the current regexp syntax to recognize. Can + also be assigned to arbitrarily: each pattern buffer stores its own + syntax, so it can be changed between regex compilations. */ +/* This has no initializer because initialized variables in Emacs + become read-only after dumping. */ +reg_syntax_t re_syntax_options; + + +/* Specify the precise syntax of regexps for compilation. This provides + for compatibility for various utilities which historically have + different, incompatible syntaxes. + + The argument SYNTAX is a bit mask comprised of the various bits + defined in regex.h. We return the old syntax. */ + +reg_syntax_t +re_set_syntax (reg_syntax_t syntax) +{ + reg_syntax_t ret = re_syntax_options; + + re_syntax_options = syntax; + return ret; +} +weak_alias (__re_set_syntax, re_set_syntax) + +int +re_compile_fastmap (struct re_pattern_buffer *bufp) +{ + re_dfa_t *dfa = bufp->buffer; + char *fastmap = bufp->fastmap; + + memset (fastmap, '\0', sizeof (char) * SBC_MAX); + re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); + if (dfa->init_state != dfa->init_state_word) + re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); + if (dfa->init_state != dfa->init_state_nl) + re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); + if (dfa->init_state != dfa->init_state_begbuf) + re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); + bufp->fastmap_accurate = 1; + return 0; +} +weak_alias (__re_compile_fastmap, re_compile_fastmap) + +static inline void +__attribute__ ((always_inline)) +re_set_fastmap (char *fastmap, bool icase, int ch) +{ + fastmap[ch] = 1; + if (icase) + fastmap[tolower (ch)] = 1; +} + +/* Helper function for re_compile_fastmap. + Compile fastmap for the initial_state INIT_STATE. */ + +static void +re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, + char *fastmap) +{ + re_dfa_t *dfa = bufp->buffer; + Idx node_cnt; + bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); + for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) + { + Idx node = init_state->nodes.elems[node_cnt]; + re_token_type_t type = dfa->nodes[node].type; + + if (type == CHARACTER) + { + re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); +#ifdef RE_ENABLE_I18N + if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) + { + unsigned char buf[MB_LEN_MAX]; + unsigned char *p; + wchar_t wc; + mbstate_t state; + + p = buf; + *p++ = dfa->nodes[node].opr.c; + while (++node < dfa->nodes_len + && dfa->nodes[node].type == CHARACTER + && dfa->nodes[node].mb_partial) + *p++ = dfa->nodes[node].opr.c; + memset (&state, '\0', sizeof (state)); + if (__mbrtowc (&wc, (const char *) buf, p - buf, + &state) == p - buf + && (__wcrtomb ((char *) buf, __towlower (wc), &state) + != (size_t) -1)) + re_set_fastmap (fastmap, false, buf[0]); + } +#endif + } + else if (type == SIMPLE_BRACKET) + { + int i, ch; + for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + { + int j; + bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + if (w & ((bitset_word_t) 1 << j)) + re_set_fastmap (fastmap, icase, ch); + } + } +#ifdef RE_ENABLE_I18N + else if (type == COMPLEX_BRACKET) + { + re_charset_t *cset = dfa->nodes[node].opr.mbcset; + Idx i; + +# ifdef _LIBC + /* See if we have to try all bytes which start multiple collation + elements. + e.g. In da_DK, we want to catch 'a' since "aa" is a valid + collation element, and don't catch 'b' since 'b' is + the only collation element which starts from 'b' (and + it is caught by SIMPLE_BRACKET). */ + if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0 + && (cset->ncoll_syms || cset->nranges)) + { + const int32_t *table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + for (i = 0; i < SBC_MAX; ++i) + if (table[i] < 0) + re_set_fastmap (fastmap, icase, i); + } +# endif /* _LIBC */ + + /* See if we have to start the match at all multibyte characters, + i.e. where we would not find an invalid sequence. This only + applies to multibyte character sets; for single byte character + sets, the SIMPLE_BRACKET again suffices. */ + if (dfa->mb_cur_max > 1 + && (cset->nchar_classes || cset->non_match || cset->nranges +# ifdef _LIBC + || cset->nequiv_classes +# endif /* _LIBC */ + )) + { + unsigned char c = 0; + do + { + mbstate_t mbs; + memset (&mbs, 0, sizeof (mbs)); + if (__mbrtowc (NULL, (char *) &c, 1, &mbs) == (size_t) -2) + re_set_fastmap (fastmap, false, (int) c); + } + while (++c != 0); + } + + else + { + /* ... Else catch all bytes which can start the mbchars. */ + for (i = 0; i < cset->nmbchars; ++i) + { + char buf[256]; + mbstate_t state; + memset (&state, '\0', sizeof (state)); + if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) + re_set_fastmap (fastmap, icase, *(unsigned char *) buf); + if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) + { + if (__wcrtomb (buf, __towlower (cset->mbchars[i]), &state) + != (size_t) -1) + re_set_fastmap (fastmap, false, *(unsigned char *) buf); + } + } + } + } +#endif /* RE_ENABLE_I18N */ + else if (type == OP_PERIOD +#ifdef RE_ENABLE_I18N + || type == OP_UTF8_PERIOD +#endif /* RE_ENABLE_I18N */ + || type == END_OF_RE) + { + memset (fastmap, '\1', sizeof (char) * SBC_MAX); + if (type == END_OF_RE) + bufp->can_be_null = 1; + return; + } + } +} + +/* Entry point for POSIX code. */ +/* regcomp takes a regular expression as a string and compiles it. + + PREG is a regex_t *. We do not expect any fields to be initialized, + since POSIX says we shouldn't. Thus, we set + + 'buffer' to the compiled pattern; + 'used' to the length of the compiled pattern; + 'syntax' to RE_SYNTAX_POSIX_EXTENDED if the + REG_EXTENDED bit in CFLAGS is set; otherwise, to + RE_SYNTAX_POSIX_BASIC; + 'newline_anchor' to REG_NEWLINE being set in CFLAGS; + 'fastmap' to an allocated space for the fastmap; + 'fastmap_accurate' to zero; + 're_nsub' to the number of subexpressions in PATTERN. + + PATTERN is the address of the pattern string. + + CFLAGS is a series of bits which affect compilation. + + If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we + use POSIX basic syntax. + + If REG_NEWLINE is set, then . and [^...] don't match newline. + Also, regexec will try a match beginning after every newline. + + If REG_ICASE is set, then we considers upper- and lowercase + versions of letters to be equivalent when matching. + + If REG_NOSUB is set, then when PREG is passed to regexec, that + routine will report only success or failure, and nothing about the + registers. + + It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for + the return codes and their meanings.) */ + +int +regcomp (regex_t *__restrict preg, const char *__restrict pattern, int cflags) +{ + reg_errcode_t ret; + reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED + : RE_SYNTAX_POSIX_BASIC); + + preg->buffer = NULL; + preg->allocated = 0; + preg->used = 0; + + /* Try to allocate space for the fastmap. */ + preg->fastmap = re_malloc (char, SBC_MAX); + if (__glibc_unlikely (preg->fastmap == NULL)) + return REG_ESPACE; + + syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; + + /* If REG_NEWLINE is set, newlines are treated differently. */ + if (cflags & REG_NEWLINE) + { /* REG_NEWLINE implies neither . nor [^...] match newline. */ + syntax &= ~RE_DOT_NEWLINE; + syntax |= RE_HAT_LISTS_NOT_NEWLINE; + /* It also changes the matching behavior. */ + preg->newline_anchor = 1; + } + else + preg->newline_anchor = 0; + preg->no_sub = !!(cflags & REG_NOSUB); + preg->translate = NULL; + + ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); + + /* POSIX doesn't distinguish between an unmatched open-group and an + unmatched close-group: both are REG_EPAREN. */ + if (ret == REG_ERPAREN) + ret = REG_EPAREN; + + /* We have already checked preg->fastmap != NULL. */ + if (__glibc_likely (ret == REG_NOERROR)) + /* Compute the fastmap now, since regexec cannot modify the pattern + buffer. This function never fails in this implementation. */ + (void) re_compile_fastmap (preg); + else + { + /* Some error occurred while compiling the expression. */ + re_free (preg->fastmap); + preg->fastmap = NULL; + } + + return (int) ret; +} +libc_hidden_def (__regcomp) +weak_alias (__regcomp, regcomp) + +/* Returns a message corresponding to an error code, ERRCODE, returned + from either regcomp or regexec. We don't use PREG here. */ + +size_t +regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf, + size_t errbuf_size) +{ + const char *msg; + size_t msg_size; + int nerrcodes = sizeof __re_error_msgid_idx / sizeof __re_error_msgid_idx[0]; + + if (__glibc_unlikely (errcode < 0 || errcode >= nerrcodes)) + /* Only error codes returned by the rest of the code should be passed + to this routine. If we are given anything else, or if other regex + code generates an invalid error code, then the program has a bug. + Dump core so we can fix it. */ + msg = gettext ("unknown regexp error"); + else + msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); + + msg_size = strlen (msg) + 1; /* Includes the null. */ + + if (__glibc_likely (errbuf_size != 0)) + { + size_t cpy_size = msg_size; + if (__glibc_unlikely (msg_size > errbuf_size)) + { + cpy_size = errbuf_size - 1; + errbuf[cpy_size] = '\0'; + } + memcpy (errbuf, msg, cpy_size); + } + + return msg_size; +} +weak_alias (__regerror, regerror) + + +#ifdef RE_ENABLE_I18N +/* This static array is used for the map to single-byte characters when + UTF-8 is used. Otherwise we would allocate memory just to initialize + it the same all the time. UTF-8 is the preferred encoding so this is + a worthwhile optimization. */ +static const bitset_t utf8_sb_map = +{ + /* Set the first 128 bits. */ +# if defined __GNUC__ && !defined __STRICT_ANSI__ + [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX +# else +# if 4 * BITSET_WORD_BITS < ASCII_CHARS +# error "bitset_word_t is narrower than 32 bits" +# elif 3 * BITSET_WORD_BITS < ASCII_CHARS + BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, +# elif 2 * BITSET_WORD_BITS < ASCII_CHARS + BITSET_WORD_MAX, BITSET_WORD_MAX, +# elif 1 * BITSET_WORD_BITS < ASCII_CHARS + BITSET_WORD_MAX, +# endif + (BITSET_WORD_MAX + >> (SBC_MAX % BITSET_WORD_BITS == 0 + ? 0 + : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS)) +# endif +}; +#endif + + +static void +free_dfa_content (re_dfa_t *dfa) +{ + Idx i, j; + + if (dfa->nodes) + for (i = 0; i < dfa->nodes_len; ++i) + free_token (dfa->nodes + i); + re_free (dfa->nexts); + for (i = 0; i < dfa->nodes_len; ++i) + { + if (dfa->eclosures != NULL) + re_node_set_free (dfa->eclosures + i); + if (dfa->inveclosures != NULL) + re_node_set_free (dfa->inveclosures + i); + if (dfa->edests != NULL) + re_node_set_free (dfa->edests + i); + } + re_free (dfa->edests); + re_free (dfa->eclosures); + re_free (dfa->inveclosures); + re_free (dfa->nodes); + + if (dfa->state_table) + for (i = 0; i <= dfa->state_hash_mask; ++i) + { + struct re_state_table_entry *entry = dfa->state_table + i; + for (j = 0; j < entry->num; ++j) + { + re_dfastate_t *state = entry->array[j]; + free_state (state); + } + re_free (entry->array); + } + re_free (dfa->state_table); +#ifdef RE_ENABLE_I18N + if (dfa->sb_char != utf8_sb_map) + re_free (dfa->sb_char); +#endif + re_free (dfa->subexp_map); +#ifdef DEBUG + re_free (dfa->re_str); +#endif + + re_free (dfa); +} + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree (regex_t *preg) +{ + re_dfa_t *dfa = preg->buffer; + if (__glibc_likely (dfa != NULL)) + { + lock_fini (dfa->lock); + free_dfa_content (dfa); + } + preg->buffer = NULL; + preg->allocated = 0; + + re_free (preg->fastmap); + preg->fastmap = NULL; + + re_free (preg->translate); + preg->translate = NULL; +} +libc_hidden_def (__regfree) +weak_alias (__regfree, regfree) + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them unless specifically requested. */ + +#if defined _REGEX_RE_COMP || defined _LIBC + +/* BSD has one and only one pattern buffer. */ +static struct re_pattern_buffer re_comp_buf; + +char * +# ifdef _LIBC +/* Make these definitions weak in libc, so POSIX programs can redefine + these names if they don't use our functions, and still use + regcomp/regexec above without link errors. */ +weak_function +# endif +re_comp (const char *s) +{ + reg_errcode_t ret; + char *fastmap; + + if (!s) + { + if (!re_comp_buf.buffer) + return gettext ("No previous regular expression"); + return 0; + } + + if (re_comp_buf.buffer) + { + fastmap = re_comp_buf.fastmap; + re_comp_buf.fastmap = NULL; + __regfree (&re_comp_buf); + memset (&re_comp_buf, '\0', sizeof (re_comp_buf)); + re_comp_buf.fastmap = fastmap; + } + + if (re_comp_buf.fastmap == NULL) + { + re_comp_buf.fastmap = re_malloc (char, SBC_MAX); + if (re_comp_buf.fastmap == NULL) + return (char *) gettext (__re_error_msgid + + __re_error_msgid_idx[(int) REG_ESPACE]); + } + + /* Since 're_exec' always passes NULL for the 'regs' argument, we + don't need to initialize the pattern buffer fields which affect it. */ + + /* Match anchors at newlines. */ + re_comp_buf.newline_anchor = 1; + + ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options); + + if (!ret) + return NULL; + + /* Yes, we're discarding 'const' here if !HAVE_LIBINTL. */ + return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); +} + +#ifdef _LIBC +libc_freeres_fn (free_mem) +{ + __regfree (&re_comp_buf); +} +#endif + +#endif /* _REGEX_RE_COMP */ + +/* Internal entry point. + Compile the regular expression PATTERN, whose length is LENGTH. + SYNTAX indicate regular expression's syntax. */ + +static reg_errcode_t +re_compile_internal (regex_t *preg, const char * pattern, size_t length, + reg_syntax_t syntax) +{ + reg_errcode_t err = REG_NOERROR; + re_dfa_t *dfa; + re_string_t regexp; + + /* Initialize the pattern buffer. */ + preg->fastmap_accurate = 0; + preg->syntax = syntax; + preg->not_bol = preg->not_eol = 0; + preg->used = 0; + preg->re_nsub = 0; + preg->can_be_null = 0; + preg->regs_allocated = REGS_UNALLOCATED; + + /* Initialize the dfa. */ + dfa = preg->buffer; + if (__glibc_unlikely (preg->allocated < sizeof (re_dfa_t))) + { + /* If zero allocated, but buffer is non-null, try to realloc + enough space. This loses if buffer's address is bogus, but + that is the user's responsibility. If ->buffer is NULL this + is a simple allocation. */ + dfa = re_realloc (preg->buffer, re_dfa_t, 1); + if (dfa == NULL) + return REG_ESPACE; + preg->allocated = sizeof (re_dfa_t); + preg->buffer = dfa; + } + preg->used = sizeof (re_dfa_t); + + err = init_dfa (dfa, length); + if (__glibc_unlikely (err == REG_NOERROR && lock_init (dfa->lock) != 0)) + err = REG_ESPACE; + if (__glibc_unlikely (err != REG_NOERROR)) + { + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + return err; + } +#ifdef DEBUG + /* Note: length+1 will not overflow since it is checked in init_dfa. */ + dfa->re_str = re_malloc (char, length + 1); + strncpy (dfa->re_str, pattern, length + 1); +#endif + + err = re_string_construct (®exp, pattern, length, preg->translate, + (syntax & RE_ICASE) != 0, dfa); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_compile_internal_free_return: + free_workarea_compile (preg); + re_string_destruct (®exp); + lock_fini (dfa->lock); + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + return err; + } + + /* Parse the regular expression, and build a structure tree. */ + preg->re_nsub = 0; + dfa->str_tree = parse (®exp, preg, syntax, &err); + if (__glibc_unlikely (dfa->str_tree == NULL)) + goto re_compile_internal_free_return; + + /* Analyze the tree and create the nfa. */ + err = analyze (preg); + if (__glibc_unlikely (err != REG_NOERROR)) + goto re_compile_internal_free_return; + +#ifdef RE_ENABLE_I18N + /* If possible, do searching in single byte encoding to speed things up. */ + if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) + optimize_utf8 (dfa); +#endif + + /* Then create the initial state of the dfa. */ + err = create_initial_state (dfa); + + /* Release work areas. */ + free_workarea_compile (preg); + re_string_destruct (®exp); + + if (__glibc_unlikely (err != REG_NOERROR)) + { + lock_fini (dfa->lock); + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + } + + return err; +} + +/* Initialize DFA. We use the length of the regular expression PAT_LEN + as the initial length of some arrays. */ + +static reg_errcode_t +init_dfa (re_dfa_t *dfa, size_t pat_len) +{ + __re_size_t table_size; +#ifndef _LIBC + const char *codeset_name; +#endif +#ifdef RE_ENABLE_I18N + size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t)); +#else + size_t max_i18n_object_size = 0; +#endif + size_t max_object_size = + MAX (sizeof (struct re_state_table_entry), + MAX (sizeof (re_token_t), + MAX (sizeof (re_node_set), + MAX (sizeof (regmatch_t), + max_i18n_object_size)))); + + memset (dfa, '\0', sizeof (re_dfa_t)); + + /* Force allocation of str_tree_storage the first time. */ + dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; + + /* Avoid overflows. The extra "/ 2" is for the table_size doubling + calculation below, and for similar doubling calculations + elsewhere. And it's <= rather than <, because some of the + doubling calculations add 1 afterwards. */ + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) / 2 + <= pat_len)) + return REG_ESPACE; + + dfa->nodes_alloc = pat_len + 1; + dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); + + /* table_size = 2 ^ ceil(log pat_len) */ + for (table_size = 1; ; table_size <<= 1) + if (table_size > pat_len) + break; + + dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); + dfa->state_hash_mask = table_size - 1; + + dfa->mb_cur_max = MB_CUR_MAX; +#ifdef _LIBC + if (dfa->mb_cur_max == 6 + && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) + dfa->is_utf8 = 1; + dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) + != 0); +#else + codeset_name = nl_langinfo (CODESET); + if ((codeset_name[0] == 'U' || codeset_name[0] == 'u') + && (codeset_name[1] == 'T' || codeset_name[1] == 't') + && (codeset_name[2] == 'F' || codeset_name[2] == 'f') + && strcmp (codeset_name + 3 + (codeset_name[3] == '-'), "8") == 0) + dfa->is_utf8 = 1; + + /* We check exhaustively in the loop below if this charset is a + superset of ASCII. */ + dfa->map_notascii = 0; +#endif + +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + if (dfa->is_utf8) + dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; + else + { + int i, j, ch; + + dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); + if (__glibc_unlikely (dfa->sb_char == NULL)) + return REG_ESPACE; + + /* Set the bits corresponding to single byte chars. */ + for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + { + wint_t wch = __btowc (ch); + if (wch != WEOF) + dfa->sb_char[i] |= (bitset_word_t) 1 << j; +# ifndef _LIBC + if (isascii (ch) && wch != ch) + dfa->map_notascii = 1; +# endif + } + } + } +#endif + + if (__glibc_unlikely (dfa->nodes == NULL || dfa->state_table == NULL)) + return REG_ESPACE; + return REG_NOERROR; +} + +/* Initialize WORD_CHAR table, which indicate which character is + "word". In this case "word" means that it is the word construction + character used by some operators like "\<", "\>", etc. */ + +static void +init_word_char (re_dfa_t *dfa) +{ + int i = 0; + int j; + int ch = 0; + dfa->word_ops_used = 1; + if (__glibc_likely (dfa->map_notascii == 0)) + { + /* Avoid uint32_t and uint64_t as some non-GCC platforms lack + them, an issue when this code is used in Gnulib. */ + bitset_word_t bits0 = 0x00000000; + bitset_word_t bits1 = 0x03ff0000; + bitset_word_t bits2 = 0x87fffffe; + bitset_word_t bits3 = 0x07fffffe; + if (BITSET_WORD_BITS == 64) + { + /* Pacify gcc -Woverflow on 32-bit platformns. */ + dfa->word_char[0] = bits1 << 31 << 1 | bits0; + dfa->word_char[1] = bits3 << 31 << 1 | bits2; + i = 2; + } + else if (BITSET_WORD_BITS == 32) + { + dfa->word_char[0] = bits0; + dfa->word_char[1] = bits1; + dfa->word_char[2] = bits2; + dfa->word_char[3] = bits3; + i = 4; + } + else + goto general_case; + ch = 128; + + if (__glibc_likely (dfa->is_utf8)) + { + memset (&dfa->word_char[i], '\0', (SBC_MAX - ch) / 8); + return; + } + } + + general_case: + for (; i < BITSET_WORDS; ++i) + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + if (isalnum (ch) || ch == '_') + dfa->word_char[i] |= (bitset_word_t) 1 << j; +} + +/* Free the work area which are only used while compiling. */ + +static void +free_workarea_compile (regex_t *preg) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_storage_t *storage, *next; + for (storage = dfa->str_tree_storage; storage; storage = next) + { + next = storage->next; + re_free (storage); + } + dfa->str_tree_storage = NULL; + dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; + dfa->str_tree = NULL; + re_free (dfa->org_indices); + dfa->org_indices = NULL; +} + +/* Create initial states for all contexts. */ + +static reg_errcode_t +create_initial_state (re_dfa_t *dfa) +{ + Idx first, i; + reg_errcode_t err; + re_node_set init_nodes; + + /* Initial states have the epsilon closure of the node which is + the first node of the regular expression. */ + first = dfa->str_tree->first->node_idx; + dfa->init_node = first; + err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + /* The back-references which are in initial states can epsilon transit, + since in this case all of the subexpressions can be null. + Then we add epsilon closures of the nodes which are the next nodes of + the back-references. */ + if (dfa->nbackref > 0) + for (i = 0; i < init_nodes.nelem; ++i) + { + Idx node_idx = init_nodes.elems[i]; + re_token_type_t type = dfa->nodes[node_idx].type; + + Idx clexp_idx; + if (type != OP_BACK_REF) + continue; + for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) + { + re_token_t *clexp_node; + clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; + if (clexp_node->type == OP_CLOSE_SUBEXP + && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) + break; + } + if (clexp_idx == init_nodes.nelem) + continue; + + if (type == OP_BACK_REF) + { + Idx dest_idx = dfa->edests[node_idx].elems[0]; + if (!re_node_set_contains (&init_nodes, dest_idx)) + { + reg_errcode_t merge_err + = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); + if (merge_err != REG_NOERROR) + return merge_err; + i = 0; + } + } + } + + /* It must be the first time to invoke acquire_state. */ + dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); + /* We don't check ERR here, since the initial state must not be NULL. */ + if (__glibc_unlikely (dfa->init_state == NULL)) + return err; + if (dfa->init_state->has_constraint) + { + dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, + CONTEXT_WORD); + dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, + CONTEXT_NEWLINE); + dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, + &init_nodes, + CONTEXT_NEWLINE + | CONTEXT_BEGBUF); + if (__glibc_unlikely (dfa->init_state_word == NULL + || dfa->init_state_nl == NULL + || dfa->init_state_begbuf == NULL)) + return err; + } + else + dfa->init_state_word = dfa->init_state_nl + = dfa->init_state_begbuf = dfa->init_state; + + re_node_set_free (&init_nodes); + return REG_NOERROR; +} + +#ifdef RE_ENABLE_I18N +/* If it is possible to do searching in single byte encoding instead of UTF-8 + to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change + DFA nodes where needed. */ + +static void +optimize_utf8 (re_dfa_t *dfa) +{ + Idx node; + int i; + bool mb_chars = false; + bool has_period = false; + + for (node = 0; node < dfa->nodes_len; ++node) + switch (dfa->nodes[node].type) + { + case CHARACTER: + if (dfa->nodes[node].opr.c >= ASCII_CHARS) + mb_chars = true; + break; + case ANCHOR: + switch (dfa->nodes[node].opr.ctx_type) + { + case LINE_FIRST: + case LINE_LAST: + case BUF_FIRST: + case BUF_LAST: + break; + default: + /* Word anchors etc. cannot be handled. It's okay to test + opr.ctx_type since constraints (for all DFA nodes) are + created by ORing one or more opr.ctx_type values. */ + return; + } + break; + case OP_PERIOD: + has_period = true; + break; + case OP_BACK_REF: + case OP_ALT: + case END_OF_RE: + case OP_DUP_ASTERISK: + case OP_OPEN_SUBEXP: + case OP_CLOSE_SUBEXP: + break; + case COMPLEX_BRACKET: + return; + case SIMPLE_BRACKET: + /* Just double check. */ + { + int rshift = (ASCII_CHARS % BITSET_WORD_BITS == 0 + ? 0 + : BITSET_WORD_BITS - ASCII_CHARS % BITSET_WORD_BITS); + for (i = ASCII_CHARS / BITSET_WORD_BITS; i < BITSET_WORDS; ++i) + { + if (dfa->nodes[node].opr.sbcset[i] >> rshift != 0) + return; + rshift = 0; + } + } + break; + default: + break; + } + + if (mb_chars || has_period) + for (node = 0; node < dfa->nodes_len; ++node) + { + if (dfa->nodes[node].type == CHARACTER + && dfa->nodes[node].opr.c >= ASCII_CHARS) + dfa->nodes[node].mb_partial = 0; + else if (dfa->nodes[node].type == OP_PERIOD) + dfa->nodes[node].type = OP_UTF8_PERIOD; + } + + /* The search can be in single byte locale. */ + dfa->mb_cur_max = 1; + dfa->is_utf8 = 0; + dfa->has_mb_node = dfa->nbackref > 0 || has_period; +} +#endif + +/* Analyze the structure tree, and calculate "first", "next", "edest", + "eclosure", and "inveclosure". */ + +static reg_errcode_t +analyze (regex_t *preg) +{ + re_dfa_t *dfa = preg->buffer; + reg_errcode_t ret; + + /* Allocate arrays. */ + dfa->nexts = re_malloc (Idx, dfa->nodes_alloc); + dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc); + dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); + dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); + if (__glibc_unlikely (dfa->nexts == NULL || dfa->org_indices == NULL + || dfa->edests == NULL || dfa->eclosures == NULL)) + return REG_ESPACE; + + dfa->subexp_map = re_malloc (Idx, preg->re_nsub); + if (dfa->subexp_map != NULL) + { + Idx i; + for (i = 0; i < preg->re_nsub; i++) + dfa->subexp_map[i] = i; + preorder (dfa->str_tree, optimize_subexps, dfa); + for (i = 0; i < preg->re_nsub; i++) + if (dfa->subexp_map[i] != i) + break; + if (i == preg->re_nsub) + { + re_free (dfa->subexp_map); + dfa->subexp_map = NULL; + } + } + + ret = postorder (dfa->str_tree, lower_subexps, preg); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + ret = postorder (dfa->str_tree, calc_first, dfa); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + preorder (dfa->str_tree, calc_next, dfa); + ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + ret = calc_eclosure (dfa); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + + /* We only need this during the prune_impossible_nodes pass in regexec.c; + skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */ + if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match) + || dfa->nbackref) + { + dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); + if (__glibc_unlikely (dfa->inveclosures == NULL)) + return REG_ESPACE; + ret = calc_inveclosure (dfa); + } + + return ret; +} + +/* Our parse trees are very unbalanced, so we cannot use a stack to + implement parse tree visits. Instead, we use parent pointers and + some hairy code in these two functions. */ +static reg_errcode_t +postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra) +{ + bin_tree_t *node, *prev; + + for (node = root; ; ) + { + /* Descend down the tree, preferably to the left (or to the right + if that's the only child). */ + while (node->left || node->right) + if (node->left) + node = node->left; + else + node = node->right; + + do + { + reg_errcode_t err = fn (extra, node); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + if (node->parent == NULL) + return REG_NOERROR; + prev = node; + node = node->parent; + } + /* Go up while we have a node that is reached from the right. */ + while (node->right == prev || node->right == NULL); + node = node->right; + } +} + +static reg_errcode_t +preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra) +{ + bin_tree_t *node; + + for (node = root; ; ) + { + reg_errcode_t err = fn (extra, node); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + /* Go to the left node, or up and to the right. */ + if (node->left) + node = node->left; + else + { + bin_tree_t *prev = NULL; + while (node->right == prev || node->right == NULL) + { + prev = node; + node = node->parent; + if (!node) + return REG_NOERROR; + } + node = node->right; + } + } +} + +/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell + re_search_internal to map the inner one's opr.idx to this one's. Adjust + backreferences as well. Requires a preorder visit. */ +static reg_errcode_t +optimize_subexps (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + + if (node->token.type == OP_BACK_REF && dfa->subexp_map) + { + int idx = node->token.opr.idx; + node->token.opr.idx = dfa->subexp_map[idx]; + dfa->used_bkref_map |= 1 << node->token.opr.idx; + } + + else if (node->token.type == SUBEXP + && node->left && node->left->token.type == SUBEXP) + { + Idx other_idx = node->left->token.opr.idx; + + node->left = node->left->left; + if (node->left) + node->left->parent = node; + + dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx]; + if (other_idx < BITSET_WORD_BITS) + dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx); + } + + return REG_NOERROR; +} + +/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation + of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */ +static reg_errcode_t +lower_subexps (void *extra, bin_tree_t *node) +{ + regex_t *preg = (regex_t *) extra; + reg_errcode_t err = REG_NOERROR; + + if (node->left && node->left->token.type == SUBEXP) + { + node->left = lower_subexp (&err, preg, node->left); + if (node->left) + node->left->parent = node; + } + if (node->right && node->right->token.type == SUBEXP) + { + node->right = lower_subexp (&err, preg, node->right); + if (node->right) + node->right->parent = node; + } + + return err; +} + +static bin_tree_t * +lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_t *body = node->left; + bin_tree_t *op, *cls, *tree1, *tree; + + if (preg->no_sub + /* We do not optimize empty subexpressions, because otherwise we may + have bad CONCAT nodes with NULL children. This is obviously not + very common, so we do not lose much. An example that triggers + this case is the sed "script" /\(\)/x. */ + && node->left != NULL + && (node->token.opr.idx >= BITSET_WORD_BITS + || !(dfa->used_bkref_map + & ((bitset_word_t) 1 << node->token.opr.idx)))) + return node->left; + + /* Convert the SUBEXP node to the concatenation of an + OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ + op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); + cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); + tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; + tree = create_tree (dfa, op, tree1, CONCAT); + if (__glibc_unlikely (tree == NULL || tree1 == NULL + || op == NULL || cls == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + + op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx; + op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp; + return tree; +} + +/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton + nodes. Requires a postorder visit. */ +static reg_errcode_t +calc_first (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + if (node->token.type == CONCAT) + { + node->first = node->left->first; + node->node_idx = node->left->node_idx; + } + else + { + node->first = node; + node->node_idx = re_dfa_add_node (dfa, node->token); + if (__glibc_unlikely (node->node_idx == -1)) + return REG_ESPACE; + if (node->token.type == ANCHOR) + dfa->nodes[node->node_idx].constraint = node->token.opr.ctx_type; + } + return REG_NOERROR; +} + +/* Pass 2: compute NEXT on the tree. Preorder visit. */ +static reg_errcode_t +calc_next (void *extra, bin_tree_t *node) +{ + switch (node->token.type) + { + case OP_DUP_ASTERISK: + node->left->next = node; + break; + case CONCAT: + node->left->next = node->right->first; + node->right->next = node->next; + break; + default: + if (node->left) + node->left->next = node->next; + if (node->right) + node->right->next = node->next; + break; + } + return REG_NOERROR; +} + +/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */ +static reg_errcode_t +link_nfa_nodes (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + Idx idx = node->node_idx; + reg_errcode_t err = REG_NOERROR; + + switch (node->token.type) + { + case CONCAT: + break; + + case END_OF_RE: + assert (node->next == NULL); + break; + + case OP_DUP_ASTERISK: + case OP_ALT: + { + Idx left, right; + dfa->has_plural_match = 1; + if (node->left != NULL) + left = node->left->first->node_idx; + else + left = node->next->node_idx; + if (node->right != NULL) + right = node->right->first->node_idx; + else + right = node->next->node_idx; + assert (left > -1); + assert (right > -1); + err = re_node_set_init_2 (dfa->edests + idx, left, right); + } + break; + + case ANCHOR: + case OP_OPEN_SUBEXP: + case OP_CLOSE_SUBEXP: + err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx); + break; + + case OP_BACK_REF: + dfa->nexts[idx] = node->next->node_idx; + if (node->token.type == OP_BACK_REF) + err = re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); + break; + + default: + assert (!IS_EPSILON_NODE (node->token.type)); + dfa->nexts[idx] = node->next->node_idx; + break; + } + + return err; +} + +/* Duplicate the epsilon closure of the node ROOT_NODE. + Note that duplicated nodes have constraint INIT_CONSTRAINT in addition + to their own constraint. */ + +static reg_errcode_t +duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node, + Idx root_node, unsigned int init_constraint) +{ + Idx org_node, clone_node; + bool ok; + unsigned int constraint = init_constraint; + for (org_node = top_org_node, clone_node = top_clone_node;;) + { + Idx org_dest, clone_dest; + if (dfa->nodes[org_node].type == OP_BACK_REF) + { + /* If the back reference epsilon-transit, its destination must + also have the constraint. Then duplicate the epsilon closure + of the destination of the back reference, and store it in + edests of the back reference. */ + org_dest = dfa->nexts[org_node]; + re_node_set_empty (dfa->edests + clone_node); + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (__glibc_unlikely (clone_dest == -1)) + return REG_ESPACE; + dfa->nexts[clone_node] = dfa->nexts[org_node]; + ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + else if (dfa->edests[org_node].nelem == 0) + { + /* In case of the node can't epsilon-transit, don't duplicate the + destination and store the original destination as the + destination of the node. */ + dfa->nexts[clone_node] = dfa->nexts[org_node]; + break; + } + else if (dfa->edests[org_node].nelem == 1) + { + /* In case of the node can epsilon-transit, and it has only one + destination. */ + org_dest = dfa->edests[org_node].elems[0]; + re_node_set_empty (dfa->edests + clone_node); + /* If the node is root_node itself, it means the epsilon closure + has a loop. Then tie it to the destination of the root_node. */ + if (org_node == root_node && clone_node != org_node) + { + ok = re_node_set_insert (dfa->edests + clone_node, org_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + break; + } + /* In case the node has another constraint, append it. */ + constraint |= dfa->nodes[org_node].constraint; + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (__glibc_unlikely (clone_dest == -1)) + return REG_ESPACE; + ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + else /* dfa->edests[org_node].nelem == 2 */ + { + /* In case of the node can epsilon-transit, and it has two + destinations. In the bin_tree_t and DFA, that's '|' and '*'. */ + org_dest = dfa->edests[org_node].elems[0]; + re_node_set_empty (dfa->edests + clone_node); + /* Search for a duplicated node which satisfies the constraint. */ + clone_dest = search_duplicated_node (dfa, org_dest, constraint); + if (clone_dest == -1) + { + /* There is no such duplicated node, create a new one. */ + reg_errcode_t err; + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (__glibc_unlikely (clone_dest == -1)) + return REG_ESPACE; + ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + err = duplicate_node_closure (dfa, org_dest, clone_dest, + root_node, constraint); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + else + { + /* There is a duplicated node which satisfies the constraint, + use it to avoid infinite loop. */ + ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + + org_dest = dfa->edests[org_node].elems[1]; + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (__glibc_unlikely (clone_dest == -1)) + return REG_ESPACE; + ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + org_node = org_dest; + clone_node = clone_dest; + } + return REG_NOERROR; +} + +/* Search for a node which is duplicated from the node ORG_NODE, and + satisfies the constraint CONSTRAINT. */ + +static Idx +search_duplicated_node (const re_dfa_t *dfa, Idx org_node, + unsigned int constraint) +{ + Idx idx; + for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) + { + if (org_node == dfa->org_indices[idx] + && constraint == dfa->nodes[idx].constraint) + return idx; /* Found. */ + } + return -1; /* Not found. */ +} + +/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. + Return the index of the new node, or -1 if insufficient storage is + available. */ + +static Idx +duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint) +{ + Idx dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]); + if (__glibc_likely (dup_idx != -1)) + { + dfa->nodes[dup_idx].constraint = constraint; + dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].constraint; + dfa->nodes[dup_idx].duplicated = 1; + + /* Store the index of the original node. */ + dfa->org_indices[dup_idx] = org_idx; + } + return dup_idx; +} + +static reg_errcode_t +calc_inveclosure (re_dfa_t *dfa) +{ + Idx src, idx; + bool ok; + for (idx = 0; idx < dfa->nodes_len; ++idx) + re_node_set_init_empty (dfa->inveclosures + idx); + + for (src = 0; src < dfa->nodes_len; ++src) + { + Idx *elems = dfa->eclosures[src].elems; + for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) + { + ok = re_node_set_insert_last (dfa->inveclosures + elems[idx], src); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + } + + return REG_NOERROR; +} + +/* Calculate "eclosure" for all the node in DFA. */ + +static reg_errcode_t +calc_eclosure (re_dfa_t *dfa) +{ + Idx node_idx; + bool incomplete; +#ifdef DEBUG + assert (dfa->nodes_len > 0); +#endif + incomplete = false; + /* For each nodes, calculate epsilon closure. */ + for (node_idx = 0; ; ++node_idx) + { + reg_errcode_t err; + re_node_set eclosure_elem; + if (node_idx == dfa->nodes_len) + { + if (!incomplete) + break; + incomplete = false; + node_idx = 0; + } + +#ifdef DEBUG + assert (dfa->eclosures[node_idx].nelem != -1); +#endif + + /* If we have already calculated, skip it. */ + if (dfa->eclosures[node_idx].nelem != 0) + continue; + /* Calculate epsilon closure of 'node_idx'. */ + err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + if (dfa->eclosures[node_idx].nelem == 0) + { + incomplete = true; + re_node_set_free (&eclosure_elem); + } + } + return REG_NOERROR; +} + +/* Calculate epsilon closure of NODE. */ + +static reg_errcode_t +calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) +{ + reg_errcode_t err; + Idx i; + re_node_set eclosure; + bool ok; + bool incomplete = false; + err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + /* This indicates that we are calculating this node now. + We reference this value to avoid infinite loop. */ + dfa->eclosures[node].nelem = -1; + + /* If the current node has constraints, duplicate all nodes + since they must inherit the constraints. */ + if (dfa->nodes[node].constraint + && dfa->edests[node].nelem + && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) + { + err = duplicate_node_closure (dfa, node, node, node, + dfa->nodes[node].constraint); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + + /* Expand each epsilon destination nodes. */ + if (IS_EPSILON_NODE(dfa->nodes[node].type)) + for (i = 0; i < dfa->edests[node].nelem; ++i) + { + re_node_set eclosure_elem; + Idx edest = dfa->edests[node].elems[i]; + /* If calculating the epsilon closure of 'edest' is in progress, + return intermediate result. */ + if (dfa->eclosures[edest].nelem == -1) + { + incomplete = true; + continue; + } + /* If we haven't calculated the epsilon closure of 'edest' yet, + calculate now. Otherwise use calculated epsilon closure. */ + if (dfa->eclosures[edest].nelem == 0) + { + err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + else + eclosure_elem = dfa->eclosures[edest]; + /* Merge the epsilon closure of 'edest'. */ + err = re_node_set_merge (&eclosure, &eclosure_elem); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + /* If the epsilon closure of 'edest' is incomplete, + the epsilon closure of this node is also incomplete. */ + if (dfa->eclosures[edest].nelem == 0) + { + incomplete = true; + re_node_set_free (&eclosure_elem); + } + } + + /* An epsilon closure includes itself. */ + ok = re_node_set_insert (&eclosure, node); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + if (incomplete && !root) + dfa->eclosures[node].nelem = 0; + else + dfa->eclosures[node] = eclosure; + *new_set = eclosure; + return REG_NOERROR; +} + +/* Functions for token which are used in the parser. */ + +/* Fetch a token from INPUT. + We must not use this function inside bracket expressions. */ + +static void +fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax) +{ + re_string_skip_bytes (input, peek_token (result, input, syntax)); +} + +/* Peek a token from INPUT, and return the length of the token. + We must not use this function inside bracket expressions. */ + +static int +peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) +{ + unsigned char c; + + if (re_string_eoi (input)) + { + token->type = END_OF_RE; + return 0; + } + + c = re_string_peek_byte (input, 0); + token->opr.c = c; + + token->word_char = 0; +#ifdef RE_ENABLE_I18N + token->mb_partial = 0; + if (input->mb_cur_max > 1 && + !re_string_first_byte (input, re_string_cur_idx (input))) + { + token->type = CHARACTER; + token->mb_partial = 1; + return 1; + } +#endif + if (c == '\\') + { + unsigned char c2; + if (re_string_cur_idx (input) + 1 >= re_string_length (input)) + { + token->type = BACK_SLASH; + return 1; + } + + c2 = re_string_peek_byte_case (input, 1); + token->opr.c = c2; + token->type = CHARACTER; +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1) + { + wint_t wc = re_string_wchar_at (input, + re_string_cur_idx (input) + 1); + token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; + } + else +#endif + token->word_char = IS_WORD_CHAR (c2) != 0; + + switch (c2) + { + case '|': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) + token->type = OP_ALT; + break; + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + if (!(syntax & RE_NO_BK_REFS)) + { + token->type = OP_BACK_REF; + token->opr.idx = c2 - '1'; + } + break; + case '<': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_FIRST; + } + break; + case '>': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_LAST; + } + break; + case 'b': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_DELIM; + } + break; + case 'B': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = NOT_WORD_DELIM; + } + break; + case 'w': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_WORD; + break; + case 'W': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_NOTWORD; + break; + case 's': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_SPACE; + break; + case 'S': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_NOTSPACE; + break; + case '`': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = BUF_FIRST; + } + break; + case '\'': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = BUF_LAST; + } + break; + case '(': + if (!(syntax & RE_NO_BK_PARENS)) + token->type = OP_OPEN_SUBEXP; + break; + case ')': + if (!(syntax & RE_NO_BK_PARENS)) + token->type = OP_CLOSE_SUBEXP; + break; + case '+': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_PLUS; + break; + case '?': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_QUESTION; + break; + case '{': + if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) + token->type = OP_OPEN_DUP_NUM; + break; + case '}': + if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) + token->type = OP_CLOSE_DUP_NUM; + break; + default: + break; + } + return 2; + } + + token->type = CHARACTER; +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1) + { + wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); + token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; + } + else +#endif + token->word_char = IS_WORD_CHAR (token->opr.c); + + switch (c) + { + case '\n': + if (syntax & RE_NEWLINE_ALT) + token->type = OP_ALT; + break; + case '|': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) + token->type = OP_ALT; + break; + case '*': + token->type = OP_DUP_ASTERISK; + break; + case '+': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_PLUS; + break; + case '?': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_QUESTION; + break; + case '{': + if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + token->type = OP_OPEN_DUP_NUM; + break; + case '}': + if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + token->type = OP_CLOSE_DUP_NUM; + break; + case '(': + if (syntax & RE_NO_BK_PARENS) + token->type = OP_OPEN_SUBEXP; + break; + case ')': + if (syntax & RE_NO_BK_PARENS) + token->type = OP_CLOSE_SUBEXP; + break; + case '[': + token->type = OP_OPEN_BRACKET; + break; + case '.': + token->type = OP_PERIOD; + break; + case '^': + if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) && + re_string_cur_idx (input) != 0) + { + char prev = re_string_peek_byte (input, -1); + if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') + break; + } + token->type = ANCHOR; + token->opr.ctx_type = LINE_FIRST; + break; + case '$': + if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) && + re_string_cur_idx (input) + 1 != re_string_length (input)) + { + re_token_t next; + re_string_skip_bytes (input, 1); + peek_token (&next, input, syntax); + re_string_skip_bytes (input, -1); + if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) + break; + } + token->type = ANCHOR; + token->opr.ctx_type = LINE_LAST; + break; + default: + break; + } + return 1; +} + +/* Peek a token from INPUT, and return the length of the token. + We must not use this function out of bracket expressions. */ + +static int +peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) +{ + unsigned char c; + if (re_string_eoi (input)) + { + token->type = END_OF_RE; + return 0; + } + c = re_string_peek_byte (input, 0); + token->opr.c = c; + +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1 && + !re_string_first_byte (input, re_string_cur_idx (input))) + { + token->type = CHARACTER; + return 1; + } +#endif /* RE_ENABLE_I18N */ + + if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) + && re_string_cur_idx (input) + 1 < re_string_length (input)) + { + /* In this case, '\' escape a character. */ + unsigned char c2; + re_string_skip_bytes (input, 1); + c2 = re_string_peek_byte (input, 0); + token->opr.c = c2; + token->type = CHARACTER; + return 1; + } + if (c == '[') /* '[' is a special char in a bracket exps. */ + { + unsigned char c2; + int token_len; + if (re_string_cur_idx (input) + 1 < re_string_length (input)) + c2 = re_string_peek_byte (input, 1); + else + c2 = 0; + token->opr.c = c2; + token_len = 2; + switch (c2) + { + case '.': + token->type = OP_OPEN_COLL_ELEM; + break; + + case '=': + token->type = OP_OPEN_EQUIV_CLASS; + break; + + case ':': + if (syntax & RE_CHAR_CLASSES) + { + token->type = OP_OPEN_CHAR_CLASS; + break; + } + FALLTHROUGH; + default: + token->type = CHARACTER; + token->opr.c = c; + token_len = 1; + break; + } + return token_len; + } + switch (c) + { + case '-': + token->type = OP_CHARSET_RANGE; + break; + case ']': + token->type = OP_CLOSE_BRACKET; + break; + case '^': + token->type = OP_NON_MATCH_LIST; + break; + default: + token->type = CHARACTER; + } + return 1; +} + +/* Functions for parser. */ + +/* Entry point of the parser. + Parse the regular expression REGEXP and return the structure tree. + If an error occurs, ERR is set by error code, and return NULL. + This function build the following tree, from regular expression <reg_exp>: + CAT + / \ + / \ + <reg_exp> EOR + + CAT means concatenation. + EOR means end of regular expression. */ + +static bin_tree_t * +parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, + reg_errcode_t *err) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_t *tree, *eor, *root; + re_token_t current_token; + dfa->syntax = syntax; + fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); + tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + eor = create_tree (dfa, NULL, NULL, END_OF_RE); + if (tree != NULL) + root = create_tree (dfa, tree, eor, CONCAT); + else + root = eor; + if (__glibc_unlikely (eor == NULL || root == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + return root; +} + +/* This function build the following tree, from regular expression + <branch1>|<branch2>: + ALT + / \ + / \ + <branch1> <branch2> + + ALT means alternative, which represents the operator '|'. */ + +static bin_tree_t * +parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, Idx nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_t *tree, *branch = NULL; + bitset_word_t initial_bkref_map = dfa->completed_bkref_map; + tree = parse_branch (regexp, preg, token, syntax, nest, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + + while (token->type == OP_ALT) + { + fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); + if (token->type != OP_ALT && token->type != END_OF_RE + && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) + { + bitset_word_t accumulated_bkref_map = dfa->completed_bkref_map; + dfa->completed_bkref_map = initial_bkref_map; + branch = parse_branch (regexp, preg, token, syntax, nest, err); + if (__glibc_unlikely (*err != REG_NOERROR && branch == NULL)) + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + return NULL; + } + dfa->completed_bkref_map |= accumulated_bkref_map; + } + else + branch = NULL; + tree = create_tree (dfa, tree, branch, OP_ALT); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + } + return tree; +} + +/* This function build the following tree, from regular expression + <exp1><exp2>: + CAT + / \ + / \ + <exp1> <exp2> + + CAT means concatenation. */ + +static bin_tree_t * +parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, Idx nest, reg_errcode_t *err) +{ + bin_tree_t *tree, *expr; + re_dfa_t *dfa = preg->buffer; + tree = parse_expression (regexp, preg, token, syntax, nest, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + + while (token->type != OP_ALT && token->type != END_OF_RE + && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) + { + expr = parse_expression (regexp, preg, token, syntax, nest, err); + if (__glibc_unlikely (*err != REG_NOERROR && expr == NULL)) + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + return NULL; + } + if (tree != NULL && expr != NULL) + { + bin_tree_t *newtree = create_tree (dfa, tree, expr, CONCAT); + if (newtree == NULL) + { + postorder (expr, free_tree, NULL); + postorder (tree, free_tree, NULL); + *err = REG_ESPACE; + return NULL; + } + tree = newtree; + } + else if (tree == NULL) + tree = expr; + /* Otherwise expr == NULL, we don't need to create new tree. */ + } + return tree; +} + +/* This function build the following tree, from regular expression a*: + * + | + a +*/ + +static bin_tree_t * +parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, Idx nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_t *tree; + switch (token->type) + { + case CHARACTER: + tree = create_token_tree (dfa, NULL, NULL, token); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + while (!re_string_eoi (regexp) + && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) + { + bin_tree_t *mbc_remain; + fetch_token (token, regexp, syntax); + mbc_remain = create_token_tree (dfa, NULL, NULL, token); + tree = create_tree (dfa, tree, mbc_remain, CONCAT); + if (__glibc_unlikely (mbc_remain == NULL || tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + } + } +#endif + break; + + case OP_OPEN_SUBEXP: + tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + break; + + case OP_OPEN_BRACKET: + tree = parse_bracket_exp (regexp, dfa, token, syntax, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + break; + + case OP_BACK_REF: + if (!__glibc_likely (dfa->completed_bkref_map & (1 << token->opr.idx))) + { + *err = REG_ESUBREG; + return NULL; + } + dfa->used_bkref_map |= 1 << token->opr.idx; + tree = create_token_tree (dfa, NULL, NULL, token); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + ++dfa->nbackref; + dfa->has_mb_node = 1; + break; + + case OP_OPEN_DUP_NUM: + if (syntax & RE_CONTEXT_INVALID_DUP) + { + *err = REG_BADRPT; + return NULL; + } + FALLTHROUGH; + case OP_DUP_ASTERISK: + case OP_DUP_PLUS: + case OP_DUP_QUESTION: + if (syntax & RE_CONTEXT_INVALID_OPS) + { + *err = REG_BADRPT; + return NULL; + } + else if (syntax & RE_CONTEXT_INDEP_OPS) + { + fetch_token (token, regexp, syntax); + return parse_expression (regexp, preg, token, syntax, nest, err); + } + FALLTHROUGH; + case OP_CLOSE_SUBEXP: + if ((token->type == OP_CLOSE_SUBEXP) && + !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) + { + *err = REG_ERPAREN; + return NULL; + } + FALLTHROUGH; + case OP_CLOSE_DUP_NUM: + /* We treat it as a normal character. */ + + /* Then we can these characters as normal characters. */ + token->type = CHARACTER; + /* mb_partial and word_char bits should be initialized already + by peek_token. */ + tree = create_token_tree (dfa, NULL, NULL, token); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + break; + + case ANCHOR: + if ((token->opr.ctx_type + & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) + && dfa->word_ops_used == 0) + init_word_char (dfa); + if (token->opr.ctx_type == WORD_DELIM + || token->opr.ctx_type == NOT_WORD_DELIM) + { + bin_tree_t *tree_first, *tree_last; + if (token->opr.ctx_type == WORD_DELIM) + { + token->opr.ctx_type = WORD_FIRST; + tree_first = create_token_tree (dfa, NULL, NULL, token); + token->opr.ctx_type = WORD_LAST; + } + else + { + token->opr.ctx_type = INSIDE_WORD; + tree_first = create_token_tree (dfa, NULL, NULL, token); + token->opr.ctx_type = INSIDE_NOTWORD; + } + tree_last = create_token_tree (dfa, NULL, NULL, token); + tree = create_tree (dfa, tree_first, tree_last, OP_ALT); + if (__glibc_unlikely (tree_first == NULL || tree_last == NULL + || tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + } + else + { + tree = create_token_tree (dfa, NULL, NULL, token); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + } + /* We must return here, since ANCHORs can't be followed + by repetition operators. + eg. RE"^*" is invalid or "<ANCHOR(^)><CHAR(*)>", + it must not be "<ANCHOR(^)><REPEAT(*)>". */ + fetch_token (token, regexp, syntax); + return tree; + + case OP_PERIOD: + tree = create_token_tree (dfa, NULL, NULL, token); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + if (dfa->mb_cur_max > 1) + dfa->has_mb_node = 1; + break; + + case OP_WORD: + case OP_NOTWORD: + tree = build_charclass_op (dfa, regexp->trans, + "alnum", + "_", + token->type == OP_NOTWORD, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + break; + + case OP_SPACE: + case OP_NOTSPACE: + tree = build_charclass_op (dfa, regexp->trans, + "space", + "", + token->type == OP_NOTSPACE, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + break; + + case OP_ALT: + case END_OF_RE: + return NULL; + + case BACK_SLASH: + *err = REG_EESCAPE; + return NULL; + + default: + /* Must not happen? */ +#ifdef DEBUG + assert (0); +#endif + return NULL; + } + fetch_token (token, regexp, syntax); + + while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS + || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) + { + bin_tree_t *dup_tree = parse_dup_op (tree, regexp, dfa, token, + syntax, err); + if (__glibc_unlikely (*err != REG_NOERROR && dup_tree == NULL)) + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + return NULL; + } + tree = dup_tree; + /* In BRE consecutive duplications are not allowed. */ + if ((syntax & RE_CONTEXT_INVALID_DUP) + && (token->type == OP_DUP_ASTERISK + || token->type == OP_OPEN_DUP_NUM)) + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + *err = REG_BADRPT; + return NULL; + } + } + + return tree; +} + +/* This function build the following tree, from regular expression + (<reg_exp>): + SUBEXP + | + <reg_exp> +*/ + +static bin_tree_t * +parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, Idx nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_t *tree; + size_t cur_nsub; + cur_nsub = preg->re_nsub++; + + fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); + + /* The subexpression may be a null string. */ + if (token->type == OP_CLOSE_SUBEXP) + tree = NULL; + else + { + tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); + if (__glibc_unlikely (*err == REG_NOERROR + && token->type != OP_CLOSE_SUBEXP)) + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + *err = REG_EPAREN; + } + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + } + + if (cur_nsub <= '9' - '1') + dfa->completed_bkref_map |= 1 << cur_nsub; + + tree = create_tree (dfa, tree, NULL, SUBEXP); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + tree->token.opr.idx = cur_nsub; + return tree; +} + +/* This function parse repetition operators like "*", "+", "{1,3}" etc. */ + +static bin_tree_t * +parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, + re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) +{ + bin_tree_t *tree = NULL, *old_tree = NULL; + Idx i, start, end, start_idx = re_string_cur_idx (regexp); + re_token_t start_token = *token; + + if (token->type == OP_OPEN_DUP_NUM) + { + end = 0; + start = fetch_number (regexp, token, syntax); + if (start == -1) + { + if (token->type == CHARACTER && token->opr.c == ',') + start = 0; /* We treat "{,m}" as "{0,m}". */ + else + { + *err = REG_BADBR; /* <re>{} is invalid. */ + return NULL; + } + } + if (__glibc_likely (start != -2)) + { + /* We treat "{n}" as "{n,n}". */ + end = ((token->type == OP_CLOSE_DUP_NUM) ? start + : ((token->type == CHARACTER && token->opr.c == ',') + ? fetch_number (regexp, token, syntax) : -2)); + } + if (__glibc_unlikely (start == -2 || end == -2)) + { + /* Invalid sequence. */ + if (__glibc_unlikely (!(syntax & RE_INVALID_INTERVAL_ORD))) + { + if (token->type == END_OF_RE) + *err = REG_EBRACE; + else + *err = REG_BADBR; + + return NULL; + } + + /* If the syntax bit is set, rollback. */ + re_string_set_index (regexp, start_idx); + *token = start_token; + token->type = CHARACTER; + /* mb_partial and word_char bits should be already initialized by + peek_token. */ + return elem; + } + + if (__glibc_unlikely ((end != -1 && start > end) + || token->type != OP_CLOSE_DUP_NUM)) + { + /* First number greater than second. */ + *err = REG_BADBR; + return NULL; + } + + if (__glibc_unlikely (RE_DUP_MAX < (end == -1 ? start : end))) + { + *err = REG_ESIZE; + return NULL; + } + } + else + { + start = (token->type == OP_DUP_PLUS) ? 1 : 0; + end = (token->type == OP_DUP_QUESTION) ? 1 : -1; + } + + fetch_token (token, regexp, syntax); + + if (__glibc_unlikely (elem == NULL)) + return NULL; + if (__glibc_unlikely (start == 0 && end == 0)) + { + postorder (elem, free_tree, NULL); + return NULL; + } + + /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}". */ + if (__glibc_unlikely (start > 0)) + { + tree = elem; + for (i = 2; i <= start; ++i) + { + elem = duplicate_tree (elem, dfa); + tree = create_tree (dfa, tree, elem, CONCAT); + if (__glibc_unlikely (elem == NULL || tree == NULL)) + goto parse_dup_op_espace; + } + + if (start == end) + return tree; + + /* Duplicate ELEM before it is marked optional. */ + elem = duplicate_tree (elem, dfa); + if (__glibc_unlikely (elem == NULL)) + goto parse_dup_op_espace; + old_tree = tree; + } + else + old_tree = NULL; + + if (elem->token.type == SUBEXP) + { + uintptr_t subidx = elem->token.opr.idx; + postorder (elem, mark_opt_subexp, (void *) subidx); + } + + tree = create_tree (dfa, elem, NULL, + (end == -1 ? OP_DUP_ASTERISK : OP_ALT)); + if (__glibc_unlikely (tree == NULL)) + goto parse_dup_op_espace; + + /* This loop is actually executed only when end != -1, + to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?... We have + already created the start+1-th copy. */ + if (TYPE_SIGNED (Idx) || end != -1) + for (i = start + 2; i <= end; ++i) + { + elem = duplicate_tree (elem, dfa); + tree = create_tree (dfa, tree, elem, CONCAT); + if (__glibc_unlikely (elem == NULL || tree == NULL)) + goto parse_dup_op_espace; + + tree = create_tree (dfa, tree, NULL, OP_ALT); + if (__glibc_unlikely (tree == NULL)) + goto parse_dup_op_espace; + } + + if (old_tree) + tree = create_tree (dfa, old_tree, tree, CONCAT); + + return tree; + + parse_dup_op_espace: + *err = REG_ESPACE; + return NULL; +} + +/* Size of the names for collating symbol/equivalence_class/character_class. + I'm not sure, but maybe enough. */ +#define BRACKET_NAME_BUF_SIZE 32 + +#ifndef _LIBC + +# ifdef RE_ENABLE_I18N +/* Convert the byte B to the corresponding wide character. In a + unibyte locale, treat B as itself. In a multibyte locale, return + WEOF if B is an encoding error. */ +static wint_t +parse_byte (unsigned char b, re_charset_t *mbcset) +{ + return mbcset == NULL ? b : __btowc (b); +} +# endif + + /* Local function for parse_bracket_exp only used in case of NOT _LIBC. + Build the range expression which starts from START_ELEM, and ends + at END_ELEM. The result are written to MBCSET and SBCSET. + RANGE_ALLOC is the allocated size of mbcset->range_starts, and + mbcset->range_ends, is a pointer argument since we may + update it. */ + +static reg_errcode_t +# ifdef RE_ENABLE_I18N +build_range_exp (const reg_syntax_t syntax, + bitset_t sbcset, + re_charset_t *mbcset, + Idx *range_alloc, + const bracket_elem_t *start_elem, + const bracket_elem_t *end_elem) +# else /* not RE_ENABLE_I18N */ +build_range_exp (const reg_syntax_t syntax, + bitset_t sbcset, + const bracket_elem_t *start_elem, + const bracket_elem_t *end_elem) +# endif /* not RE_ENABLE_I18N */ +{ + unsigned int start_ch, end_ch; + /* Equivalence Classes and Character Classes can't be a range start/end. */ + if (__glibc_unlikely (start_elem->type == EQUIV_CLASS + || start_elem->type == CHAR_CLASS + || end_elem->type == EQUIV_CLASS + || end_elem->type == CHAR_CLASS)) + return REG_ERANGE; + + /* We can handle no multi character collating elements without libc + support. */ + if (__glibc_unlikely ((start_elem->type == COLL_SYM + && strlen ((char *) start_elem->opr.name) > 1) + || (end_elem->type == COLL_SYM + && strlen ((char *) end_elem->opr.name) > 1))) + return REG_ECOLLATE; + +# ifdef RE_ENABLE_I18N + { + wchar_t wc; + wint_t start_wc; + wint_t end_wc; + + start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch + : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] + : 0)); + end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch + : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] + : 0)); + start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) + ? parse_byte (start_ch, mbcset) : start_elem->opr.wch); + end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) + ? parse_byte (end_ch, mbcset) : end_elem->opr.wch); + if (start_wc == WEOF || end_wc == WEOF) + return REG_ECOLLATE; + else if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES) + && start_wc > end_wc)) + return REG_ERANGE; + + /* Got valid collation sequence values, add them as a new entry. + However, for !_LIBC we have no collation elements: if the + character set is single byte, the single byte character set + that we build below suffices. parse_bracket_exp passes + no MBCSET if dfa->mb_cur_max == 1. */ + if (mbcset) + { + /* Check the space of the arrays. */ + if (__glibc_unlikely (*range_alloc == mbcset->nranges)) + { + /* There is not enough space, need realloc. */ + wchar_t *new_array_start, *new_array_end; + Idx new_nranges; + + /* +1 in case of mbcset->nranges is 0. */ + new_nranges = 2 * mbcset->nranges + 1; + /* Use realloc since mbcset->range_starts and mbcset->range_ends + are NULL if *range_alloc == 0. */ + new_array_start = re_realloc (mbcset->range_starts, wchar_t, + new_nranges); + new_array_end = re_realloc (mbcset->range_ends, wchar_t, + new_nranges); + + if (__glibc_unlikely (new_array_start == NULL + || new_array_end == NULL)) + { + re_free (new_array_start); + re_free (new_array_end); + return REG_ESPACE; + } + + mbcset->range_starts = new_array_start; + mbcset->range_ends = new_array_end; + *range_alloc = new_nranges; + } + + mbcset->range_starts[mbcset->nranges] = start_wc; + mbcset->range_ends[mbcset->nranges++] = end_wc; + } + + /* Build the table for single byte characters. */ + for (wc = 0; wc < SBC_MAX; ++wc) + { + if (start_wc <= wc && wc <= end_wc) + bitset_set (sbcset, wc); + } + } +# else /* not RE_ENABLE_I18N */ + { + unsigned int ch; + start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch + : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] + : 0)); + end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch + : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] + : 0)); + if (start_ch > end_ch) + return REG_ERANGE; + /* Build the table for single byte characters. */ + for (ch = 0; ch < SBC_MAX; ++ch) + if (start_ch <= ch && ch <= end_ch) + bitset_set (sbcset, ch); + } +# endif /* not RE_ENABLE_I18N */ + return REG_NOERROR; +} +#endif /* not _LIBC */ + +#ifndef _LIBC +/* Helper function for parse_bracket_exp only used in case of NOT _LIBC.. + Build the collating element which is represented by NAME. + The result are written to MBCSET and SBCSET. + COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a + pointer argument since we may update it. */ + +static reg_errcode_t +# ifdef RE_ENABLE_I18N +build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, + Idx *coll_sym_alloc, const unsigned char *name) +# else /* not RE_ENABLE_I18N */ +build_collating_symbol (bitset_t sbcset, const unsigned char *name) +# endif /* not RE_ENABLE_I18N */ +{ + size_t name_len = strlen ((const char *) name); + if (__glibc_unlikely (name_len != 1)) + return REG_ECOLLATE; + else + { + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } +} +#endif /* not _LIBC */ + +/* This function parse bracket expression like "[abc]", "[a-c]", + "[[.a-a.]]" etc. */ + +static bin_tree_t * +parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + reg_syntax_t syntax, reg_errcode_t *err) +{ +#ifdef _LIBC + const unsigned char *collseqmb; + const char *collseqwc; + uint32_t nrules; + int32_t table_size; + const int32_t *symb_table; + const unsigned char *extra; + + /* Local function for parse_bracket_exp used in _LIBC environment. + Seek the collating symbol entry corresponding to NAME. + Return the index of the symbol in the SYMB_TABLE, + or -1 if not found. */ + + auto inline int32_t + __attribute__ ((always_inline)) + seek_collating_symbol_entry (const unsigned char *name, size_t name_len) + { + int32_t elem; + + for (elem = 0; elem < table_size; elem++) + if (symb_table[2 * elem] != 0) + { + int32_t idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + if (/* Compare the length of the name. */ + name_len == extra[idx] + /* Compare the name. */ + && memcmp (name, &extra[idx + 1], name_len) == 0) + /* Yep, this is the entry. */ + return elem; + } + return -1; + } + + /* Local function for parse_bracket_exp used in _LIBC environment. + Look up the collation sequence value of BR_ELEM. + Return the value if succeeded, UINT_MAX otherwise. */ + + auto inline unsigned int + __attribute__ ((always_inline)) + lookup_collation_sequence_value (bracket_elem_t *br_elem) + { + if (br_elem->type == SB_CHAR) + { + /* + if (MB_CUR_MAX == 1) + */ + if (nrules == 0) + return collseqmb[br_elem->opr.ch]; + else + { + wint_t wc = __btowc (br_elem->opr.ch); + return __collseq_table_lookup (collseqwc, wc); + } + } + else if (br_elem->type == MB_CHAR) + { + if (nrules != 0) + return __collseq_table_lookup (collseqwc, br_elem->opr.wch); + } + else if (br_elem->type == COLL_SYM) + { + size_t sym_name_len = strlen ((char *) br_elem->opr.name); + if (nrules != 0) + { + int32_t elem, idx; + elem = seek_collating_symbol_entry (br_elem->opr.name, + sym_name_len); + if (elem != -1) + { + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + /* Skip the byte sequence of the collating element. */ + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + /* Skip the multibyte collation sequence value. */ + idx += sizeof (unsigned int); + /* Skip the wide char sequence of the collating element. */ + idx += sizeof (unsigned int) * + (1 + *(unsigned int *) (extra + idx)); + /* Return the collation sequence value. */ + return *(unsigned int *) (extra + idx); + } + else if (sym_name_len == 1) + { + /* No valid character. Match it as a single byte + character. */ + return collseqmb[br_elem->opr.name[0]]; + } + } + else if (sym_name_len == 1) + return collseqmb[br_elem->opr.name[0]]; + } + return UINT_MAX; + } + + /* Local function for parse_bracket_exp used in _LIBC environment. + Build the range expression which starts from START_ELEM, and ends + at END_ELEM. The result are written to MBCSET and SBCSET. + RANGE_ALLOC is the allocated size of mbcset->range_starts, and + mbcset->range_ends, is a pointer argument since we may + update it. */ + + auto inline reg_errcode_t + __attribute__ ((always_inline)) + build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc, + bracket_elem_t *start_elem, bracket_elem_t *end_elem) + { + unsigned int ch; + uint32_t start_collseq; + uint32_t end_collseq; + + /* Equivalence Classes and Character Classes can't be a range + start/end. */ + if (__glibc_unlikely (start_elem->type == EQUIV_CLASS + || start_elem->type == CHAR_CLASS + || end_elem->type == EQUIV_CLASS + || end_elem->type == CHAR_CLASS)) + return REG_ERANGE; + + /* FIXME: Implement rational ranges here, too. */ + start_collseq = lookup_collation_sequence_value (start_elem); + end_collseq = lookup_collation_sequence_value (end_elem); + /* Check start/end collation sequence values. */ + if (__glibc_unlikely (start_collseq == UINT_MAX + || end_collseq == UINT_MAX)) + return REG_ECOLLATE; + if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES) + && start_collseq > end_collseq)) + return REG_ERANGE; + + /* Got valid collation sequence values, add them as a new entry. + However, if we have no collation elements, and the character set + is single byte, the single byte character set that we + build below suffices. */ + if (nrules > 0 || dfa->mb_cur_max > 1) + { + /* Check the space of the arrays. */ + if (__glibc_unlikely (*range_alloc == mbcset->nranges)) + { + /* There is not enough space, need realloc. */ + uint32_t *new_array_start; + uint32_t *new_array_end; + Idx new_nranges; + + /* +1 in case of mbcset->nranges is 0. */ + new_nranges = 2 * mbcset->nranges + 1; + new_array_start = re_realloc (mbcset->range_starts, uint32_t, + new_nranges); + new_array_end = re_realloc (mbcset->range_ends, uint32_t, + new_nranges); + + if (__glibc_unlikely (new_array_start == NULL + || new_array_end == NULL)) + return REG_ESPACE; + + mbcset->range_starts = new_array_start; + mbcset->range_ends = new_array_end; + *range_alloc = new_nranges; + } + + mbcset->range_starts[mbcset->nranges] = start_collseq; + mbcset->range_ends[mbcset->nranges++] = end_collseq; + } + + /* Build the table for single byte characters. */ + for (ch = 0; ch < SBC_MAX; ch++) + { + uint32_t ch_collseq; + /* + if (MB_CUR_MAX == 1) + */ + if (nrules == 0) + ch_collseq = collseqmb[ch]; + else + ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); + if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) + bitset_set (sbcset, ch); + } + return REG_NOERROR; + } + + /* Local function for parse_bracket_exp used in _LIBC environment. + Build the collating element which is represented by NAME. + The result are written to MBCSET and SBCSET. + COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a + pointer argument since we may update it. */ + + auto inline reg_errcode_t + __attribute__ ((always_inline)) + build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, + Idx *coll_sym_alloc, const unsigned char *name) + { + int32_t elem, idx; + size_t name_len = strlen ((const char *) name); + if (nrules != 0) + { + elem = seek_collating_symbol_entry (name, name_len); + if (elem != -1) + { + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + } + else if (name_len == 1) + { + /* No valid character, treat it as a normal + character. */ + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } + else + return REG_ECOLLATE; + + /* Got valid collation sequence, add it as a new entry. */ + /* Check the space of the arrays. */ + if (__glibc_unlikely (*coll_sym_alloc == mbcset->ncoll_syms)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->ncoll_syms is 0. */ + Idx new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; + /* Use realloc since mbcset->coll_syms is NULL + if *alloc == 0. */ + int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, + new_coll_sym_alloc); + if (__glibc_unlikely (new_coll_syms == NULL)) + return REG_ESPACE; + mbcset->coll_syms = new_coll_syms; + *coll_sym_alloc = new_coll_sym_alloc; + } + mbcset->coll_syms[mbcset->ncoll_syms++] = idx; + return REG_NOERROR; + } + else + { + if (__glibc_unlikely (name_len != 1)) + return REG_ECOLLATE; + else + { + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } + } + } +#endif + + re_token_t br_token; + re_bitset_ptr_t sbcset; +#ifdef RE_ENABLE_I18N + re_charset_t *mbcset; + Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; + Idx equiv_class_alloc = 0, char_class_alloc = 0; +#endif /* not RE_ENABLE_I18N */ + bool non_match = false; + bin_tree_t *work_tree; + int token_len; + bool first_round = true; +#ifdef _LIBC + collseqmb = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules) + { + /* + if (MB_CUR_MAX > 1) + */ + collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); + table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + } +#endif + sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); +#ifdef RE_ENABLE_I18N + mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); +#endif /* RE_ENABLE_I18N */ +#ifdef RE_ENABLE_I18N + if (__glibc_unlikely (sbcset == NULL || mbcset == NULL)) +#else + if (__glibc_unlikely (sbcset == NULL)) +#endif /* RE_ENABLE_I18N */ + { + re_free (sbcset); +#ifdef RE_ENABLE_I18N + re_free (mbcset); +#endif + *err = REG_ESPACE; + return NULL; + } + + token_len = peek_token_bracket (token, regexp, syntax); + if (__glibc_unlikely (token->type == END_OF_RE)) + { + *err = REG_BADPAT; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_NON_MATCH_LIST) + { +#ifdef RE_ENABLE_I18N + mbcset->non_match = 1; +#endif /* not RE_ENABLE_I18N */ + non_match = true; + if (syntax & RE_HAT_LISTS_NOT_NEWLINE) + bitset_set (sbcset, '\n'); + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + token_len = peek_token_bracket (token, regexp, syntax); + if (__glibc_unlikely (token->type == END_OF_RE)) + { + *err = REG_BADPAT; + goto parse_bracket_exp_free_return; + } + } + + /* We treat the first ']' as a normal character. */ + if (token->type == OP_CLOSE_BRACKET) + token->type = CHARACTER; + + while (1) + { + bracket_elem_t start_elem, end_elem; + unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; + unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; + reg_errcode_t ret; + int token_len2 = 0; + bool is_range_exp = false; + re_token_t token2; + + start_elem.opr.name = start_name_buf; + start_elem.type = COLL_SYM; + ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, + syntax, first_round); + if (__glibc_unlikely (ret != REG_NOERROR)) + { + *err = ret; + goto parse_bracket_exp_free_return; + } + first_round = false; + + /* Get information about the next token. We need it in any case. */ + token_len = peek_token_bracket (token, regexp, syntax); + + /* Do not check for ranges if we know they are not allowed. */ + if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) + { + if (__glibc_unlikely (token->type == END_OF_RE)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_CHARSET_RANGE) + { + re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ + token_len2 = peek_token_bracket (&token2, regexp, syntax); + if (__glibc_unlikely (token2.type == END_OF_RE)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token2.type == OP_CLOSE_BRACKET) + { + /* We treat the last '-' as a normal character. */ + re_string_skip_bytes (regexp, -token_len); + token->type = CHARACTER; + } + else + is_range_exp = true; + } + } + + if (is_range_exp == true) + { + end_elem.opr.name = end_name_buf; + end_elem.type = COLL_SYM; + ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, + dfa, syntax, true); + if (__glibc_unlikely (ret != REG_NOERROR)) + { + *err = ret; + goto parse_bracket_exp_free_return; + } + + token_len = peek_token_bracket (token, regexp, syntax); + +#ifdef _LIBC + *err = build_range_exp (sbcset, mbcset, &range_alloc, + &start_elem, &end_elem); +#else +# ifdef RE_ENABLE_I18N + *err = build_range_exp (syntax, sbcset, + dfa->mb_cur_max > 1 ? mbcset : NULL, + &range_alloc, &start_elem, &end_elem); +# else + *err = build_range_exp (syntax, sbcset, &start_elem, &end_elem); +# endif +#endif /* RE_ENABLE_I18N */ + if (__glibc_unlikely (*err != REG_NOERROR)) + goto parse_bracket_exp_free_return; + } + else + { + switch (start_elem.type) + { + case SB_CHAR: + bitset_set (sbcset, start_elem.opr.ch); + break; +#ifdef RE_ENABLE_I18N + case MB_CHAR: + /* Check whether the array has enough space. */ + if (__glibc_unlikely (mbchar_alloc == mbcset->nmbchars)) + { + wchar_t *new_mbchars; + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nmbchars is 0. */ + mbchar_alloc = 2 * mbcset->nmbchars + 1; + /* Use realloc since array is NULL if *alloc == 0. */ + new_mbchars = re_realloc (mbcset->mbchars, wchar_t, + mbchar_alloc); + if (__glibc_unlikely (new_mbchars == NULL)) + goto parse_bracket_exp_espace; + mbcset->mbchars = new_mbchars; + } + mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; + break; +#endif /* RE_ENABLE_I18N */ + case EQUIV_CLASS: + *err = build_equiv_class (sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &equiv_class_alloc, +#endif /* RE_ENABLE_I18N */ + start_elem.opr.name); + if (__glibc_unlikely (*err != REG_NOERROR)) + goto parse_bracket_exp_free_return; + break; + case COLL_SYM: + *err = build_collating_symbol (sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &coll_sym_alloc, +#endif /* RE_ENABLE_I18N */ + start_elem.opr.name); + if (__glibc_unlikely (*err != REG_NOERROR)) + goto parse_bracket_exp_free_return; + break; + case CHAR_CLASS: + *err = build_charclass (regexp->trans, sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &char_class_alloc, +#endif /* RE_ENABLE_I18N */ + (const char *) start_elem.opr.name, + syntax); + if (__glibc_unlikely (*err != REG_NOERROR)) + goto parse_bracket_exp_free_return; + break; + default: + assert (0); + break; + } + } + if (__glibc_unlikely (token->type == END_OF_RE)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_CLOSE_BRACKET) + break; + } + + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + + /* If it is non-matching list. */ + if (non_match) + bitset_not (sbcset); + +#ifdef RE_ENABLE_I18N + /* Ensure only single byte characters are set. */ + if (dfa->mb_cur_max > 1) + bitset_mask (sbcset, dfa->sb_char); + + if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes + || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes + || mbcset->non_match))) + { + bin_tree_t *mbc_tree; + int sbc_idx; + /* Build a tree for complex bracket. */ + dfa->has_mb_node = 1; + br_token.type = COMPLEX_BRACKET; + br_token.opr.mbcset = mbcset; + mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (__glibc_unlikely (mbc_tree == NULL)) + goto parse_bracket_exp_espace; + for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx) + if (sbcset[sbc_idx]) + break; + /* If there are no bits set in sbcset, there is no point + of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ + if (sbc_idx < BITSET_WORDS) + { + /* Build a tree for simple bracket. */ + br_token.type = SIMPLE_BRACKET; + br_token.opr.sbcset = sbcset; + work_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (__glibc_unlikely (work_tree == NULL)) + goto parse_bracket_exp_espace; + + /* Then join them by ALT node. */ + work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT); + if (__glibc_unlikely (work_tree == NULL)) + goto parse_bracket_exp_espace; + } + else + { + re_free (sbcset); + work_tree = mbc_tree; + } + } + else +#endif /* not RE_ENABLE_I18N */ + { +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif + /* Build a tree for simple bracket. */ + br_token.type = SIMPLE_BRACKET; + br_token.opr.sbcset = sbcset; + work_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (__glibc_unlikely (work_tree == NULL)) + goto parse_bracket_exp_espace; + } + return work_tree; + + parse_bracket_exp_espace: + *err = REG_ESPACE; + parse_bracket_exp_free_return: + re_free (sbcset); +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif /* RE_ENABLE_I18N */ + return NULL; +} + +/* Parse an element in the bracket expression. */ + +static reg_errcode_t +parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, + re_token_t *token, int token_len, re_dfa_t *dfa, + reg_syntax_t syntax, bool accept_hyphen) +{ +#ifdef RE_ENABLE_I18N + int cur_char_size; + cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); + if (cur_char_size > 1) + { + elem->type = MB_CHAR; + elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); + re_string_skip_bytes (regexp, cur_char_size); + return REG_NOERROR; + } +#endif /* RE_ENABLE_I18N */ + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS + || token->type == OP_OPEN_EQUIV_CLASS) + return parse_bracket_symbol (elem, regexp, token); + if (__glibc_unlikely (token->type == OP_CHARSET_RANGE) && !accept_hyphen) + { + /* A '-' must only appear as anything but a range indicator before + the closing bracket. Everything else is an error. */ + re_token_t token2; + (void) peek_token_bracket (&token2, regexp, syntax); + if (token2.type != OP_CLOSE_BRACKET) + /* The actual error value is not standardized since this whole + case is undefined. But ERANGE makes good sense. */ + return REG_ERANGE; + } + elem->type = SB_CHAR; + elem->opr.ch = token->opr.c; + return REG_NOERROR; +} + +/* Parse a bracket symbol in the bracket expression. Bracket symbols are + such as [:<character_class>:], [.<collating_element>.], and + [=<equivalent_class>=]. */ + +static reg_errcode_t +parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, + re_token_t *token) +{ + unsigned char ch, delim = token->opr.c; + int i = 0; + if (re_string_eoi(regexp)) + return REG_EBRACK; + for (;; ++i) + { + if (i >= BRACKET_NAME_BUF_SIZE) + return REG_EBRACK; + if (token->type == OP_OPEN_CHAR_CLASS) + ch = re_string_fetch_byte_case (regexp); + else + ch = re_string_fetch_byte (regexp); + if (re_string_eoi(regexp)) + return REG_EBRACK; + if (ch == delim && re_string_peek_byte (regexp, 0) == ']') + break; + elem->opr.name[i] = ch; + } + re_string_skip_bytes (regexp, 1); + elem->opr.name[i] = '\0'; + switch (token->type) + { + case OP_OPEN_COLL_ELEM: + elem->type = COLL_SYM; + break; + case OP_OPEN_EQUIV_CLASS: + elem->type = EQUIV_CLASS; + break; + case OP_OPEN_CHAR_CLASS: + elem->type = CHAR_CLASS; + break; + default: + break; + } + return REG_NOERROR; +} + + /* Helper function for parse_bracket_exp. + Build the equivalence class which is represented by NAME. + The result are written to MBCSET and SBCSET. + EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, + is a pointer argument since we may update it. */ + +static reg_errcode_t +#ifdef RE_ENABLE_I18N +build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, + Idx *equiv_class_alloc, const unsigned char *name) +#else /* not RE_ENABLE_I18N */ +build_equiv_class (bitset_t sbcset, const unsigned char *name) +#endif /* not RE_ENABLE_I18N */ +{ +#ifdef _LIBC + uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { + const int32_t *table, *indirect; + const unsigned char *weights, *extra, *cp; + unsigned char char_buf[2]; + int32_t idx1, idx2; + unsigned int ch; + size_t len; + /* Calculate the index for equivalence class. */ + cp = name; + table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_INDIRECTMB); + idx1 = findidx (table, indirect, extra, &cp, -1); + if (__glibc_unlikely (idx1 == 0 || *cp != '\0')) + /* This isn't a valid character. */ + return REG_ECOLLATE; + + /* Build single byte matching table for this equivalence class. */ + len = weights[idx1 & 0xffffff]; + for (ch = 0; ch < SBC_MAX; ++ch) + { + char_buf[0] = ch; + cp = char_buf; + idx2 = findidx (table, indirect, extra, &cp, 1); +/* + idx2 = table[ch]; +*/ + if (idx2 == 0) + /* This isn't a valid character. */ + continue; + /* Compare only if the length matches and the collation rule + index is the same. */ + if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24) + && memcmp (weights + (idx1 & 0xffffff) + 1, + weights + (idx2 & 0xffffff) + 1, len) == 0) + bitset_set (sbcset, ch); + } + /* Check whether the array has enough space. */ + if (__glibc_unlikely (*equiv_class_alloc == mbcset->nequiv_classes)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nequiv_classes is 0. */ + Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; + /* Use realloc since the array is NULL if *alloc == 0. */ + int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, + int32_t, + new_equiv_class_alloc); + if (__glibc_unlikely (new_equiv_classes == NULL)) + return REG_ESPACE; + mbcset->equiv_classes = new_equiv_classes; + *equiv_class_alloc = new_equiv_class_alloc; + } + mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; + } + else +#endif /* _LIBC */ + { + if (__glibc_unlikely (strlen ((const char *) name) != 1)) + return REG_ECOLLATE; + bitset_set (sbcset, *name); + } + return REG_NOERROR; +} + + /* Helper function for parse_bracket_exp. + Build the character class which is represented by NAME. + The result are written to MBCSET and SBCSET. + CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, + is a pointer argument since we may update it. */ + +static reg_errcode_t +#ifdef RE_ENABLE_I18N +build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, + re_charset_t *mbcset, Idx *char_class_alloc, + const char *class_name, reg_syntax_t syntax) +#else /* not RE_ENABLE_I18N */ +build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, + const char *class_name, reg_syntax_t syntax) +#endif /* not RE_ENABLE_I18N */ +{ + int i; + const char *name = class_name; + + /* In case of REG_ICASE "upper" and "lower" match the both of + upper and lower cases. */ + if ((syntax & RE_ICASE) + && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) + name = "alpha"; + +#ifdef RE_ENABLE_I18N + /* Check the space of the arrays. */ + if (__glibc_unlikely (*char_class_alloc == mbcset->nchar_classes)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nchar_classes is 0. */ + Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1; + /* Use realloc since array is NULL if *alloc == 0. */ + wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, + new_char_class_alloc); + if (__glibc_unlikely (new_char_classes == NULL)) + return REG_ESPACE; + mbcset->char_classes = new_char_classes; + *char_class_alloc = new_char_class_alloc; + } + mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); +#endif /* RE_ENABLE_I18N */ + +#define BUILD_CHARCLASS_LOOP(ctype_func) \ + do { \ + if (__glibc_unlikely (trans != NULL)) \ + { \ + for (i = 0; i < SBC_MAX; ++i) \ + if (ctype_func (i)) \ + bitset_set (sbcset, trans[i]); \ + } \ + else \ + { \ + for (i = 0; i < SBC_MAX; ++i) \ + if (ctype_func (i)) \ + bitset_set (sbcset, i); \ + } \ + } while (0) + + if (strcmp (name, "alnum") == 0) + BUILD_CHARCLASS_LOOP (isalnum); + else if (strcmp (name, "cntrl") == 0) + BUILD_CHARCLASS_LOOP (iscntrl); + else if (strcmp (name, "lower") == 0) + BUILD_CHARCLASS_LOOP (islower); + else if (strcmp (name, "space") == 0) + BUILD_CHARCLASS_LOOP (isspace); + else if (strcmp (name, "alpha") == 0) + BUILD_CHARCLASS_LOOP (isalpha); + else if (strcmp (name, "digit") == 0) + BUILD_CHARCLASS_LOOP (isdigit); + else if (strcmp (name, "print") == 0) + BUILD_CHARCLASS_LOOP (isprint); + else if (strcmp (name, "upper") == 0) + BUILD_CHARCLASS_LOOP (isupper); + else if (strcmp (name, "blank") == 0) + BUILD_CHARCLASS_LOOP (isblank); + else if (strcmp (name, "graph") == 0) + BUILD_CHARCLASS_LOOP (isgraph); + else if (strcmp (name, "punct") == 0) + BUILD_CHARCLASS_LOOP (ispunct); + else if (strcmp (name, "xdigit") == 0) + BUILD_CHARCLASS_LOOP (isxdigit); + else + return REG_ECTYPE; + + return REG_NOERROR; +} + +static bin_tree_t * +build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, + const char *class_name, + const char *extra, bool non_match, + reg_errcode_t *err) +{ + re_bitset_ptr_t sbcset; +#ifdef RE_ENABLE_I18N + re_charset_t *mbcset; + Idx alloc = 0; +#endif /* not RE_ENABLE_I18N */ + reg_errcode_t ret; + re_token_t br_token = {0}; + bin_tree_t *tree; + + sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); + if (__glibc_unlikely (sbcset == NULL)) + { + *err = REG_ESPACE; + return NULL; + } +#ifdef RE_ENABLE_I18N + mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); + if (__glibc_unlikely (mbcset == NULL)) + { + re_free (sbcset); + *err = REG_ESPACE; + return NULL; + } + mbcset->non_match = non_match; +#endif /* RE_ENABLE_I18N */ + + /* We don't care the syntax in this case. */ + ret = build_charclass (trans, sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &alloc, +#endif /* RE_ENABLE_I18N */ + class_name, 0); + + if (__glibc_unlikely (ret != REG_NOERROR)) + { + re_free (sbcset); +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif /* RE_ENABLE_I18N */ + *err = ret; + return NULL; + } + /* \w match '_' also. */ + for (; *extra; extra++) + bitset_set (sbcset, *extra); + + /* If it is non-matching list. */ + if (non_match) + bitset_not (sbcset); + +#ifdef RE_ENABLE_I18N + /* Ensure only single byte characters are set. */ + if (dfa->mb_cur_max > 1) + bitset_mask (sbcset, dfa->sb_char); +#endif + + /* Build a tree for simple bracket. */ +#if defined GCC_LINT || defined lint + memset (&br_token, 0, sizeof br_token); +#endif + br_token.type = SIMPLE_BRACKET; + br_token.opr.sbcset = sbcset; + tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (__glibc_unlikely (tree == NULL)) + goto build_word_op_espace; + +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + bin_tree_t *mbc_tree; + /* Build a tree for complex bracket. */ + br_token.type = COMPLEX_BRACKET; + br_token.opr.mbcset = mbcset; + dfa->has_mb_node = 1; + mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (__glibc_unlikely (mbc_tree == NULL)) + goto build_word_op_espace; + /* Then join them by ALT node. */ + tree = create_tree (dfa, tree, mbc_tree, OP_ALT); + if (__glibc_likely (mbc_tree != NULL)) + return tree; + } + else + { + free_charset (mbcset); + return tree; + } +#else /* not RE_ENABLE_I18N */ + return tree; +#endif /* not RE_ENABLE_I18N */ + + build_word_op_espace: + re_free (sbcset); +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif /* RE_ENABLE_I18N */ + *err = REG_ESPACE; + return NULL; +} + +/* This is intended for the expressions like "a{1,3}". + Fetch a number from 'input', and return the number. + Return -1 if the number field is empty like "{,1}". + Return RE_DUP_MAX + 1 if the number field is too large. + Return -2 if an error occurred. */ + +static Idx +fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) +{ + Idx num = -1; + unsigned char c; + while (1) + { + fetch_token (token, input, syntax); + c = token->opr.c; + if (__glibc_unlikely (token->type == END_OF_RE)) + return -2; + if (token->type == OP_CLOSE_DUP_NUM || c == ',') + break; + num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2) + ? -2 + : num == -1 + ? c - '0' + : MIN (RE_DUP_MAX + 1, num * 10 + c - '0')); + } + return num; +} + +#ifdef RE_ENABLE_I18N +static void +free_charset (re_charset_t *cset) +{ + re_free (cset->mbchars); +# ifdef _LIBC + re_free (cset->coll_syms); + re_free (cset->equiv_classes); +# endif + re_free (cset->range_starts); + re_free (cset->range_ends); + re_free (cset->char_classes); + re_free (cset); +} +#endif /* RE_ENABLE_I18N */ + +/* Functions for binary tree operation. */ + +/* Create a tree node. */ + +static bin_tree_t * +create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, + re_token_type_t type) +{ + re_token_t t = { .type = type }; + return create_token_tree (dfa, left, right, &t); +} + +static bin_tree_t * +create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, + const re_token_t *token) +{ + bin_tree_t *tree; + if (__glibc_unlikely (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE)) + { + bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); + + if (storage == NULL) + return NULL; + storage->next = dfa->str_tree_storage; + dfa->str_tree_storage = storage; + dfa->str_tree_storage_idx = 0; + } + tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; + + tree->parent = NULL; + tree->left = left; + tree->right = right; + tree->token = *token; + tree->token.duplicated = 0; + tree->token.opt_subexp = 0; + tree->first = NULL; + tree->next = NULL; + tree->node_idx = -1; + + if (left != NULL) + left->parent = tree; + if (right != NULL) + right->parent = tree; + return tree; +} + +/* Mark the tree SRC as an optional subexpression. + To be called from preorder or postorder. */ + +static reg_errcode_t +mark_opt_subexp (void *extra, bin_tree_t *node) +{ + Idx idx = (uintptr_t) extra; + if (node->token.type == SUBEXP && node->token.opr.idx == idx) + node->token.opt_subexp = 1; + + return REG_NOERROR; +} + +/* Free the allocated memory inside NODE. */ + +static void +free_token (re_token_t *node) +{ +#ifdef RE_ENABLE_I18N + if (node->type == COMPLEX_BRACKET && node->duplicated == 0) + free_charset (node->opr.mbcset); + else +#endif /* RE_ENABLE_I18N */ + if (node->type == SIMPLE_BRACKET && node->duplicated == 0) + re_free (node->opr.sbcset); +} + +/* Worker function for tree walking. Free the allocated memory inside NODE + and its children. */ + +static reg_errcode_t +free_tree (void *extra, bin_tree_t *node) +{ + free_token (&node->token); + return REG_NOERROR; +} + + +/* Duplicate the node SRC, and return new node. This is a preorder + visit similar to the one implemented by the generic visitor, but + we need more infrastructure to maintain two parallel trees --- so, + it's easier to duplicate. */ + +static bin_tree_t * +duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa) +{ + const bin_tree_t *node; + bin_tree_t *dup_root; + bin_tree_t **p_new = &dup_root, *dup_node = root->parent; + + for (node = root; ; ) + { + /* Create a new tree and link it back to the current parent. */ + *p_new = create_token_tree (dfa, NULL, NULL, &node->token); + if (*p_new == NULL) + return NULL; + (*p_new)->parent = dup_node; + (*p_new)->token.duplicated = 1; + dup_node = *p_new; + + /* Go to the left node, or up and to the right. */ + if (node->left) + { + node = node->left; + p_new = &dup_node->left; + } + else + { + const bin_tree_t *prev = NULL; + while (node->right == prev || node->right == NULL) + { + prev = node; + node = node->parent; + dup_node = dup_node->parent; + if (!node) + return dup_root; + } + node = node->right; + p_new = &dup_node->right; + } + } +} diff --git a/grub-core/lib/gnulib/regex.c b/grub-core/lib/gnulib/regex.c new file mode 100644 index 0000000..eab7a48 --- /dev/null +++ b/grub-core/lib/gnulib/regex.c @@ -0,0 +1,81 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _LIBC +# include <libc-config.h> + +# if __GNUC_PREREQ (4, 6) +# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" +# endif +# if __GNUC_PREREQ (4, 3) +# pragma GCC diagnostic ignored "-Wold-style-definition" +# pragma GCC diagnostic ignored "-Wtype-limits" +# endif +#endif + +/* Make sure no one compiles this code with a C++ compiler. */ +#if defined __cplusplus && defined _LIBC +# error "This is C code, use a C compiler" +#endif + +#ifdef _LIBC +/* We have to keep the namespace clean. */ +# define regfree(preg) __regfree (preg) +# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) +# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) +# define regerror(errcode, preg, errbuf, errbuf_size) \ + __regerror(errcode, preg, errbuf, errbuf_size) +# define re_set_registers(bu, re, nu, st, en) \ + __re_set_registers (bu, re, nu, st, en) +# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ + __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) +# define re_match(bufp, string, size, pos, regs) \ + __re_match (bufp, string, size, pos, regs) +# define re_search(bufp, string, size, startpos, range, regs) \ + __re_search (bufp, string, size, startpos, range, regs) +# define re_compile_pattern(pattern, length, bufp) \ + __re_compile_pattern (pattern, length, bufp) +# define re_set_syntax(syntax) __re_set_syntax (syntax) +# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ + __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) +# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) + +# include "../locale/localeinfo.h" +#endif + +/* On some systems, limits.h sets RE_DUP_MAX to a lower value than + GNU regex allows. Include it before <regex.h>, which correctly + #undefs RE_DUP_MAX and sets it to the right value. */ +#include <limits.h> + +#include <regex.h> +#include "regex_internal.h" + +#include "regex_internal.c" +#include "regcomp.c" +#include "regexec.c" + +/* Binary backward compatibility. */ +#if _LIBC +# include <shlib-compat.h> +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) +link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") +int re_max_failures = 2000; +# endif +#endif diff --git a/grub-core/lib/gnulib/regex.h b/grub-core/lib/gnulib/regex.h new file mode 100644 index 0000000..77ac1a5 --- /dev/null +++ b/grub-core/lib/gnulib/regex.h @@ -0,0 +1,658 @@ +/* Definitions for data structures and routines for the regular + expression library. + Copyright (C) 1985, 1989-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _REGEX_H +#define _REGEX_H 1 + +#include <sys/types.h> + +/* Allow the use in C++ code. */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Define __USE_GNU to declare GNU extensions that violate the + POSIX name space rules. */ +#ifdef _GNU_SOURCE +# define __USE_GNU 1 +#endif + +#ifdef _REGEX_LARGE_OFFSETS + +/* Use types and values that are wide enough to represent signed and + unsigned byte offsets in memory. This currently works only when + the regex code is used outside of the GNU C library; it is not yet + supported within glibc itself, and glibc users should not define + _REGEX_LARGE_OFFSETS. */ + +/* The type of object sizes. */ +typedef size_t __re_size_t; + +/* The type of object sizes, in places where the traditional code + uses unsigned long int. */ +typedef size_t __re_long_size_t; + +#else + +/* The traditional GNU regex implementation mishandles strings longer + than INT_MAX. */ +typedef unsigned int __re_size_t; +typedef unsigned long int __re_long_size_t; + +#endif + +/* The following two types have to be signed and unsigned integer type + wide enough to hold a value of a pointer. For most ANSI compilers + ptrdiff_t and size_t should be likely OK. Still size of these two + types is 2 for Microsoft C. Ugh... */ +typedef long int s_reg_t; +typedef unsigned long int active_reg_t; + +/* The following bits are used to determine the regexp syntax we + recognize. The set/not-set meanings are chosen so that Emacs syntax + remains the value 0. The bits are given in alphabetical order, and + the definitions shifted by one from the previous bit; thus, when we + add or remove a bit, only one other definition need change. */ +typedef unsigned long int reg_syntax_t; + +#ifdef __USE_GNU +/* If this bit is not set, then \ inside a bracket expression is literal. + If set, then such a \ quotes the following character. */ +# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) + +/* If this bit is not set, then + and ? are operators, and \+ and \? are + literals. + If set, then \+ and \? are operators and + and ? are literals. */ +# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) + +/* If this bit is set, then character classes are supported. They are: + [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], + [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. + If not set, then character classes are not supported. */ +# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) + +/* If this bit is set, then ^ and $ are always anchors (outside bracket + expressions, of course). + If this bit is not set, then it depends: + ^ is an anchor if it is at the beginning of a regular + expression or after an open-group or an alternation operator; + $ is an anchor if it is at the end of a regular expression, or + before a close-group or an alternation operator. + + This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because + POSIX draft 11.2 says that * etc. in leading positions is undefined. + We already implemented a previous draft which made those constructs + invalid, though, so we haven't changed the code back. */ +# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) + +/* If this bit is set, then special characters are always special + regardless of where they are in the pattern. + If this bit is not set, then special characters are special only in + some contexts; otherwise they are ordinary. Specifically, + * + ? and intervals are only special when not after the beginning, + open-group, or alternation operator. */ +# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) + +/* If this bit is set, then *, +, ?, and { cannot be first in an re or + immediately after an alternation or begin-group operator. */ +# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) + +/* If this bit is set, then . matches newline. + If not set, then it doesn't. */ +# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) + +/* If this bit is set, then . doesn't match NUL. + If not set, then it does. */ +# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) + +/* If this bit is set, nonmatching lists [^...] do not match newline. + If not set, they do. */ +# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) + +/* If this bit is set, either \{...\} or {...} defines an + interval, depending on RE_NO_BK_BRACES. + If not set, \{, \}, {, and } are literals. */ +# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) + +/* If this bit is set, +, ? and | aren't recognized as operators. + If not set, they are. */ +# define RE_LIMITED_OPS (RE_INTERVALS << 1) + +/* If this bit is set, newline is an alternation operator. + If not set, newline is literal. */ +# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) + +/* If this bit is set, then '{...}' defines an interval, and \{ and \} + are literals. + If not set, then '\{...\}' defines an interval. */ +# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) + +/* If this bit is set, (...) defines a group, and \( and \) are literals. + If not set, \(...\) defines a group, and ( and ) are literals. */ +# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) + +/* If this bit is set, then \<digit> matches <digit>. + If not set, then \<digit> is a back-reference. */ +# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) + +/* If this bit is set, then | is an alternation operator, and \| is literal. + If not set, then \| is an alternation operator, and | is literal. */ +# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) + +/* If this bit is set, then an ending range point collating higher + than the starting range point, as in [z-a], is invalid. + If not set, then when ending range point collates higher than the + starting range point, the range is ignored. */ +# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) + +/* If this bit is set, then an unmatched ) is ordinary. + If not set, then an unmatched ) is invalid. */ +# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) + +/* If this bit is set, succeed as soon as we match the whole pattern, + without further backtracking. */ +# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) + +/* If this bit is set, do not process the GNU regex operators. + If not set, then the GNU regex operators are recognized. */ +# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) + +/* If this bit is set, turn on internal regex debugging. + If not set, and debugging was on, turn it off. + This only works if regex.c is compiled -DDEBUG. + We define this bit always, so that all that's needed to turn on + debugging is to recompile regex.c; the calling code can always have + this bit set, and it won't affect anything in the normal case. */ +# define RE_DEBUG (RE_NO_GNU_OPS << 1) + +/* If this bit is set, a syntactically invalid interval is treated as + a string of ordinary characters. For example, the ERE 'a{1' is + treated as 'a\{1'. */ +# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) + +/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only + for ^, because it is difficult to scan the regex backwards to find + whether ^ should be special. */ +# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) + +/* If this bit is set, then \{ cannot be first in a regex or + immediately after an alternation, open-group or \} operator. */ +# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) + +/* If this bit is set, then no_sub will be set to 1 during + re_compile_pattern. */ +# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) +#endif + +/* This global variable defines the particular regexp syntax to use (for + some interfaces). When a regexp is compiled, the syntax used is + stored in the pattern buffer, so changing this does not affect + already-compiled regexps. */ +extern reg_syntax_t re_syntax_options; + +#ifdef __USE_GNU +/* Define combinations of the above bits for the standard possibilities. + (The [[[ comments delimit what gets put into the Texinfo file, so + don't delete them!) */ +/* [[[begin syntaxes]]] */ +# define RE_SYNTAX_EMACS 0 + +# define RE_SYNTAX_AWK \ + (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ + | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CHAR_CLASSES \ + | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) + +# define RE_SYNTAX_GNU_AWK \ + ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ + | RE_INVALID_INTERVAL_ORD) \ + & ~(RE_DOT_NOT_NULL | RE_CONTEXT_INDEP_OPS \ + | RE_CONTEXT_INVALID_OPS )) + +# define RE_SYNTAX_POSIX_AWK \ + (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ + | RE_INTERVALS | RE_NO_GNU_OPS \ + | RE_INVALID_INTERVAL_ORD) + +# define RE_SYNTAX_GREP \ + ((RE_SYNTAX_POSIX_BASIC | RE_NEWLINE_ALT) \ + & ~(RE_CONTEXT_INVALID_DUP | RE_DOT_NOT_NULL)) + +# define RE_SYNTAX_EGREP \ + ((RE_SYNTAX_POSIX_EXTENDED | RE_INVALID_INTERVAL_ORD | RE_NEWLINE_ALT) \ + & ~(RE_CONTEXT_INVALID_OPS | RE_DOT_NOT_NULL)) + +/* POSIX grep -E behavior is no longer incompatible with GNU. */ +# define RE_SYNTAX_POSIX_EGREP \ + RE_SYNTAX_EGREP + +/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ +# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC + +# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC + +/* Syntax bits common to both basic and extended POSIX regex syntax. */ +# define _RE_SYNTAX_POSIX_COMMON \ + (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ + | RE_INTERVALS | RE_NO_EMPTY_RANGES) + +# define RE_SYNTAX_POSIX_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) + +/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes + RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this + isn't minimal, since other operators, such as \`, aren't disabled. */ +# define RE_SYNTAX_POSIX_MINIMAL_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) + +# define RE_SYNTAX_POSIX_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is + removed and RE_NO_BK_REFS is added. */ +# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) +/* [[[end syntaxes]]] */ + +/* Maximum number of duplicates an interval can allow. POSIX-conforming + systems might define this in <limits.h>, but we want our + value, so remove any previous define. */ +# ifdef _REGEX_INCLUDE_LIMITS_H +# include <limits.h> +# endif +# ifdef RE_DUP_MAX +# undef RE_DUP_MAX +# endif + +/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored + the counter as a 2-byte signed integer. This is no longer true, so + RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to + ((SIZE_MAX - 9) / 10) if _REGEX_LARGE_OFFSETS is defined. + However, there would be a huge performance problem if someone + actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains + its historical value. */ +# define RE_DUP_MAX (0x7fff) +#endif + + +/* POSIX 'cflags' bits (i.e., information for 'regcomp'). */ + +/* If this bit is set, then use extended regular expression syntax. + If not set, then use basic regular expression syntax. */ +#define REG_EXTENDED 1 + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +#define REG_ICASE (1 << 1) + +/* If this bit is set, then anchors do not match at newline + characters in the string. + If not set, then anchors do match at newlines. */ +#define REG_NEWLINE (1 << 2) + +/* If this bit is set, then report only success or fail in regexec. + If not set, then returns differ between not matching and errors. */ +#define REG_NOSUB (1 << 3) + + +/* POSIX 'eflags' bits (i.e., information for regexec). */ + +/* If this bit is set, then the beginning-of-line operator doesn't match + the beginning of the string (presumably because it's not the + beginning of a line). + If not set, then the beginning-of-line operator does match the + beginning of the string. */ +#define REG_NOTBOL 1 + +/* Like REG_NOTBOL, except for the end-of-line. */ +#define REG_NOTEOL (1 << 1) + +/* Use PMATCH[0] to delimit the start and end of the search in the + buffer. */ +#define REG_STARTEND (1 << 2) + + +/* If any error codes are removed, changed, or added, update the + '__re_error_msgid' table in regcomp.c. */ + +typedef enum +{ + _REG_ENOSYS = -1, /* This will never happen for this implementation. */ + _REG_NOERROR = 0, /* Success. */ + _REG_NOMATCH, /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ + _REG_BADPAT, /* Invalid pattern. */ + _REG_ECOLLATE, /* Invalid collating element. */ + _REG_ECTYPE, /* Invalid character class name. */ + _REG_EESCAPE, /* Trailing backslash. */ + _REG_ESUBREG, /* Invalid back reference. */ + _REG_EBRACK, /* Unmatched left bracket. */ + _REG_EPAREN, /* Parenthesis imbalance. */ + _REG_EBRACE, /* Unmatched \{. */ + _REG_BADBR, /* Invalid contents of \{\}. */ + _REG_ERANGE, /* Invalid range end. */ + _REG_ESPACE, /* Ran out of memory. */ + _REG_BADRPT, /* No preceding re for repetition op. */ + + /* Error codes we've added. */ + _REG_EEND, /* Premature end. */ + _REG_ESIZE, /* Too large (e.g., repeat count too large). */ + _REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ +} reg_errcode_t; + +#if defined _XOPEN_SOURCE || defined __USE_XOPEN2K +# define REG_ENOSYS _REG_ENOSYS +#endif +#define REG_NOERROR _REG_NOERROR +#define REG_NOMATCH _REG_NOMATCH +#define REG_BADPAT _REG_BADPAT +#define REG_ECOLLATE _REG_ECOLLATE +#define REG_ECTYPE _REG_ECTYPE +#define REG_EESCAPE _REG_EESCAPE +#define REG_ESUBREG _REG_ESUBREG +#define REG_EBRACK _REG_EBRACK +#define REG_EPAREN _REG_EPAREN +#define REG_EBRACE _REG_EBRACE +#define REG_BADBR _REG_BADBR +#define REG_ERANGE _REG_ERANGE +#define REG_ESPACE _REG_ESPACE +#define REG_BADRPT _REG_BADRPT +#define REG_EEND _REG_EEND +#define REG_ESIZE _REG_ESIZE +#define REG_ERPAREN _REG_ERPAREN + +/* This data structure represents a compiled pattern. Before calling + the pattern compiler, the fields 'buffer', 'allocated', 'fastmap', + and 'translate' can be set. After the pattern has been compiled, + the fields 're_nsub', 'not_bol' and 'not_eol' are available. All + other fields are private to the regex routines. */ + +#ifndef RE_TRANSLATE_TYPE +# define __RE_TRANSLATE_TYPE unsigned char * +# ifdef __USE_GNU +# define RE_TRANSLATE_TYPE __RE_TRANSLATE_TYPE +# endif +#endif + +#ifdef __USE_GNU +# define __REPB_PREFIX(name) name +#else +# define __REPB_PREFIX(name) __##name +#endif + +struct re_pattern_buffer +{ + /* Space that holds the compiled pattern. The type + 'struct re_dfa_t' is private and is not declared here. */ + struct re_dfa_t *__REPB_PREFIX(buffer); + + /* Number of bytes to which 'buffer' points. */ + __re_long_size_t __REPB_PREFIX(allocated); + + /* Number of bytes actually used in 'buffer'. */ + __re_long_size_t __REPB_PREFIX(used); + + /* Syntax setting with which the pattern was compiled. */ + reg_syntax_t __REPB_PREFIX(syntax); + + /* Pointer to a fastmap, if any, otherwise zero. re_search uses the + fastmap, if there is one, to skip over impossible starting points + for matches. */ + char *__REPB_PREFIX(fastmap); + + /* Either a translate table to apply to all characters before + comparing them, or zero for no translation. The translation is + applied to a pattern when it is compiled and to a string when it + is matched. */ + __RE_TRANSLATE_TYPE __REPB_PREFIX(translate); + + /* Number of subexpressions found by the compiler. */ + size_t re_nsub; + + /* Zero if this pattern cannot match the empty string, one else. + Well, in truth it's used only in 're_search_2', to see whether or + not we should use the fastmap, so we don't set this absolutely + perfectly; see 're_compile_fastmap' (the "duplicate" case). */ + unsigned __REPB_PREFIX(can_be_null) : 1; + + /* If REGS_UNALLOCATED, allocate space in the 'regs' structure + for 'max (RE_NREGS, re_nsub + 1)' groups. + If REGS_REALLOCATE, reallocate space if necessary. + If REGS_FIXED, use what's there. */ +#ifdef __USE_GNU +# define REGS_UNALLOCATED 0 +# define REGS_REALLOCATE 1 +# define REGS_FIXED 2 +#endif + unsigned __REPB_PREFIX(regs_allocated) : 2; + + /* Set to zero when 're_compile_pattern' compiles a pattern; set to + one by 're_compile_fastmap' if it updates the fastmap. */ + unsigned __REPB_PREFIX(fastmap_accurate) : 1; + + /* If set, 're_match_2' does not return information about + subexpressions. */ + unsigned __REPB_PREFIX(no_sub) : 1; + + /* If set, a beginning-of-line anchor doesn't match at the beginning + of the string. */ + unsigned __REPB_PREFIX(not_bol) : 1; + + /* Similarly for an end-of-line anchor. */ + unsigned __REPB_PREFIX(not_eol) : 1; + + /* If true, an anchor at a newline matches. */ + unsigned __REPB_PREFIX(newline_anchor) : 1; +}; + +typedef struct re_pattern_buffer regex_t; + +/* Type for byte offsets within the string. POSIX mandates this. */ +#ifdef _REGEX_LARGE_OFFSETS +/* POSIX 1003.1-2008 requires that regoff_t be at least as wide as + ptrdiff_t and ssize_t. We don't know of any hosts where ptrdiff_t + is wider than ssize_t, so ssize_t is safe. ptrdiff_t is not + visible here, so use ssize_t. */ +typedef ssize_t regoff_t; +#else +/* The traditional GNU regex implementation mishandles strings longer + than INT_MAX. */ +typedef int regoff_t; +#endif + + +#ifdef __USE_GNU +/* This is the structure we store register match data in. See + regex.texinfo for a full description of what registers match. */ +struct re_registers +{ + __re_size_t num_regs; + regoff_t *start; + regoff_t *end; +}; + + +/* If 'regs_allocated' is REGS_UNALLOCATED in the pattern buffer, + 're_match_2' returns information about at least this many registers + the first time a 'regs' structure is passed. */ +# ifndef RE_NREGS +# define RE_NREGS 30 +# endif +#endif + + +/* POSIX specification for registers. Aside from the different names than + 're_registers', POSIX uses an array of structures, instead of a + structure of arrays. */ +typedef struct +{ + regoff_t rm_so; /* Byte offset from string's start to substring's start. */ + regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ +} regmatch_t; + +/* Declarations for routines. */ + +#ifdef __USE_GNU +/* Sets the current default syntax to SYNTAX, and return the old syntax. + You can also simply assign to the 're_syntax_options' variable. */ +extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); + +/* Compile the regular expression PATTERN, with length LENGTH + and syntax given by the global 're_syntax_options', into the buffer + BUFFER. Return NULL if successful, and an error string if not. + + To free the allocated storage, you must call 'regfree' on BUFFER. + Note that the translate table must either have been initialized by + 'regcomp', with a malloc'ed value, or set to NULL before calling + 'regfree'. */ +extern const char *re_compile_pattern (const char *__pattern, size_t __length, + struct re_pattern_buffer *__buffer); + + +/* Compile a fastmap for the compiled pattern in BUFFER; used to + accelerate searches. Return 0 if successful and -2 if was an + internal error. */ +extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); + + +/* Search in the string STRING (with length LENGTH) for the pattern + compiled into BUFFER. Start searching at position START, for RANGE + characters. Return the starting position of the match, -1 for no + match, or -2 for an internal error. Also return register + information in REGS (if REGS and BUFFER->no_sub are nonzero). */ +extern regoff_t re_search (struct re_pattern_buffer *__buffer, + const char *__String, regoff_t __length, + regoff_t __start, regoff_t __range, + struct re_registers *__regs); + + +/* Like 're_search', but search in the concatenation of STRING1 and + STRING2. Also, stop searching at index START + STOP. */ +extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, + const char *__string1, regoff_t __length1, + const char *__string2, regoff_t __length2, + regoff_t __start, regoff_t __range, + struct re_registers *__regs, + regoff_t __stop); + + +/* Like 're_search', but return how many characters in STRING the regexp + in BUFFER matched, starting at position START. */ +extern regoff_t re_match (struct re_pattern_buffer *__buffer, + const char *__String, regoff_t __length, + regoff_t __start, struct re_registers *__regs); + + +/* Relates to 're_match' as 're_search_2' relates to 're_search'. */ +extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, + const char *__string1, regoff_t __length1, + const char *__string2, regoff_t __length2, + regoff_t __start, struct re_registers *__regs, + regoff_t __stop); + + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using BUFFER and REGS will use this memory + for recording register information. STARTS and ENDS must be + allocated with malloc, and must each be at least 'NUM_REGS * sizeof + (regoff_t)' bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + BUFFER will allocate its own register data, without + freeing the old data. */ +extern void re_set_registers (struct re_pattern_buffer *__buffer, + struct re_registers *__regs, + __re_size_t __num_regs, + regoff_t *__starts, regoff_t *__ends); +#endif /* Use GNU */ + +#if defined _REGEX_RE_COMP || (defined _LIBC && defined __USE_MISC) +# ifndef _CRAY +/* 4.2 bsd compatibility. */ +extern char *re_comp (const char *); +extern int re_exec (const char *); +# endif +#endif + +/* For plain 'restrict', use glibc's __restrict if defined. + Otherwise, GCC 2.95 and later have "__restrict"; C99 compilers have + "restrict", and "configure" may have defined "restrict". + Other compilers use __restrict, __restrict__, and _Restrict, and + 'configure' might #define 'restrict' to those words, so pick a + different name. */ +#ifndef _Restrict_ +# if defined __restrict || 2 < __GNUC__ + (95 <= __GNUC_MINOR__) +# define _Restrict_ __restrict +# elif 199901L <= __STDC_VERSION__ || defined restrict +# define _Restrict_ restrict +# else +# define _Restrict_ +# endif +#endif +/* For [restrict], use glibc's __restrict_arr if available. + Otherwise, GCC 3.1 (not in C++ mode) and C99 support [restrict]. */ +#ifndef _Restrict_arr_ +# ifdef __restrict_arr +# define _Restrict_arr_ __restrict_arr +# elif ((199901L <= __STDC_VERSION__ || 3 < __GNUC__ + (1 <= __GNUC_MINOR__)) \ + && !defined __GNUG__) +# define _Restrict_arr_ _Restrict_ +# else +# define _Restrict_arr_ +# endif +#endif + +/* POSIX compatibility. */ +extern int regcomp (regex_t *_Restrict_ __preg, + const char *_Restrict_ __pattern, + int __cflags); + +extern int regexec (const regex_t *_Restrict_ __preg, + const char *_Restrict_ __String, size_t __nmatch, + regmatch_t __pmatch[_Restrict_arr_], + int __eflags); + +extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg, + char *_Restrict_ __errbuf, size_t __errbuf_size); + +extern void regfree (regex_t *__preg); + + +#ifdef __cplusplus +} +#endif /* C++ */ + +#endif /* regex.h */ diff --git a/grub-core/lib/gnulib/regex_internal.c b/grub-core/lib/gnulib/regex_internal.c new file mode 100644 index 0000000..b592f06 --- /dev/null +++ b/grub-core/lib/gnulib/regex_internal.c @@ -0,0 +1,1746 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +static void re_string_construct_common (const char *str, Idx len, + re_string_t *pstr, + RE_TRANSLATE_TYPE trans, bool icase, + const re_dfa_t *dfa); +static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, + const re_node_set *nodes, + re_hashval_t hash); +static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, + const re_node_set *nodes, + unsigned int context, + re_hashval_t hash); +static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, + Idx new_buf_len); +#ifdef RE_ENABLE_I18N +static void build_wcs_buffer (re_string_t *pstr); +static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr); +#endif /* RE_ENABLE_I18N */ +static void build_upper_buffer (re_string_t *pstr); +static void re_string_translate_buffer (re_string_t *pstr); +static unsigned int re_string_context_at (const re_string_t *input, Idx idx, + int eflags) __attribute__ ((pure)); + +/* Functions for string operation. */ + +/* This function allocate the buffers. It is necessary to call + re_string_reconstruct before using the object. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len, + RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) +{ + reg_errcode_t ret; + Idx init_buf_len; + + /* Ensure at least one character fits into the buffers. */ + if (init_len < dfa->mb_cur_max) + init_len = dfa->mb_cur_max; + init_buf_len = (len + 1 < init_len) ? len + 1: init_len; + re_string_construct_common (str, len, pstr, trans, icase, dfa); + + ret = re_string_realloc_buffers (pstr, init_buf_len); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + + pstr->word_char = dfa->word_char; + pstr->word_ops_used = dfa->word_ops_used; + pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; + pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; + pstr->valid_raw_len = pstr->valid_len; + return REG_NOERROR; +} + +/* This function allocate the buffers, and initialize them. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_string_construct (re_string_t *pstr, const char *str, Idx len, + RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) +{ + reg_errcode_t ret; + memset (pstr, '\0', sizeof (re_string_t)); + re_string_construct_common (str, len, pstr, trans, icase, dfa); + + if (len > 0) + { + ret = re_string_realloc_buffers (pstr, len + 1); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + } + pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; + + if (icase) + { +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + while (1) + { + ret = build_wcs_upper_buffer (pstr); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + if (pstr->valid_raw_len >= len) + break; + if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) + break; + ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + } + } + else +#endif /* RE_ENABLE_I18N */ + build_upper_buffer (pstr); + } + else + { +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + build_wcs_buffer (pstr); + else +#endif /* RE_ENABLE_I18N */ + { + if (trans != NULL) + re_string_translate_buffer (pstr); + else + { + pstr->valid_len = pstr->bufs_len; + pstr->valid_raw_len = pstr->bufs_len; + } + } + } + + return REG_NOERROR; +} + +/* Helper functions for re_string_allocate, and re_string_construct. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) +{ +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + wint_t *new_wcs; + + /* Avoid overflow in realloc. */ + const size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) + < new_buf_len)) + return REG_ESPACE; + + new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); + if (__glibc_unlikely (new_wcs == NULL)) + return REG_ESPACE; + pstr->wcs = new_wcs; + if (pstr->offsets != NULL) + { + Idx *new_offsets = re_realloc (pstr->offsets, Idx, new_buf_len); + if (__glibc_unlikely (new_offsets == NULL)) + return REG_ESPACE; + pstr->offsets = new_offsets; + } + } +#endif /* RE_ENABLE_I18N */ + if (pstr->mbs_allocated) + { + unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, + new_buf_len); + if (__glibc_unlikely (new_mbs == NULL)) + return REG_ESPACE; + pstr->mbs = new_mbs; + } + pstr->bufs_len = new_buf_len; + return REG_NOERROR; +} + + +static void +re_string_construct_common (const char *str, Idx len, re_string_t *pstr, + RE_TRANSLATE_TYPE trans, bool icase, + const re_dfa_t *dfa) +{ + pstr->raw_mbs = (const unsigned char *) str; + pstr->len = len; + pstr->raw_len = len; + pstr->trans = trans; + pstr->icase = icase; + pstr->mbs_allocated = (trans != NULL || icase); + pstr->mb_cur_max = dfa->mb_cur_max; + pstr->is_utf8 = dfa->is_utf8; + pstr->map_notascii = dfa->map_notascii; + pstr->stop = pstr->len; + pstr->raw_stop = pstr->stop; +} + +#ifdef RE_ENABLE_I18N + +/* Build wide character buffer PSTR->WCS. + If the byte sequence of the string are: + <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3> + Then wide character buffer will be: + <wc1> , WEOF , <wc2> , WEOF , <wc3> + We use WEOF for padding, they indicate that the position isn't + a first byte of a multibyte character. + + Note that this function assumes PSTR->VALID_LEN elements are already + built and starts from PSTR->VALID_LEN. */ + +static void +build_wcs_buffer (re_string_t *pstr) +{ +#ifdef _LIBC + unsigned char buf[MB_LEN_MAX]; + assert (MB_LEN_MAX >= pstr->mb_cur_max); +#else + unsigned char buf[64]; +#endif + mbstate_t prev_st; + Idx byte_idx, end_idx, remain_len; + size_t mbclen; + + /* Build the buffers from pstr->valid_len to either pstr->len or + pstr->bufs_len. */ + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + for (byte_idx = pstr->valid_len; byte_idx < end_idx;) + { + wchar_t wc; + const char *p; + + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + /* Apply the translation if we need. */ + if (__glibc_unlikely (pstr->trans != NULL)) + { + int i, ch; + + for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) + { + ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; + buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; + } + p = (const char *) buf; + } + else + p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; + mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); + if (__glibc_unlikely (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 + && pstr->bufs_len >= pstr->len))) + { + /* We treat these cases as a singlebyte character. */ + mbclen = 1; + wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; + if (__glibc_unlikely (pstr->trans != NULL)) + wc = pstr->trans[wc]; + pstr->cur_state = prev_st; + } + else if (__glibc_unlikely (mbclen == (size_t) -2)) + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + + /* Write wide character and padding. */ + pstr->wcs[byte_idx++] = wc; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = byte_idx; +} + +/* Build wide character buffer PSTR->WCS like build_wcs_buffer, + but for REG_ICASE. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +build_wcs_upper_buffer (re_string_t *pstr) +{ + mbstate_t prev_st; + Idx src_idx, byte_idx, end_idx, remain_len; + size_t mbclen; +#ifdef _LIBC + char buf[MB_LEN_MAX]; + assert (MB_LEN_MAX >= pstr->mb_cur_max); +#else + char buf[64]; +#endif + + byte_idx = pstr->valid_len; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + /* The following optimization assumes that ASCII characters can be + mapped to wide characters with a simple cast. */ + if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) + { + while (byte_idx < end_idx) + { + wchar_t wc; + + if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]) + && mbsinit (&pstr->cur_state)) + { + /* In case of a singlebyte character. */ + pstr->mbs[byte_idx] + = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]); + /* The next step uses the assumption that wchar_t is encoded + ASCII-safe: all ASCII values can be converted like this. */ + pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx]; + ++byte_idx; + continue; + } + + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + mbclen = __mbrtowc (&wc, + ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx + + byte_idx), remain_len, &pstr->cur_state); + if (__glibc_likely (0 < mbclen && mbclen < (size_t) -2)) + { + wchar_t wcu = __towupper (wc); + if (wcu != wc) + { + size_t mbcdlen; + + mbcdlen = __wcrtomb (buf, wcu, &prev_st); + if (__glibc_likely (mbclen == mbcdlen)) + memcpy (pstr->mbs + byte_idx, buf, mbclen); + else + { + src_idx = byte_idx; + goto offsets_needed; + } + } + else + memcpy (pstr->mbs + byte_idx, + pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); + pstr->wcs[byte_idx++] = wcu; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + else if (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) + { + /* It is an invalid character, an incomplete character + at the end of the string, or '\0'. Just use the byte. */ + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; + pstr->mbs[byte_idx] = ch; + /* And also cast it to wide char. */ + pstr->wcs[byte_idx++] = (wchar_t) ch; + if (__glibc_unlikely (mbclen == (size_t) -1)) + pstr->cur_state = prev_st; + } + else + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = byte_idx; + return REG_NOERROR; + } + else + for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) + { + wchar_t wc; + const char *p; + offsets_needed: + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + if (__glibc_unlikely (pstr->trans != NULL)) + { + int i, ch; + + for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) + { + ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; + buf[i] = pstr->trans[ch]; + } + p = (const char *) buf; + } + else + p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; + mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); + if (__glibc_likely (0 < mbclen && mbclen < (size_t) -2)) + { + wchar_t wcu = __towupper (wc); + if (wcu != wc) + { + size_t mbcdlen; + + mbcdlen = __wcrtomb ((char *) buf, wcu, &prev_st); + if (__glibc_likely (mbclen == mbcdlen)) + memcpy (pstr->mbs + byte_idx, buf, mbclen); + else if (mbcdlen != (size_t) -1) + { + size_t i; + + if (byte_idx + mbcdlen > pstr->bufs_len) + { + pstr->cur_state = prev_st; + break; + } + + if (pstr->offsets == NULL) + { + pstr->offsets = re_malloc (Idx, pstr->bufs_len); + + if (pstr->offsets == NULL) + return REG_ESPACE; + } + if (!pstr->offsets_needed) + { + for (i = 0; i < (size_t) byte_idx; ++i) + pstr->offsets[i] = i; + pstr->offsets_needed = 1; + } + + memcpy (pstr->mbs + byte_idx, buf, mbcdlen); + pstr->wcs[byte_idx] = wcu; + pstr->offsets[byte_idx] = src_idx; + for (i = 1; i < mbcdlen; ++i) + { + pstr->offsets[byte_idx + i] + = src_idx + (i < mbclen ? i : mbclen - 1); + pstr->wcs[byte_idx + i] = WEOF; + } + pstr->len += mbcdlen - mbclen; + if (pstr->raw_stop > src_idx) + pstr->stop += mbcdlen - mbclen; + end_idx = (pstr->bufs_len > pstr->len) + ? pstr->len : pstr->bufs_len; + byte_idx += mbcdlen; + src_idx += mbclen; + continue; + } + else + memcpy (pstr->mbs + byte_idx, p, mbclen); + } + else + memcpy (pstr->mbs + byte_idx, p, mbclen); + + if (__glibc_unlikely (pstr->offsets_needed != 0)) + { + size_t i; + for (i = 0; i < mbclen; ++i) + pstr->offsets[byte_idx + i] = src_idx + i; + } + src_idx += mbclen; + + pstr->wcs[byte_idx++] = wcu; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + else if (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) + { + /* It is an invalid character or '\0'. Just use the byte. */ + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; + + if (__glibc_unlikely (pstr->trans != NULL)) + ch = pstr->trans [ch]; + pstr->mbs[byte_idx] = ch; + + if (__glibc_unlikely (pstr->offsets_needed != 0)) + pstr->offsets[byte_idx] = src_idx; + ++src_idx; + + /* And also cast it to wide char. */ + pstr->wcs[byte_idx++] = (wchar_t) ch; + if (__glibc_unlikely (mbclen == (size_t) -1)) + pstr->cur_state = prev_st; + } + else + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = src_idx; + return REG_NOERROR; +} + +/* Skip characters until the index becomes greater than NEW_RAW_IDX. + Return the index. */ + +static Idx +re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc) +{ + mbstate_t prev_st; + Idx rawbuf_idx; + size_t mbclen; + wint_t wc = WEOF; + + /* Skip the characters which are not necessary to check. */ + for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; + rawbuf_idx < new_raw_idx;) + { + wchar_t wc2; + Idx remain_len = pstr->raw_len - rawbuf_idx; + prev_st = pstr->cur_state; + mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx, + remain_len, &pstr->cur_state); + if (__glibc_unlikely (mbclen == (size_t) -2 || mbclen == (size_t) -1 + || mbclen == 0)) + { + /* We treat these cases as a single byte character. */ + if (mbclen == 0 || remain_len == 0) + wc = L'\0'; + else + wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx); + mbclen = 1; + pstr->cur_state = prev_st; + } + else + wc = wc2; + /* Then proceed the next character. */ + rawbuf_idx += mbclen; + } + *last_wc = wc; + return rawbuf_idx; +} +#endif /* RE_ENABLE_I18N */ + +/* Build the buffer PSTR->MBS, and apply the translation if we need. + This function is used in case of REG_ICASE. */ + +static void +build_upper_buffer (re_string_t *pstr) +{ + Idx char_idx, end_idx; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) + { + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; + if (__glibc_unlikely (pstr->trans != NULL)) + ch = pstr->trans[ch]; + pstr->mbs[char_idx] = toupper (ch); + } + pstr->valid_len = char_idx; + pstr->valid_raw_len = char_idx; +} + +/* Apply TRANS to the buffer in PSTR. */ + +static void +re_string_translate_buffer (re_string_t *pstr) +{ + Idx buf_idx, end_idx; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) + { + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; + pstr->mbs[buf_idx] = pstr->trans[ch]; + } + + pstr->valid_len = buf_idx; + pstr->valid_raw_len = buf_idx; +} + +/* This function re-construct the buffers. + Concretely, convert to wide character in case of pstr->mb_cur_max > 1, + convert to upper case in case of REG_ICASE, apply translation. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) +{ + Idx offset; + + if (__glibc_unlikely (pstr->raw_mbs_idx <= idx)) + offset = idx - pstr->raw_mbs_idx; + else + { + /* Reset buffer. */ +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); +#endif /* RE_ENABLE_I18N */ + pstr->len = pstr->raw_len; + pstr->stop = pstr->raw_stop; + pstr->valid_len = 0; + pstr->raw_mbs_idx = 0; + pstr->valid_raw_len = 0; + pstr->offsets_needed = 0; + pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF + : CONTEXT_NEWLINE | CONTEXT_BEGBUF); + if (!pstr->mbs_allocated) + pstr->mbs = (unsigned char *) pstr->raw_mbs; + offset = idx; + } + + if (__glibc_likely (offset != 0)) + { + /* Should the already checked characters be kept? */ + if (__glibc_likely (offset < pstr->valid_raw_len)) + { + /* Yes, move them to the front of the buffer. */ +#ifdef RE_ENABLE_I18N + if (__glibc_unlikely (pstr->offsets_needed)) + { + Idx low = 0, high = pstr->valid_len, mid; + do + { + mid = (high + low) / 2; + if (pstr->offsets[mid] > offset) + high = mid; + else if (pstr->offsets[mid] < offset) + low = mid + 1; + else + break; + } + while (low < high); + if (pstr->offsets[mid] < offset) + ++mid; + pstr->tip_context = re_string_context_at (pstr, mid - 1, + eflags); + /* This can be quite complicated, so handle specially + only the common and easy case where the character with + different length representation of lower and upper + case is present at or after offset. */ + if (pstr->valid_len > offset + && mid == offset && pstr->offsets[mid] == offset) + { + memmove (pstr->wcs, pstr->wcs + offset, + (pstr->valid_len - offset) * sizeof (wint_t)); + memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); + pstr->valid_len -= offset; + pstr->valid_raw_len -= offset; + for (low = 0; low < pstr->valid_len; low++) + pstr->offsets[low] = pstr->offsets[low + offset] - offset; + } + else + { + /* Otherwise, just find out how long the partial multibyte + character at offset is and fill it with WEOF/255. */ + pstr->len = pstr->raw_len - idx + offset; + pstr->stop = pstr->raw_stop - idx + offset; + pstr->offsets_needed = 0; + while (mid > 0 && pstr->offsets[mid - 1] == offset) + --mid; + while (mid < pstr->valid_len) + if (pstr->wcs[mid] != WEOF) + break; + else + ++mid; + if (mid == pstr->valid_len) + pstr->valid_len = 0; + else + { + pstr->valid_len = pstr->offsets[mid] - offset; + if (pstr->valid_len) + { + for (low = 0; low < pstr->valid_len; ++low) + pstr->wcs[low] = WEOF; + memset (pstr->mbs, 255, pstr->valid_len); + } + } + pstr->valid_raw_len = pstr->valid_len; + } + } + else +#endif + { + pstr->tip_context = re_string_context_at (pstr, offset - 1, + eflags); +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + memmove (pstr->wcs, pstr->wcs + offset, + (pstr->valid_len - offset) * sizeof (wint_t)); +#endif /* RE_ENABLE_I18N */ + if (__glibc_unlikely (pstr->mbs_allocated)) + memmove (pstr->mbs, pstr->mbs + offset, + pstr->valid_len - offset); + pstr->valid_len -= offset; + pstr->valid_raw_len -= offset; +#if defined DEBUG && DEBUG + assert (pstr->valid_len > 0); +#endif + } + } + else + { +#ifdef RE_ENABLE_I18N + /* No, skip all characters until IDX. */ + Idx prev_valid_len = pstr->valid_len; + + if (__glibc_unlikely (pstr->offsets_needed)) + { + pstr->len = pstr->raw_len - idx + offset; + pstr->stop = pstr->raw_stop - idx + offset; + pstr->offsets_needed = 0; + } +#endif + pstr->valid_len = 0; +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + Idx wcs_idx; + wint_t wc = WEOF; + + if (pstr->is_utf8) + { + const unsigned char *raw, *p, *end; + + /* Special case UTF-8. Multi-byte chars start with any + byte other than 0x80 - 0xbf. */ + raw = pstr->raw_mbs + pstr->raw_mbs_idx; + end = raw + (offset - pstr->mb_cur_max); + if (end < pstr->raw_mbs) + end = pstr->raw_mbs; + p = raw + offset - 1; +#ifdef _LIBC + /* We know the wchar_t encoding is UCS4, so for the simple + case, ASCII characters, skip the conversion step. */ + if (isascii (*p) && __glibc_likely (pstr->trans == NULL)) + { + memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); + /* pstr->valid_len = 0; */ + wc = (wchar_t) *p; + } + else +#endif + for (; p >= end; --p) + if ((*p & 0xc0) != 0x80) + { + mbstate_t cur_state; + wchar_t wc2; + Idx mlen = raw + pstr->len - p; + unsigned char buf[6]; + size_t mbclen; + + const unsigned char *pp = p; + if (__glibc_unlikely (pstr->trans != NULL)) + { + int i = mlen < 6 ? mlen : 6; + while (--i >= 0) + buf[i] = pstr->trans[p[i]]; + pp = buf; + } + /* XXX Don't use mbrtowc, we know which conversion + to use (UTF-8 -> UCS4). */ + memset (&cur_state, 0, sizeof (cur_state)); + mbclen = __mbrtowc (&wc2, (const char *) pp, mlen, + &cur_state); + if (raw + offset - p <= mbclen + && mbclen < (size_t) -2) + { + memset (&pstr->cur_state, '\0', + sizeof (mbstate_t)); + pstr->valid_len = mbclen - (raw + offset - p); + wc = wc2; + } + break; + } + } + + if (wc == WEOF) + pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; + if (wc == WEOF) + pstr->tip_context + = re_string_context_at (pstr, prev_valid_len - 1, eflags); + else + pstr->tip_context = ((__glibc_unlikely (pstr->word_ops_used != 0) + && IS_WIDE_WORD_CHAR (wc)) + ? CONTEXT_WORD + : ((IS_WIDE_NEWLINE (wc) + && pstr->newline_anchor) + ? CONTEXT_NEWLINE : 0)); + if (__glibc_unlikely (pstr->valid_len)) + { + for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) + pstr->wcs[wcs_idx] = WEOF; + if (pstr->mbs_allocated) + memset (pstr->mbs, 255, pstr->valid_len); + } + pstr->valid_raw_len = pstr->valid_len; + } + else +#endif /* RE_ENABLE_I18N */ + { + int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; + pstr->valid_raw_len = 0; + if (pstr->trans) + c = pstr->trans[c]; + pstr->tip_context = (bitset_contain (pstr->word_char, c) + ? CONTEXT_WORD + : ((IS_NEWLINE (c) && pstr->newline_anchor) + ? CONTEXT_NEWLINE : 0)); + } + } + if (!__glibc_unlikely (pstr->mbs_allocated)) + pstr->mbs += offset; + } + pstr->raw_mbs_idx = idx; + pstr->len -= offset; + pstr->stop -= offset; + + /* Then build the buffers. */ +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + if (pstr->icase) + { + reg_errcode_t ret = build_wcs_upper_buffer (pstr); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + } + else + build_wcs_buffer (pstr); + } + else +#endif /* RE_ENABLE_I18N */ + if (__glibc_unlikely (pstr->mbs_allocated)) + { + if (pstr->icase) + build_upper_buffer (pstr); + else if (pstr->trans != NULL) + re_string_translate_buffer (pstr); + } + else + pstr->valid_len = pstr->len; + + pstr->cur_idx = 0; + return REG_NOERROR; +} + +static unsigned char +__attribute__ ((pure)) +re_string_peek_byte_case (const re_string_t *pstr, Idx idx) +{ + int ch; + Idx off; + + /* Handle the common (easiest) cases first. */ + if (__glibc_likely (!pstr->mbs_allocated)) + return re_string_peek_byte (pstr, idx); + +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1 + && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) + return re_string_peek_byte (pstr, idx); +#endif + + off = pstr->cur_idx + idx; +#ifdef RE_ENABLE_I18N + if (pstr->offsets_needed) + off = pstr->offsets[off]; +#endif + + ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; + +#ifdef RE_ENABLE_I18N + /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I + this function returns CAPITAL LETTER I instead of first byte of + DOTLESS SMALL LETTER I. The latter would confuse the parser, + since peek_byte_case doesn't advance cur_idx in any way. */ + if (pstr->offsets_needed && !isascii (ch)) + return re_string_peek_byte (pstr, idx); +#endif + + return ch; +} + +static unsigned char +re_string_fetch_byte_case (re_string_t *pstr) +{ + if (__glibc_likely (!pstr->mbs_allocated)) + return re_string_fetch_byte (pstr); + +#ifdef RE_ENABLE_I18N + if (pstr->offsets_needed) + { + Idx off; + int ch; + + /* For tr_TR.UTF-8 [[:islower:]] there is + [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip + in that case the whole multi-byte character and return + the original letter. On the other side, with + [[: DOTLESS SMALL LETTER I return [[:I, as doing + anything else would complicate things too much. */ + + if (!re_string_first_byte (pstr, pstr->cur_idx)) + return re_string_fetch_byte (pstr); + + off = pstr->offsets[pstr->cur_idx]; + ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; + + if (! isascii (ch)) + return re_string_fetch_byte (pstr); + + re_string_skip_bytes (pstr, + re_string_char_size_at (pstr, pstr->cur_idx)); + return ch; + } +#endif + + return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; +} + +static void +re_string_destruct (re_string_t *pstr) +{ +#ifdef RE_ENABLE_I18N + re_free (pstr->wcs); + re_free (pstr->offsets); +#endif /* RE_ENABLE_I18N */ + if (pstr->mbs_allocated) + re_free (pstr->mbs); +} + +/* Return the context at IDX in INPUT. */ + +static unsigned int +re_string_context_at (const re_string_t *input, Idx idx, int eflags) +{ + int c; + if (__glibc_unlikely (idx < 0)) + /* In this case, we use the value stored in input->tip_context, + since we can't know the character in input->mbs[-1] here. */ + return input->tip_context; + if (__glibc_unlikely (idx == input->len)) + return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF + : CONTEXT_NEWLINE | CONTEXT_ENDBUF); +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1) + { + wint_t wc; + Idx wc_idx = idx; + while(input->wcs[wc_idx] == WEOF) + { +#if defined DEBUG && DEBUG + /* It must not happen. */ + assert (wc_idx >= 0); +#endif + --wc_idx; + if (wc_idx < 0) + return input->tip_context; + } + wc = input->wcs[wc_idx]; + if (__glibc_unlikely (input->word_ops_used != 0) + && IS_WIDE_WORD_CHAR (wc)) + return CONTEXT_WORD; + return (IS_WIDE_NEWLINE (wc) && input->newline_anchor + ? CONTEXT_NEWLINE : 0); + } + else +#endif + { + c = re_string_byte_at (input, idx); + if (bitset_contain (input->word_char, c)) + return CONTEXT_WORD; + return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; + } +} + +/* Functions for set operation. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_alloc (re_node_set *set, Idx size) +{ + set->alloc = size; + set->nelem = 0; + set->elems = re_malloc (Idx, size); + if (__glibc_unlikely (set->elems == NULL) + && (MALLOC_0_IS_NONNULL || size != 0)) + return REG_ESPACE; + return REG_NOERROR; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_init_1 (re_node_set *set, Idx elem) +{ + set->alloc = 1; + set->nelem = 1; + set->elems = re_malloc (Idx, 1); + if (__glibc_unlikely (set->elems == NULL)) + { + set->alloc = set->nelem = 0; + return REG_ESPACE; + } + set->elems[0] = elem; + return REG_NOERROR; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2) +{ + set->alloc = 2; + set->elems = re_malloc (Idx, 2); + if (__glibc_unlikely (set->elems == NULL)) + return REG_ESPACE; + if (elem1 == elem2) + { + set->nelem = 1; + set->elems[0] = elem1; + } + else + { + set->nelem = 2; + if (elem1 < elem2) + { + set->elems[0] = elem1; + set->elems[1] = elem2; + } + else + { + set->elems[0] = elem2; + set->elems[1] = elem1; + } + } + return REG_NOERROR; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_init_copy (re_node_set *dest, const re_node_set *src) +{ + dest->nelem = src->nelem; + if (src->nelem > 0) + { + dest->alloc = dest->nelem; + dest->elems = re_malloc (Idx, dest->alloc); + if (__glibc_unlikely (dest->elems == NULL)) + { + dest->alloc = dest->nelem = 0; + return REG_ESPACE; + } + memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); + } + else + re_node_set_init_empty (dest); + return REG_NOERROR; +} + +/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. + Note: We assume dest->elems is NULL, when dest->alloc is 0. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, + const re_node_set *src2) +{ + Idx i1, i2, is, id, delta, sbase; + if (src1->nelem == 0 || src2->nelem == 0) + return REG_NOERROR; + + /* We need dest->nelem + 2 * elems_in_intersection; this is a + conservative estimate. */ + if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) + { + Idx new_alloc = src1->nelem + src2->nelem + dest->alloc; + Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc); + if (__glibc_unlikely (new_elems == NULL)) + return REG_ESPACE; + dest->elems = new_elems; + dest->alloc = new_alloc; + } + + /* Find the items in the intersection of SRC1 and SRC2, and copy + into the top of DEST those that are not already in DEST itself. */ + sbase = dest->nelem + src1->nelem + src2->nelem; + i1 = src1->nelem - 1; + i2 = src2->nelem - 1; + id = dest->nelem - 1; + for (;;) + { + if (src1->elems[i1] == src2->elems[i2]) + { + /* Try to find the item in DEST. Maybe we could binary search? */ + while (id >= 0 && dest->elems[id] > src1->elems[i1]) + --id; + + if (id < 0 || dest->elems[id] != src1->elems[i1]) + dest->elems[--sbase] = src1->elems[i1]; + + if (--i1 < 0 || --i2 < 0) + break; + } + + /* Lower the highest of the two items. */ + else if (src1->elems[i1] < src2->elems[i2]) + { + if (--i2 < 0) + break; + } + else + { + if (--i1 < 0) + break; + } + } + + id = dest->nelem - 1; + is = dest->nelem + src1->nelem + src2->nelem - 1; + delta = is - sbase + 1; + + /* Now copy. When DELTA becomes zero, the remaining + DEST elements are already in place; this is more or + less the same loop that is in re_node_set_merge. */ + dest->nelem += delta; + if (delta > 0 && id >= 0) + for (;;) + { + if (dest->elems[is] > dest->elems[id]) + { + /* Copy from the top. */ + dest->elems[id + delta--] = dest->elems[is--]; + if (delta == 0) + break; + } + else + { + /* Slide from the bottom. */ + dest->elems[id + delta] = dest->elems[id]; + if (--id < 0) + break; + } + } + + /* Copy remaining SRC elements. */ + memcpy (dest->elems, dest->elems + sbase, delta * sizeof (Idx)); + + return REG_NOERROR; +} + +/* Calculate the union set of the sets SRC1 and SRC2. And store it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_init_union (re_node_set *dest, const re_node_set *src1, + const re_node_set *src2) +{ + Idx i1, i2, id; + if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) + { + dest->alloc = src1->nelem + src2->nelem; + dest->elems = re_malloc (Idx, dest->alloc); + if (__glibc_unlikely (dest->elems == NULL)) + return REG_ESPACE; + } + else + { + if (src1 != NULL && src1->nelem > 0) + return re_node_set_init_copy (dest, src1); + else if (src2 != NULL && src2->nelem > 0) + return re_node_set_init_copy (dest, src2); + else + re_node_set_init_empty (dest); + return REG_NOERROR; + } + for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) + { + if (src1->elems[i1] > src2->elems[i2]) + { + dest->elems[id++] = src2->elems[i2++]; + continue; + } + if (src1->elems[i1] == src2->elems[i2]) + ++i2; + dest->elems[id++] = src1->elems[i1++]; + } + if (i1 < src1->nelem) + { + memcpy (dest->elems + id, src1->elems + i1, + (src1->nelem - i1) * sizeof (Idx)); + id += src1->nelem - i1; + } + else if (i2 < src2->nelem) + { + memcpy (dest->elems + id, src2->elems + i2, + (src2->nelem - i2) * sizeof (Idx)); + id += src2->nelem - i2; + } + dest->nelem = id; + return REG_NOERROR; +} + +/* Calculate the union set of the sets DEST and SRC. And store it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_merge (re_node_set *dest, const re_node_set *src) +{ + Idx is, id, sbase, delta; + if (src == NULL || src->nelem == 0) + return REG_NOERROR; + if (dest->alloc < 2 * src->nelem + dest->nelem) + { + Idx new_alloc = 2 * (src->nelem + dest->alloc); + Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc); + if (__glibc_unlikely (new_buffer == NULL)) + return REG_ESPACE; + dest->elems = new_buffer; + dest->alloc = new_alloc; + } + + if (__glibc_unlikely (dest->nelem == 0)) + { + dest->nelem = src->nelem; + memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); + return REG_NOERROR; + } + + /* Copy into the top of DEST the items of SRC that are not + found in DEST. Maybe we could binary search in DEST? */ + for (sbase = dest->nelem + 2 * src->nelem, + is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; ) + { + if (dest->elems[id] == src->elems[is]) + is--, id--; + else if (dest->elems[id] < src->elems[is]) + dest->elems[--sbase] = src->elems[is--]; + else /* if (dest->elems[id] > src->elems[is]) */ + --id; + } + + if (is >= 0) + { + /* If DEST is exhausted, the remaining items of SRC must be unique. */ + sbase -= is + 1; + memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (Idx)); + } + + id = dest->nelem - 1; + is = dest->nelem + 2 * src->nelem - 1; + delta = is - sbase + 1; + if (delta == 0) + return REG_NOERROR; + + /* Now copy. When DELTA becomes zero, the remaining + DEST elements are already in place. */ + dest->nelem += delta; + for (;;) + { + if (dest->elems[is] > dest->elems[id]) + { + /* Copy from the top. */ + dest->elems[id + delta--] = dest->elems[is--]; + if (delta == 0) + break; + } + else + { + /* Slide from the bottom. */ + dest->elems[id + delta] = dest->elems[id]; + if (--id < 0) + { + /* Copy remaining SRC elements. */ + memcpy (dest->elems, dest->elems + sbase, + delta * sizeof (Idx)); + break; + } + } + } + + return REG_NOERROR; +} + +/* Insert the new element ELEM to the re_node_set* SET. + SET should not already have ELEM. + Return true if successful. */ + +static bool +__attribute_warn_unused_result__ +re_node_set_insert (re_node_set *set, Idx elem) +{ + Idx idx; + /* In case the set is empty. */ + if (set->alloc == 0) + return __glibc_likely (re_node_set_init_1 (set, elem) == REG_NOERROR); + + if (__glibc_unlikely (set->nelem) == 0) + { + /* We already guaranteed above that set->alloc != 0. */ + set->elems[0] = elem; + ++set->nelem; + return true; + } + + /* Realloc if we need. */ + if (set->alloc == set->nelem) + { + Idx *new_elems; + set->alloc = set->alloc * 2; + new_elems = re_realloc (set->elems, Idx, set->alloc); + if (__glibc_unlikely (new_elems == NULL)) + return false; + set->elems = new_elems; + } + + /* Move the elements which follows the new element. Test the + first element separately to skip a check in the inner loop. */ + if (elem < set->elems[0]) + { + idx = 0; + for (idx = set->nelem; idx > 0; idx--) + set->elems[idx] = set->elems[idx - 1]; + } + else + { + for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) + set->elems[idx] = set->elems[idx - 1]; + } + + /* Insert the new element. */ + set->elems[idx] = elem; + ++set->nelem; + return true; +} + +/* Insert the new element ELEM to the re_node_set* SET. + SET should not already have any element greater than or equal to ELEM. + Return true if successful. */ + +static bool +__attribute_warn_unused_result__ +re_node_set_insert_last (re_node_set *set, Idx elem) +{ + /* Realloc if we need. */ + if (set->alloc == set->nelem) + { + Idx *new_elems; + set->alloc = (set->alloc + 1) * 2; + new_elems = re_realloc (set->elems, Idx, set->alloc); + if (__glibc_unlikely (new_elems == NULL)) + return false; + set->elems = new_elems; + } + + /* Insert the new element. */ + set->elems[set->nelem++] = elem; + return true; +} + +/* Compare two node sets SET1 and SET2. + Return true if SET1 and SET2 are equivalent. */ + +static bool +__attribute__ ((pure)) +re_node_set_compare (const re_node_set *set1, const re_node_set *set2) +{ + Idx i; + if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) + return false; + for (i = set1->nelem ; --i >= 0 ; ) + if (set1->elems[i] != set2->elems[i]) + return false; + return true; +} + +/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ + +static Idx +__attribute__ ((pure)) +re_node_set_contains (const re_node_set *set, Idx elem) +{ + __re_size_t idx, right, mid; + if (set->nelem <= 0) + return 0; + + /* Binary search the element. */ + idx = 0; + right = set->nelem - 1; + while (idx < right) + { + mid = (idx + right) / 2; + if (set->elems[mid] < elem) + idx = mid + 1; + else + right = mid; + } + return set->elems[idx] == elem ? idx + 1 : 0; +} + +static void +re_node_set_remove_at (re_node_set *set, Idx idx) +{ + if (idx < 0 || idx >= set->nelem) + return; + --set->nelem; + for (; idx < set->nelem; idx++) + set->elems[idx] = set->elems[idx + 1]; +} + + +/* Add the token TOKEN to dfa->nodes, and return the index of the token. + Or return -1 if an error occurred. */ + +static Idx +re_dfa_add_node (re_dfa_t *dfa, re_token_t token) +{ + if (__glibc_unlikely (dfa->nodes_len >= dfa->nodes_alloc)) + { + size_t new_nodes_alloc = dfa->nodes_alloc * 2; + Idx *new_nexts, *new_indices; + re_node_set *new_edests, *new_eclosures; + re_token_t *new_nodes; + + /* Avoid overflows in realloc. */ + const size_t max_object_size = MAX (sizeof (re_token_t), + MAX (sizeof (re_node_set), + sizeof (Idx))); + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) + < new_nodes_alloc)) + return -1; + + new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); + if (__glibc_unlikely (new_nodes == NULL)) + return -1; + dfa->nodes = new_nodes; + new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc); + new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc); + new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); + new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); + if (__glibc_unlikely (new_nexts == NULL || new_indices == NULL + || new_edests == NULL || new_eclosures == NULL)) + { + re_free (new_nexts); + re_free (new_indices); + re_free (new_edests); + re_free (new_eclosures); + return -1; + } + dfa->nexts = new_nexts; + dfa->org_indices = new_indices; + dfa->edests = new_edests; + dfa->eclosures = new_eclosures; + dfa->nodes_alloc = new_nodes_alloc; + } + dfa->nodes[dfa->nodes_len] = token; + dfa->nodes[dfa->nodes_len].constraint = 0; +#ifdef RE_ENABLE_I18N + dfa->nodes[dfa->nodes_len].accept_mb = + ((token.type == OP_PERIOD && dfa->mb_cur_max > 1) + || token.type == COMPLEX_BRACKET); +#endif + dfa->nexts[dfa->nodes_len] = -1; + re_node_set_init_empty (dfa->edests + dfa->nodes_len); + re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); + return dfa->nodes_len++; +} + +static re_hashval_t +calc_state_hash (const re_node_set *nodes, unsigned int context) +{ + re_hashval_t hash = nodes->nelem + context; + Idx i; + for (i = 0 ; i < nodes->nelem ; i++) + hash += nodes->elems[i]; + return hash; +} + +/* Search for the state whose node_set is equivalent to NODES. + Return the pointer to the state, if we found it in the DFA. + Otherwise create the new one and return it. In case of an error + return NULL and set the error code in ERR. + Note: - We assume NULL as the invalid state, then it is possible that + return value is NULL and ERR is REG_NOERROR. + - We never return non-NULL value in case of any errors, it is for + optimization. */ + +static re_dfastate_t * +__attribute_warn_unused_result__ +re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, + const re_node_set *nodes) +{ + re_hashval_t hash; + re_dfastate_t *new_state; + struct re_state_table_entry *spot; + Idx i; +#if defined GCC_LINT || defined lint + /* Suppress bogus uninitialized-variable warnings. */ + *err = REG_NOERROR; +#endif + if (__glibc_unlikely (nodes->nelem == 0)) + { + *err = REG_NOERROR; + return NULL; + } + hash = calc_state_hash (nodes, 0); + spot = dfa->state_table + (hash & dfa->state_hash_mask); + + for (i = 0 ; i < spot->num ; i++) + { + re_dfastate_t *state = spot->array[i]; + if (hash != state->hash) + continue; + if (re_node_set_compare (&state->nodes, nodes)) + return state; + } + + /* There are no appropriate state in the dfa, create the new one. */ + new_state = create_ci_newstate (dfa, nodes, hash); + if (__glibc_unlikely (new_state == NULL)) + *err = REG_ESPACE; + + return new_state; +} + +/* Search for the state whose node_set is equivalent to NODES and + whose context is equivalent to CONTEXT. + Return the pointer to the state, if we found it in the DFA. + Otherwise create the new one and return it. In case of an error + return NULL and set the error code in ERR. + Note: - We assume NULL as the invalid state, then it is possible that + return value is NULL and ERR is REG_NOERROR. + - We never return non-NULL value in case of any errors, it is for + optimization. */ + +static re_dfastate_t * +__attribute_warn_unused_result__ +re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, + const re_node_set *nodes, unsigned int context) +{ + re_hashval_t hash; + re_dfastate_t *new_state; + struct re_state_table_entry *spot; + Idx i; +#if defined GCC_LINT || defined lint + /* Suppress bogus uninitialized-variable warnings. */ + *err = REG_NOERROR; +#endif + if (nodes->nelem == 0) + { + *err = REG_NOERROR; + return NULL; + } + hash = calc_state_hash (nodes, context); + spot = dfa->state_table + (hash & dfa->state_hash_mask); + + for (i = 0 ; i < spot->num ; i++) + { + re_dfastate_t *state = spot->array[i]; + if (state->hash == hash + && state->context == context + && re_node_set_compare (state->entrance_nodes, nodes)) + return state; + } + /* There are no appropriate state in 'dfa', create the new one. */ + new_state = create_cd_newstate (dfa, nodes, context, hash); + if (__glibc_unlikely (new_state == NULL)) + *err = REG_ESPACE; + + return new_state; +} + +/* Finish initialization of the new state NEWSTATE, and using its hash value + HASH put in the appropriate bucket of DFA's state table. Return value + indicates the error code if failed. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, + re_hashval_t hash) +{ + struct re_state_table_entry *spot; + reg_errcode_t err; + Idx i; + + newstate->hash = hash; + err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); + if (__glibc_unlikely (err != REG_NOERROR)) + return REG_ESPACE; + for (i = 0; i < newstate->nodes.nelem; i++) + { + Idx elem = newstate->nodes.elems[i]; + if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) + if (! re_node_set_insert_last (&newstate->non_eps_nodes, elem)) + return REG_ESPACE; + } + + spot = dfa->state_table + (hash & dfa->state_hash_mask); + if (__glibc_unlikely (spot->alloc <= spot->num)) + { + Idx new_alloc = 2 * spot->num + 2; + re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, + new_alloc); + if (__glibc_unlikely (new_array == NULL)) + return REG_ESPACE; + spot->array = new_array; + spot->alloc = new_alloc; + } + spot->array[spot->num++] = newstate; + return REG_NOERROR; +} + +static void +free_state (re_dfastate_t *state) +{ + re_node_set_free (&state->non_eps_nodes); + re_node_set_free (&state->inveclosure); + if (state->entrance_nodes != &state->nodes) + { + re_node_set_free (state->entrance_nodes); + re_free (state->entrance_nodes); + } + re_node_set_free (&state->nodes); + re_free (state->word_trtable); + re_free (state->trtable); + re_free (state); +} + +/* Create the new state which is independent of contexts. + Return the new state if succeeded, otherwise return NULL. */ + +static re_dfastate_t * +__attribute_warn_unused_result__ +create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, + re_hashval_t hash) +{ + Idx i; + reg_errcode_t err; + re_dfastate_t *newstate; + + newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); + if (__glibc_unlikely (newstate == NULL)) + return NULL; + err = re_node_set_init_copy (&newstate->nodes, nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_free (newstate); + return NULL; + } + + newstate->entrance_nodes = &newstate->nodes; + for (i = 0 ; i < nodes->nelem ; i++) + { + re_token_t *node = dfa->nodes + nodes->elems[i]; + re_token_type_t type = node->type; + if (type == CHARACTER && !node->constraint) + continue; +#ifdef RE_ENABLE_I18N + newstate->accept_mb |= node->accept_mb; +#endif /* RE_ENABLE_I18N */ + + /* If the state has the halt node, the state is a halt state. */ + if (type == END_OF_RE) + newstate->halt = 1; + else if (type == OP_BACK_REF) + newstate->has_backref = 1; + else if (type == ANCHOR || node->constraint) + newstate->has_constraint = 1; + } + err = register_state (dfa, newstate, hash); + if (__glibc_unlikely (err != REG_NOERROR)) + { + free_state (newstate); + newstate = NULL; + } + return newstate; +} + +/* Create the new state which is depend on the context CONTEXT. + Return the new state if succeeded, otherwise return NULL. */ + +static re_dfastate_t * +__attribute_warn_unused_result__ +create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, + unsigned int context, re_hashval_t hash) +{ + Idx i, nctx_nodes = 0; + reg_errcode_t err; + re_dfastate_t *newstate; + + newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); + if (__glibc_unlikely (newstate == NULL)) + return NULL; + err = re_node_set_init_copy (&newstate->nodes, nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_free (newstate); + return NULL; + } + + newstate->context = context; + newstate->entrance_nodes = &newstate->nodes; + + for (i = 0 ; i < nodes->nelem ; i++) + { + re_token_t *node = dfa->nodes + nodes->elems[i]; + re_token_type_t type = node->type; + unsigned int constraint = node->constraint; + + if (type == CHARACTER && !constraint) + continue; +#ifdef RE_ENABLE_I18N + newstate->accept_mb |= node->accept_mb; +#endif /* RE_ENABLE_I18N */ + + /* If the state has the halt node, the state is a halt state. */ + if (type == END_OF_RE) + newstate->halt = 1; + else if (type == OP_BACK_REF) + newstate->has_backref = 1; + + if (constraint) + { + if (newstate->entrance_nodes == &newstate->nodes) + { + newstate->entrance_nodes = re_malloc (re_node_set, 1); + if (__glibc_unlikely (newstate->entrance_nodes == NULL)) + { + free_state (newstate); + return NULL; + } + if (re_node_set_init_copy (newstate->entrance_nodes, nodes) + != REG_NOERROR) + return NULL; + nctx_nodes = 0; + newstate->has_constraint = 1; + } + + if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) + { + re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); + ++nctx_nodes; + } + } + } + err = register_state (dfa, newstate, hash); + if (__glibc_unlikely (err != REG_NOERROR)) + { + free_state (newstate); + newstate = NULL; + } + return newstate; +} diff --git a/grub-core/lib/gnulib/regex_internal.h b/grub-core/lib/gnulib/regex_internal.h new file mode 100644 index 0000000..a3aedda --- /dev/null +++ b/grub-core/lib/gnulib/regex_internal.h @@ -0,0 +1,874 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _REGEX_INTERNAL_H +#define _REGEX_INTERNAL_H 1 + +#include <assert.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <langinfo.h> +#include <locale.h> +#include <wchar.h> +#include <wctype.h> +#include <stdbool.h> +#include <stdint.h> + +#include <intprops.h> + +#ifdef _LIBC +# include <libc-lock.h> +# define lock_define(name) __libc_lock_define (, name) +# define lock_init(lock) (__libc_lock_init (lock), 0) +# define lock_fini(lock) ((void) 0) +# define lock_lock(lock) __libc_lock_lock (lock) +# define lock_unlock(lock) __libc_lock_unlock (lock) +#elif defined GNULIB_LOCK && !defined USE_UNLOCKED_IO +# include "glthread/lock.h" + /* Use gl_lock_define if empty macro arguments are known to work. + Otherwise, fall back on less-portable substitutes. */ +# if ((defined __GNUC__ && !defined __STRICT_ANSI__) \ + || (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__)) +# define lock_define(name) gl_lock_define (, name) +# elif USE_POSIX_THREADS +# define lock_define(name) pthread_mutex_t name; +# elif USE_PTH_THREADS +# define lock_define(name) pth_mutex_t name; +# elif USE_SOLARIS_THREADS +# define lock_define(name) mutex_t name; +# elif USE_WINDOWS_THREADS +# define lock_define(name) gl_lock_t name; +# else +# define lock_define(name) +# endif +# define lock_init(lock) glthread_lock_init (&(lock)) +# define lock_fini(lock) glthread_lock_destroy (&(lock)) +# define lock_lock(lock) glthread_lock_lock (&(lock)) +# define lock_unlock(lock) glthread_lock_unlock (&(lock)) +#elif defined GNULIB_PTHREAD && !defined USE_UNLOCKED_IO +# include <pthread.h> +# define lock_define(name) pthread_mutex_t name; +# define lock_init(lock) pthread_mutex_init (&(lock), 0) +# define lock_fini(lock) pthread_mutex_destroy (&(lock)) +# define lock_lock(lock) pthread_mutex_lock (&(lock)) +# define lock_unlock(lock) pthread_mutex_unlock (&(lock)) +#else +# define lock_define(name) +# define lock_init(lock) 0 +# define lock_fini(lock) ((void) 0) + /* The 'dfa' avoids an "unused variable 'dfa'" warning from GCC. */ +# define lock_lock(lock) ((void) dfa) +# define lock_unlock(lock) ((void) 0) +#endif + +/* In case that the system doesn't have isblank(). */ +#if !defined _LIBC && ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK)) +# define isblank(ch) ((ch) == ' ' || (ch) == '\t') +#endif + +#ifdef _LIBC +# ifndef _RE_DEFINE_LOCALE_FUNCTIONS +# define _RE_DEFINE_LOCALE_FUNCTIONS 1 +# include <locale/localeinfo.h> +# include <locale/coll-lookup.h> +# endif +#endif + +/* This is for other GNU distributions with internationalized messages. */ +#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC +# include <libintl.h> +# ifdef _LIBC +# undef gettext +# define gettext(msgid) \ + __dcgettext (_libc_intl_domainname, msgid, LC_MESSAGES) +# endif +#else +# undef gettext +# define gettext(msgid) (msgid) +#endif + +#ifndef gettext_noop +/* This define is so xgettext can find the internationalizable + strings. */ +# define gettext_noop(String) String +#endif + +#if (defined MB_CUR_MAX && HAVE_WCTYPE_H && HAVE_ISWCTYPE) || _LIBC +# define RE_ENABLE_I18N +#endif + +/* Number of ASCII characters. */ +#define ASCII_CHARS 0x80 + +/* Number of single byte characters. */ +#define SBC_MAX (UCHAR_MAX + 1) + +#define COLL_ELEM_LEN_MAX 8 + +/* The character which represents newline. */ +#define NEWLINE_CHAR '\n' +#define WIDE_NEWLINE_CHAR L'\n' + +/* Rename to standard API for using out of glibc. */ +#ifndef _LIBC +# undef __wctype +# undef __iswalnum +# undef __iswctype +# undef __towlower +# undef __towupper +# define __wctype wctype +# define __iswalnum iswalnum +# define __iswctype iswctype +# define __towlower towlower +# define __towupper towupper +# define __btowc btowc +# define __mbrtowc mbrtowc +# define __wcrtomb wcrtomb +# define __regfree regfree +#endif /* not _LIBC */ + +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif + +/* The type of indexes into strings. This is signed, not size_t, + since the API requires indexes to fit in regoff_t anyway, and using + signed integers makes the code a bit smaller and presumably faster. + The traditional GNU regex implementation uses int for indexes. + The POSIX-compatible implementation uses a possibly-wider type. + The name 'Idx' is three letters to minimize the hassle of + reindenting a lot of regex code that formerly used 'int'. */ +typedef regoff_t Idx; +#ifdef _REGEX_LARGE_OFFSETS +# define IDX_MAX SSIZE_MAX +#else +# define IDX_MAX INT_MAX +#endif + +/* A hash value, suitable for computing hash tables. */ +typedef __re_size_t re_hashval_t; + +/* An integer used to represent a set of bits. It must be unsigned, + and must be at least as wide as unsigned int. */ +typedef unsigned long int bitset_word_t; +/* All bits set in a bitset_word_t. */ +#define BITSET_WORD_MAX ULONG_MAX + +/* Number of bits in a bitset_word_t. For portability to hosts with + padding bits, do not use '(sizeof (bitset_word_t) * CHAR_BIT)'; + instead, deduce it directly from BITSET_WORD_MAX. Avoid + greater-than-32-bit integers and unconditional shifts by more than + 31 bits, as they're not portable. */ +#if BITSET_WORD_MAX == 0xffffffffUL +# define BITSET_WORD_BITS 32 +#elif BITSET_WORD_MAX >> 31 >> 4 == 1 +# define BITSET_WORD_BITS 36 +#elif BITSET_WORD_MAX >> 31 >> 16 == 1 +# define BITSET_WORD_BITS 48 +#elif BITSET_WORD_MAX >> 31 >> 28 == 1 +# define BITSET_WORD_BITS 60 +#elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1 +# define BITSET_WORD_BITS 64 +#elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1 +# define BITSET_WORD_BITS 72 +#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1 +# define BITSET_WORD_BITS 128 +#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1 +# define BITSET_WORD_BITS 256 +#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1 +# define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */ +# if BITSET_WORD_BITS <= SBC_MAX +# error "Invalid SBC_MAX" +# endif +#else +# error "Add case for new bitset_word_t size" +#endif + +/* Number of bitset_word_t values in a bitset_t. */ +#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS) + +typedef bitset_word_t bitset_t[BITSET_WORDS]; +typedef bitset_word_t *re_bitset_ptr_t; +typedef const bitset_word_t *re_const_bitset_ptr_t; + +#define PREV_WORD_CONSTRAINT 0x0001 +#define PREV_NOTWORD_CONSTRAINT 0x0002 +#define NEXT_WORD_CONSTRAINT 0x0004 +#define NEXT_NOTWORD_CONSTRAINT 0x0008 +#define PREV_NEWLINE_CONSTRAINT 0x0010 +#define NEXT_NEWLINE_CONSTRAINT 0x0020 +#define PREV_BEGBUF_CONSTRAINT 0x0040 +#define NEXT_ENDBUF_CONSTRAINT 0x0080 +#define WORD_DELIM_CONSTRAINT 0x0100 +#define NOT_WORD_DELIM_CONSTRAINT 0x0200 + +typedef enum +{ + INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, + WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, + WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, + INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, + LINE_FIRST = PREV_NEWLINE_CONSTRAINT, + LINE_LAST = NEXT_NEWLINE_CONSTRAINT, + BUF_FIRST = PREV_BEGBUF_CONSTRAINT, + BUF_LAST = NEXT_ENDBUF_CONSTRAINT, + WORD_DELIM = WORD_DELIM_CONSTRAINT, + NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT +} re_context_type; + +typedef struct +{ + Idx alloc; + Idx nelem; + Idx *elems; +} re_node_set; + +typedef enum +{ + NON_TYPE = 0, + + /* Node type, These are used by token, node, tree. */ + CHARACTER = 1, + END_OF_RE = 2, + SIMPLE_BRACKET = 3, + OP_BACK_REF = 4, + OP_PERIOD = 5, +#ifdef RE_ENABLE_I18N + COMPLEX_BRACKET = 6, + OP_UTF8_PERIOD = 7, +#endif /* RE_ENABLE_I18N */ + + /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used + when the debugger shows values of this enum type. */ +#define EPSILON_BIT 8 + OP_OPEN_SUBEXP = EPSILON_BIT | 0, + OP_CLOSE_SUBEXP = EPSILON_BIT | 1, + OP_ALT = EPSILON_BIT | 2, + OP_DUP_ASTERISK = EPSILON_BIT | 3, + ANCHOR = EPSILON_BIT | 4, + + /* Tree type, these are used only by tree. */ + CONCAT = 16, + SUBEXP = 17, + + /* Token type, these are used only by token. */ + OP_DUP_PLUS = 18, + OP_DUP_QUESTION, + OP_OPEN_BRACKET, + OP_CLOSE_BRACKET, + OP_CHARSET_RANGE, + OP_OPEN_DUP_NUM, + OP_CLOSE_DUP_NUM, + OP_NON_MATCH_LIST, + OP_OPEN_COLL_ELEM, + OP_CLOSE_COLL_ELEM, + OP_OPEN_EQUIV_CLASS, + OP_CLOSE_EQUIV_CLASS, + OP_OPEN_CHAR_CLASS, + OP_CLOSE_CHAR_CLASS, + OP_WORD, + OP_NOTWORD, + OP_SPACE, + OP_NOTSPACE, + BACK_SLASH + +} re_token_type_t; + +#ifdef RE_ENABLE_I18N +typedef struct +{ + /* Multibyte characters. */ + wchar_t *mbchars; + + /* Collating symbols. */ +# ifdef _LIBC + int32_t *coll_syms; +# endif + + /* Equivalence classes. */ +# ifdef _LIBC + int32_t *equiv_classes; +# endif + + /* Range expressions. */ +# ifdef _LIBC + uint32_t *range_starts; + uint32_t *range_ends; +# else /* not _LIBC */ + wchar_t *range_starts; + wchar_t *range_ends; +# endif /* not _LIBC */ + + /* Character classes. */ + wctype_t *char_classes; + + /* If this character set is the non-matching list. */ + unsigned int non_match : 1; + + /* # of multibyte characters. */ + Idx nmbchars; + + /* # of collating symbols. */ + Idx ncoll_syms; + + /* # of equivalence classes. */ + Idx nequiv_classes; + + /* # of range expressions. */ + Idx nranges; + + /* # of character classes. */ + Idx nchar_classes; +} re_charset_t; +#endif /* RE_ENABLE_I18N */ + +typedef struct +{ + union + { + unsigned char c; /* for CHARACTER */ + re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ +#ifdef RE_ENABLE_I18N + re_charset_t *mbcset; /* for COMPLEX_BRACKET */ +#endif /* RE_ENABLE_I18N */ + Idx idx; /* for BACK_REF */ + re_context_type ctx_type; /* for ANCHOR */ + } opr; +#if __GNUC__ >= 2 && !defined __STRICT_ANSI__ + re_token_type_t type : 8; +#else + re_token_type_t type; +#endif + unsigned int constraint : 10; /* context constraint */ + unsigned int duplicated : 1; + unsigned int opt_subexp : 1; +#ifdef RE_ENABLE_I18N + unsigned int accept_mb : 1; + /* These 2 bits can be moved into the union if needed (e.g. if running out + of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ + unsigned int mb_partial : 1; +#endif + unsigned int word_char : 1; +} re_token_t; + +#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) + +struct re_string_t +{ + /* Indicate the raw buffer which is the original string passed as an + argument of regexec(), re_search(), etc.. */ + const unsigned char *raw_mbs; + /* Store the multibyte string. In case of "case insensitive mode" like + REG_ICASE, upper cases of the string are stored, otherwise MBS points + the same address that RAW_MBS points. */ + unsigned char *mbs; +#ifdef RE_ENABLE_I18N + /* Store the wide character string which is corresponding to MBS. */ + wint_t *wcs; + Idx *offsets; + mbstate_t cur_state; +#endif + /* Index in RAW_MBS. Each character mbs[i] corresponds to + raw_mbs[raw_mbs_idx + i]. */ + Idx raw_mbs_idx; + /* The length of the valid characters in the buffers. */ + Idx valid_len; + /* The corresponding number of bytes in raw_mbs array. */ + Idx valid_raw_len; + /* The length of the buffers MBS and WCS. */ + Idx bufs_len; + /* The index in MBS, which is updated by re_string_fetch_byte. */ + Idx cur_idx; + /* length of RAW_MBS array. */ + Idx raw_len; + /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ + Idx len; + /* End of the buffer may be shorter than its length in the cases such + as re_match_2, re_search_2. Then, we use STOP for end of the buffer + instead of LEN. */ + Idx raw_stop; + /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ + Idx stop; + + /* The context of mbs[0]. We store the context independently, since + the context of mbs[0] may be different from raw_mbs[0], which is + the beginning of the input string. */ + unsigned int tip_context; + /* The translation passed as a part of an argument of re_compile_pattern. */ + RE_TRANSLATE_TYPE trans; + /* Copy of re_dfa_t's word_char. */ + re_const_bitset_ptr_t word_char; + /* true if REG_ICASE. */ + unsigned char icase; + unsigned char is_utf8; + unsigned char map_notascii; + unsigned char mbs_allocated; + unsigned char offsets_needed; + unsigned char newline_anchor; + unsigned char word_ops_used; + int mb_cur_max; +}; +typedef struct re_string_t re_string_t; + + +struct re_dfa_t; +typedef struct re_dfa_t re_dfa_t; + +#ifndef _LIBC +# define IS_IN(libc) false +#endif + +#define re_string_peek_byte(pstr, offset) \ + ((pstr)->mbs[(pstr)->cur_idx + offset]) +#define re_string_fetch_byte(pstr) \ + ((pstr)->mbs[(pstr)->cur_idx++]) +#define re_string_first_byte(pstr, idx) \ + ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) +#define re_string_is_single_byte_char(pstr, idx) \ + ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ + || (pstr)->wcs[(idx) + 1] != WEOF)) +#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) +#define re_string_cur_idx(pstr) ((pstr)->cur_idx) +#define re_string_get_buffer(pstr) ((pstr)->mbs) +#define re_string_length(pstr) ((pstr)->len) +#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) +#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) +#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) + +#if defined _LIBC || HAVE_ALLOCA +# include <alloca.h> +#endif + +#ifndef _LIBC +# if HAVE_ALLOCA +/* The OS usually guarantees only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + allocate anything larger than 4096 bytes. Also care for the possibility + of a few compiler-allocated temporary stack slots. */ +# define __libc_use_alloca(n) ((n) < 4032) +# else +/* alloca is implemented with malloc, so just use malloc. */ +# define __libc_use_alloca(n) 0 +# undef alloca +# define alloca(n) malloc (n) +# endif +#endif + +#ifdef _LIBC +# define MALLOC_0_IS_NONNULL 1 +#elif !defined MALLOC_0_IS_NONNULL +# define MALLOC_0_IS_NONNULL 0 +#endif + +#ifndef MAX +# define MAX(a,b) ((a) < (b) ? (b) : (a)) +#endif +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) +#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) +#define re_free(p) free (p) + +struct bin_tree_t +{ + struct bin_tree_t *parent; + struct bin_tree_t *left; + struct bin_tree_t *right; + struct bin_tree_t *first; + struct bin_tree_t *next; + + re_token_t token; + + /* 'node_idx' is the index in dfa->nodes, if 'type' == 0. + Otherwise 'type' indicate the type of this node. */ + Idx node_idx; +}; +typedef struct bin_tree_t bin_tree_t; + +#define BIN_TREE_STORAGE_SIZE \ + ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) + +struct bin_tree_storage_t +{ + struct bin_tree_storage_t *next; + bin_tree_t data[BIN_TREE_STORAGE_SIZE]; +}; +typedef struct bin_tree_storage_t bin_tree_storage_t; + +#define CONTEXT_WORD 1 +#define CONTEXT_NEWLINE (CONTEXT_WORD << 1) +#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) +#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) + +#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) +#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) +#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) +#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) +#define IS_ORDINARY_CONTEXT(c) ((c) == 0) + +#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') +#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) +#define IS_WIDE_WORD_CHAR(ch) (__iswalnum (ch) || (ch) == L'_') +#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) + +#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ + ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ + || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ + || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ + || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) + +#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ + ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ + || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ + || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ + || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) + +struct re_dfastate_t +{ + re_hashval_t hash; + re_node_set nodes; + re_node_set non_eps_nodes; + re_node_set inveclosure; + re_node_set *entrance_nodes; + struct re_dfastate_t **trtable, **word_trtable; + unsigned int context : 4; + unsigned int halt : 1; + /* If this state can accept "multi byte". + Note that we refer to multibyte characters, and multi character + collating elements as "multi byte". */ + unsigned int accept_mb : 1; + /* If this state has backreference node(s). */ + unsigned int has_backref : 1; + unsigned int has_constraint : 1; +}; +typedef struct re_dfastate_t re_dfastate_t; + +struct re_state_table_entry +{ + Idx num; + Idx alloc; + re_dfastate_t **array; +}; + +/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ + +typedef struct +{ + Idx next_idx; + Idx alloc; + re_dfastate_t **array; +} state_array_t; + +/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ + +typedef struct +{ + Idx node; + Idx str_idx; /* The position NODE match at. */ + state_array_t path; +} re_sub_match_last_t; + +/* Store information about the node NODE whose type is OP_OPEN_SUBEXP. + And information about the node, whose type is OP_CLOSE_SUBEXP, + corresponding to NODE is stored in LASTS. */ + +typedef struct +{ + Idx str_idx; + Idx node; + state_array_t *path; + Idx alasts; /* Allocation size of LASTS. */ + Idx nlasts; /* The number of LASTS. */ + re_sub_match_last_t **lasts; +} re_sub_match_top_t; + +struct re_backref_cache_entry +{ + Idx node; + Idx str_idx; + Idx subexp_from; + Idx subexp_to; + char more; + char unused; + unsigned short int eps_reachable_subexps_map; +}; + +typedef struct +{ + /* The string object corresponding to the input string. */ + re_string_t input; +#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) + const re_dfa_t *const dfa; +#else + const re_dfa_t *dfa; +#endif + /* EFLAGS of the argument of regexec. */ + int eflags; + /* Where the matching ends. */ + Idx match_last; + Idx last_node; + /* The state log used by the matcher. */ + re_dfastate_t **state_log; + Idx state_log_top; + /* Back reference cache. */ + Idx nbkref_ents; + Idx abkref_ents; + struct re_backref_cache_entry *bkref_ents; + int max_mb_elem_len; + Idx nsub_tops; + Idx asub_tops; + re_sub_match_top_t **sub_tops; +} re_match_context_t; + +typedef struct +{ + re_dfastate_t **sifted_states; + re_dfastate_t **limited_states; + Idx last_node; + Idx last_str_idx; + re_node_set limits; +} re_sift_context_t; + +struct re_fail_stack_ent_t +{ + Idx idx; + Idx node; + regmatch_t *regs; + re_node_set eps_via_nodes; +}; + +struct re_fail_stack_t +{ + Idx num; + Idx alloc; + struct re_fail_stack_ent_t *stack; +}; + +struct re_dfa_t +{ + re_token_t *nodes; + size_t nodes_alloc; + size_t nodes_len; + Idx *nexts; + Idx *org_indices; + re_node_set *edests; + re_node_set *eclosures; + re_node_set *inveclosures; + struct re_state_table_entry *state_table; + re_dfastate_t *init_state; + re_dfastate_t *init_state_word; + re_dfastate_t *init_state_nl; + re_dfastate_t *init_state_begbuf; + bin_tree_t *str_tree; + bin_tree_storage_t *str_tree_storage; + re_bitset_ptr_t sb_char; + int str_tree_storage_idx; + + /* number of subexpressions 're_nsub' is in regex_t. */ + re_hashval_t state_hash_mask; + Idx init_node; + Idx nbackref; /* The number of backreference in this dfa. */ + + /* Bitmap expressing which backreference is used. */ + bitset_word_t used_bkref_map; + bitset_word_t completed_bkref_map; + + unsigned int has_plural_match : 1; + /* If this dfa has "multibyte node", which is a backreference or + a node which can accept multibyte character or multi character + collating element. */ + unsigned int has_mb_node : 1; + unsigned int is_utf8 : 1; + unsigned int map_notascii : 1; + unsigned int word_ops_used : 1; + int mb_cur_max; + bitset_t word_char; + reg_syntax_t syntax; + Idx *subexp_map; +#ifdef DEBUG + char* re_str; +#endif + lock_define (lock) +}; + +#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) +#define re_node_set_remove(set,id) \ + (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) +#define re_node_set_empty(p) ((p)->nelem = 0) +#define re_node_set_free(set) re_free ((set)->elems) + + +typedef enum +{ + SB_CHAR, + MB_CHAR, + EQUIV_CLASS, + COLL_SYM, + CHAR_CLASS +} bracket_elem_type; + +typedef struct +{ + bracket_elem_type type; + union + { + unsigned char ch; + unsigned char *name; + wchar_t wch; + } opr; +} bracket_elem_t; + + +/* Functions for bitset_t operation. */ + +static inline void +bitset_set (bitset_t set, Idx i) +{ + set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS; +} + +static inline void +bitset_clear (bitset_t set, Idx i) +{ + set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS); +} + +static inline bool +bitset_contain (const bitset_t set, Idx i) +{ + return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1; +} + +static inline void +bitset_empty (bitset_t set) +{ + memset (set, '\0', sizeof (bitset_t)); +} + +static inline void +bitset_set_all (bitset_t set) +{ + memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS)); + if (SBC_MAX % BITSET_WORD_BITS != 0) + set[BITSET_WORDS - 1] = + ((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1; +} + +static inline void +bitset_copy (bitset_t dest, const bitset_t src) +{ + memcpy (dest, src, sizeof (bitset_t)); +} + +static inline void +bitset_not (bitset_t set) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i) + set[bitset_i] = ~set[bitset_i]; + if (SBC_MAX % BITSET_WORD_BITS != 0) + set[BITSET_WORDS - 1] = + ((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1) + & ~set[BITSET_WORDS - 1]); +} + +static inline void +bitset_merge (bitset_t dest, const bitset_t src) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) + dest[bitset_i] |= src[bitset_i]; +} + +static inline void +bitset_mask (bitset_t dest, const bitset_t src) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) + dest[bitset_i] &= src[bitset_i]; +} + +#ifdef RE_ENABLE_I18N +/* Functions for re_string. */ +static int +__attribute__ ((pure, unused)) +re_string_char_size_at (const re_string_t *pstr, Idx idx) +{ + int byte_idx; + if (pstr->mb_cur_max == 1) + return 1; + for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) + if (pstr->wcs[idx + byte_idx] != WEOF) + break; + return byte_idx; +} + +static wint_t +__attribute__ ((pure, unused)) +re_string_wchar_at (const re_string_t *pstr, Idx idx) +{ + if (pstr->mb_cur_max == 1) + return (wint_t) pstr->mbs[idx]; + return (wint_t) pstr->wcs[idx]; +} + +# ifdef _LIBC +# include <locale/weight.h> +# endif + +static int +__attribute__ ((pure, unused)) +re_string_elem_size_at (const re_string_t *pstr, Idx idx) +{ +# ifdef _LIBC + const unsigned char *p, *extra; + const int32_t *table, *indirect; + uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + + if (nrules != 0) + { + table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_INDIRECTMB); + p = pstr->mbs + idx; + findidx (table, indirect, extra, &p, pstr->len - idx); + return p - pstr->mbs - idx; + } + else +# endif /* _LIBC */ + return 1; +} +#endif /* RE_ENABLE_I18N */ + +#ifndef FALLTHROUGH +# if __GNUC__ < 7 +# define FALLTHROUGH ((void) 0) +# else +# define FALLTHROUGH __attribute__ ((__fallthrough__)) +# endif +#endif + +#endif /* _REGEX_INTERNAL_H */ diff --git a/grub-core/lib/gnulib/regexec.c b/grub-core/lib/gnulib/regexec.c new file mode 100644 index 0000000..be787f0 --- /dev/null +++ b/grub-core/lib/gnulib/regexec.c @@ -0,0 +1,4341 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, + Idx n); +static void match_ctx_clean (re_match_context_t *mctx); +static void match_ctx_free (re_match_context_t *cache); +static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, Idx node, + Idx str_idx, Idx from, Idx to); +static Idx search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx); +static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, Idx node, + Idx str_idx); +static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, + Idx node, Idx str_idx); +static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, + re_dfastate_t **limited_sts, Idx last_node, + Idx last_str_idx); +static reg_errcode_t re_search_internal (const regex_t *preg, + const char *string, Idx length, + Idx start, Idx last_start, Idx stop, + size_t nmatch, regmatch_t pmatch[], + int eflags); +static regoff_t re_search_2_stub (struct re_pattern_buffer *bufp, + const char *string1, Idx length1, + const char *string2, Idx length2, + Idx start, regoff_t range, + struct re_registers *regs, + Idx stop, bool ret_len); +static regoff_t re_search_stub (struct re_pattern_buffer *bufp, + const char *string, Idx length, Idx start, + regoff_t range, Idx stop, + struct re_registers *regs, + bool ret_len); +static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, + Idx nregs, int regs_allocated); +static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx); +static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match, + Idx *p_match_first); +static Idx check_halt_state_context (const re_match_context_t *mctx, + const re_dfastate_t *state, Idx idx); +static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, + regmatch_t *prev_idx_match, Idx cur_node, + Idx cur_idx, Idx nmatch); +static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, + Idx str_idx, Idx dest_node, Idx nregs, + regmatch_t *regs, + re_node_set *eps_via_nodes); +static reg_errcode_t set_regs (const regex_t *preg, + const re_match_context_t *mctx, + size_t nmatch, regmatch_t *pmatch, + bool fl_backtrack); +static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs); + +#ifdef RE_ENABLE_I18N +static int sift_states_iter_mb (const re_match_context_t *mctx, + re_sift_context_t *sctx, + Idx node_idx, Idx str_idx, Idx max_str_idx); +#endif /* RE_ENABLE_I18N */ +static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, + re_sift_context_t *sctx); +static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, + re_sift_context_t *sctx, Idx str_idx, + re_node_set *cur_dest); +static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx, + re_sift_context_t *sctx, + Idx str_idx, + re_node_set *dest_nodes); +static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa, + re_node_set *dest_nodes, + const re_node_set *candidates); +static bool check_dst_limits (const re_match_context_t *mctx, + const re_node_set *limits, + Idx dst_node, Idx dst_idx, Idx src_node, + Idx src_idx); +static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, + int boundaries, Idx subexp_idx, + Idx from_node, Idx bkref_idx); +static int check_dst_limits_calc_pos (const re_match_context_t *mctx, + Idx limit, Idx subexp_idx, + Idx node, Idx str_idx, + Idx bkref_idx); +static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa, + re_node_set *dest_nodes, + const re_node_set *candidates, + re_node_set *limits, + struct re_backref_cache_entry *bkref_ents, + Idx str_idx); +static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx, + re_sift_context_t *sctx, + Idx str_idx, const re_node_set *candidates); +static reg_errcode_t merge_state_array (const re_dfa_t *dfa, + re_dfastate_t **dst, + re_dfastate_t **src, Idx num); +static re_dfastate_t *find_recover_state (reg_errcode_t *err, + re_match_context_t *mctx); +static re_dfastate_t *transit_state (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *state); +static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *next_state); +static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, + re_node_set *cur_nodes, + Idx str_idx); +#if 0 +static re_dfastate_t *transit_state_sb (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *pstate); +#endif +#ifdef RE_ENABLE_I18N +static reg_errcode_t transit_state_mb (re_match_context_t *mctx, + re_dfastate_t *pstate); +#endif /* RE_ENABLE_I18N */ +static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, + const re_node_set *nodes); +static reg_errcode_t get_subexp (re_match_context_t *mctx, + Idx bkref_node, Idx bkref_str_idx); +static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, + const re_sub_match_top_t *sub_top, + re_sub_match_last_t *sub_last, + Idx bkref_node, Idx bkref_str); +static Idx find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, + Idx subexp_idx, int type); +static reg_errcode_t check_arrival (re_match_context_t *mctx, + state_array_t *path, Idx top_node, + Idx top_str, Idx last_node, Idx last_str, + int type); +static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, + Idx str_idx, + re_node_set *cur_nodes, + re_node_set *next_nodes); +static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa, + re_node_set *cur_nodes, + Idx ex_subexp, int type); +static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa, + re_node_set *dst_nodes, + Idx target, Idx ex_subexp, + int type); +static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, + re_node_set *cur_nodes, Idx cur_str, + Idx subexp_num, int type); +static bool build_trtable (const re_dfa_t *dfa, re_dfastate_t *state); +#ifdef RE_ENABLE_I18N +static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, + const re_string_t *input, Idx idx); +# ifdef _LIBC +static unsigned int find_collation_sequence_value (const unsigned char *mbs, + size_t name_len); +# endif /* _LIBC */ +#endif /* RE_ENABLE_I18N */ +static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa, + const re_dfastate_t *state, + re_node_set *states_node, + bitset_t *states_ch); +static bool check_node_accept (const re_match_context_t *mctx, + const re_token_t *node, Idx idx); +static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len); + +/* Entry point for POSIX code. */ + +/* regexec searches for a given pattern, specified by PREG, in the + string STRING. + + If NMATCH is zero or REG_NOSUB was set in the cflags argument to + 'regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at + least NMATCH elements, and we set them to the offsets of the + corresponding matched substrings. + + EFLAGS specifies "execution flags" which affect matching: if + REG_NOTBOL is set, then ^ does not match at the beginning of the + string; if REG_NOTEOL is set, then $ does not match at the end. + + We return 0 if we find a match and REG_NOMATCH if not. */ + +int +regexec (const regex_t *__restrict preg, const char *__restrict string, + size_t nmatch, regmatch_t pmatch[], int eflags) +{ + reg_errcode_t err; + Idx start, length; + re_dfa_t *dfa = preg->buffer; + + if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) + return REG_BADPAT; + + if (eflags & REG_STARTEND) + { + start = pmatch[0].rm_so; + length = pmatch[0].rm_eo; + } + else + { + start = 0; + length = strlen (string); + } + + lock_lock (dfa->lock); + if (preg->no_sub) + err = re_search_internal (preg, string, length, start, length, + length, 0, NULL, eflags); + else + err = re_search_internal (preg, string, length, start, length, + length, nmatch, pmatch, eflags); + lock_unlock (dfa->lock); + return err != REG_NOERROR; +} + +#ifdef _LIBC +libc_hidden_def (__regexec) + +# include <shlib-compat.h> +versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); + +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) +__typeof__ (__regexec) __compat_regexec; + +int +attribute_compat_text_section +__compat_regexec (const regex_t *__restrict preg, + const char *__restrict string, size_t nmatch, + regmatch_t pmatch[], int eflags) +{ + return regexec (preg, string, nmatch, pmatch, + eflags & (REG_NOTBOL | REG_NOTEOL)); +} +compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); +# endif +#endif + +/* Entry points for GNU code. */ + +/* re_match, re_search, re_match_2, re_search_2 + + The former two functions operate on STRING with length LENGTH, + while the later two operate on concatenation of STRING1 and STRING2 + with lengths LENGTH1 and LENGTH2, respectively. + + re_match() matches the compiled pattern in BUFP against the string, + starting at index START. + + re_search() first tries matching at index START, then it tries to match + starting from index START + 1, and so on. The last start position tried + is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same + way as re_match().) + + The parameter STOP of re_{match,search}_2 specifies that no match exceeding + the first STOP characters of the concatenation of the strings should be + concerned. + + If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match + and all groups is stored in REGS. (For the "_2" variants, the offsets are + computed relative to the concatenation, not relative to the individual + strings.) + + On success, re_match* functions return the length of the match, re_search* + return the position of the start of the match. Return value -1 means no + match was found and -2 indicates an internal error. */ + +regoff_t +re_match (struct re_pattern_buffer *bufp, const char *string, Idx length, + Idx start, struct re_registers *regs) +{ + return re_search_stub (bufp, string, length, start, 0, length, regs, true); +} +#ifdef _LIBC +weak_alias (__re_match, re_match) +#endif + +regoff_t +re_search (struct re_pattern_buffer *bufp, const char *string, Idx length, + Idx start, regoff_t range, struct re_registers *regs) +{ + return re_search_stub (bufp, string, length, start, range, length, regs, + false); +} +#ifdef _LIBC +weak_alias (__re_search, re_search) +#endif + +regoff_t +re_match_2 (struct re_pattern_buffer *bufp, const char *string1, Idx length1, + const char *string2, Idx length2, Idx start, + struct re_registers *regs, Idx stop) +{ + return re_search_2_stub (bufp, string1, length1, string2, length2, + start, 0, regs, stop, true); +} +#ifdef _LIBC +weak_alias (__re_match_2, re_match_2) +#endif + +regoff_t +re_search_2 (struct re_pattern_buffer *bufp, const char *string1, Idx length1, + const char *string2, Idx length2, Idx start, regoff_t range, + struct re_registers *regs, Idx stop) +{ + return re_search_2_stub (bufp, string1, length1, string2, length2, + start, range, regs, stop, false); +} +#ifdef _LIBC +weak_alias (__re_search_2, re_search_2) +#endif + +static regoff_t +re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1, + Idx length1, const char *string2, Idx length2, Idx start, + regoff_t range, struct re_registers *regs, + Idx stop, bool ret_len) +{ + const char *str; + regoff_t rval; + Idx len; + char *s = NULL; + + if (__glibc_unlikely ((length1 < 0 || length2 < 0 || stop < 0 + || INT_ADD_WRAPV (length1, length2, &len)))) + return -2; + + /* Concatenate the strings. */ + if (length2 > 0) + if (length1 > 0) + { + s = re_malloc (char, len); + + if (__glibc_unlikely (s == NULL)) + return -2; +#ifdef _LIBC + memcpy (__mempcpy (s, string1, length1), string2, length2); +#else + memcpy (s, string1, length1); + memcpy (s + length1, string2, length2); +#endif + str = s; + } + else + str = string2; + else + str = string1; + + rval = re_search_stub (bufp, str, len, start, range, stop, regs, + ret_len); + re_free (s); + return rval; +} + +/* The parameters have the same meaning as those of re_search. + Additional parameters: + If RET_LEN is true the length of the match is returned (re_match style); + otherwise the position of the match is returned. */ + +static regoff_t +re_search_stub (struct re_pattern_buffer *bufp, const char *string, Idx length, + Idx start, regoff_t range, Idx stop, struct re_registers *regs, + bool ret_len) +{ + reg_errcode_t result; + regmatch_t *pmatch; + Idx nregs; + regoff_t rval; + int eflags = 0; + re_dfa_t *dfa = bufp->buffer; + Idx last_start = start + range; + + /* Check for out-of-range. */ + if (__glibc_unlikely (start < 0 || start > length)) + return -1; + if (__glibc_unlikely (length < last_start + || (0 <= range && last_start < start))) + last_start = length; + else if (__glibc_unlikely (last_start < 0 + || (range < 0 && start <= last_start))) + last_start = 0; + + lock_lock (dfa->lock); + + eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; + eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; + + /* Compile fastmap if we haven't yet. */ + if (start < last_start && bufp->fastmap != NULL && !bufp->fastmap_accurate) + re_compile_fastmap (bufp); + + if (__glibc_unlikely (bufp->no_sub)) + regs = NULL; + + /* We need at least 1 register. */ + if (regs == NULL) + nregs = 1; + else if (__glibc_unlikely (bufp->regs_allocated == REGS_FIXED + && regs->num_regs <= bufp->re_nsub)) + { + nregs = regs->num_regs; + if (__glibc_unlikely (nregs < 1)) + { + /* Nothing can be copied to regs. */ + regs = NULL; + nregs = 1; + } + } + else + nregs = bufp->re_nsub + 1; + pmatch = re_malloc (regmatch_t, nregs); + if (__glibc_unlikely (pmatch == NULL)) + { + rval = -2; + goto out; + } + + result = re_search_internal (bufp, string, length, start, last_start, stop, + nregs, pmatch, eflags); + + rval = 0; + + /* I hope we needn't fill their regs with -1's when no match was found. */ + if (result != REG_NOERROR) + rval = result == REG_NOMATCH ? -1 : -2; + else if (regs != NULL) + { + /* If caller wants register contents data back, copy them. */ + bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, + bufp->regs_allocated); + if (__glibc_unlikely (bufp->regs_allocated == REGS_UNALLOCATED)) + rval = -2; + } + + if (__glibc_likely (rval == 0)) + { + if (ret_len) + { + assert (pmatch[0].rm_so == start); + rval = pmatch[0].rm_eo - start; + } + else + rval = pmatch[0].rm_so; + } + re_free (pmatch); + out: + lock_unlock (dfa->lock); + return rval; +} + +static unsigned +re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs, + int regs_allocated) +{ + int rval = REGS_REALLOCATE; + Idx i; + Idx need_regs = nregs + 1; + /* We need one extra element beyond 'num_regs' for the '-1' marker GNU code + uses. */ + + /* Have the register data arrays been allocated? */ + if (regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. */ + regs->start = re_malloc (regoff_t, need_regs); + if (__glibc_unlikely (regs->start == NULL)) + return REGS_UNALLOCATED; + regs->end = re_malloc (regoff_t, need_regs); + if (__glibc_unlikely (regs->end == NULL)) + { + re_free (regs->start); + return REGS_UNALLOCATED; + } + regs->num_regs = need_regs; + } + else if (regs_allocated == REGS_REALLOCATE) + { /* Yes. If we need more elements than were already + allocated, reallocate them. If we need fewer, just + leave it alone. */ + if (__glibc_unlikely (need_regs > regs->num_regs)) + { + regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); + regoff_t *new_end; + if (__glibc_unlikely (new_start == NULL)) + return REGS_UNALLOCATED; + new_end = re_realloc (regs->end, regoff_t, need_regs); + if (__glibc_unlikely (new_end == NULL)) + { + re_free (new_start); + return REGS_UNALLOCATED; + } + regs->start = new_start; + regs->end = new_end; + regs->num_regs = need_regs; + } + } + else + { + assert (regs_allocated == REGS_FIXED); + /* This function may not be called with REGS_FIXED and nregs too big. */ + assert (regs->num_regs >= nregs); + rval = REGS_FIXED; + } + + /* Copy the regs. */ + for (i = 0; i < nregs; ++i) + { + regs->start[i] = pmatch[i].rm_so; + regs->end[i] = pmatch[i].rm_eo; + } + for ( ; i < regs->num_regs; ++i) + regs->start[i] = regs->end[i] = -1; + + return rval; +} + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use + this memory for recording register information. STARTS and ENDS + must be allocated using the malloc library routine, and must each + be at least NUM_REGS * sizeof (regoff_t) bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ + +void +re_set_registers (struct re_pattern_buffer *bufp, struct re_registers *regs, + __re_size_t num_regs, regoff_t *starts, regoff_t *ends) +{ + if (num_regs) + { + bufp->regs_allocated = REGS_REALLOCATE; + regs->num_regs = num_regs; + regs->start = starts; + regs->end = ends; + } + else + { + bufp->regs_allocated = REGS_UNALLOCATED; + regs->num_regs = 0; + regs->start = regs->end = NULL; + } +} +#ifdef _LIBC +weak_alias (__re_set_registers, re_set_registers) +#endif + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them unless specifically requested. */ + +#if defined _REGEX_RE_COMP || defined _LIBC +int +# ifdef _LIBC +weak_function +# endif +re_exec (const char *s) +{ + return 0 == regexec (&re_comp_buf, s, 0, NULL, 0); +} +#endif /* _REGEX_RE_COMP */ + +/* Internal entry point. */ + +/* Searches for a compiled pattern PREG in the string STRING, whose + length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same + meaning as with regexec. LAST_START is START + RANGE, where + START and RANGE have the same meaning as with re_search. + Return REG_NOERROR if we find a match, and REG_NOMATCH if not, + otherwise return the error code. + Note: We assume front end functions already check ranges. + (0 <= LAST_START && LAST_START <= LENGTH) */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_search_internal (const regex_t *preg, const char *string, Idx length, + Idx start, Idx last_start, Idx stop, size_t nmatch, + regmatch_t pmatch[], int eflags) +{ + reg_errcode_t err; + const re_dfa_t *dfa = preg->buffer; + Idx left_lim, right_lim; + int incr; + bool fl_longest_match; + int match_kind; + Idx match_first; + Idx match_last = -1; + Idx extra_nmatch; + bool sb; + int ch; +#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) + re_match_context_t mctx = { .dfa = dfa }; +#else + re_match_context_t mctx; +#endif + char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate + && start != last_start && !preg->can_be_null) + ? preg->fastmap : NULL); + RE_TRANSLATE_TYPE t = preg->translate; + +#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) + memset (&mctx, '\0', sizeof (re_match_context_t)); + mctx.dfa = dfa; +#endif + + extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0; + nmatch -= extra_nmatch; + + /* Check if the DFA haven't been compiled. */ + if (__glibc_unlikely (preg->used == 0 || dfa->init_state == NULL + || dfa->init_state_word == NULL + || dfa->init_state_nl == NULL + || dfa->init_state_begbuf == NULL)) + return REG_NOMATCH; + +#ifdef DEBUG + /* We assume front-end functions already check them. */ + assert (0 <= last_start && last_start <= length); +#endif + + /* If initial states with non-begbuf contexts have no elements, + the regex must be anchored. If preg->newline_anchor is set, + we'll never use init_state_nl, so do not check it. */ + if (dfa->init_state->nodes.nelem == 0 + && dfa->init_state_word->nodes.nelem == 0 + && (dfa->init_state_nl->nodes.nelem == 0 + || !preg->newline_anchor)) + { + if (start != 0 && last_start != 0) + return REG_NOMATCH; + start = last_start = 0; + } + + /* We must check the longest matching, if nmatch > 0. */ + fl_longest_match = (nmatch != 0 || dfa->nbackref); + + err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, + preg->translate, (preg->syntax & RE_ICASE) != 0, + dfa); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + mctx.input.stop = stop; + mctx.input.raw_stop = stop; + mctx.input.newline_anchor = preg->newline_anchor; + + err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + + /* We will log all the DFA states through which the dfa pass, + if nmatch > 1, or this dfa has "multibyte node", which is a + back-reference or a node which can accept multibyte character or + multi character collating element. */ + if (nmatch > 1 || dfa->has_mb_node) + { + /* Avoid overflow. */ + if (__glibc_unlikely ((MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) + <= mctx.input.bufs_len))) + { + err = REG_ESPACE; + goto free_return; + } + + mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); + if (__glibc_unlikely (mctx.state_log == NULL)) + { + err = REG_ESPACE; + goto free_return; + } + } + else + mctx.state_log = NULL; + + match_first = start; + mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF + : CONTEXT_NEWLINE | CONTEXT_BEGBUF; + + /* Check incrementally whether the input string matches. */ + incr = (last_start < start) ? -1 : 1; + left_lim = (last_start < start) ? last_start : start; + right_lim = (last_start < start) ? start : last_start; + sb = dfa->mb_cur_max == 1; + match_kind = + (fastmap + ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) + | (start <= last_start ? 2 : 0) + | (t != NULL ? 1 : 0)) + : 8); + + for (;; match_first += incr) + { + err = REG_NOMATCH; + if (match_first < left_lim || right_lim < match_first) + goto free_return; + + /* Advance as rapidly as possible through the string, until we + find a plausible place to start matching. This may be done + with varying efficiency, so there are various possibilities: + only the most common of them are specialized, in order to + save on code size. We use a switch statement for speed. */ + switch (match_kind) + { + case 8: + /* No fastmap. */ + break; + + case 7: + /* Fastmap with single-byte translation, match forward. */ + while (__glibc_likely (match_first < right_lim) + && !fastmap[t[(unsigned char) string[match_first]]]) + ++match_first; + goto forward_match_found_start_or_reached_end; + + case 6: + /* Fastmap without translation, match forward. */ + while (__glibc_likely (match_first < right_lim) + && !fastmap[(unsigned char) string[match_first]]) + ++match_first; + + forward_match_found_start_or_reached_end: + if (__glibc_unlikely (match_first == right_lim)) + { + ch = match_first >= length + ? 0 : (unsigned char) string[match_first]; + if (!fastmap[t ? t[ch] : ch]) + goto free_return; + } + break; + + case 4: + case 5: + /* Fastmap without multi-byte translation, match backwards. */ + while (match_first >= left_lim) + { + ch = match_first >= length + ? 0 : (unsigned char) string[match_first]; + if (fastmap[t ? t[ch] : ch]) + break; + --match_first; + } + if (match_first < left_lim) + goto free_return; + break; + + default: + /* In this case, we can't determine easily the current byte, + since it might be a component byte of a multibyte + character. Then we use the constructed buffer instead. */ + for (;;) + { + /* If MATCH_FIRST is out of the valid range, reconstruct the + buffers. */ + __re_size_t offset = match_first - mctx.input.raw_mbs_idx; + if (__glibc_unlikely (offset + >= (__re_size_t) mctx.input.valid_raw_len)) + { + err = re_string_reconstruct (&mctx.input, match_first, + eflags); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + + offset = match_first - mctx.input.raw_mbs_idx; + } + /* If MATCH_FIRST is out of the buffer, leave it as '\0'. + Note that MATCH_FIRST must not be smaller than 0. */ + ch = (match_first >= length + ? 0 : re_string_byte_at (&mctx.input, offset)); + if (fastmap[ch]) + break; + match_first += incr; + if (match_first < left_lim || match_first > right_lim) + { + err = REG_NOMATCH; + goto free_return; + } + } + break; + } + + /* Reconstruct the buffers so that the matcher can assume that + the matching starts from the beginning of the buffer. */ + err = re_string_reconstruct (&mctx.input, match_first, eflags); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + +#ifdef RE_ENABLE_I18N + /* Don't consider this char as a possible match start if it part, + yet isn't the head, of a multibyte character. */ + if (!sb && !re_string_first_byte (&mctx.input, 0)) + continue; +#endif + + /* It seems to be appropriate one, then use the matcher. */ + /* We assume that the matching starts from 0. */ + mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; + match_last = check_matching (&mctx, fl_longest_match, + start <= last_start ? &match_first : NULL); + if (match_last != -1) + { + if (__glibc_unlikely (match_last == -2)) + { + err = REG_ESPACE; + goto free_return; + } + else + { + mctx.match_last = match_last; + if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) + { + re_dfastate_t *pstate = mctx.state_log[match_last]; + mctx.last_node = check_halt_state_context (&mctx, pstate, + match_last); + } + if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) + || dfa->nbackref) + { + err = prune_impossible_nodes (&mctx); + if (err == REG_NOERROR) + break; + if (__glibc_unlikely (err != REG_NOMATCH)) + goto free_return; +#ifdef DEBUG + /* Only used for assertion below when DEBUG is set, otherwise + it will be over-written when we loop around. */ + match_last = -1; +#endif + } + else + break; /* We found a match. */ + } + } + + match_ctx_clean (&mctx); + } + +#ifdef DEBUG + assert (match_last != -1); + assert (err == REG_NOERROR); +#endif + + /* Set pmatch[] if we need. */ + if (nmatch > 0) + { + Idx reg_idx; + + /* Initialize registers. */ + for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) + pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; + + /* Set the points where matching start/end. */ + pmatch[0].rm_so = 0; + pmatch[0].rm_eo = mctx.match_last; + /* FIXME: This function should fail if mctx.match_last exceeds + the maximum possible regoff_t value. We need a new error + code REG_OVERFLOW. */ + + if (!preg->no_sub && nmatch > 1) + { + err = set_regs (preg, &mctx, nmatch, pmatch, + dfa->has_plural_match && dfa->nbackref > 0); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + + /* At last, add the offset to each register, since we slid + the buffers so that we could assume that the matching starts + from 0. */ + for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) + if (pmatch[reg_idx].rm_so != -1) + { +#ifdef RE_ENABLE_I18N + if (__glibc_unlikely (mctx.input.offsets_needed != 0)) + { + pmatch[reg_idx].rm_so = + (pmatch[reg_idx].rm_so == mctx.input.valid_len + ? mctx.input.valid_raw_len + : mctx.input.offsets[pmatch[reg_idx].rm_so]); + pmatch[reg_idx].rm_eo = + (pmatch[reg_idx].rm_eo == mctx.input.valid_len + ? mctx.input.valid_raw_len + : mctx.input.offsets[pmatch[reg_idx].rm_eo]); + } +#else + assert (mctx.input.offsets_needed == 0); +#endif + pmatch[reg_idx].rm_so += match_first; + pmatch[reg_idx].rm_eo += match_first; + } + for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx) + { + pmatch[nmatch + reg_idx].rm_so = -1; + pmatch[nmatch + reg_idx].rm_eo = -1; + } + + if (dfa->subexp_map) + for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++) + if (dfa->subexp_map[reg_idx] != reg_idx) + { + pmatch[reg_idx + 1].rm_so + = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; + pmatch[reg_idx + 1].rm_eo + = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; + } + } + + free_return: + re_free (mctx.state_log); + if (dfa->nbackref) + match_ctx_free (&mctx); + re_string_destruct (&mctx.input); + return err; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +prune_impossible_nodes (re_match_context_t *mctx) +{ + const re_dfa_t *const dfa = mctx->dfa; + Idx halt_node, match_last; + reg_errcode_t ret; + re_dfastate_t **sifted_states; + re_dfastate_t **lim_states = NULL; + re_sift_context_t sctx; +#ifdef DEBUG + assert (mctx->state_log != NULL); +#endif + match_last = mctx->match_last; + halt_node = mctx->last_node; + + /* Avoid overflow. */ + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) + <= match_last)) + return REG_ESPACE; + + sifted_states = re_malloc (re_dfastate_t *, match_last + 1); + if (__glibc_unlikely (sifted_states == NULL)) + { + ret = REG_ESPACE; + goto free_return; + } + if (dfa->nbackref) + { + lim_states = re_malloc (re_dfastate_t *, match_last + 1); + if (__glibc_unlikely (lim_states == NULL)) + { + ret = REG_ESPACE; + goto free_return; + } + while (1) + { + memset (lim_states, '\0', + sizeof (re_dfastate_t *) * (match_last + 1)); + sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, + match_last); + ret = sift_states_backward (mctx, &sctx); + re_node_set_free (&sctx.limits); + if (__glibc_unlikely (ret != REG_NOERROR)) + goto free_return; + if (sifted_states[0] != NULL || lim_states[0] != NULL) + break; + do + { + --match_last; + if (match_last < 0) + { + ret = REG_NOMATCH; + goto free_return; + } + } while (mctx->state_log[match_last] == NULL + || !mctx->state_log[match_last]->halt); + halt_node = check_halt_state_context (mctx, + mctx->state_log[match_last], + match_last); + } + ret = merge_state_array (dfa, sifted_states, lim_states, + match_last + 1); + re_free (lim_states); + lim_states = NULL; + if (__glibc_unlikely (ret != REG_NOERROR)) + goto free_return; + } + else + { + sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); + ret = sift_states_backward (mctx, &sctx); + re_node_set_free (&sctx.limits); + if (__glibc_unlikely (ret != REG_NOERROR)) + goto free_return; + if (sifted_states[0] == NULL) + { + ret = REG_NOMATCH; + goto free_return; + } + } + re_free (mctx->state_log); + mctx->state_log = sifted_states; + sifted_states = NULL; + mctx->last_node = halt_node; + mctx->match_last = match_last; + ret = REG_NOERROR; + free_return: + re_free (sifted_states); + re_free (lim_states); + return ret; +} + +/* Acquire an initial state and return it. + We must select appropriate initial state depending on the context, + since initial states may have constraints like "\<", "^", etc.. */ + +static inline re_dfastate_t * +__attribute__ ((always_inline)) +acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, + Idx idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + if (dfa->init_state->has_constraint) + { + unsigned int context; + context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); + if (IS_WORD_CONTEXT (context)) + return dfa->init_state_word; + else if (IS_ORDINARY_CONTEXT (context)) + return dfa->init_state; + else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) + return dfa->init_state_begbuf; + else if (IS_NEWLINE_CONTEXT (context)) + return dfa->init_state_nl; + else if (IS_BEGBUF_CONTEXT (context)) + { + /* It is relatively rare case, then calculate on demand. */ + return re_acquire_state_context (err, dfa, + dfa->init_state->entrance_nodes, + context); + } + else + /* Must not happen? */ + return dfa->init_state; + } + else + return dfa->init_state; +} + +/* Check whether the regular expression match input string INPUT or not, + and return the index where the matching end. Return -1 if + there is no match, and return -2 in case of an error. + FL_LONGEST_MATCH means we want the POSIX longest matching. + If P_MATCH_FIRST is not NULL, and the match fails, it is set to the + next place where we may want to try matching. + Note that the matcher assumes that the matching starts from the current + index of the buffer. */ + +static Idx +__attribute_warn_unused_result__ +check_matching (re_match_context_t *mctx, bool fl_longest_match, + Idx *p_match_first) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + Idx match = 0; + Idx match_last = -1; + Idx cur_str_idx = re_string_cur_idx (&mctx->input); + re_dfastate_t *cur_state; + bool at_init_state = p_match_first != NULL; + Idx next_start_idx = cur_str_idx; + + err = REG_NOERROR; + cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); + /* An initial state must not be NULL (invalid). */ + if (__glibc_unlikely (cur_state == NULL)) + { + assert (err == REG_ESPACE); + return -2; + } + + if (mctx->state_log != NULL) + { + mctx->state_log[cur_str_idx] = cur_state; + + /* Check OP_OPEN_SUBEXP in the initial state in case that we use them + later. E.g. Processing back references. */ + if (__glibc_unlikely (dfa->nbackref)) + { + at_init_state = false; + err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + if (cur_state->has_backref) + { + err = transit_state_bkref (mctx, &cur_state->nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + } + + /* If the RE accepts NULL string. */ + if (__glibc_unlikely (cur_state->halt)) + { + if (!cur_state->has_constraint + || check_halt_state_context (mctx, cur_state, cur_str_idx)) + { + if (!fl_longest_match) + return cur_str_idx; + else + { + match_last = cur_str_idx; + match = 1; + } + } + } + + while (!re_string_eoi (&mctx->input)) + { + re_dfastate_t *old_state = cur_state; + Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1; + + if ((__glibc_unlikely (next_char_idx >= mctx->input.bufs_len) + && mctx->input.bufs_len < mctx->input.len) + || (__glibc_unlikely (next_char_idx >= mctx->input.valid_len) + && mctx->input.valid_len < mctx->input.len)) + { + err = extend_buffers (mctx, next_char_idx + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + { + assert (err == REG_ESPACE); + return -2; + } + } + + cur_state = transit_state (&err, mctx, cur_state); + if (mctx->state_log != NULL) + cur_state = merge_state_with_log (&err, mctx, cur_state); + + if (cur_state == NULL) + { + /* Reached the invalid state or an error. Try to recover a valid + state using the state log, if available and if we have not + already found a valid (even if not the longest) match. */ + if (__glibc_unlikely (err != REG_NOERROR)) + return -2; + + if (mctx->state_log == NULL + || (match && !fl_longest_match) + || (cur_state = find_recover_state (&err, mctx)) == NULL) + break; + } + + if (__glibc_unlikely (at_init_state)) + { + if (old_state == cur_state) + next_start_idx = next_char_idx; + else + at_init_state = false; + } + + if (cur_state->halt) + { + /* Reached a halt state. + Check the halt state can satisfy the current context. */ + if (!cur_state->has_constraint + || check_halt_state_context (mctx, cur_state, + re_string_cur_idx (&mctx->input))) + { + /* We found an appropriate halt state. */ + match_last = re_string_cur_idx (&mctx->input); + match = 1; + + /* We found a match, do not modify match_first below. */ + p_match_first = NULL; + if (!fl_longest_match) + break; + } + } + } + + if (p_match_first) + *p_match_first += next_start_idx; + + return match_last; +} + +/* Check NODE match the current context. */ + +static bool +check_halt_node_context (const re_dfa_t *dfa, Idx node, unsigned int context) +{ + re_token_type_t type = dfa->nodes[node].type; + unsigned int constraint = dfa->nodes[node].constraint; + if (type != END_OF_RE) + return false; + if (!constraint) + return true; + if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) + return false; + return true; +} + +/* Check the halt state STATE match the current context. + Return 0 if not match, if the node, STATE has, is a halt node and + match the context, return the node. */ + +static Idx +check_halt_state_context (const re_match_context_t *mctx, + const re_dfastate_t *state, Idx idx) +{ + Idx i; + unsigned int context; +#ifdef DEBUG + assert (state->halt); +#endif + context = re_string_context_at (&mctx->input, idx, mctx->eflags); + for (i = 0; i < state->nodes.nelem; ++i) + if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) + return state->nodes.elems[i]; + return 0; +} + +/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA + corresponding to the DFA). + Return the destination node, and update EPS_VIA_NODES; + return -1 in case of errors. */ + +static Idx +proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, + Idx *pidx, Idx node, re_node_set *eps_via_nodes, + struct re_fail_stack_t *fs) +{ + const re_dfa_t *const dfa = mctx->dfa; + Idx i; + bool ok; + if (IS_EPSILON_NODE (dfa->nodes[node].type)) + { + re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; + re_node_set *edests = &dfa->edests[node]; + Idx dest_node; + ok = re_node_set_insert (eps_via_nodes, node); + if (__glibc_unlikely (! ok)) + return -2; + /* Pick up a valid destination, or return -1 if none + is found. */ + for (dest_node = -1, i = 0; i < edests->nelem; ++i) + { + Idx candidate = edests->elems[i]; + if (!re_node_set_contains (cur_nodes, candidate)) + continue; + if (dest_node == -1) + dest_node = candidate; + + else + { + /* In order to avoid infinite loop like "(a*)*", return the second + epsilon-transition if the first was already considered. */ + if (re_node_set_contains (eps_via_nodes, dest_node)) + return candidate; + + /* Otherwise, push the second epsilon-transition on the fail stack. */ + else if (fs != NULL + && push_fail_stack (fs, *pidx, candidate, nregs, regs, + eps_via_nodes)) + return -2; + + /* We know we are going to exit. */ + break; + } + } + return dest_node; + } + else + { + Idx naccepted = 0; + re_token_type_t type = dfa->nodes[node].type; + +#ifdef RE_ENABLE_I18N + if (dfa->nodes[node].accept_mb) + naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); + else +#endif /* RE_ENABLE_I18N */ + if (type == OP_BACK_REF) + { + Idx subexp_idx = dfa->nodes[node].opr.idx + 1; + naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; + if (fs != NULL) + { + if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1) + return -1; + else if (naccepted) + { + char *buf = (char *) re_string_get_buffer (&mctx->input); + if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, + naccepted) != 0) + return -1; + } + } + + if (naccepted == 0) + { + Idx dest_node; + ok = re_node_set_insert (eps_via_nodes, node); + if (__glibc_unlikely (! ok)) + return -2; + dest_node = dfa->edests[node].elems[0]; + if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, + dest_node)) + return dest_node; + } + } + + if (naccepted != 0 + || check_node_accept (mctx, dfa->nodes + node, *pidx)) + { + Idx dest_node = dfa->nexts[node]; + *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; + if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL + || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, + dest_node))) + return -1; + re_node_set_empty (eps_via_nodes); + return dest_node; + } + } + return -1; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node, + Idx nregs, regmatch_t *regs, re_node_set *eps_via_nodes) +{ + reg_errcode_t err; + Idx num = fs->num++; + if (fs->num == fs->alloc) + { + struct re_fail_stack_ent_t *new_array; + new_array = re_realloc (fs->stack, struct re_fail_stack_ent_t, + fs->alloc * 2); + if (new_array == NULL) + return REG_ESPACE; + fs->alloc *= 2; + fs->stack = new_array; + } + fs->stack[num].idx = str_idx; + fs->stack[num].node = dest_node; + fs->stack[num].regs = re_malloc (regmatch_t, nregs); + if (fs->stack[num].regs == NULL) + return REG_ESPACE; + memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); + err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); + return err; +} + +static Idx +pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs, + regmatch_t *regs, re_node_set *eps_via_nodes) +{ + Idx num = --fs->num; + assert (num >= 0); + *pidx = fs->stack[num].idx; + memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); + re_node_set_free (eps_via_nodes); + re_free (fs->stack[num].regs); + *eps_via_nodes = fs->stack[num].eps_via_nodes; + return fs->stack[num].node; +} + +/* Set the positions where the subexpressions are starts/ends to registers + PMATCH. + Note: We assume that pmatch[0] is already set, and + pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, + regmatch_t *pmatch, bool fl_backtrack) +{ + const re_dfa_t *dfa = preg->buffer; + Idx idx, cur_node; + re_node_set eps_via_nodes; + struct re_fail_stack_t *fs; + struct re_fail_stack_t fs_body = { 0, 2, NULL }; + regmatch_t *prev_idx_match; + bool prev_idx_match_malloced = false; + +#ifdef DEBUG + assert (nmatch > 1); + assert (mctx->state_log != NULL); +#endif + if (fl_backtrack) + { + fs = &fs_body; + fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); + if (fs->stack == NULL) + return REG_ESPACE; + } + else + fs = NULL; + + cur_node = dfa->init_node; + re_node_set_init_empty (&eps_via_nodes); + + if (__libc_use_alloca (nmatch * sizeof (regmatch_t))) + prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t)); + else + { + prev_idx_match = re_malloc (regmatch_t, nmatch); + if (prev_idx_match == NULL) + { + free_fail_stack_return (fs); + return REG_ESPACE; + } + prev_idx_match_malloced = true; + } + memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); + + for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) + { + update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); + + if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) + { + Idx reg_idx; + if (fs) + { + for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) + if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) + break; + if (reg_idx == nmatch) + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return free_fail_stack_return (fs); + } + cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, + &eps_via_nodes); + } + else + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return REG_NOERROR; + } + } + + /* Proceed to next node. */ + cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node, + &eps_via_nodes, fs); + + if (__glibc_unlikely (cur_node < 0)) + { + if (__glibc_unlikely (cur_node == -2)) + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + free_fail_stack_return (fs); + return REG_ESPACE; + } + if (fs) + cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, + &eps_via_nodes); + else + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return REG_NOMATCH; + } + } + } + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return free_fail_stack_return (fs); +} + +static reg_errcode_t +free_fail_stack_return (struct re_fail_stack_t *fs) +{ + if (fs) + { + Idx fs_idx; + for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) + { + re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); + re_free (fs->stack[fs_idx].regs); + } + re_free (fs->stack); + } + return REG_NOERROR; +} + +static void +update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, + regmatch_t *prev_idx_match, Idx cur_node, Idx cur_idx, Idx nmatch) +{ + int type = dfa->nodes[cur_node].type; + if (type == OP_OPEN_SUBEXP) + { + Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; + + /* We are at the first node of this sub expression. */ + if (reg_num < nmatch) + { + pmatch[reg_num].rm_so = cur_idx; + pmatch[reg_num].rm_eo = -1; + } + } + else if (type == OP_CLOSE_SUBEXP) + { + Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; + if (reg_num < nmatch) + { + /* We are at the last node of this sub expression. */ + if (pmatch[reg_num].rm_so < cur_idx) + { + pmatch[reg_num].rm_eo = cur_idx; + /* This is a non-empty match or we are not inside an optional + subexpression. Accept this right away. */ + memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); + } + else + { + if (dfa->nodes[cur_node].opt_subexp + && prev_idx_match[reg_num].rm_so != -1) + /* We transited through an empty match for an optional + subexpression, like (a?)*, and this is not the subexp's + first match. Copy back the old content of the registers + so that matches of an inner subexpression are undone as + well, like in ((a?))*. */ + memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); + else + /* We completed a subexpression, but it may be part of + an optional one, so do not update PREV_IDX_MATCH. */ + pmatch[reg_num].rm_eo = cur_idx; + } + } + } +} + +/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 + and sift the nodes in each states according to the following rules. + Updated state_log will be wrote to STATE_LOG. + + Rules: We throw away the Node 'a' in the STATE_LOG[STR_IDX] if... + 1. When STR_IDX == MATCH_LAST(the last index in the state_log): + If 'a' isn't the LAST_NODE and 'a' can't epsilon transit to + the LAST_NODE, we throw away the node 'a'. + 2. When 0 <= STR_IDX < MATCH_LAST and 'a' accepts + string 's' and transit to 'b': + i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw + away the node 'a'. + ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is + thrown away, we throw away the node 'a'. + 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': + i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the + node 'a'. + ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, + we throw away the node 'a'. */ + +#define STATE_NODE_CONTAINS(state,node) \ + ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) + +static reg_errcode_t +sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) +{ + reg_errcode_t err; + int null_cnt = 0; + Idx str_idx = sctx->last_str_idx; + re_node_set cur_dest; + +#ifdef DEBUG + assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); +#endif + + /* Build sifted state_log[str_idx]. It has the nodes which can epsilon + transit to the last_node and the last_node itself. */ + err = re_node_set_init_1 (&cur_dest, sctx->last_node); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + + /* Then check each states in the state_log. */ + while (str_idx > 0) + { + /* Update counters. */ + null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; + if (null_cnt > mctx->max_mb_elem_len) + { + memset (sctx->sifted_states, '\0', + sizeof (re_dfastate_t *) * str_idx); + re_node_set_free (&cur_dest); + return REG_NOERROR; + } + re_node_set_empty (&cur_dest); + --str_idx; + + if (mctx->state_log[str_idx]) + { + err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + + /* Add all the nodes which satisfy the following conditions: + - It can epsilon transit to a node in CUR_DEST. + - It is in CUR_SRC. + And update state_log. */ + err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + err = REG_NOERROR; + free_return: + re_node_set_free (&cur_dest); + return err; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, + Idx str_idx, re_node_set *cur_dest) +{ + const re_dfa_t *const dfa = mctx->dfa; + const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; + Idx i; + + /* Then build the next sifted state. + We build the next sifted state on 'cur_dest', and update + 'sifted_states[str_idx]' with 'cur_dest'. + Note: + 'cur_dest' is the sifted state from 'state_log[str_idx + 1]'. + 'cur_src' points the node_set of the old 'state_log[str_idx]' + (with the epsilon nodes pre-filtered out). */ + for (i = 0; i < cur_src->nelem; i++) + { + Idx prev_node = cur_src->elems[i]; + int naccepted = 0; + bool ok; + +#ifdef DEBUG + re_token_type_t type = dfa->nodes[prev_node].type; + assert (!IS_EPSILON_NODE (type)); +#endif +#ifdef RE_ENABLE_I18N + /* If the node may accept "multi byte". */ + if (dfa->nodes[prev_node].accept_mb) + naccepted = sift_states_iter_mb (mctx, sctx, prev_node, + str_idx, sctx->last_str_idx); +#endif /* RE_ENABLE_I18N */ + + /* We don't check backreferences here. + See update_cur_sifted_state(). */ + if (!naccepted + && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) + && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], + dfa->nexts[prev_node])) + naccepted = 1; + + if (naccepted == 0) + continue; + + if (sctx->limits.nelem) + { + Idx to_idx = str_idx + naccepted; + if (check_dst_limits (mctx, &sctx->limits, + dfa->nexts[prev_node], to_idx, + prev_node, str_idx)) + continue; + } + ok = re_node_set_insert (cur_dest, prev_node); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + + return REG_NOERROR; +} + +/* Helper functions. */ + +static reg_errcode_t +clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx) +{ + Idx top = mctx->state_log_top; + + if (mctx->state_log == NULL) + return REG_NOERROR; + + if ((next_state_log_idx >= mctx->input.bufs_len + && mctx->input.bufs_len < mctx->input.len) + || (next_state_log_idx >= mctx->input.valid_len + && mctx->input.valid_len < mctx->input.len)) + { + reg_errcode_t err; + err = extend_buffers (mctx, next_state_log_idx + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + + if (top < next_state_log_idx) + { + memset (mctx->state_log + top + 1, '\0', + sizeof (re_dfastate_t *) * (next_state_log_idx - top)); + mctx->state_log_top = next_state_log_idx; + } + return REG_NOERROR; +} + +static reg_errcode_t +merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, + re_dfastate_t **src, Idx num) +{ + Idx st_idx; + reg_errcode_t err; + for (st_idx = 0; st_idx < num; ++st_idx) + { + if (dst[st_idx] == NULL) + dst[st_idx] = src[st_idx]; + else if (src[st_idx] != NULL) + { + re_node_set merged_set; + err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, + &src[st_idx]->nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); + re_node_set_free (&merged_set); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + return REG_NOERROR; +} + +static reg_errcode_t +update_cur_sifted_state (const re_match_context_t *mctx, + re_sift_context_t *sctx, Idx str_idx, + re_node_set *dest_nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err = REG_NOERROR; + const re_node_set *candidates; + candidates = ((mctx->state_log[str_idx] == NULL) ? NULL + : &mctx->state_log[str_idx]->nodes); + + if (dest_nodes->nelem == 0) + sctx->sifted_states[str_idx] = NULL; + else + { + if (candidates) + { + /* At first, add the nodes which can epsilon transit to a node in + DEST_NODE. */ + err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + /* Then, check the limitations in the current sift_context. */ + if (sctx->limits.nelem) + { + err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, + mctx->bkref_ents, str_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + + sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + + if (candidates && mctx->state_log[str_idx]->has_backref) + { + err = sift_states_bkref (mctx, sctx, str_idx, candidates); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + return REG_NOERROR; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, + const re_node_set *candidates) +{ + reg_errcode_t err = REG_NOERROR; + Idx i; + + re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + if (!state->inveclosure.alloc) + { + err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); + if (__glibc_unlikely (err != REG_NOERROR)) + return REG_ESPACE; + for (i = 0; i < dest_nodes->nelem; i++) + { + err = re_node_set_merge (&state->inveclosure, + dfa->inveclosures + dest_nodes->elems[i]); + if (__glibc_unlikely (err != REG_NOERROR)) + return REG_ESPACE; + } + } + return re_node_set_add_intersect (dest_nodes, candidates, + &state->inveclosure); +} + +static reg_errcode_t +sub_epsilon_src_nodes (const re_dfa_t *dfa, Idx node, re_node_set *dest_nodes, + const re_node_set *candidates) +{ + Idx ecl_idx; + reg_errcode_t err; + re_node_set *inv_eclosure = dfa->inveclosures + node; + re_node_set except_nodes; + re_node_set_init_empty (&except_nodes); + for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) + { + Idx cur_node = inv_eclosure->elems[ecl_idx]; + if (cur_node == node) + continue; + if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) + { + Idx edst1 = dfa->edests[cur_node].elems[0]; + Idx edst2 = ((dfa->edests[cur_node].nelem > 1) + ? dfa->edests[cur_node].elems[1] : -1); + if ((!re_node_set_contains (inv_eclosure, edst1) + && re_node_set_contains (dest_nodes, edst1)) + || (edst2 > 0 + && !re_node_set_contains (inv_eclosure, edst2) + && re_node_set_contains (dest_nodes, edst2))) + { + err = re_node_set_add_intersect (&except_nodes, candidates, + dfa->inveclosures + cur_node); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&except_nodes); + return err; + } + } + } + } + for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) + { + Idx cur_node = inv_eclosure->elems[ecl_idx]; + if (!re_node_set_contains (&except_nodes, cur_node)) + { + Idx idx = re_node_set_contains (dest_nodes, cur_node) - 1; + re_node_set_remove_at (dest_nodes, idx); + } + } + re_node_set_free (&except_nodes); + return REG_NOERROR; +} + +static bool +check_dst_limits (const re_match_context_t *mctx, const re_node_set *limits, + Idx dst_node, Idx dst_idx, Idx src_node, Idx src_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + Idx lim_idx, src_pos, dst_pos; + + Idx dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); + Idx src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); + for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) + { + Idx subexp_idx; + struct re_backref_cache_entry *ent; + ent = mctx->bkref_ents + limits->elems[lim_idx]; + subexp_idx = dfa->nodes[ent->node].opr.idx; + + dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], + subexp_idx, dst_node, dst_idx, + dst_bkref_idx); + src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], + subexp_idx, src_node, src_idx, + src_bkref_idx); + + /* In case of: + <src> <dst> ( <subexp> ) + ( <subexp> ) <src> <dst> + ( <subexp1> <src> <subexp2> <dst> <subexp3> ) */ + if (src_pos == dst_pos) + continue; /* This is unrelated limitation. */ + else + return true; + } + return false; +} + +static int +check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, + Idx subexp_idx, Idx from_node, Idx bkref_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + const re_node_set *eclosures = dfa->eclosures + from_node; + Idx node_idx; + + /* Else, we are on the boundary: examine the nodes on the epsilon + closure. */ + for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) + { + Idx node = eclosures->elems[node_idx]; + switch (dfa->nodes[node].type) + { + case OP_BACK_REF: + if (bkref_idx != -1) + { + struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; + do + { + Idx dst; + int cpos; + + if (ent->node != node) + continue; + + if (subexp_idx < BITSET_WORD_BITS + && !(ent->eps_reachable_subexps_map + & ((bitset_word_t) 1 << subexp_idx))) + continue; + + /* Recurse trying to reach the OP_OPEN_SUBEXP and + OP_CLOSE_SUBEXP cases below. But, if the + destination node is the same node as the source + node, don't recurse because it would cause an + infinite loop: a regex that exhibits this behavior + is ()\1*\1* */ + dst = dfa->edests[node].elems[0]; + if (dst == from_node) + { + if (boundaries & 1) + return -1; + else /* if (boundaries & 2) */ + return 0; + } + + cpos = + check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, + dst, bkref_idx); + if (cpos == -1 /* && (boundaries & 1) */) + return -1; + if (cpos == 0 && (boundaries & 2)) + return 0; + + if (subexp_idx < BITSET_WORD_BITS) + ent->eps_reachable_subexps_map + &= ~((bitset_word_t) 1 << subexp_idx); + } + while (ent++->more); + } + break; + + case OP_OPEN_SUBEXP: + if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) + return -1; + break; + + case OP_CLOSE_SUBEXP: + if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) + return 0; + break; + + default: + break; + } + } + + return (boundaries & 2) ? 1 : 0; +} + +static int +check_dst_limits_calc_pos (const re_match_context_t *mctx, Idx limit, + Idx subexp_idx, Idx from_node, Idx str_idx, + Idx bkref_idx) +{ + struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; + int boundaries; + + /* If we are outside the range of the subexpression, return -1 or 1. */ + if (str_idx < lim->subexp_from) + return -1; + + if (lim->subexp_to < str_idx) + return 1; + + /* If we are within the subexpression, return 0. */ + boundaries = (str_idx == lim->subexp_from); + boundaries |= (str_idx == lim->subexp_to) << 1; + if (boundaries == 0) + return 0; + + /* Else, examine epsilon closure. */ + return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, + from_node, bkref_idx); +} + +/* Check the limitations of sub expressions LIMITS, and remove the nodes + which are against limitations from DEST_NODES. */ + +static reg_errcode_t +check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, + const re_node_set *candidates, re_node_set *limits, + struct re_backref_cache_entry *bkref_ents, Idx str_idx) +{ + reg_errcode_t err; + Idx node_idx, lim_idx; + + for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) + { + Idx subexp_idx; + struct re_backref_cache_entry *ent; + ent = bkref_ents + limits->elems[lim_idx]; + + if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) + continue; /* This is unrelated limitation. */ + + subexp_idx = dfa->nodes[ent->node].opr.idx; + if (ent->subexp_to == str_idx) + { + Idx ops_node = -1; + Idx cls_node = -1; + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + Idx node = dest_nodes->elems[node_idx]; + re_token_type_t type = dfa->nodes[node].type; + if (type == OP_OPEN_SUBEXP + && subexp_idx == dfa->nodes[node].opr.idx) + ops_node = node; + else if (type == OP_CLOSE_SUBEXP + && subexp_idx == dfa->nodes[node].opr.idx) + cls_node = node; + } + + /* Check the limitation of the open subexpression. */ + /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ + if (ops_node >= 0) + { + err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, + candidates); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + + /* Check the limitation of the close subexpression. */ + if (cls_node >= 0) + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + Idx node = dest_nodes->elems[node_idx]; + if (!re_node_set_contains (dfa->inveclosures + node, + cls_node) + && !re_node_set_contains (dfa->eclosures + node, + cls_node)) + { + /* It is against this limitation. + Remove it form the current sifted state. */ + err = sub_epsilon_src_nodes (dfa, node, dest_nodes, + candidates); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + --node_idx; + } + } + } + else /* (ent->subexp_to != str_idx) */ + { + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + Idx node = dest_nodes->elems[node_idx]; + re_token_type_t type = dfa->nodes[node].type; + if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) + { + if (subexp_idx != dfa->nodes[node].opr.idx) + continue; + /* It is against this limitation. + Remove it form the current sifted state. */ + err = sub_epsilon_src_nodes (dfa, node, dest_nodes, + candidates); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + } + } + return REG_NOERROR; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, + Idx str_idx, const re_node_set *candidates) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + Idx node_idx, node; + re_sift_context_t local_sctx; + Idx first_idx = search_cur_bkref_entry (mctx, str_idx); + + if (first_idx == -1) + return REG_NOERROR; + + local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ + + for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) + { + Idx enabled_idx; + re_token_type_t type; + struct re_backref_cache_entry *entry; + node = candidates->elems[node_idx]; + type = dfa->nodes[node].type; + /* Avoid infinite loop for the REs like "()\1+". */ + if (node == sctx->last_node && str_idx == sctx->last_str_idx) + continue; + if (type != OP_BACK_REF) + continue; + + entry = mctx->bkref_ents + first_idx; + enabled_idx = first_idx; + do + { + Idx subexp_len; + Idx to_idx; + Idx dst_node; + bool ok; + re_dfastate_t *cur_state; + + if (entry->node != node) + continue; + subexp_len = entry->subexp_to - entry->subexp_from; + to_idx = str_idx + subexp_len; + dst_node = (subexp_len ? dfa->nexts[node] + : dfa->edests[node].elems[0]); + + if (to_idx > sctx->last_str_idx + || sctx->sifted_states[to_idx] == NULL + || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) + || check_dst_limits (mctx, &sctx->limits, node, + str_idx, dst_node, to_idx)) + continue; + + if (local_sctx.sifted_states == NULL) + { + local_sctx = *sctx; + err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + local_sctx.last_node = node; + local_sctx.last_str_idx = str_idx; + ok = re_node_set_insert (&local_sctx.limits, enabled_idx); + if (__glibc_unlikely (! ok)) + { + err = REG_ESPACE; + goto free_return; + } + cur_state = local_sctx.sifted_states[str_idx]; + err = sift_states_backward (mctx, &local_sctx); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + if (sctx->limited_states != NULL) + { + err = merge_state_array (dfa, sctx->limited_states, + local_sctx.sifted_states, + str_idx + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + local_sctx.sifted_states[str_idx] = cur_state; + re_node_set_remove (&local_sctx.limits, enabled_idx); + + /* mctx->bkref_ents may have changed, reload the pointer. */ + entry = mctx->bkref_ents + enabled_idx; + } + while (enabled_idx++, entry++->more); + } + err = REG_NOERROR; + free_return: + if (local_sctx.sifted_states != NULL) + { + re_node_set_free (&local_sctx.limits); + } + + return err; +} + + +#ifdef RE_ENABLE_I18N +static int +sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, + Idx node_idx, Idx str_idx, Idx max_str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + int naccepted; + /* Check the node can accept "multi byte". */ + naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); + if (naccepted > 0 && str_idx + naccepted <= max_str_idx && + !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], + dfa->nexts[node_idx])) + /* The node can't accept the "multi byte", or the + destination was already thrown away, then the node + could't accept the current input "multi byte". */ + naccepted = 0; + /* Otherwise, it is sure that the node could accept + 'naccepted' bytes input. */ + return naccepted; +} +#endif /* RE_ENABLE_I18N */ + + +/* Functions for state transition. */ + +/* Return the next state to which the current state STATE will transit by + accepting the current input byte, and update STATE_LOG if necessary. + If STATE can accept a multibyte char/collating element/back reference + update the destination of STATE_LOG. */ + +static re_dfastate_t * +__attribute_warn_unused_result__ +transit_state (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *state) +{ + re_dfastate_t **trtable; + unsigned char ch; + +#ifdef RE_ENABLE_I18N + /* If the current state can accept multibyte. */ + if (__glibc_unlikely (state->accept_mb)) + { + *err = transit_state_mb (mctx, state); + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + } +#endif /* RE_ENABLE_I18N */ + + /* Then decide the next state with the single byte. */ +#if 0 + if (0) + /* don't use transition table */ + return transit_state_sb (err, mctx, state); +#endif + + /* Use transition table */ + ch = re_string_fetch_byte (&mctx->input); + for (;;) + { + trtable = state->trtable; + if (__glibc_likely (trtable != NULL)) + return trtable[ch]; + + trtable = state->word_trtable; + if (__glibc_likely (trtable != NULL)) + { + unsigned int context; + context + = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input) - 1, + mctx->eflags); + if (IS_WORD_CONTEXT (context)) + return trtable[ch + SBC_MAX]; + else + return trtable[ch]; + } + + if (!build_trtable (mctx->dfa, state)) + { + *err = REG_ESPACE; + return NULL; + } + + /* Retry, we now have a transition table. */ + } +} + +/* Update the state_log if we need */ +static re_dfastate_t * +merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *next_state) +{ + const re_dfa_t *const dfa = mctx->dfa; + Idx cur_idx = re_string_cur_idx (&mctx->input); + + if (cur_idx > mctx->state_log_top) + { + mctx->state_log[cur_idx] = next_state; + mctx->state_log_top = cur_idx; + } + else if (mctx->state_log[cur_idx] == 0) + { + mctx->state_log[cur_idx] = next_state; + } + else + { + re_dfastate_t *pstate; + unsigned int context; + re_node_set next_nodes, *log_nodes, *table_nodes = NULL; + /* If (state_log[cur_idx] != 0), it implies that cur_idx is + the destination of a multibyte char/collating element/ + back reference. Then the next state is the union set of + these destinations and the results of the transition table. */ + pstate = mctx->state_log[cur_idx]; + log_nodes = pstate->entrance_nodes; + if (next_state != NULL) + { + table_nodes = next_state->entrance_nodes; + *err = re_node_set_init_union (&next_nodes, table_nodes, + log_nodes); + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + } + else + next_nodes = *log_nodes; + /* Note: We already add the nodes of the initial state, + then we don't need to add them here. */ + + context = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input) - 1, + mctx->eflags); + next_state = mctx->state_log[cur_idx] + = re_acquire_state_context (err, dfa, &next_nodes, context); + /* We don't need to check errors here, since the return value of + this function is next_state and ERR is already set. */ + + if (table_nodes != NULL) + re_node_set_free (&next_nodes); + } + + if (__glibc_unlikely (dfa->nbackref) && next_state != NULL) + { + /* Check OP_OPEN_SUBEXP in the current state in case that we use them + later. We must check them here, since the back references in the + next state might use them. */ + *err = check_subexp_matching_top (mctx, &next_state->nodes, + cur_idx); + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + + /* If the next state has back references. */ + if (next_state->has_backref) + { + *err = transit_state_bkref (mctx, &next_state->nodes); + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + next_state = mctx->state_log[cur_idx]; + } + } + + return next_state; +} + +/* Skip bytes in the input that correspond to part of a + multi-byte match, then look in the log for a state + from which to restart matching. */ +static re_dfastate_t * +find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) +{ + re_dfastate_t *cur_state; + do + { + Idx max = mctx->state_log_top; + Idx cur_str_idx = re_string_cur_idx (&mctx->input); + + do + { + if (++cur_str_idx > max) + return NULL; + re_string_skip_bytes (&mctx->input, 1); + } + while (mctx->state_log[cur_str_idx] == NULL); + + cur_state = merge_state_with_log (err, mctx, NULL); + } + while (*err == REG_NOERROR && cur_state == NULL); + return cur_state; +} + +/* Helper functions for transit_state. */ + +/* From the node set CUR_NODES, pick up the nodes whose types are + OP_OPEN_SUBEXP and which have corresponding back references in the regular + expression. And register them to use them later for evaluating the + corresponding back references. */ + +static reg_errcode_t +check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, + Idx str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + Idx node_idx; + reg_errcode_t err; + + /* TODO: This isn't efficient. + Because there might be more than one nodes whose types are + OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all + nodes. + E.g. RE: (a){2} */ + for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) + { + Idx node = cur_nodes->elems[node_idx]; + if (dfa->nodes[node].type == OP_OPEN_SUBEXP + && dfa->nodes[node].opr.idx < BITSET_WORD_BITS + && (dfa->used_bkref_map + & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx))) + { + err = match_ctx_add_subtop (mctx, node, str_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + return REG_NOERROR; +} + +#if 0 +/* Return the next state to which the current state STATE will transit by + accepting the current input byte. */ + +static re_dfastate_t * +transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *state) +{ + const re_dfa_t *const dfa = mctx->dfa; + re_node_set next_nodes; + re_dfastate_t *next_state; + Idx node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); + unsigned int context; + + *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) + { + Idx cur_node = state->nodes.elems[node_cnt]; + if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) + { + *err = re_node_set_merge (&next_nodes, + dfa->eclosures + dfa->nexts[cur_node]); + if (__glibc_unlikely (*err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return NULL; + } + } + } + context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); + next_state = re_acquire_state_context (err, dfa, &next_nodes, context); + /* We don't need to check errors here, since the return value of + this function is next_state and ERR is already set. */ + + re_node_set_free (&next_nodes); + re_string_skip_bytes (&mctx->input, 1); + return next_state; +} +#endif + +#ifdef RE_ENABLE_I18N +static reg_errcode_t +transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + Idx i; + + for (i = 0; i < pstate->nodes.nelem; ++i) + { + re_node_set dest_nodes, *new_nodes; + Idx cur_node_idx = pstate->nodes.elems[i]; + int naccepted; + Idx dest_idx; + unsigned int context; + re_dfastate_t *dest_state; + + if (!dfa->nodes[cur_node_idx].accept_mb) + continue; + + if (dfa->nodes[cur_node_idx].constraint) + { + context = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input), + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, + context)) + continue; + } + + /* How many bytes the node can accept? */ + naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, + re_string_cur_idx (&mctx->input)); + if (naccepted == 0) + continue; + + /* The node can accepts 'naccepted' bytes. */ + dest_idx = re_string_cur_idx (&mctx->input) + naccepted; + mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted + : mctx->max_mb_elem_len); + err = clean_state_log_if_needed (mctx, dest_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; +#ifdef DEBUG + assert (dfa->nexts[cur_node_idx] != -1); +#endif + new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx]; + + dest_state = mctx->state_log[dest_idx]; + if (dest_state == NULL) + dest_nodes = *new_nodes; + else + { + err = re_node_set_init_union (&dest_nodes, + dest_state->entrance_nodes, new_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + context = re_string_context_at (&mctx->input, dest_idx - 1, + mctx->eflags); + mctx->state_log[dest_idx] + = re_acquire_state_context (&err, dfa, &dest_nodes, context); + if (dest_state != NULL) + re_node_set_free (&dest_nodes); + if (__glibc_unlikely (mctx->state_log[dest_idx] == NULL + && err != REG_NOERROR)) + return err; + } + return REG_NOERROR; +} +#endif /* RE_ENABLE_I18N */ + +static reg_errcode_t +transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + Idx i; + Idx cur_str_idx = re_string_cur_idx (&mctx->input); + + for (i = 0; i < nodes->nelem; ++i) + { + Idx dest_str_idx, prev_nelem, bkc_idx; + Idx node_idx = nodes->elems[i]; + unsigned int context; + const re_token_t *node = dfa->nodes + node_idx; + re_node_set *new_dest_nodes; + + /* Check whether 'node' is a backreference or not. */ + if (node->type != OP_BACK_REF) + continue; + + if (node->constraint) + { + context = re_string_context_at (&mctx->input, cur_str_idx, + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) + continue; + } + + /* 'node' is a backreference. + Check the substring which the substring matched. */ + bkc_idx = mctx->nbkref_ents; + err = get_subexp (mctx, node_idx, cur_str_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + + /* And add the epsilon closures (which is 'new_dest_nodes') of + the backreference to appropriate state_log. */ +#ifdef DEBUG + assert (dfa->nexts[node_idx] != -1); +#endif + for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) + { + Idx subexp_len; + re_dfastate_t *dest_state; + struct re_backref_cache_entry *bkref_ent; + bkref_ent = mctx->bkref_ents + bkc_idx; + if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) + continue; + subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; + new_dest_nodes = (subexp_len == 0 + ? dfa->eclosures + dfa->edests[node_idx].elems[0] + : dfa->eclosures + dfa->nexts[node_idx]); + dest_str_idx = (cur_str_idx + bkref_ent->subexp_to + - bkref_ent->subexp_from); + context = re_string_context_at (&mctx->input, dest_str_idx - 1, + mctx->eflags); + dest_state = mctx->state_log[dest_str_idx]; + prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 + : mctx->state_log[cur_str_idx]->nodes.nelem); + /* Add 'new_dest_node' to state_log. */ + if (dest_state == NULL) + { + mctx->state_log[dest_str_idx] + = re_acquire_state_context (&err, dfa, new_dest_nodes, + context); + if (__glibc_unlikely (mctx->state_log[dest_str_idx] == NULL + && err != REG_NOERROR)) + goto free_return; + } + else + { + re_node_set dest_nodes; + err = re_node_set_init_union (&dest_nodes, + dest_state->entrance_nodes, + new_dest_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&dest_nodes); + goto free_return; + } + mctx->state_log[dest_str_idx] + = re_acquire_state_context (&err, dfa, &dest_nodes, context); + re_node_set_free (&dest_nodes); + if (__glibc_unlikely (mctx->state_log[dest_str_idx] == NULL + && err != REG_NOERROR)) + goto free_return; + } + /* We need to check recursively if the backreference can epsilon + transit. */ + if (subexp_len == 0 + && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) + { + err = check_subexp_matching_top (mctx, new_dest_nodes, + cur_str_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + err = transit_state_bkref (mctx, new_dest_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + } + } + err = REG_NOERROR; + free_return: + return err; +} + +/* Enumerate all the candidates which the backreference BKREF_NODE can match + at BKREF_STR_IDX, and register them by match_ctx_add_entry(). + Note that we might collect inappropriate candidates here. + However, the cost of checking them strictly here is too high, then we + delay these checking for prune_impossible_nodes(). */ + +static reg_errcode_t +__attribute_warn_unused_result__ +get_subexp (re_match_context_t *mctx, Idx bkref_node, Idx bkref_str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + Idx subexp_num, sub_top_idx; + const char *buf = (const char *) re_string_get_buffer (&mctx->input); + /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ + Idx cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); + if (cache_idx != -1) + { + const struct re_backref_cache_entry *entry + = mctx->bkref_ents + cache_idx; + do + if (entry->node == bkref_node) + return REG_NOERROR; /* We already checked it. */ + while (entry++->more); + } + + subexp_num = dfa->nodes[bkref_node].opr.idx; + + /* For each sub expression */ + for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) + { + reg_errcode_t err; + re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; + re_sub_match_last_t *sub_last; + Idx sub_last_idx, sl_str, bkref_str_off; + + if (dfa->nodes[sub_top->node].opr.idx != subexp_num) + continue; /* It isn't related. */ + + sl_str = sub_top->str_idx; + bkref_str_off = bkref_str_idx; + /* At first, check the last node of sub expressions we already + evaluated. */ + for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) + { + regoff_t sl_str_diff; + sub_last = sub_top->lasts[sub_last_idx]; + sl_str_diff = sub_last->str_idx - sl_str; + /* The matched string by the sub expression match with the substring + at the back reference? */ + if (sl_str_diff > 0) + { + if (__glibc_unlikely (bkref_str_off + sl_str_diff + > mctx->input.valid_len)) + { + /* Not enough chars for a successful match. */ + if (bkref_str_off + sl_str_diff > mctx->input.len) + break; + + err = clean_state_log_if_needed (mctx, + bkref_str_off + + sl_str_diff); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + buf = (const char *) re_string_get_buffer (&mctx->input); + } + if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) + /* We don't need to search this sub expression any more. */ + break; + } + bkref_str_off += sl_str_diff; + sl_str += sl_str_diff; + err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, + bkref_str_idx); + + /* Reload buf, since the preceding call might have reallocated + the buffer. */ + buf = (const char *) re_string_get_buffer (&mctx->input); + + if (err == REG_NOMATCH) + continue; + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + + if (sub_last_idx < sub_top->nlasts) + continue; + if (sub_last_idx > 0) + ++sl_str; + /* Then, search for the other last nodes of the sub expression. */ + for (; sl_str <= bkref_str_idx; ++sl_str) + { + Idx cls_node; + regoff_t sl_str_off; + const re_node_set *nodes; + sl_str_off = sl_str - sub_top->str_idx; + /* The matched string by the sub expression match with the substring + at the back reference? */ + if (sl_str_off > 0) + { + if (__glibc_unlikely (bkref_str_off >= mctx->input.valid_len)) + { + /* If we are at the end of the input, we cannot match. */ + if (bkref_str_off >= mctx->input.len) + break; + + err = extend_buffers (mctx, bkref_str_off + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + buf = (const char *) re_string_get_buffer (&mctx->input); + } + if (buf [bkref_str_off++] != buf[sl_str - 1]) + break; /* We don't need to search this sub expression + any more. */ + } + if (mctx->state_log[sl_str] == NULL) + continue; + /* Does this state have a ')' of the sub expression? */ + nodes = &mctx->state_log[sl_str]->nodes; + cls_node = find_subexp_node (dfa, nodes, subexp_num, + OP_CLOSE_SUBEXP); + if (cls_node == -1) + continue; /* No. */ + if (sub_top->path == NULL) + { + sub_top->path = calloc (sizeof (state_array_t), + sl_str - sub_top->str_idx + 1); + if (sub_top->path == NULL) + return REG_ESPACE; + } + /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node + in the current context? */ + err = check_arrival (mctx, sub_top->path, sub_top->node, + sub_top->str_idx, cls_node, sl_str, + OP_CLOSE_SUBEXP); + if (err == REG_NOMATCH) + continue; + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); + if (__glibc_unlikely (sub_last == NULL)) + return REG_ESPACE; + err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, + bkref_str_idx); + buf = (const char *) re_string_get_buffer (&mctx->input); + if (err == REG_NOMATCH) + continue; + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + return REG_NOERROR; +} + +/* Helper functions for get_subexp(). */ + +/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. + If it can arrive, register the sub expression expressed with SUB_TOP + and SUB_LAST. */ + +static reg_errcode_t +get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, + re_sub_match_last_t *sub_last, Idx bkref_node, Idx bkref_str) +{ + reg_errcode_t err; + Idx to_idx; + /* Can the subexpression arrive the back reference? */ + err = check_arrival (mctx, &sub_last->path, sub_last->node, + sub_last->str_idx, bkref_node, bkref_str, + OP_OPEN_SUBEXP); + if (err != REG_NOERROR) + return err; + err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, + sub_last->str_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; + return clean_state_log_if_needed (mctx, to_idx); +} + +/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. + Search '(' if FL_OPEN, or search ')' otherwise. + TODO: This function isn't efficient... + Because there might be more than one nodes whose types are + OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all + nodes. + E.g. RE: (a){2} */ + +static Idx +find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, + Idx subexp_idx, int type) +{ + Idx cls_idx; + for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) + { + Idx cls_node = nodes->elems[cls_idx]; + const re_token_t *node = dfa->nodes + cls_node; + if (node->type == type + && node->opr.idx == subexp_idx) + return cls_node; + } + return -1; +} + +/* Check whether the node TOP_NODE at TOP_STR can arrive to the node + LAST_NODE at LAST_STR. We record the path onto PATH since it will be + heavily reused. + Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node, + Idx top_str, Idx last_node, Idx last_str, int type) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err = REG_NOERROR; + Idx subexp_num, backup_cur_idx, str_idx, null_cnt; + re_dfastate_t *cur_state = NULL; + re_node_set *cur_nodes, next_nodes; + re_dfastate_t **backup_state_log; + unsigned int context; + + subexp_num = dfa->nodes[top_node].opr.idx; + /* Extend the buffer if we need. */ + if (__glibc_unlikely (path->alloc < last_str + mctx->max_mb_elem_len + 1)) + { + re_dfastate_t **new_array; + Idx old_alloc = path->alloc; + Idx incr_alloc = last_str + mctx->max_mb_elem_len + 1; + Idx new_alloc; + if (__glibc_unlikely (IDX_MAX - old_alloc < incr_alloc)) + return REG_ESPACE; + new_alloc = old_alloc + incr_alloc; + if (__glibc_unlikely (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc)) + return REG_ESPACE; + new_array = re_realloc (path->array, re_dfastate_t *, new_alloc); + if (__glibc_unlikely (new_array == NULL)) + return REG_ESPACE; + path->array = new_array; + path->alloc = new_alloc; + memset (new_array + old_alloc, '\0', + sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); + } + + str_idx = path->next_idx ? path->next_idx : top_str; + + /* Temporary modify MCTX. */ + backup_state_log = mctx->state_log; + backup_cur_idx = mctx->input.cur_idx; + mctx->state_log = path->array; + mctx->input.cur_idx = str_idx; + + /* Setup initial node set. */ + context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); + if (str_idx == top_str) + { + err = re_node_set_init_1 (&next_nodes, top_node); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + } + else + { + cur_state = mctx->state_log[str_idx]; + if (cur_state && cur_state->has_backref) + { + err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + else + re_node_set_init_empty (&next_nodes); + } + if (str_idx == top_str || (cur_state && cur_state->has_backref)) + { + if (next_nodes.nelem) + { + err = expand_bkref_cache (mctx, &next_nodes, str_idx, + subexp_num, type); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + } + cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); + if (__glibc_unlikely (cur_state == NULL && err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + mctx->state_log[str_idx] = cur_state; + } + + for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) + { + re_node_set_empty (&next_nodes); + if (mctx->state_log[str_idx + 1]) + { + err = re_node_set_merge (&next_nodes, + &mctx->state_log[str_idx + 1]->nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + } + if (cur_state) + { + err = check_arrival_add_next_nodes (mctx, str_idx, + &cur_state->non_eps_nodes, + &next_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + } + ++str_idx; + if (next_nodes.nelem) + { + err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + err = expand_bkref_cache (mctx, &next_nodes, str_idx, + subexp_num, type); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + } + context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); + cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); + if (__glibc_unlikely (cur_state == NULL && err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + mctx->state_log[str_idx] = cur_state; + null_cnt = cur_state == NULL ? null_cnt + 1 : 0; + } + re_node_set_free (&next_nodes); + cur_nodes = (mctx->state_log[last_str] == NULL ? NULL + : &mctx->state_log[last_str]->nodes); + path->next_idx = str_idx; + + /* Fix MCTX. */ + mctx->state_log = backup_state_log; + mctx->input.cur_idx = backup_cur_idx; + + /* Then check the current node set has the node LAST_NODE. */ + if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) + return REG_NOERROR; + + return REG_NOMATCH; +} + +/* Helper functions for check_arrival. */ + +/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them + to NEXT_NODES. + TODO: This function is similar to the functions transit_state*(), + however this function has many additional works. + Can't we unify them? */ + +static reg_errcode_t +__attribute_warn_unused_result__ +check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx, + re_node_set *cur_nodes, re_node_set *next_nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + bool ok; + Idx cur_idx; +#ifdef RE_ENABLE_I18N + reg_errcode_t err = REG_NOERROR; +#endif + re_node_set union_set; + re_node_set_init_empty (&union_set); + for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) + { + int naccepted = 0; + Idx cur_node = cur_nodes->elems[cur_idx]; +#ifdef DEBUG + re_token_type_t type = dfa->nodes[cur_node].type; + assert (!IS_EPSILON_NODE (type)); +#endif +#ifdef RE_ENABLE_I18N + /* If the node may accept "multi byte". */ + if (dfa->nodes[cur_node].accept_mb) + { + naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, + str_idx); + if (naccepted > 1) + { + re_dfastate_t *dest_state; + Idx next_node = dfa->nexts[cur_node]; + Idx next_idx = str_idx + naccepted; + dest_state = mctx->state_log[next_idx]; + re_node_set_empty (&union_set); + if (dest_state) + { + err = re_node_set_merge (&union_set, &dest_state->nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&union_set); + return err; + } + } + ok = re_node_set_insert (&union_set, next_node); + if (__glibc_unlikely (! ok)) + { + re_node_set_free (&union_set); + return REG_ESPACE; + } + mctx->state_log[next_idx] = re_acquire_state (&err, dfa, + &union_set); + if (__glibc_unlikely (mctx->state_log[next_idx] == NULL + && err != REG_NOERROR)) + { + re_node_set_free (&union_set); + return err; + } + } + } +#endif /* RE_ENABLE_I18N */ + if (naccepted + || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) + { + ok = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); + if (__glibc_unlikely (! ok)) + { + re_node_set_free (&union_set); + return REG_ESPACE; + } + } + } + re_node_set_free (&union_set); + return REG_NOERROR; +} + +/* For all the nodes in CUR_NODES, add the epsilon closures of them to + CUR_NODES, however exclude the nodes which are: + - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. + - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. +*/ + +static reg_errcode_t +check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, + Idx ex_subexp, int type) +{ + reg_errcode_t err; + Idx idx, outside_node; + re_node_set new_nodes; +#ifdef DEBUG + assert (cur_nodes->nelem); +#endif + err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + /* Create a new node set NEW_NODES with the nodes which are epsilon + closures of the node in CUR_NODES. */ + + for (idx = 0; idx < cur_nodes->nelem; ++idx) + { + Idx cur_node = cur_nodes->elems[idx]; + const re_node_set *eclosure = dfa->eclosures + cur_node; + outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); + if (outside_node == -1) + { + /* There are no problematic nodes, just merge them. */ + err = re_node_set_merge (&new_nodes, eclosure); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&new_nodes); + return err; + } + } + else + { + /* There are problematic nodes, re-calculate incrementally. */ + err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, + ex_subexp, type); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&new_nodes); + return err; + } + } + } + re_node_set_free (cur_nodes); + *cur_nodes = new_nodes; + return REG_NOERROR; +} + +/* Helper function for check_arrival_expand_ecl. + Check incrementally the epsilon closure of TARGET, and if it isn't + problematic append it to DST_NODES. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, + Idx target, Idx ex_subexp, int type) +{ + Idx cur_node; + for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) + { + bool ok; + + if (dfa->nodes[cur_node].type == type + && dfa->nodes[cur_node].opr.idx == ex_subexp) + { + if (type == OP_CLOSE_SUBEXP) + { + ok = re_node_set_insert (dst_nodes, cur_node); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + break; + } + ok = re_node_set_insert (dst_nodes, cur_node); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + if (dfa->edests[cur_node].nelem == 0) + break; + if (dfa->edests[cur_node].nelem == 2) + { + reg_errcode_t err; + err = check_arrival_expand_ecl_sub (dfa, dst_nodes, + dfa->edests[cur_node].elems[1], + ex_subexp, type); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + cur_node = dfa->edests[cur_node].elems[0]; + } + return REG_NOERROR; +} + + +/* For all the back references in the current state, calculate the + destination of the back references by the appropriate entry + in MCTX->BKREF_ENTS. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, + Idx cur_str, Idx subexp_num, int type) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + Idx cache_idx_start = search_cur_bkref_entry (mctx, cur_str); + struct re_backref_cache_entry *ent; + + if (cache_idx_start == -1) + return REG_NOERROR; + + restart: + ent = mctx->bkref_ents + cache_idx_start; + do + { + Idx to_idx, next_node; + + /* Is this entry ENT is appropriate? */ + if (!re_node_set_contains (cur_nodes, ent->node)) + continue; /* No. */ + + to_idx = cur_str + ent->subexp_to - ent->subexp_from; + /* Calculate the destination of the back reference, and append it + to MCTX->STATE_LOG. */ + if (to_idx == cur_str) + { + /* The backreference did epsilon transit, we must re-check all the + node in the current state. */ + re_node_set new_dests; + reg_errcode_t err2, err3; + next_node = dfa->edests[ent->node].elems[0]; + if (re_node_set_contains (cur_nodes, next_node)) + continue; + err = re_node_set_init_1 (&new_dests, next_node); + err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); + err3 = re_node_set_merge (cur_nodes, &new_dests); + re_node_set_free (&new_dests); + if (__glibc_unlikely (err != REG_NOERROR || err2 != REG_NOERROR + || err3 != REG_NOERROR)) + { + err = (err != REG_NOERROR ? err + : (err2 != REG_NOERROR ? err2 : err3)); + return err; + } + /* TODO: It is still inefficient... */ + goto restart; + } + else + { + re_node_set union_set; + next_node = dfa->nexts[ent->node]; + if (mctx->state_log[to_idx]) + { + bool ok; + if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, + next_node)) + continue; + err = re_node_set_init_copy (&union_set, + &mctx->state_log[to_idx]->nodes); + ok = re_node_set_insert (&union_set, next_node); + if (__glibc_unlikely (err != REG_NOERROR || ! ok)) + { + re_node_set_free (&union_set); + err = err != REG_NOERROR ? err : REG_ESPACE; + return err; + } + } + else + { + err = re_node_set_init_1 (&union_set, next_node); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); + re_node_set_free (&union_set); + if (__glibc_unlikely (mctx->state_log[to_idx] == NULL + && err != REG_NOERROR)) + return err; + } + } + while (ent++->more); + return REG_NOERROR; +} + +/* Build transition table for the state. + Return true if successful. */ + +static bool +build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) +{ + reg_errcode_t err; + Idx i, j; + int ch; + bool need_word_trtable = false; + bitset_word_t elem, mask; + bool dests_node_malloced = false; + bool dest_states_malloced = false; + Idx ndests; /* Number of the destination states from 'state'. */ + re_dfastate_t **trtable; + re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; + re_node_set follows, *dests_node; + bitset_t *dests_ch; + bitset_t acceptable; + + struct dests_alloc + { + re_node_set dests_node[SBC_MAX]; + bitset_t dests_ch[SBC_MAX]; + } *dests_alloc; + + /* We build DFA states which corresponds to the destination nodes + from 'state'. 'dests_node[i]' represents the nodes which i-th + destination state contains, and 'dests_ch[i]' represents the + characters which i-th destination state accepts. */ + if (__libc_use_alloca (sizeof (struct dests_alloc))) + dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc)); + else + { + dests_alloc = re_malloc (struct dests_alloc, 1); + if (__glibc_unlikely (dests_alloc == NULL)) + return false; + dests_node_malloced = true; + } + dests_node = dests_alloc->dests_node; + dests_ch = dests_alloc->dests_ch; + + /* Initialize transition table. */ + state->word_trtable = state->trtable = NULL; + + /* At first, group all nodes belonging to 'state' into several + destinations. */ + ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); + if (__glibc_unlikely (ndests <= 0)) + { + if (dests_node_malloced) + re_free (dests_alloc); + /* Return false in case of an error, true otherwise. */ + if (ndests == 0) + { + state->trtable = (re_dfastate_t **) + calloc (sizeof (re_dfastate_t *), SBC_MAX); + if (__glibc_unlikely (state->trtable == NULL)) + return false; + return true; + } + return false; + } + + err = re_node_set_alloc (&follows, ndests + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + goto out_free; + + /* Avoid arithmetic overflow in size calculation. */ + size_t ndests_max + = ((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX) + / (3 * sizeof (re_dfastate_t *))); + if (__glibc_unlikely (ndests_max < ndests)) + goto out_free; + + if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX + + ndests * 3 * sizeof (re_dfastate_t *))) + dest_states = (re_dfastate_t **) + alloca (ndests * 3 * sizeof (re_dfastate_t *)); + else + { + dest_states = re_malloc (re_dfastate_t *, ndests * 3); + if (__glibc_unlikely (dest_states == NULL)) + { +out_free: + if (dest_states_malloced) + re_free (dest_states); + re_node_set_free (&follows); + for (i = 0; i < ndests; ++i) + re_node_set_free (dests_node + i); + if (dests_node_malloced) + re_free (dests_alloc); + return false; + } + dest_states_malloced = true; + } + dest_states_word = dest_states + ndests; + dest_states_nl = dest_states_word + ndests; + bitset_empty (acceptable); + + /* Then build the states for all destinations. */ + for (i = 0; i < ndests; ++i) + { + Idx next_node; + re_node_set_empty (&follows); + /* Merge the follows of this destination states. */ + for (j = 0; j < dests_node[i].nelem; ++j) + { + next_node = dfa->nexts[dests_node[i].elems[j]]; + if (next_node != -1) + { + err = re_node_set_merge (&follows, dfa->eclosures + next_node); + if (__glibc_unlikely (err != REG_NOERROR)) + goto out_free; + } + } + dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); + if (__glibc_unlikely (dest_states[i] == NULL && err != REG_NOERROR)) + goto out_free; + /* If the new state has context constraint, + build appropriate states for these contexts. */ + if (dest_states[i]->has_constraint) + { + dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, + CONTEXT_WORD); + if (__glibc_unlikely (dest_states_word[i] == NULL + && err != REG_NOERROR)) + goto out_free; + + if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) + need_word_trtable = true; + + dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, + CONTEXT_NEWLINE); + if (__glibc_unlikely (dest_states_nl[i] == NULL && err != REG_NOERROR)) + goto out_free; + } + else + { + dest_states_word[i] = dest_states[i]; + dest_states_nl[i] = dest_states[i]; + } + bitset_merge (acceptable, dests_ch[i]); + } + + if (!__glibc_unlikely (need_word_trtable)) + { + /* We don't care about whether the following character is a word + character, or we are in a single-byte character set so we can + discern by looking at the character code: allocate a + 256-entry transition table. */ + trtable = state->trtable = + (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); + if (__glibc_unlikely (trtable == NULL)) + goto out_free; + + /* For all characters ch...: */ + for (i = 0; i < BITSET_WORDS; ++i) + for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; + elem; + mask <<= 1, elem >>= 1, ++ch) + if (__glibc_unlikely (elem & 1)) + { + /* There must be exactly one destination which accepts + character ch. See group_nodes_into_DFAstates. */ + for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) + ; + + /* j-th destination accepts the word character ch. */ + if (dfa->word_char[i] & mask) + trtable[ch] = dest_states_word[j]; + else + trtable[ch] = dest_states[j]; + } + } + else + { + /* We care about whether the following character is a word + character, and we are in a multi-byte character set: discern + by looking at the character code: build two 256-entry + transition tables, one starting at trtable[0] and one + starting at trtable[SBC_MAX]. */ + trtable = state->word_trtable = + (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); + if (__glibc_unlikely (trtable == NULL)) + goto out_free; + + /* For all characters ch...: */ + for (i = 0; i < BITSET_WORDS; ++i) + for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; + elem; + mask <<= 1, elem >>= 1, ++ch) + if (__glibc_unlikely (elem & 1)) + { + /* There must be exactly one destination which accepts + character ch. See group_nodes_into_DFAstates. */ + for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) + ; + + /* j-th destination accepts the word character ch. */ + trtable[ch] = dest_states[j]; + trtable[ch + SBC_MAX] = dest_states_word[j]; + } + } + + /* new line */ + if (bitset_contain (acceptable, NEWLINE_CHAR)) + { + /* The current state accepts newline character. */ + for (j = 0; j < ndests; ++j) + if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) + { + /* k-th destination accepts newline character. */ + trtable[NEWLINE_CHAR] = dest_states_nl[j]; + if (need_word_trtable) + trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; + /* There must be only one destination which accepts + newline. See group_nodes_into_DFAstates. */ + break; + } + } + + if (dest_states_malloced) + re_free (dest_states); + + re_node_set_free (&follows); + for (i = 0; i < ndests; ++i) + re_node_set_free (dests_node + i); + + if (dests_node_malloced) + re_free (dests_alloc); + + return true; +} + +/* Group all nodes belonging to STATE into several destinations. + Then for all destinations, set the nodes belonging to the destination + to DESTS_NODE[i] and set the characters accepted by the destination + to DEST_CH[i]. This function return the number of destinations. */ + +static Idx +group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, + re_node_set *dests_node, bitset_t *dests_ch) +{ + reg_errcode_t err; + bool ok; + Idx i, j, k; + Idx ndests; /* Number of the destinations from 'state'. */ + bitset_t accepts; /* Characters a node can accept. */ + const re_node_set *cur_nodes = &state->nodes; + bitset_empty (accepts); + ndests = 0; + + /* For all the nodes belonging to 'state', */ + for (i = 0; i < cur_nodes->nelem; ++i) + { + re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; + re_token_type_t type = node->type; + unsigned int constraint = node->constraint; + + /* Enumerate all single byte character this node can accept. */ + if (type == CHARACTER) + bitset_set (accepts, node->opr.c); + else if (type == SIMPLE_BRACKET) + { + bitset_merge (accepts, node->opr.sbcset); + } + else if (type == OP_PERIOD) + { +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + bitset_merge (accepts, dfa->sb_char); + else +#endif + bitset_set_all (accepts); + if (!(dfa->syntax & RE_DOT_NEWLINE)) + bitset_clear (accepts, '\n'); + if (dfa->syntax & RE_DOT_NOT_NULL) + bitset_clear (accepts, '\0'); + } +#ifdef RE_ENABLE_I18N + else if (type == OP_UTF8_PERIOD) + { + if (ASCII_CHARS % BITSET_WORD_BITS == 0) + memset (accepts, -1, ASCII_CHARS / CHAR_BIT); + else + bitset_merge (accepts, utf8_sb_map); + if (!(dfa->syntax & RE_DOT_NEWLINE)) + bitset_clear (accepts, '\n'); + if (dfa->syntax & RE_DOT_NOT_NULL) + bitset_clear (accepts, '\0'); + } +#endif + else + continue; + + /* Check the 'accepts' and sift the characters which are not + match it the context. */ + if (constraint) + { + if (constraint & NEXT_NEWLINE_CONSTRAINT) + { + bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); + bitset_empty (accepts); + if (accepts_newline) + bitset_set (accepts, NEWLINE_CHAR); + else + continue; + } + if (constraint & NEXT_ENDBUF_CONSTRAINT) + { + bitset_empty (accepts); + continue; + } + + if (constraint & NEXT_WORD_CONSTRAINT) + { + bitset_word_t any_set = 0; + if (type == CHARACTER && !node->word_char) + { + bitset_empty (accepts); + continue; + } +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); + else +#endif + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= dfa->word_char[j]); + if (!any_set) + continue; + } + if (constraint & NEXT_NOTWORD_CONSTRAINT) + { + bitset_word_t any_set = 0; + if (type == CHARACTER && node->word_char) + { + bitset_empty (accepts); + continue; + } +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); + else +#endif + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= ~dfa->word_char[j]); + if (!any_set) + continue; + } + } + + /* Then divide 'accepts' into DFA states, or create a new + state. Above, we make sure that accepts is not empty. */ + for (j = 0; j < ndests; ++j) + { + bitset_t intersec; /* Intersection sets, see below. */ + bitset_t remains; + /* Flags, see below. */ + bitset_word_t has_intersec, not_subset, not_consumed; + + /* Optimization, skip if this state doesn't accept the character. */ + if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) + continue; + + /* Enumerate the intersection set of this state and 'accepts'. */ + has_intersec = 0; + for (k = 0; k < BITSET_WORDS; ++k) + has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; + /* And skip if the intersection set is empty. */ + if (!has_intersec) + continue; + + /* Then check if this state is a subset of 'accepts'. */ + not_subset = not_consumed = 0; + for (k = 0; k < BITSET_WORDS; ++k) + { + not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; + not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; + } + + /* If this state isn't a subset of 'accepts', create a + new group state, which has the 'remains'. */ + if (not_subset) + { + bitset_copy (dests_ch[ndests], remains); + bitset_copy (dests_ch[j], intersec); + err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); + if (__glibc_unlikely (err != REG_NOERROR)) + goto error_return; + ++ndests; + } + + /* Put the position in the current group. */ + ok = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); + if (__glibc_unlikely (! ok)) + goto error_return; + + /* If all characters are consumed, go to next node. */ + if (!not_consumed) + break; + } + /* Some characters remain, create a new group. */ + if (j == ndests) + { + bitset_copy (dests_ch[ndests], accepts); + err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); + if (__glibc_unlikely (err != REG_NOERROR)) + goto error_return; + ++ndests; + bitset_empty (accepts); + } + } + return ndests; + error_return: + for (j = 0; j < ndests; ++j) + re_node_set_free (dests_node + j); + return -1; +} + +#ifdef RE_ENABLE_I18N +/* Check how many bytes the node 'dfa->nodes[node_idx]' accepts. + Return the number of the bytes the node accepts. + STR_IDX is the current index of the input string. + + This function handles the nodes which can accept one character, or + one collating element like '.', '[a-z]', opposite to the other nodes + can only accept one byte. */ + +# ifdef _LIBC +# include <locale/weight.h> +# endif + +static int +check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, + const re_string_t *input, Idx str_idx) +{ + const re_token_t *node = dfa->nodes + node_idx; + int char_len, elem_len; + Idx i; + + if (__glibc_unlikely (node->type == OP_UTF8_PERIOD)) + { + unsigned char c = re_string_byte_at (input, str_idx), d; + if (__glibc_likely (c < 0xc2)) + return 0; + + if (str_idx + 2 > input->len) + return 0; + + d = re_string_byte_at (input, str_idx + 1); + if (c < 0xe0) + return (d < 0x80 || d > 0xbf) ? 0 : 2; + else if (c < 0xf0) + { + char_len = 3; + if (c == 0xe0 && d < 0xa0) + return 0; + } + else if (c < 0xf8) + { + char_len = 4; + if (c == 0xf0 && d < 0x90) + return 0; + } + else if (c < 0xfc) + { + char_len = 5; + if (c == 0xf8 && d < 0x88) + return 0; + } + else if (c < 0xfe) + { + char_len = 6; + if (c == 0xfc && d < 0x84) + return 0; + } + else + return 0; + + if (str_idx + char_len > input->len) + return 0; + + for (i = 1; i < char_len; ++i) + { + d = re_string_byte_at (input, str_idx + i); + if (d < 0x80 || d > 0xbf) + return 0; + } + return char_len; + } + + char_len = re_string_char_size_at (input, str_idx); + if (node->type == OP_PERIOD) + { + if (char_len <= 1) + return 0; + /* FIXME: I don't think this if is needed, as both '\n' + and '\0' are char_len == 1. */ + /* '.' accepts any one character except the following two cases. */ + if ((!(dfa->syntax & RE_DOT_NEWLINE) && + re_string_byte_at (input, str_idx) == '\n') || + ((dfa->syntax & RE_DOT_NOT_NULL) && + re_string_byte_at (input, str_idx) == '\0')) + return 0; + return char_len; + } + + elem_len = re_string_elem_size_at (input, str_idx); + if ((elem_len <= 1 && char_len <= 1) || char_len == 0) + return 0; + + if (node->type == COMPLEX_BRACKET) + { + const re_charset_t *cset = node->opr.mbcset; +# ifdef _LIBC + const unsigned char *pin + = ((const unsigned char *) re_string_get_buffer (input) + str_idx); + Idx j; + uint32_t nrules; +# endif /* _LIBC */ + int match_len = 0; + wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) + ? re_string_wchar_at (input, str_idx) : 0); + + /* match with multibyte character? */ + for (i = 0; i < cset->nmbchars; ++i) + if (wc == cset->mbchars[i]) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + /* match with character_class? */ + for (i = 0; i < cset->nchar_classes; ++i) + { + wctype_t wt = cset->char_classes[i]; + if (__iswctype (wc, wt)) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + } + +# ifdef _LIBC + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { + unsigned int in_collseq = 0; + const int32_t *table, *indirect; + const unsigned char *weights, *extra; + const char *collseqwc; + + /* match with collating_symbol? */ + if (cset->ncoll_syms) + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + for (i = 0; i < cset->ncoll_syms; ++i) + { + const unsigned char *coll_sym = extra + cset->coll_syms[i]; + /* Compare the length of input collating element and + the length of current collating element. */ + if (*coll_sym != elem_len) + continue; + /* Compare each bytes. */ + for (j = 0; j < *coll_sym; j++) + if (pin[j] != coll_sym[1 + j]) + break; + if (j == *coll_sym) + { + /* Match if every bytes is equal. */ + match_len = j; + goto check_node_accept_bytes_match; + } + } + + if (cset->nranges) + { + if (elem_len <= char_len) + { + collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); + in_collseq = __collseq_table_lookup (collseqwc, wc); + } + else + in_collseq = find_collation_sequence_value (pin, elem_len); + } + /* match with range expression? */ + /* FIXME: Implement rational ranges here, too. */ + for (i = 0; i < cset->nranges; ++i) + if (cset->range_starts[i] <= in_collseq + && in_collseq <= cset->range_ends[i]) + { + match_len = elem_len; + goto check_node_accept_bytes_match; + } + + /* match with equivalence_class? */ + if (cset->nequiv_classes) + { + const unsigned char *cp = pin; + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); + int32_t idx = findidx (table, indirect, extra, &cp, elem_len); + int32_t rule = idx >> 24; + idx &= 0xffffff; + if (idx > 0) + { + size_t weight_len = weights[idx]; + for (i = 0; i < cset->nequiv_classes; ++i) + { + int32_t equiv_class_idx = cset->equiv_classes[i]; + int32_t equiv_class_rule = equiv_class_idx >> 24; + equiv_class_idx &= 0xffffff; + if (weights[equiv_class_idx] == weight_len + && equiv_class_rule == rule + && memcmp (weights + idx + 1, + weights + equiv_class_idx + 1, + weight_len) == 0) + { + match_len = elem_len; + goto check_node_accept_bytes_match; + } + } + } + } + } + else +# endif /* _LIBC */ + { + /* match with range expression? */ + for (i = 0; i < cset->nranges; ++i) + { + if (cset->range_starts[i] <= wc && wc <= cset->range_ends[i]) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + } + } + check_node_accept_bytes_match: + if (!cset->non_match) + return match_len; + else + { + if (match_len > 0) + return 0; + else + return (elem_len > char_len) ? elem_len : char_len; + } + } + return 0; +} + +# ifdef _LIBC +static unsigned int +find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) +{ + uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules == 0) + { + if (mbs_len == 1) + { + /* No valid character. Match it as a single byte character. */ + const unsigned char *collseq = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); + return collseq[mbs[0]]; + } + return UINT_MAX; + } + else + { + int32_t idx; + const unsigned char *extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + int32_t extrasize = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; + + for (idx = 0; idx < extrasize;) + { + int mbs_cnt; + bool found = false; + int32_t elem_mbs_len; + /* Skip the name of collating element name. */ + idx = idx + extra[idx] + 1; + elem_mbs_len = extra[idx++]; + if (mbs_len == elem_mbs_len) + { + for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) + if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) + break; + if (mbs_cnt == elem_mbs_len) + /* Found the entry. */ + found = true; + } + /* Skip the byte sequence of the collating element. */ + idx += elem_mbs_len; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + /* Skip the collation sequence value. */ + idx += sizeof (uint32_t); + /* Skip the wide char sequence of the collating element. */ + idx = idx + sizeof (uint32_t) * (*(int32_t *) (extra + idx) + 1); + /* If we found the entry, return the sequence value. */ + if (found) + return *(uint32_t *) (extra + idx); + /* Skip the collation sequence value. */ + idx += sizeof (uint32_t); + } + return UINT_MAX; + } +} +# endif /* _LIBC */ +#endif /* RE_ENABLE_I18N */ + +/* Check whether the node accepts the byte which is IDX-th + byte of the INPUT. */ + +static bool +check_node_accept (const re_match_context_t *mctx, const re_token_t *node, + Idx idx) +{ + unsigned char ch; + ch = re_string_byte_at (&mctx->input, idx); + switch (node->type) + { + case CHARACTER: + if (node->opr.c != ch) + return false; + break; + + case SIMPLE_BRACKET: + if (!bitset_contain (node->opr.sbcset, ch)) + return false; + break; + +#ifdef RE_ENABLE_I18N + case OP_UTF8_PERIOD: + if (ch >= ASCII_CHARS) + return false; + FALLTHROUGH; +#endif + case OP_PERIOD: + if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) + || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) + return false; + break; + + default: + return false; + } + + if (node->constraint) + { + /* The node has constraints. Check whether the current context + satisfies the constraints. */ + unsigned int context = re_string_context_at (&mctx->input, idx, + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) + return false; + } + + return true; +} + +/* Extend the buffers, if the buffers have run out. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +extend_buffers (re_match_context_t *mctx, int min_len) +{ + reg_errcode_t ret; + re_string_t *pstr = &mctx->input; + + /* Avoid overflow. */ + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) / 2 + <= pstr->bufs_len)) + return REG_ESPACE; + + /* Double the lengths of the buffers, but allocate at least MIN_LEN. */ + ret = re_string_realloc_buffers (pstr, + MAX (min_len, + MIN (pstr->len, pstr->bufs_len * 2))); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + + if (mctx->state_log != NULL) + { + /* And double the length of state_log. */ + /* XXX We have no indication of the size of this buffer. If this + allocation fail we have no indication that the state_log array + does not have the right size. */ + re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, + pstr->bufs_len + 1); + if (__glibc_unlikely (new_array == NULL)) + return REG_ESPACE; + mctx->state_log = new_array; + } + + /* Then reconstruct the buffers. */ + if (pstr->icase) + { +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + ret = build_wcs_upper_buffer (pstr); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + } + else +#endif /* RE_ENABLE_I18N */ + build_upper_buffer (pstr); + } + else + { +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + build_wcs_buffer (pstr); + else +#endif /* RE_ENABLE_I18N */ + { + if (pstr->trans != NULL) + re_string_translate_buffer (pstr); + } + } + return REG_NOERROR; +} + + +/* Functions for matching context. */ + +/* Initialize MCTX. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +match_ctx_init (re_match_context_t *mctx, int eflags, Idx n) +{ + mctx->eflags = eflags; + mctx->match_last = -1; + if (n > 0) + { + /* Avoid overflow. */ + size_t max_object_size = + MAX (sizeof (struct re_backref_cache_entry), + sizeof (re_sub_match_top_t *)); + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) < n)) + return REG_ESPACE; + + mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); + mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); + if (__glibc_unlikely (mctx->bkref_ents == NULL || mctx->sub_tops == NULL)) + return REG_ESPACE; + } + /* Already zero-ed by the caller. + else + mctx->bkref_ents = NULL; + mctx->nbkref_ents = 0; + mctx->nsub_tops = 0; */ + mctx->abkref_ents = n; + mctx->max_mb_elem_len = 1; + mctx->asub_tops = n; + return REG_NOERROR; +} + +/* Clean the entries which depend on the current input in MCTX. + This function must be invoked when the matcher changes the start index + of the input, or changes the input string. */ + +static void +match_ctx_clean (re_match_context_t *mctx) +{ + Idx st_idx; + for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) + { + Idx sl_idx; + re_sub_match_top_t *top = mctx->sub_tops[st_idx]; + for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) + { + re_sub_match_last_t *last = top->lasts[sl_idx]; + re_free (last->path.array); + re_free (last); + } + re_free (top->lasts); + if (top->path) + { + re_free (top->path->array); + re_free (top->path); + } + re_free (top); + } + + mctx->nsub_tops = 0; + mctx->nbkref_ents = 0; +} + +/* Free all the memory associated with MCTX. */ + +static void +match_ctx_free (re_match_context_t *mctx) +{ + /* First, free all the memory associated with MCTX->SUB_TOPS. */ + match_ctx_clean (mctx); + re_free (mctx->sub_tops); + re_free (mctx->bkref_ents); +} + +/* Add a new backreference entry to MCTX. + Note that we assume that caller never call this function with duplicate + entry, and call with STR_IDX which isn't smaller than any existing entry. +*/ + +static reg_errcode_t +__attribute_warn_unused_result__ +match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from, + Idx to) +{ + if (mctx->nbkref_ents >= mctx->abkref_ents) + { + struct re_backref_cache_entry* new_entry; + new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, + mctx->abkref_ents * 2); + if (__glibc_unlikely (new_entry == NULL)) + { + re_free (mctx->bkref_ents); + return REG_ESPACE; + } + mctx->bkref_ents = new_entry; + memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', + sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); + mctx->abkref_ents *= 2; + } + if (mctx->nbkref_ents > 0 + && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) + mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; + + mctx->bkref_ents[mctx->nbkref_ents].node = node; + mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; + mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; + mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; + + /* This is a cache that saves negative results of check_dst_limits_calc_pos. + If bit N is clear, means that this entry won't epsilon-transition to + an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If + it is set, check_dst_limits_calc_pos_1 will recurse and try to find one + such node. + + A backreference does not epsilon-transition unless it is empty, so set + to all zeros if FROM != TO. */ + mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map + = (from == to ? -1 : 0); + + mctx->bkref_ents[mctx->nbkref_ents++].more = 0; + if (mctx->max_mb_elem_len < to - from) + mctx->max_mb_elem_len = to - from; + return REG_NOERROR; +} + +/* Return the first entry with the same str_idx, or -1 if none is + found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ + +static Idx +search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx) +{ + Idx left, right, mid, last; + last = right = mctx->nbkref_ents; + for (left = 0; left < right;) + { + mid = (left + right) / 2; + if (mctx->bkref_ents[mid].str_idx < str_idx) + left = mid + 1; + else + right = mid; + } + if (left < last && mctx->bkref_ents[left].str_idx == str_idx) + return left; + else + return -1; +} + +/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches + at STR_IDX. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx) +{ +#ifdef DEBUG + assert (mctx->sub_tops != NULL); + assert (mctx->asub_tops > 0); +#endif + if (__glibc_unlikely (mctx->nsub_tops == mctx->asub_tops)) + { + Idx new_asub_tops = mctx->asub_tops * 2; + re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, + re_sub_match_top_t *, + new_asub_tops); + if (__glibc_unlikely (new_array == NULL)) + return REG_ESPACE; + mctx->sub_tops = new_array; + mctx->asub_tops = new_asub_tops; + } + mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); + if (__glibc_unlikely (mctx->sub_tops[mctx->nsub_tops] == NULL)) + return REG_ESPACE; + mctx->sub_tops[mctx->nsub_tops]->node = node; + mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; + return REG_NOERROR; +} + +/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches + at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */ + +static re_sub_match_last_t * +match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx) +{ + re_sub_match_last_t *new_entry; + if (__glibc_unlikely (subtop->nlasts == subtop->alasts)) + { + Idx new_alasts = 2 * subtop->alasts + 1; + re_sub_match_last_t **new_array = re_realloc (subtop->lasts, + re_sub_match_last_t *, + new_alasts); + if (__glibc_unlikely (new_array == NULL)) + return NULL; + subtop->lasts = new_array; + subtop->alasts = new_alasts; + } + new_entry = calloc (1, sizeof (re_sub_match_last_t)); + if (__glibc_likely (new_entry != NULL)) + { + subtop->lasts[subtop->nlasts] = new_entry; + new_entry->node = node; + new_entry->str_idx = str_idx; + ++subtop->nlasts; + } + return new_entry; +} + +static void +sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, + re_dfastate_t **limited_sts, Idx last_node, Idx last_str_idx) +{ + sctx->sifted_states = sifted_sts; + sctx->limited_states = limited_sts; + sctx->last_node = last_node; + sctx->last_str_idx = last_str_idx; + re_node_set_init_empty (&sctx->limits); +} diff --git a/grub-core/lib/gnulib/save-cwd.c b/grub-core/lib/gnulib/save-cwd.c new file mode 100644 index 0000000..a67d95d --- /dev/null +++ b/grub-core/lib/gnulib/save-cwd.c @@ -0,0 +1,97 @@ +/* save-cwd.c -- Save and restore current working directory. + + Copyright (C) 1995, 1997-1998, 2003-2006, 2009-2019 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Jim Meyering. */ + +#include <config.h> + +#include "save-cwd.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +#include "chdir-long.h" +#include "unistd--.h" + +#if GNULIB_FCNTL_SAFER +# include "fcntl--.h" +#else +# define GNULIB_FCNTL_SAFER 0 +#endif + +/* Record the location of the current working directory in CWD so that + the program may change to other directories and later use restore_cwd + to return to the recorded location. This function may allocate + space using malloc (via getcwd) or leave a file descriptor open; + use free_cwd to perform the necessary free or close. Upon failure, + no memory is allocated, any locally opened file descriptors are + closed; return non-zero -- in that case, free_cwd need not be + called, but doing so is ok. Otherwise, return zero. + + The _raison d'etre_ for this interface is that the working directory + is sometimes inaccessible, and getcwd is not robust or as efficient. + So, we prefer to use the open/fchdir approach, but fall back on + getcwd if necessary. This module works for most cases with just + the getcwd-lgpl module, but to be truly robust, use the getcwd module. + + Some systems lack fchdir altogether: e.g., OS/2, pre-2001 Cygwin, + SCO Xenix. Also, SunOS 4 and Irix 5.3 provide the function, yet it + doesn't work for partitions on which auditing is enabled. If + you're still using an obsolete system with these problems, please + send email to the maintainer of this code. */ + +int +save_cwd (struct saved_cwd *cwd) +{ + cwd->name = NULL; + + cwd->desc = open (".", O_SEARCH | O_CLOEXEC); + if (!GNULIB_FCNTL_SAFER) + cwd->desc = fd_safer_flag (cwd->desc, O_CLOEXEC); + if (cwd->desc < 0) + { + cwd->name = getcwd (NULL, 0); + return cwd->name ? 0 : -1; + } + + return 0; +} + +/* Change to recorded location, CWD, in directory hierarchy. + Upon failure, return -1 (errno is set by chdir or fchdir). + Upon success, return zero. */ + +int +restore_cwd (const struct saved_cwd *cwd) +{ + if (0 <= cwd->desc) + return fchdir (cwd->desc); + else + return chdir_long (cwd->name); +} + +void +free_cwd (struct saved_cwd *cwd) +{ + if (cwd->desc >= 0) + close (cwd->desc); + free (cwd->name); +} diff --git a/grub-core/lib/gnulib/save-cwd.h b/grub-core/lib/gnulib/save-cwd.h new file mode 100644 index 0000000..6a78070 --- /dev/null +++ b/grub-core/lib/gnulib/save-cwd.h @@ -0,0 +1,34 @@ +/* Save and restore current working directory. + + Copyright (C) 1995, 1997-1998, 2003, 2009-2019 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Jim Meyering. */ + +#ifndef SAVE_CWD_H +# define SAVE_CWD_H 1 + +struct saved_cwd + { + int desc; + char *name; + }; + +int save_cwd (struct saved_cwd *cwd); +int restore_cwd (const struct saved_cwd *cwd); +void free_cwd (struct saved_cwd *cwd); + +#endif /* SAVE_CWD_H */ diff --git a/grub-core/lib/gnulib/size_max.h b/grub-core/lib/gnulib/size_max.h new file mode 100644 index 0000000..e265fb9 --- /dev/null +++ b/grub-core/lib/gnulib/size_max.h @@ -0,0 +1,30 @@ +/* size_max.h -- declare SIZE_MAX through system headers + Copyright (C) 2005-2006, 2009-2019 Free Software Foundation, Inc. + Written by Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef GNULIB_SIZE_MAX_H +#define GNULIB_SIZE_MAX_H + +/* Get SIZE_MAX declaration on systems like Solaris 7/8/9. */ +# include <limits.h> +/* Get SIZE_MAX declaration on systems like glibc 2. */ +# if HAVE_STDINT_H +# include <stdint.h> +# endif +/* On systems where these include files don't define it, SIZE_MAX is defined + in config.h. */ + +#endif /* GNULIB_SIZE_MAX_H */ diff --git a/grub-core/lib/gnulib/sleep.c b/grub-core/lib/gnulib/sleep.c new file mode 100644 index 0000000..c5218e5 --- /dev/null +++ b/grub-core/lib/gnulib/sleep.c @@ -0,0 +1,76 @@ +/* Pausing execution of the current thread. + Copyright (C) 2007, 2009-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2007. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <unistd.h> + +#include <limits.h> + +#include "verify.h" + +#if defined _WIN32 && ! defined __CYGWIN__ + +# define WIN32_LEAN_AND_MEAN /* avoid including junk */ +# include <windows.h> + +unsigned int +sleep (unsigned int seconds) +{ + unsigned int remaining; + + /* Sleep for 1 second many times, because + 1. Sleep is not interruptible by Ctrl-C, + 2. we want to avoid arithmetic overflow while multiplying with 1000. */ + for (remaining = seconds; remaining > 0; remaining--) + Sleep (1000); + + return remaining; +} + +#elif HAVE_SLEEP + +# undef sleep + +/* Guarantee unlimited sleep and a reasonable return value. Cygwin + 1.5.x rejects attempts to sleep more than 49.7 days (2**32 + milliseconds), but uses uninitialized memory which results in a + garbage answer. Similarly, Linux 2.6.9 with glibc 2.3.4 has a too + small return value when asked to sleep more than 24.85 days. */ +unsigned int +rpl_sleep (unsigned int seconds) +{ + /* This requires int larger than 16 bits. */ + verify (UINT_MAX / 24 / 24 / 60 / 60); + const unsigned int limit = 24 * 24 * 60 * 60; + while (limit < seconds) + { + unsigned int result; + seconds -= limit; + result = sleep (limit); + if (result) + return seconds + result; + } + return sleep (seconds); +} + +#else /* !HAVE_SLEEP */ + + #error "Please port gnulib sleep.c to your platform, possibly using usleep() or select(), then report this to bug-gnulib." + +#endif diff --git a/grub-core/lib/gnulib/stat-time.c b/grub-core/lib/gnulib/stat-time.c new file mode 100644 index 0000000..81b83dd --- /dev/null +++ b/grub-core/lib/gnulib/stat-time.c @@ -0,0 +1,3 @@ +#include <config.h> +#define _GL_STAT_TIME_INLINE _GL_EXTERN_INLINE +#include "stat-time.h" diff --git a/grub-core/lib/gnulib/stat-time.h b/grub-core/lib/gnulib/stat-time.h new file mode 100644 index 0000000..d4f1f96 --- /dev/null +++ b/grub-core/lib/gnulib/stat-time.h @@ -0,0 +1,252 @@ +/* stat-related time functions. + + Copyright (C) 2005, 2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +#ifndef STAT_TIME_H +#define STAT_TIME_H 1 + +#include "intprops.h" + +#include <errno.h> +#include <stddef.h> +#include <sys/stat.h> +#include <time.h> + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_STAT_TIME_INLINE +# define _GL_STAT_TIME_INLINE _GL_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type + struct timespec, if available. If not, then STAT_TIMESPEC_NS (ST, + ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST, + if available. ST_XTIM can be st_atim, st_ctim, st_mtim, or st_birthtim + for access, status change, data modification, or birth (creation) + time respectively. + + These macros are private to stat-time.h. */ +#if _GL_WINDOWS_STAT_TIMESPEC || defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC +# if _GL_WINDOWS_STAT_TIMESPEC || defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC +# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim) +# else +# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec) +# endif +#elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC +# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec) +#elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC +# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec) +#elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC +# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec) +#endif + +/* Return the nanosecond component of *ST's access time. */ +_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE +get_stat_atime_ns (struct stat const *st) +{ +# if defined STAT_TIMESPEC + return STAT_TIMESPEC (st, st_atim).tv_nsec; +# elif defined STAT_TIMESPEC_NS + return STAT_TIMESPEC_NS (st, st_atim); +# else + return 0; +# endif +} + +/* Return the nanosecond component of *ST's status change time. */ +_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE +get_stat_ctime_ns (struct stat const *st) +{ +# if defined STAT_TIMESPEC + return STAT_TIMESPEC (st, st_ctim).tv_nsec; +# elif defined STAT_TIMESPEC_NS + return STAT_TIMESPEC_NS (st, st_ctim); +# else + return 0; +# endif +} + +/* Return the nanosecond component of *ST's data modification time. */ +_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE +get_stat_mtime_ns (struct stat const *st) +{ +# if defined STAT_TIMESPEC + return STAT_TIMESPEC (st, st_mtim).tv_nsec; +# elif defined STAT_TIMESPEC_NS + return STAT_TIMESPEC_NS (st, st_mtim); +# else + return 0; +# endif +} + +/* Return the nanosecond component of *ST's birth time. */ +_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE +get_stat_birthtime_ns (struct stat const *st _GL_UNUSED) +{ +# if defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC + return STAT_TIMESPEC (st, st_birthtim).tv_nsec; +# elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC + return STAT_TIMESPEC_NS (st, st_birthtim); +# else + return 0; +# endif +} + +/* Return *ST's access time. */ +_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE +get_stat_atime (struct stat const *st) +{ +#ifdef STAT_TIMESPEC + return STAT_TIMESPEC (st, st_atim); +#else + struct timespec t; + t.tv_sec = st->st_atime; + t.tv_nsec = get_stat_atime_ns (st); + return t; +#endif +} + +/* Return *ST's status change time. */ +_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE +get_stat_ctime (struct stat const *st) +{ +#ifdef STAT_TIMESPEC + return STAT_TIMESPEC (st, st_ctim); +#else + struct timespec t; + t.tv_sec = st->st_ctime; + t.tv_nsec = get_stat_ctime_ns (st); + return t; +#endif +} + +/* Return *ST's data modification time. */ +_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE +get_stat_mtime (struct stat const *st) +{ +#ifdef STAT_TIMESPEC + return STAT_TIMESPEC (st, st_mtim); +#else + struct timespec t; + t.tv_sec = st->st_mtime; + t.tv_nsec = get_stat_mtime_ns (st); + return t; +#endif +} + +/* Return *ST's birth time, if available; otherwise return a value + with tv_sec and tv_nsec both equal to -1. */ +_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE +get_stat_birthtime (struct stat const *st _GL_UNUSED) +{ + struct timespec t; + +#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \ + || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC) + t = STAT_TIMESPEC (st, st_birthtim); +#elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC + t.tv_sec = st->st_birthtime; + t.tv_nsec = st->st_birthtimensec; +#elif defined _WIN32 && ! defined __CYGWIN__ + /* Native Windows platforms (but not Cygwin) put the "file creation + time" in st_ctime (!). See + <https://msdn.microsoft.com/en-us/library/14h5k7ff(VS.80).aspx>. */ +# if _GL_WINDOWS_STAT_TIMESPEC + t = st->st_ctim; +# else + t.tv_sec = st->st_ctime; + t.tv_nsec = 0; +# endif +#else + /* Birth time is not supported. */ + t.tv_sec = -1; + t.tv_nsec = -1; +#endif + +#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \ + || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC \ + || defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC) + /* FreeBSD and NetBSD sometimes signal the absence of knowledge by + using zero. Attempt to work around this problem. Alas, this can + report failure even for valid timestamps. Also, NetBSD + sometimes returns junk in the birth time fields; work around this + bug if it is detected. */ + if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000)) + { + t.tv_sec = -1; + t.tv_nsec = -1; + } +#endif + + return t; +} + +/* If a stat-like function returned RESULT, normalize the timestamps + in *ST, in case this platform suffers from the Solaris 11 bug where + tv_nsec might be negative. Return the adjusted RESULT, setting + errno to EOVERFLOW if normalization overflowed. This function + is intended to be private to this .h file. */ +_GL_STAT_TIME_INLINE int +stat_time_normalize (int result, struct stat *st _GL_UNUSED) +{ +#if defined __sun && defined STAT_TIMESPEC + if (result == 0) + { + long int timespec_hz = 1000000000; + short int const ts_off[] = { offsetof (struct stat, st_atim), + offsetof (struct stat, st_mtim), + offsetof (struct stat, st_ctim) }; + int i; + for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++) + { + struct timespec *ts = (struct timespec *) ((char *) st + ts_off[i]); + long int q = ts->tv_nsec / timespec_hz; + long int r = ts->tv_nsec % timespec_hz; + if (r < 0) + { + r += timespec_hz; + q--; + } + ts->tv_nsec = r; + /* Overflow is possible, as Solaris 11 stat can yield + tv_sec == TYPE_MINIMUM (time_t) && tv_nsec == -1000000000. + INT_ADD_WRAPV is OK, since time_t is signed on Solaris. */ + if (INT_ADD_WRAPV (q, ts->tv_sec, &ts->tv_sec)) + { + errno = EOVERFLOW; + return -1; + } + } + } +#endif + return result; +} + +#ifdef __cplusplus +} +#endif + +_GL_INLINE_HEADER_END + +#endif diff --git a/grub-core/lib/gnulib/stat-w32.c b/grub-core/lib/gnulib/stat-w32.c new file mode 100644 index 0000000..ffa9942 --- /dev/null +++ b/grub-core/lib/gnulib/stat-w32.c @@ -0,0 +1,425 @@ +/* Core of implementation of fstat and stat for native Windows. + Copyright (C) 2017-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible. */ + +#include <config.h> + +#if defined _WIN32 && ! defined __CYGWIN__ + +/* Ensure that <windows.h> defines FILE_ID_INFO. */ +#undef _WIN32_WINNT +#define _WIN32_WINNT _WIN32_WINNT_WIN8 + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <limits.h> +#include <string.h> +#include <unistd.h> +#include <windows.h> + +/* Specification. */ +#include "stat-w32.h" + +#include "pathmax.h" +#include "verify.h" + +/* Avoid warnings from gcc -Wcast-function-type. */ +#define GetProcAddress \ + (void *) GetProcAddress + +#if _GL_WINDOWS_STAT_INODES == 2 +/* GetFileInformationByHandleEx was introduced only in Windows Vista. */ +typedef DWORD (WINAPI * GetFileInformationByHandleExFuncType) (HANDLE hFile, + FILE_INFO_BY_HANDLE_CLASS fiClass, + LPVOID lpBuffer, + DWORD dwBufferSize); +static GetFileInformationByHandleExFuncType GetFileInformationByHandleExFunc = NULL; +#endif +/* GetFinalPathNameByHandle was introduced only in Windows Vista. */ +typedef DWORD (WINAPI * GetFinalPathNameByHandleFuncType) (HANDLE hFile, + LPTSTR lpFilePath, + DWORD lenFilePath, + DWORD dwFlags); +static GetFinalPathNameByHandleFuncType GetFinalPathNameByHandleFunc = NULL; +static BOOL initialized = FALSE; + +static void +initialize (void) +{ + HMODULE kernel32 = LoadLibrary ("kernel32.dll"); + if (kernel32 != NULL) + { +#if _GL_WINDOWS_STAT_INODES == 2 + GetFileInformationByHandleExFunc = + (GetFileInformationByHandleExFuncType) GetProcAddress (kernel32, "GetFileInformationByHandleEx"); +#endif + GetFinalPathNameByHandleFunc = + (GetFinalPathNameByHandleFuncType) GetProcAddress (kernel32, "GetFinalPathNameByHandleA"); + } + initialized = TRUE; +} + +/* Converts a FILETIME to GMT time since 1970-01-01 00:00:00. */ +#if _GL_WINDOWS_STAT_TIMESPEC +struct timespec +_gl_convert_FILETIME_to_timespec (const FILETIME *ft) +{ + struct timespec result; + /* FILETIME: <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */ + unsigned long long since_1601 = + ((unsigned long long) ft->dwHighDateTime << 32) + | (unsigned long long) ft->dwLowDateTime; + if (since_1601 == 0) + { + result.tv_sec = 0; + result.tv_nsec = 0; + } + else + { + /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89 + leap years, in total 134774 days. */ + unsigned long long since_1970 = + since_1601 - (unsigned long long) 134774 * (unsigned long long) 86400 * (unsigned long long) 10000000; + result.tv_sec = since_1970 / (unsigned long long) 10000000; + result.tv_nsec = (unsigned long) (since_1970 % (unsigned long long) 10000000) * 100; + } + return result; +} +#else +time_t +_gl_convert_FILETIME_to_POSIX (const FILETIME *ft) +{ + /* FILETIME: <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */ + unsigned long long since_1601 = + ((unsigned long long) ft->dwHighDateTime << 32) + | (unsigned long long) ft->dwLowDateTime; + if (since_1601 == 0) + return 0; + else + { + /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89 + leap years, in total 134774 days. */ + unsigned long long since_1970 = + since_1601 - (unsigned long long) 134774 * (unsigned long long) 86400 * (unsigned long long) 10000000; + return since_1970 / (unsigned long long) 10000000; + } +} +#endif + +/* Fill *BUF with information about the file designated by H. + PATH is the file name, if known, otherwise NULL. + Return 0 if successful, or -1 with errno set upon failure. */ +int +_gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf) +{ + /* GetFileType + <https://msdn.microsoft.com/en-us/library/aa364960.aspx> */ + DWORD type = GetFileType (h); + if (type == FILE_TYPE_DISK) + { + if (!initialized) + initialize (); + + /* st_mode can be determined through + GetFileAttributesEx + <https://msdn.microsoft.com/en-us/library/aa364946.aspx> + <https://msdn.microsoft.com/en-us/library/aa365739.aspx> + or through + GetFileInformationByHandle + <https://msdn.microsoft.com/en-us/library/aa364952.aspx> + <https://msdn.microsoft.com/en-us/library/aa363788.aspx> + or through + GetFileInformationByHandleEx with argument FileBasicInfo + <https://msdn.microsoft.com/en-us/library/aa364953.aspx> + <https://msdn.microsoft.com/en-us/library/aa364217.aspx> + The latter requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */ + BY_HANDLE_FILE_INFORMATION info; + if (! GetFileInformationByHandle (h, &info)) + goto failed; + + /* Test for error conditions before starting to fill *buf. */ + if (sizeof (buf->st_size) <= 4 && info.nFileSizeHigh > 0) + { + errno = EOVERFLOW; + return -1; + } + +#if _GL_WINDOWS_STAT_INODES + /* st_ino can be determined through + GetFileInformationByHandle + <https://msdn.microsoft.com/en-us/library/aa364952.aspx> + <https://msdn.microsoft.com/en-us/library/aa363788.aspx> + as 64 bits, or through + GetFileInformationByHandleEx with argument FileIdInfo + <https://msdn.microsoft.com/en-us/library/aa364953.aspx> + <https://msdn.microsoft.com/en-us/library/hh802691.aspx> + as 128 bits. + The latter requires -D_WIN32_WINNT=_WIN32_WINNT_WIN8 or higher. */ + /* Experiments show that GetFileInformationByHandleEx does not provide + much more information than GetFileInformationByHandle: + * The dwVolumeSerialNumber from GetFileInformationByHandle is equal + to the low 32 bits of the 64-bit VolumeSerialNumber from + GetFileInformationByHandleEx, and is apparently sufficient for + identifying the device. + * The nFileIndex from GetFileInformationByHandle is equal to the low + 64 bits of the 128-bit FileId from GetFileInformationByHandleEx, + and the high 64 bits of this 128-bit FileId are zero. + * On a FAT file system, GetFileInformationByHandleEx fails with error + ERROR_INVALID_PARAMETER, whereas GetFileInformationByHandle + succeeds. + * On a CIFS/SMB file system, GetFileInformationByHandleEx fails with + error ERROR_INVALID_LEVEL, whereas GetFileInformationByHandle + succeeds. */ +# if _GL_WINDOWS_STAT_INODES == 2 + if (GetFileInformationByHandleExFunc != NULL) + { + FILE_ID_INFO id; + if (GetFileInformationByHandleExFunc (h, FileIdInfo, &id, sizeof (id))) + { + buf->st_dev = id.VolumeSerialNumber; + verify (sizeof (ino_t) == sizeof (id.FileId)); + memcpy (&buf->st_ino, &id.FileId, sizeof (ino_t)); + goto ino_done; + } + else + { + switch (GetLastError ()) + { + case ERROR_INVALID_PARAMETER: /* older Windows version, or FAT */ + case ERROR_INVALID_LEVEL: /* CIFS/SMB file system */ + goto fallback; + default: + goto failed; + } + } + } + fallback: ; + /* Fallback for older Windows versions. */ + buf->st_dev = info.dwVolumeSerialNumber; + buf->st_ino._gl_ino[0] = ((ULONGLONG) info.nFileIndexHigh << 32) | (ULONGLONG) info.nFileIndexLow; + buf->st_ino._gl_ino[1] = 0; + ino_done: ; +# else /* _GL_WINDOWS_STAT_INODES == 1 */ + buf->st_dev = info.dwVolumeSerialNumber; + buf->st_ino = ((ULONGLONG) info.nFileIndexHigh << 32) | (ULONGLONG) info.nFileIndexLow; +# endif +#else + /* st_ino is not wide enough for identifying a file on a device. + Without st_ino, st_dev is pointless. */ + buf->st_dev = 0; + buf->st_ino = 0; +#endif + + /* st_mode. */ + unsigned int mode = + /* XXX How to handle FILE_ATTRIBUTE_REPARSE_POINT ? */ + ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR | S_IEXEC_UGO : _S_IFREG) + | S_IREAD_UGO + | ((info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE_UGO); + if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + /* Determine whether the file is executable by looking at the file + name suffix. + If the file name is already known, use it. Otherwise, for + non-empty files, it can be determined through + GetFinalPathNameByHandle + <https://msdn.microsoft.com/en-us/library/aa364962.aspx> + or through + GetFileInformationByHandleEx with argument FileNameInfo + <https://msdn.microsoft.com/en-us/library/aa364953.aspx> + <https://msdn.microsoft.com/en-us/library/aa364388.aspx> + Both require -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */ + if (info.nFileSizeHigh > 0 || info.nFileSizeLow > 0) + { + char fpath[PATH_MAX]; + if (path != NULL + || (GetFinalPathNameByHandleFunc != NULL + && GetFinalPathNameByHandleFunc (h, fpath, sizeof (fpath), VOLUME_NAME_NONE) + < sizeof (fpath) + && (path = fpath, 1))) + { + const char *last_dot = NULL; + const char *p; + for (p = path; *p != '\0'; p++) + if (*p == '.') + last_dot = p; + if (last_dot != NULL) + { + const char *suffix = last_dot + 1; + if (_stricmp (suffix, "exe") == 0 + || _stricmp (suffix, "bat") == 0 + || _stricmp (suffix, "cmd") == 0 + || _stricmp (suffix, "com") == 0) + mode |= S_IEXEC_UGO; + } + } + else + /* Cannot determine file name. Pretend that it is executable. */ + mode |= S_IEXEC_UGO; + } + } + buf->st_mode = mode; + + /* st_nlink can be determined through + GetFileInformationByHandle + <https://msdn.microsoft.com/en-us/library/aa364952.aspx> + <https://msdn.microsoft.com/en-us/library/aa363788.aspx> + or through + GetFileInformationByHandleEx with argument FileStandardInfo + <https://msdn.microsoft.com/en-us/library/aa364953.aspx> + <https://msdn.microsoft.com/en-us/library/aa364401.aspx> + The latter requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */ + buf->st_nlink = (info.nNumberOfLinks > SHRT_MAX ? SHRT_MAX : info.nNumberOfLinks); + + /* There's no easy way to map the Windows SID concept to an integer. */ + buf->st_uid = 0; + buf->st_gid = 0; + + /* st_rdev is irrelevant for normal files and directories. */ + buf->st_rdev = 0; + + /* st_size can be determined through + GetFileSizeEx + <https://msdn.microsoft.com/en-us/library/aa364957.aspx> + or through + GetFileAttributesEx + <https://msdn.microsoft.com/en-us/library/aa364946.aspx> + <https://msdn.microsoft.com/en-us/library/aa365739.aspx> + or through + GetFileInformationByHandle + <https://msdn.microsoft.com/en-us/library/aa364952.aspx> + <https://msdn.microsoft.com/en-us/library/aa363788.aspx> + or through + GetFileInformationByHandleEx with argument FileStandardInfo + <https://msdn.microsoft.com/en-us/library/aa364953.aspx> + <https://msdn.microsoft.com/en-us/library/aa364401.aspx> + The latter requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */ + if (sizeof (buf->st_size) <= 4) + /* Range check already done above. */ + buf->st_size = info.nFileSizeLow; + else + buf->st_size = ((long long) info.nFileSizeHigh << 32) | (long long) info.nFileSizeLow; + + /* st_atime, st_mtime, st_ctime can be determined through + GetFileTime + <https://msdn.microsoft.com/en-us/library/ms724320.aspx> + or through + GetFileAttributesEx + <https://msdn.microsoft.com/en-us/library/aa364946.aspx> + <https://msdn.microsoft.com/en-us/library/aa365739.aspx> + or through + GetFileInformationByHandle + <https://msdn.microsoft.com/en-us/library/aa364952.aspx> + <https://msdn.microsoft.com/en-us/library/aa363788.aspx> + or through + GetFileInformationByHandleEx with argument FileBasicInfo + <https://msdn.microsoft.com/en-us/library/aa364953.aspx> + <https://msdn.microsoft.com/en-us/library/aa364217.aspx> + The latter requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */ +#if _GL_WINDOWS_STAT_TIMESPEC + buf->st_atim = _gl_convert_FILETIME_to_timespec (&info.ftLastAccessTime); + buf->st_mtim = _gl_convert_FILETIME_to_timespec (&info.ftLastWriteTime); + buf->st_ctim = _gl_convert_FILETIME_to_timespec (&info.ftCreationTime); +#else + buf->st_atime = _gl_convert_FILETIME_to_POSIX (&info.ftLastAccessTime); + buf->st_mtime = _gl_convert_FILETIME_to_POSIX (&info.ftLastWriteTime); + buf->st_ctime = _gl_convert_FILETIME_to_POSIX (&info.ftCreationTime); +#endif + + return 0; + } + else if (type == FILE_TYPE_CHAR || type == FILE_TYPE_PIPE) + { + buf->st_dev = 0; +#if _GL_WINDOWS_STAT_INODES == 2 + buf->st_ino._gl_ino[0] = buf->st_ino._gl_ino[1] = 0; +#else + buf->st_ino = 0; +#endif + buf->st_mode = (type == FILE_TYPE_PIPE ? _S_IFIFO : _S_IFCHR); + buf->st_nlink = 1; + buf->st_uid = 0; + buf->st_gid = 0; + buf->st_rdev = 0; + if (type == FILE_TYPE_PIPE) + { + /* PeekNamedPipe + <https://msdn.microsoft.com/en-us/library/aa365779.aspx> */ + DWORD bytes_available; + if (PeekNamedPipe (h, NULL, 0, NULL, &bytes_available, NULL)) + buf->st_size = bytes_available; + else + buf->st_size = 0; + } + else + buf->st_size = 0; +#if _GL_WINDOWS_STAT_TIMESPEC + buf->st_atim.tv_sec = 0; buf->st_atim.tv_nsec = 0; + buf->st_mtim.tv_sec = 0; buf->st_mtim.tv_nsec = 0; + buf->st_ctim.tv_sec = 0; buf->st_ctim.tv_nsec = 0; +#else + buf->st_atime = 0; + buf->st_mtime = 0; + buf->st_ctime = 0; +#endif + return 0; + } + else + { + errno = ENOENT; + return -1; + } + + failed: + { + DWORD error = GetLastError (); + #if 0 + fprintf (stderr, "_gl_fstat_by_handle error 0x%x\n", (unsigned int) error); + #endif + switch (error) + { + case ERROR_ACCESS_DENIED: + case ERROR_SHARING_VIOLATION: + errno = EACCES; + break; + + case ERROR_OUTOFMEMORY: + errno = ENOMEM; + break; + + case ERROR_WRITE_FAULT: + case ERROR_READ_FAULT: + case ERROR_GEN_FAILURE: + errno = EIO; + break; + + default: + errno = EINVAL; + break; + } + return -1; + } +} + +#else + +/* This declaration is solely to ensure that after preprocessing + this file is never empty. */ +typedef int dummy; + +#endif diff --git a/grub-core/lib/gnulib/stat-w32.h b/grub-core/lib/gnulib/stat-w32.h new file mode 100644 index 0000000..6b961d7 --- /dev/null +++ b/grub-core/lib/gnulib/stat-w32.h @@ -0,0 +1,37 @@ +/* Core of implementation of fstat and stat for native Windows. + Copyright (C) 2017-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _STAT_W32_H +#define _STAT_W32_H 1 + +/* Converts a FILETIME to GMT time since 1970-01-01 00:00:00. */ +#if _GL_WINDOWS_STAT_TIMESPEC +extern struct timespec _gl_convert_FILETIME_to_timespec (const FILETIME *ft); +#else +extern time_t _gl_convert_FILETIME_to_POSIX (const FILETIME *ft); +#endif + +/* Fill *BUF with information about the file designated by H. + PATH is the file name, if known, otherwise NULL. + Return 0 if successful, or -1 with errno set upon failure. */ +extern int _gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf); + +/* Bitmasks for st_mode. */ +#define S_IREAD_UGO (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6)) +#define S_IWRITE_UGO (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6)) +#define S_IEXEC_UGO (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6)) + +#endif /* _STAT_W32_H */ diff --git a/grub-core/lib/gnulib/stat.c b/grub-core/lib/gnulib/stat.c new file mode 100644 index 0000000..74f4795 --- /dev/null +++ b/grub-core/lib/gnulib/stat.c @@ -0,0 +1,429 @@ +/* Work around platform bugs in stat. + Copyright (C) 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Eric Blake and Bruno Haible. */ + +/* If the user's config.h happens to include <sys/stat.h>, let it include only + the system's <sys/stat.h> here, so that orig_stat doesn't recurse to + rpl_stat. */ +#define __need_system_sys_stat_h +#include <config.h> + +/* Get the original definition of stat. It might be defined as a macro. */ +#include <sys/types.h> +#include <sys/stat.h> +#undef __need_system_sys_stat_h + +#if defined _WIN32 && ! defined __CYGWIN__ +# define WINDOWS_NATIVE +#endif + +#if !defined WINDOWS_NATIVE + +static int +orig_stat (const char *filename, struct stat *buf) +{ + return stat (filename, buf); +} + +#endif + +/* Specification. */ +/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include <sys/stat.h> + above. */ +#include "sys/stat.h" + +#include "stat-time.h" + +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <string.h> +#include "filename.h" +#include "malloca.h" +#include "verify.h" + +#ifdef WINDOWS_NATIVE +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# include "stat-w32.h" +#endif + +#ifdef WINDOWS_NATIVE +/* Return TRUE if the given file name denotes an UNC root. */ +static BOOL +is_unc_root (const char *rname) +{ + /* Test whether it has the syntax '\\server\share'. */ + if (ISSLASH (rname[0]) && ISSLASH (rname[1])) + { + /* It starts with two slashes. Find the next slash. */ + const char *p = rname + 2; + const char *q = p; + while (*q != '\0' && !ISSLASH (*q)) + q++; + if (q > p && *q != '\0') + { + /* Found the next slash at q. */ + q++; + const char *r = q; + while (*r != '\0' && !ISSLASH (*r)) + r++; + if (r > q && *r == '\0') + return TRUE; + } + } + return FALSE; +} +#endif + +/* Store information about NAME into ST. Work around bugs with + trailing slashes. Mingw has other bugs (such as st_ino always + being 0 on success) which this wrapper does not work around. But + at least this implementation provides the ability to emulate fchdir + correctly. */ + +int +rpl_stat (char const *name, struct stat *buf) +{ +#ifdef WINDOWS_NATIVE + /* Fill the fields ourselves, because the original stat function returns + values for st_atime, st_mtime, st_ctime that depend on the current time + zone. See + <https://lists.gnu.org/r/bug-gnulib/2017-04/msg00134.html> */ + /* XXX Should we convert to wchar_t* and prepend '\\?\', in order to work + around length limitations + <https://msdn.microsoft.com/en-us/library/aa365247.aspx> ? */ + + /* POSIX <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13> + specifies: "More than two leading <slash> characters shall be treated as + a single <slash> character." */ + if (ISSLASH (name[0]) && ISSLASH (name[1]) && ISSLASH (name[2])) + { + name += 2; + while (ISSLASH (name[1])) + name++; + } + + size_t len = strlen (name); + size_t drive_prefix_len = (HAS_DEVICE (name) ? 2 : 0); + + /* Remove trailing slashes (except the very first one, at position + drive_prefix_len), but remember their presence. */ + size_t rlen; + bool check_dir = false; + + rlen = len; + while (rlen > drive_prefix_len && ISSLASH (name[rlen-1])) + { + check_dir = true; + if (rlen == drive_prefix_len + 1) + break; + rlen--; + } + + /* Handle '' and 'C:'. */ + if (!check_dir && rlen == drive_prefix_len) + { + errno = ENOENT; + return -1; + } + + /* Handle '\\'. */ + if (rlen == 1 && ISSLASH (name[0]) && len >= 2) + { + errno = ENOENT; + return -1; + } + + const char *rname; + char *malloca_rname; + if (rlen == len) + { + rname = name; + malloca_rname = NULL; + } + else + { + malloca_rname = malloca (rlen + 1); + if (malloca_rname == NULL) + { + errno = ENOMEM; + return -1; + } + memcpy (malloca_rname, name, rlen); + malloca_rname[rlen] = '\0'; + rname = malloca_rname; + } + + /* There are two ways to get at the requested information: + - by scanning the parent directory and examining the relevant + directory entry, + - by opening the file directly. + The first approach fails for root directories (e.g. 'C:\') and + UNC root directories (e.g. '\\server\share'). + The second approach fails for some system files (e.g. 'C:\pagefile.sys' + and 'C:\hiberfil.sys'): ERROR_SHARING_VIOLATION. + The second approach gives more information (in particular, correct + st_dev, st_ino, st_nlink fields). + So we use the second approach and, as a fallback except for root and + UNC root directories, also the first approach. */ + { + int ret; + + { + /* Approach based on the file. */ + + /* Open a handle to the file. + CreateFile + <https://msdn.microsoft.com/en-us/library/aa363858.aspx> + <https://msdn.microsoft.com/en-us/library/aa363874.aspx> */ + HANDLE h = + CreateFile (rname, + FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + /* FILE_FLAG_POSIX_SEMANTICS (treat file names that differ only + in case as different) makes sense only when applied to *all* + filesystem operations. */ + FILE_FLAG_BACKUP_SEMANTICS /* | FILE_FLAG_POSIX_SEMANTICS */, + NULL); + if (h != INVALID_HANDLE_VALUE) + { + ret = _gl_fstat_by_handle (h, rname, buf); + CloseHandle (h); + goto done; + } + } + + /* Test for root and UNC root directories. */ + if ((rlen == drive_prefix_len + 1 && ISSLASH (rname[drive_prefix_len])) + || is_unc_root (rname)) + goto failed; + + /* Fallback. */ + { + /* Approach based on the directory entry. */ + + if (strchr (rname, '?') != NULL || strchr (rname, '*') != NULL) + { + /* Other Windows API functions would fail with error + ERROR_INVALID_NAME. */ + if (malloca_rname != NULL) + freea (malloca_rname); + errno = ENOENT; + return -1; + } + + /* Get the details about the directory entry. This can be done through + FindFirstFile + <https://msdn.microsoft.com/en-us/library/aa364418.aspx> + <https://msdn.microsoft.com/en-us/library/aa365740.aspx> + or through + FindFirstFileEx with argument FindExInfoBasic + <https://msdn.microsoft.com/en-us/library/aa364419.aspx> + <https://msdn.microsoft.com/en-us/library/aa364415.aspx> + <https://msdn.microsoft.com/en-us/library/aa365740.aspx> */ + WIN32_FIND_DATA info; + HANDLE h = FindFirstFile (rname, &info); + if (h == INVALID_HANDLE_VALUE) + goto failed; + + /* Test for error conditions before starting to fill *buf. */ + if (sizeof (buf->st_size) <= 4 && info.nFileSizeHigh > 0) + { + FindClose (h); + if (malloca_rname != NULL) + freea (malloca_rname); + errno = EOVERFLOW; + return -1; + } + +# if _GL_WINDOWS_STAT_INODES + buf->st_dev = 0; +# if _GL_WINDOWS_STAT_INODES == 2 + buf->st_ino._gl_ino[0] = buf->st_ino._gl_ino[1] = 0; +# else /* _GL_WINDOWS_STAT_INODES == 1 */ + buf->st_ino = 0; +# endif +# else + /* st_ino is not wide enough for identifying a file on a device. + Without st_ino, st_dev is pointless. */ + buf->st_dev = 0; + buf->st_ino = 0; +# endif + + /* st_mode. */ + unsigned int mode = + /* XXX How to handle FILE_ATTRIBUTE_REPARSE_POINT ? */ + ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR | S_IEXEC_UGO : _S_IFREG) + | S_IREAD_UGO + | ((info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE_UGO); + if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + /* Determine whether the file is executable by looking at the file + name suffix. */ + if (info.nFileSizeHigh > 0 || info.nFileSizeLow > 0) + { + const char *last_dot = NULL; + const char *p; + for (p = info.cFileName; *p != '\0'; p++) + if (*p == '.') + last_dot = p; + if (last_dot != NULL) + { + const char *suffix = last_dot + 1; + if (_stricmp (suffix, "exe") == 0 + || _stricmp (suffix, "bat") == 0 + || _stricmp (suffix, "cmd") == 0 + || _stricmp (suffix, "com") == 0) + mode |= S_IEXEC_UGO; + } + } + } + buf->st_mode = mode; + + /* st_nlink. Ignore hard links here. */ + buf->st_nlink = 1; + + /* There's no easy way to map the Windows SID concept to an integer. */ + buf->st_uid = 0; + buf->st_gid = 0; + + /* st_rdev is irrelevant for normal files and directories. */ + buf->st_rdev = 0; + + /* st_size. */ + if (sizeof (buf->st_size) <= 4) + /* Range check already done above. */ + buf->st_size = info.nFileSizeLow; + else + buf->st_size = ((long long) info.nFileSizeHigh << 32) | (long long) info.nFileSizeLow; + + /* st_atime, st_mtime, st_ctime. */ +# if _GL_WINDOWS_STAT_TIMESPEC + buf->st_atim = _gl_convert_FILETIME_to_timespec (&info.ftLastAccessTime); + buf->st_mtim = _gl_convert_FILETIME_to_timespec (&info.ftLastWriteTime); + buf->st_ctim = _gl_convert_FILETIME_to_timespec (&info.ftCreationTime); +# else + buf->st_atime = _gl_convert_FILETIME_to_POSIX (&info.ftLastAccessTime); + buf->st_mtime = _gl_convert_FILETIME_to_POSIX (&info.ftLastWriteTime); + buf->st_ctime = _gl_convert_FILETIME_to_POSIX (&info.ftCreationTime); +# endif + + FindClose (h); + + ret = 0; + } + + done: + if (ret >= 0 && check_dir && !S_ISDIR (buf->st_mode)) + { + errno = ENOTDIR; + ret = -1; + } + if (malloca_rname != NULL) + { + int saved_errno = errno; + freea (malloca_rname); + errno = saved_errno; + } + return ret; + } + + failed: + { + DWORD error = GetLastError (); + #if 0 + fprintf (stderr, "rpl_stat error 0x%x\n", (unsigned int) error); + #endif + + if (malloca_rname != NULL) + freea (malloca_rname); + + switch (error) + { + /* Some of these errors probably cannot happen with the specific flags + that we pass to CreateFile. But who knows... */ + case ERROR_FILE_NOT_FOUND: /* The last component of rname does not exist. */ + case ERROR_PATH_NOT_FOUND: /* Some directory component in rname does not exist. */ + case ERROR_BAD_PATHNAME: /* rname is such as '\\server'. */ + case ERROR_BAD_NET_NAME: /* rname is such as '\\server\nonexistentshare'. */ + case ERROR_INVALID_NAME: /* rname contains wildcards, misplaced colon, etc. */ + case ERROR_DIRECTORY: + errno = ENOENT; + break; + + case ERROR_ACCESS_DENIED: /* rname is such as 'C:\System Volume Information\foo'. */ + case ERROR_SHARING_VIOLATION: /* rname is such as 'C:\pagefile.sys' (second approach only). */ + /* XXX map to EACCESS or EPERM? */ + errno = EACCES; + break; + + case ERROR_OUTOFMEMORY: + errno = ENOMEM; + break; + + case ERROR_WRITE_PROTECT: + errno = EROFS; + break; + + case ERROR_WRITE_FAULT: + case ERROR_READ_FAULT: + case ERROR_GEN_FAILURE: + errno = EIO; + break; + + case ERROR_BUFFER_OVERFLOW: + case ERROR_FILENAME_EXCED_RANGE: + errno = ENAMETOOLONG; + break; + + case ERROR_DELETE_PENDING: /* XXX map to EACCESS or EPERM? */ + errno = EPERM; + break; + + default: + errno = EINVAL; + break; + } + + return -1; + } +#else + int result = orig_stat (name, buf); + if (result == 0) + { +# if REPLACE_FUNC_STAT_FILE + /* Solaris 9 mistakenly succeeds when given a non-directory with a + trailing slash. */ + if (!S_ISDIR (buf->st_mode)) + { + size_t len = strlen (name); + if (ISSLASH (name[len - 1])) + { + errno = ENOTDIR; + return -1; + } + } +# endif /* REPLACE_FUNC_STAT_FILE */ + result = stat_time_normalize (result, buf); + } + return result; +#endif +} diff --git a/grub-core/lib/gnulib/stdalign.in.h b/grub-core/lib/gnulib/stdalign.in.h new file mode 100644 index 0000000..d988d7c --- /dev/null +++ b/grub-core/lib/gnulib/stdalign.in.h @@ -0,0 +1,121 @@ +/* A substitute for ISO C11 <stdalign.h>. + + Copyright 2011-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert and Bruno Haible. */ + +#ifndef _GL_STDALIGN_H +#define _GL_STDALIGN_H + +/* ISO C11 <stdalign.h> for platforms that lack it. + + References: + ISO C11 (latest free draft + <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf>) + sections 6.5.3.4, 6.7.5, 7.15. + C++11 (latest free draft + <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf>) + section 18.10. */ + +/* alignof (TYPE), also known as _Alignof (TYPE), yields the alignment + requirement of a structure member (i.e., slot or field) that is of + type TYPE, as an integer constant expression. + + This differs from GCC's __alignof__ operator, which can yield a + better-performing alignment for an object of that type. For + example, on x86 with GCC, __alignof__ (double) and __alignof__ + (long long) are 8, whereas alignof (double) and alignof (long long) + are 4 unless the option '-malign-double' is used. + + The result cannot be used as a value for an 'enum' constant, if you + want to be portable to HP-UX 10.20 cc and AIX 3.2.5 xlc. + + Include <stddef.h> for offsetof. */ +#include <stddef.h> + +/* FreeBSD 9.1 <sys/cdefs.h>, included by <stddef.h> and lots of other + standard headers, defines conflicting implementations of _Alignas + and _Alignof that are no better than ours; override them. */ +#undef _Alignas +#undef _Alignof + +/* GCC releases before GCC 4.9 had a bug in _Alignof. See GCC bug 52023 + <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023>. */ +#if (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 \ + || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9))) +# ifdef __cplusplus +# if 201103 <= __cplusplus +# define _Alignof(type) alignof (type) +# else + template <class __t> struct __alignof_helper { char __a; __t __b; }; +# define _Alignof(type) offsetof (__alignof_helper<type>, __b) +# endif +# else +# define _Alignof(type) offsetof (struct { char __a; type __b; }, __b) +# endif +#endif +#if ! (defined __cplusplus && 201103 <= __cplusplus) +# define alignof _Alignof +#endif +#define __alignof_is_defined 1 + +/* alignas (A), also known as _Alignas (A), aligns a variable or type + to the alignment A, where A is an integer constant expression. For + example: + + int alignas (8) foo; + struct s { int a; int alignas (8) bar; }; + + aligns the address of FOO and the offset of BAR to be multiples of 8. + + A should be a power of two that is at least the type's alignment + and at most the implementation's alignment limit. This limit is + 2**28 on typical GNUish hosts, and 2**13 on MSVC. To be portable + to MSVC through at least version 10.0, A should be an integer + constant, as MSVC does not support expressions such as 1 << 3. + To be portable to Sun C 5.11, do not align auto variables to + anything stricter than their default alignment. + + The following C11 requirements are not supported here: + + - If A is zero, alignas has no effect. + - alignas can be used multiple times; the strictest one wins. + - alignas (TYPE) is equivalent to alignas (alignof (TYPE)). + + */ + +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 +# if defined __cplusplus && 201103 <= __cplusplus +# define _Alignas(a) alignas (a) +# elif ((defined __APPLE__ && defined __MACH__ \ + ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \ + : __GNUC__) \ + || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \ + || __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__) +# define _Alignas(a) __attribute__ ((__aligned__ (a))) +# elif 1300 <= _MSC_VER +# define _Alignas(a) __declspec (align (a)) +# endif +#endif +#if ((defined _Alignas && ! (defined __cplusplus && 201103 <= __cplusplus)) \ + || (defined __STDC_VERSION__ && 201112 <= __STDC_VERSION__)) +# define alignas _Alignas +#endif +#if defined alignas || (defined __cplusplus && 201103 <= __cplusplus) +# define __alignas_is_defined 1 +#endif + +#endif /* _GL_STDALIGN_H */ diff --git a/grub-core/lib/gnulib/stdbool.in.h b/grub-core/lib/gnulib/stdbool.in.h new file mode 100644 index 0000000..8158b00 --- /dev/null +++ b/grub-core/lib/gnulib/stdbool.in.h @@ -0,0 +1,132 @@ +/* Copyright (C) 2001-2003, 2006-2019 Free Software Foundation, Inc. + Written by Bruno Haible <haible@clisp.cons.org>, 2001. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _GL_STDBOOL_H +#define _GL_STDBOOL_H + +/* ISO C 99 <stdbool.h> for platforms that lack it. */ + +/* Usage suggestions: + + Programs that use <stdbool.h> should be aware of some limitations + and standards compliance issues. + + Standards compliance: + + - <stdbool.h> must be #included before 'bool', 'false', 'true' + can be used. + + - You cannot assume that sizeof (bool) == 1. + + - Programs should not undefine the macros bool, true, and false, + as C99 lists that as an "obsolescent feature". + + Limitations of this substitute, when used in a C89 environment: + + - <stdbool.h> must be #included before the '_Bool' type can be used. + + - You cannot assume that _Bool is a typedef; it might be a macro. + + - Bit-fields of type 'bool' are not supported. Portable code + should use 'unsigned int foo : 1;' rather than 'bool foo : 1;'. + + - In C99, casts and automatic conversions to '_Bool' or 'bool' are + performed in such a way that every nonzero value gets converted + to 'true', and zero gets converted to 'false'. This doesn't work + with this substitute. With this substitute, only the values 0 and 1 + give the expected result when converted to _Bool' or 'bool'. + + - C99 allows the use of (_Bool)0.0 in constant expressions, but + this substitute cannot always provide this property. + + Also, it is suggested that programs use 'bool' rather than '_Bool'; + this isn't required, but 'bool' is more common. */ + + +/* 7.16. Boolean type and values */ + +/* BeOS <sys/socket.h> already #defines false 0, true 1. We use the same + definitions below, but temporarily we have to #undef them. */ +#if defined __BEOS__ && !defined __HAIKU__ +# include <OS.h> /* defines bool but not _Bool */ +# undef false +# undef true +#endif + +#ifdef __cplusplus +# define _Bool bool +# define bool bool +#else +# if defined __BEOS__ && !defined __HAIKU__ + /* A compiler known to have 'bool'. */ + /* If the compiler already has both 'bool' and '_Bool', we can assume they + are the same types. */ +# if !@HAVE__BOOL@ +typedef bool _Bool; +# endif +# else +# if !defined __GNUC__ + /* If @HAVE__BOOL@: + Some HP-UX cc and AIX IBM C compiler versions have compiler bugs when + the built-in _Bool type is used. See + https://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html + https://lists.gnu.org/r/bug-coreutils/2005-11/msg00161.html + https://lists.gnu.org/r/bug-coreutils/2005-10/msg00086.html + Similar bugs are likely with other compilers as well; this file + wouldn't be used if <stdbool.h> was working. + So we override the _Bool type. + If !@HAVE__BOOL@: + Need to define _Bool ourselves. As 'signed char' or as an enum type? + Use of a typedef, with SunPRO C, leads to a stupid + "warning: _Bool is a keyword in ISO C99". + Use of an enum type, with IRIX cc, leads to a stupid + "warning(1185): enumerated type mixed with another type". + Even the existence of an enum type, without a typedef, + "Invalid enumerator. (badenum)" with HP-UX cc on Tru64. + The only benefit of the enum, debuggability, is not important + with these compilers. So use 'signed char' and no enum. */ +# define _Bool signed char +# else + /* With this compiler, trust the _Bool type if the compiler has it. */ +# if !@HAVE__BOOL@ + /* For the sake of symbolic names in gdb, define true and false as + enum constants, not only as macros. + It is tempting to write + typedef enum { false = 0, true = 1 } _Bool; + so that gdb prints values of type 'bool' symbolically. But then + values of type '_Bool' might promote to 'int' or 'unsigned int' + (see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int' + (see ISO C 99 6.3.1.1.(2)). So add a negative value to the + enum; this ensures that '_Bool' promotes to 'int'. */ +typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool; +# endif +# endif +# endif +# define bool _Bool +#endif + +/* The other macros must be usable in preprocessor directives. */ +#ifdef __cplusplus +# define false false +# define true true +#else +# define false 0 +# define true 1 +#endif + +#define __bool_true_false_are_defined 1 + +#endif /* _GL_STDBOOL_H */ diff --git a/grub-core/lib/gnulib/stddef.in.h b/grub-core/lib/gnulib/stddef.in.h new file mode 100644 index 0000000..5aad121 --- /dev/null +++ b/grub-core/lib/gnulib/stddef.in.h @@ -0,0 +1,114 @@ +/* A substitute for POSIX 2008 <stddef.h>, for platforms that have issues. + + Copyright (C) 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Eric Blake. */ + +/* + * POSIX 2008 <stddef.h> for platforms that have issues. + * <http://www.opengroup.org/susv3xbd/stddef.h.html> + */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_wchar_t || defined __need_size_t \ + || defined __need_ptrdiff_t || defined __need_NULL \ + || defined __need_wint_t +/* Special invocation convention inside gcc header files. In + particular, gcc provides a version of <stddef.h> that blindly + redefines NULL even when __need_wint_t was defined, even though + wint_t is not normally provided by <stddef.h>. Hence, we must + remember if special invocation has ever been used to obtain wint_t, + in which case we need to clean up NULL yet again. */ + +# if !(defined _@GUARD_PREFIX@_STDDEF_H && defined _GL_STDDEF_WINT_T) +# ifdef __need_wint_t +# define _GL_STDDEF_WINT_T +# endif +# @INCLUDE_NEXT@ @NEXT_STDDEF_H@ +# endif + +#else +/* Normal invocation convention. */ + +# ifndef _@GUARD_PREFIX@_STDDEF_H + +/* The include_next requires a split double-inclusion guard. */ + +# @INCLUDE_NEXT@ @NEXT_STDDEF_H@ + +/* On NetBSD 5.0, the definition of NULL lacks proper parentheses. */ +# if (@REPLACE_NULL@ \ + && (!defined _@GUARD_PREFIX@_STDDEF_H || defined _GL_STDDEF_WINT_T)) +# undef NULL +# ifdef __cplusplus + /* ISO C++ says that the macro NULL must expand to an integer constant + expression, hence '((void *) 0)' is not allowed in C++. */ +# if __GNUG__ >= 3 + /* GNU C++ has a __null macro that behaves like an integer ('int' or + 'long') but has the same size as a pointer. Use that, to avoid + warnings. */ +# define NULL __null +# else +# define NULL 0L +# endif +# else +# define NULL ((void *) 0) +# endif +# endif + +# ifndef _@GUARD_PREFIX@_STDDEF_H +# define _@GUARD_PREFIX@_STDDEF_H + +/* Some platforms lack wchar_t. */ +#if !@HAVE_WCHAR_T@ +# define wchar_t int +#endif + +/* Some platforms lack max_align_t. The check for _GCC_MAX_ALIGN_T is + a hack in case the configure-time test was done with g++ even though + we are currently compiling with gcc. */ +#if ! (@HAVE_MAX_ALIGN_T@ || defined _GCC_MAX_ALIGN_T) +# if !GNULIB_defined_max_align_t +/* On the x86, the maximum storage alignment of double, long, etc. is 4, + but GCC's C11 ABI for x86 says that max_align_t has an alignment of 8, + and the C11 standard allows this. Work around this problem by + using __alignof__ (which returns 8 for double) rather than _Alignof + (which returns 4), and align each union member accordingly. */ +# ifdef __GNUC__ +# define _GL_STDDEF_ALIGNAS(type) \ + __attribute__ ((__aligned__ (__alignof__ (type)))) +# else +# define _GL_STDDEF_ALIGNAS(type) /* */ +# endif +typedef union +{ + char *__p _GL_STDDEF_ALIGNAS (char *); + double __d _GL_STDDEF_ALIGNAS (double); + long double __ld _GL_STDDEF_ALIGNAS (long double); + long int __i _GL_STDDEF_ALIGNAS (long int); +} rpl_max_align_t; +# define max_align_t rpl_max_align_t +# define GNULIB_defined_max_align_t 1 +# endif +#endif + +# endif /* _@GUARD_PREFIX@_STDDEF_H */ +# endif /* _@GUARD_PREFIX@_STDDEF_H */ +#endif /* __need_XXX */ diff --git a/grub-core/lib/gnulib/stdint.in.h b/grub-core/lib/gnulib/stdint.in.h new file mode 100644 index 0000000..21dd8d2 --- /dev/null +++ b/grub-core/lib/gnulib/stdint.in.h @@ -0,0 +1,726 @@ +/* Copyright (C) 2001-2002, 2004-2019 Free Software Foundation, Inc. + Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood. + This file is part of gnulib. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* + * ISO C 99 <stdint.h> for platforms that lack it. + * <http://www.opengroup.org/susv3xbd/stdint.h.html> + */ + +#ifndef _@GUARD_PREFIX@_STDINT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* When including a system file that in turn includes <inttypes.h>, + use the system <inttypes.h>, not our substitute. This avoids + problems with (for example) VMS, whose <sys/bitypes.h> includes + <inttypes.h>. */ +#define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H + +/* On Android (Bionic libc), <sys/types.h> includes this file before + having defined 'time_t'. Therefore in this case avoid including + other system header files; just include the system's <stdint.h>. + Ideally we should test __BIONIC__ here, but it is only defined after + <sys/cdefs.h> has been included; hence test __ANDROID__ instead. */ +#if defined __ANDROID__ && defined _GL_INCLUDING_SYS_TYPES_H +# @INCLUDE_NEXT@ @NEXT_STDINT_H@ +#else + +/* Get those types that are already defined in other system include + files, so that we can "#define int8_t signed char" below without + worrying about a later system include file containing a "typedef + signed char int8_t;" that will get messed up by our macro. Our + macros should all be consistent with the system versions, except + for the "fast" types and macros, which we recommend against using + in public interfaces due to compiler differences. */ + +#if @HAVE_STDINT_H@ +# if defined __sgi && ! defined __c99 + /* Bypass IRIX's <stdint.h> if in C89 mode, since it merely annoys users + with "This header file is to be used only for c99 mode compilations" + diagnostics. */ +# define __STDINT_H__ +# endif + + /* Some pre-C++11 <stdint.h> implementations need this. */ +# ifdef __cplusplus +# ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS 1 +# endif +# ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +# endif +# endif + + /* Other systems may have an incomplete or buggy <stdint.h>. + Include it before <inttypes.h>, since any "#include <stdint.h>" + in <inttypes.h> would reinclude us, skipping our contents because + _@GUARD_PREFIX@_STDINT_H is defined. + The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_STDINT_H@ +#endif + +#if ! defined _@GUARD_PREFIX@_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H +#define _@GUARD_PREFIX@_STDINT_H + +/* Get SCHAR_MIN, SCHAR_MAX, UCHAR_MAX, INT_MIN, INT_MAX, + LONG_MIN, LONG_MAX, ULONG_MAX, _GL_INTEGER_WIDTH. */ +#include <limits.h> + +/* Override WINT_MIN and WINT_MAX if gnulib's <wchar.h> or <wctype.h> overrides + wint_t. */ +#if @GNULIB_OVERRIDES_WINT_T@ +# undef WINT_MIN +# undef WINT_MAX +# define WINT_MIN 0x0U +# define WINT_MAX 0xffffffffU +#endif + +#if ! @HAVE_C99_STDINT_H@ + +/* <sys/types.h> defines some of the stdint.h types as well, on glibc, + IRIX 6.5, and OpenBSD 3.8 (via <machine/types.h>). + AIX 5.2 <sys/types.h> isn't needed and causes troubles. + Mac OS X 10.4.6 <sys/types.h> includes <stdint.h> (which is us), but + relies on the system <stdint.h> definitions, so include + <sys/types.h> after @NEXT_STDINT_H@. */ +# if @HAVE_SYS_TYPES_H@ && ! defined _AIX +# include <sys/types.h> +# endif + +# if @HAVE_INTTYPES_H@ + /* In OpenBSD 3.8, <inttypes.h> includes <machine/types.h>, which defines + int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__. + <inttypes.h> also defines intptr_t and uintptr_t. */ +# include <inttypes.h> +# elif @HAVE_SYS_INTTYPES_H@ + /* Solaris 7 <sys/inttypes.h> has the types except the *_fast*_t types, and + the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */ +# include <sys/inttypes.h> +# endif + +# if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__ + /* Linux libc4 >= 4.6.7 and libc5 have a <sys/bitypes.h> that defines + int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is + included by <sys/types.h>. */ +# include <sys/bitypes.h> +# endif + +# undef _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H + +/* Minimum and maximum values for an integer type under the usual assumption. + Return an unspecified value if BITS == 0, adding a check to pacify + picky compilers. */ + +/* These are separate macros, because if you try to merge these macros into + a single one, HP-UX cc rejects the resulting expression in constant + expressions. */ +# define _STDINT_UNSIGNED_MIN(bits, zero) \ + (zero) +# define _STDINT_SIGNED_MIN(bits, zero) \ + (~ _STDINT_MAX (1, bits, zero)) + +# define _STDINT_MAX(signed, bits, zero) \ + (((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1) + +#if !GNULIB_defined_stdint_types + +/* 7.18.1.1. Exact-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. */ + +# undef int8_t +# undef uint8_t +typedef signed char gl_int8_t; +typedef unsigned char gl_uint8_t; +# define int8_t gl_int8_t +# define uint8_t gl_uint8_t + +# undef int16_t +# undef uint16_t +typedef short int gl_int16_t; +typedef unsigned short int gl_uint16_t; +# define int16_t gl_int16_t +# define uint16_t gl_uint16_t + +# undef int32_t +# undef uint32_t +typedef int gl_int32_t; +typedef unsigned int gl_uint32_t; +# define int32_t gl_int32_t +# define uint32_t gl_uint32_t + +/* If the system defines INT64_MAX, assume int64_t works. That way, + if the underlying platform defines int64_t to be a 64-bit long long + int, the code below won't mistakenly define it to be a 64-bit long + int, which would mess up C++ name mangling. We must use #ifdef + rather than #if, to avoid an error with HP-UX 10.20 cc. */ + +# ifdef INT64_MAX +# define GL_INT64_T +# else +/* Do not undefine int64_t if gnulib is not being used with 64-bit + types, since otherwise it breaks platforms like Tandem/NSK. */ +# if LONG_MAX >> 31 >> 31 == 1 +# undef int64_t +typedef long int gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# elif defined _MSC_VER +# undef int64_t +typedef __int64 gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# elif @HAVE_LONG_LONG_INT@ +# undef int64_t +typedef long long int gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# endif +# endif + +# ifdef UINT64_MAX +# define GL_UINT64_T +# else +# if ULONG_MAX >> 31 >> 31 >> 1 == 1 +# undef uint64_t +typedef unsigned long int gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# elif defined _MSC_VER +# undef uint64_t +typedef unsigned __int64 gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# elif @HAVE_UNSIGNED_LONG_LONG_INT@ +# undef uint64_t +typedef unsigned long long int gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# endif +# endif + +/* Avoid collision with Solaris 2.5.1 <pthread.h> etc. */ +# define _UINT8_T +# define _UINT32_T +# define _UINT64_T + + +/* 7.18.1.2. Minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types + are the same as the corresponding N_t types. */ + +# undef int_least8_t +# undef uint_least8_t +# undef int_least16_t +# undef uint_least16_t +# undef int_least32_t +# undef uint_least32_t +# undef int_least64_t +# undef uint_least64_t +# define int_least8_t int8_t +# define uint_least8_t uint8_t +# define int_least16_t int16_t +# define uint_least16_t uint16_t +# define int_least32_t int32_t +# define uint_least32_t uint32_t +# ifdef GL_INT64_T +# define int_least64_t int64_t +# endif +# ifdef GL_UINT64_T +# define uint_least64_t uint64_t +# endif + +/* 7.18.1.3. Fastest minimum-width integer types */ + +/* Note: Other <stdint.h> substitutes may define these types differently. + It is not recommended to use these types in public header files. */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types + are taken from the same list of types. The following code normally + uses types consistent with glibc, as that lessens the chance of + incompatibility with older GNU hosts. */ + +# undef int_fast8_t +# undef uint_fast8_t +# undef int_fast16_t +# undef uint_fast16_t +# undef int_fast32_t +# undef uint_fast32_t +# undef int_fast64_t +# undef uint_fast64_t +typedef signed char gl_int_fast8_t; +typedef unsigned char gl_uint_fast8_t; + +# ifdef __sun +/* Define types compatible with SunOS 5.10, so that code compiled under + earlier SunOS versions works with code compiled under SunOS 5.10. */ +typedef int gl_int_fast32_t; +typedef unsigned int gl_uint_fast32_t; +# else +typedef long int gl_int_fast32_t; +typedef unsigned long int gl_uint_fast32_t; +# endif +typedef gl_int_fast32_t gl_int_fast16_t; +typedef gl_uint_fast32_t gl_uint_fast16_t; + +# define int_fast8_t gl_int_fast8_t +# define uint_fast8_t gl_uint_fast8_t +# define int_fast16_t gl_int_fast16_t +# define uint_fast16_t gl_uint_fast16_t +# define int_fast32_t gl_int_fast32_t +# define uint_fast32_t gl_uint_fast32_t +# ifdef GL_INT64_T +# define int_fast64_t int64_t +# endif +# ifdef GL_UINT64_T +# define uint_fast64_t uint64_t +# endif + +/* 7.18.1.4. Integer types capable of holding object pointers */ + +/* kLIBC's stdint.h defines _INTPTR_T_DECLARED and needs its own + definitions of intptr_t and uintptr_t (which use int and unsigned) + to avoid clashes with declarations of system functions like sbrk. */ +# ifndef _INTPTR_T_DECLARED +# undef intptr_t +# undef uintptr_t +typedef long int gl_intptr_t; +typedef unsigned long int gl_uintptr_t; +# define intptr_t gl_intptr_t +# define uintptr_t gl_uintptr_t +# endif + +/* 7.18.1.5. Greatest-width integer types */ + +/* Note: These types are compiler dependent. It may be unwise to use them in + public header files. */ + +/* If the system defines INTMAX_MAX, assume that intmax_t works, and + similarly for UINTMAX_MAX and uintmax_t. This avoids problems with + assuming one type where another is used by the system. */ + +# ifndef INTMAX_MAX +# undef INTMAX_C +# undef intmax_t +# if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 +typedef long long int gl_intmax_t; +# define intmax_t gl_intmax_t +# elif defined GL_INT64_T +# define intmax_t int64_t +# else +typedef long int gl_intmax_t; +# define intmax_t gl_intmax_t +# endif +# endif + +# ifndef UINTMAX_MAX +# undef UINTMAX_C +# undef uintmax_t +# if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 +typedef unsigned long long int gl_uintmax_t; +# define uintmax_t gl_uintmax_t +# elif defined GL_UINT64_T +# define uintmax_t uint64_t +# else +typedef unsigned long int gl_uintmax_t; +# define uintmax_t gl_uintmax_t +# endif +# endif + +/* Verify that intmax_t and uintmax_t have the same size. Too much code + breaks if this is not the case. If this check fails, the reason is likely + to be found in the autoconf macros. */ +typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t) + ? 1 : -1]; + +# define GNULIB_defined_stdint_types 1 +# endif /* !GNULIB_defined_stdint_types */ + +/* 7.18.2. Limits of specified-width integer types */ + +/* 7.18.2.1. Limits of exact-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. */ + +# undef INT8_MIN +# undef INT8_MAX +# undef UINT8_MAX +# define INT8_MIN (~ INT8_MAX) +# define INT8_MAX 127 +# define UINT8_MAX 255 + +# undef INT16_MIN +# undef INT16_MAX +# undef UINT16_MAX +# define INT16_MIN (~ INT16_MAX) +# define INT16_MAX 32767 +# define UINT16_MAX 65535 + +# undef INT32_MIN +# undef INT32_MAX +# undef UINT32_MAX +# define INT32_MIN (~ INT32_MAX) +# define INT32_MAX 2147483647 +# define UINT32_MAX 4294967295U + +# if defined GL_INT64_T && ! defined INT64_MAX +/* Prefer (- INTMAX_C (1) << 63) over (~ INT64_MAX) because SunPRO C 5.0 + evaluates the latter incorrectly in preprocessor expressions. */ +# define INT64_MIN (- INTMAX_C (1) << 63) +# define INT64_MAX INTMAX_C (9223372036854775807) +# endif + +# if defined GL_UINT64_T && ! defined UINT64_MAX +# define UINT64_MAX UINTMAX_C (18446744073709551615) +# endif + +/* 7.18.2.2. Limits of minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types + are the same as the corresponding N_t types. */ + +# undef INT_LEAST8_MIN +# undef INT_LEAST8_MAX +# undef UINT_LEAST8_MAX +# define INT_LEAST8_MIN INT8_MIN +# define INT_LEAST8_MAX INT8_MAX +# define UINT_LEAST8_MAX UINT8_MAX + +# undef INT_LEAST16_MIN +# undef INT_LEAST16_MAX +# undef UINT_LEAST16_MAX +# define INT_LEAST16_MIN INT16_MIN +# define INT_LEAST16_MAX INT16_MAX +# define UINT_LEAST16_MAX UINT16_MAX + +# undef INT_LEAST32_MIN +# undef INT_LEAST32_MAX +# undef UINT_LEAST32_MAX +# define INT_LEAST32_MIN INT32_MIN +# define INT_LEAST32_MAX INT32_MAX +# define UINT_LEAST32_MAX UINT32_MAX + +# undef INT_LEAST64_MIN +# undef INT_LEAST64_MAX +# ifdef GL_INT64_T +# define INT_LEAST64_MIN INT64_MIN +# define INT_LEAST64_MAX INT64_MAX +# endif + +# undef UINT_LEAST64_MAX +# ifdef GL_UINT64_T +# define UINT_LEAST64_MAX UINT64_MAX +# endif + +/* 7.18.2.3. Limits of fastest minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types + are taken from the same list of types. */ + +# undef INT_FAST8_MIN +# undef INT_FAST8_MAX +# undef UINT_FAST8_MAX +# define INT_FAST8_MIN SCHAR_MIN +# define INT_FAST8_MAX SCHAR_MAX +# define UINT_FAST8_MAX UCHAR_MAX + +# undef INT_FAST16_MIN +# undef INT_FAST16_MAX +# undef UINT_FAST16_MAX +# define INT_FAST16_MIN INT_FAST32_MIN +# define INT_FAST16_MAX INT_FAST32_MAX +# define UINT_FAST16_MAX UINT_FAST32_MAX + +# undef INT_FAST32_MIN +# undef INT_FAST32_MAX +# undef UINT_FAST32_MAX +# ifdef __sun +# define INT_FAST32_MIN INT_MIN +# define INT_FAST32_MAX INT_MAX +# define UINT_FAST32_MAX UINT_MAX +# else +# define INT_FAST32_MIN LONG_MIN +# define INT_FAST32_MAX LONG_MAX +# define UINT_FAST32_MAX ULONG_MAX +# endif + +# undef INT_FAST64_MIN +# undef INT_FAST64_MAX +# ifdef GL_INT64_T +# define INT_FAST64_MIN INT64_MIN +# define INT_FAST64_MAX INT64_MAX +# endif + +# undef UINT_FAST64_MAX +# ifdef GL_UINT64_T +# define UINT_FAST64_MAX UINT64_MAX +# endif + +/* 7.18.2.4. Limits of integer types capable of holding object pointers */ + +# undef INTPTR_MIN +# undef INTPTR_MAX +# undef UINTPTR_MAX +# define INTPTR_MIN LONG_MIN +# define INTPTR_MAX LONG_MAX +# define UINTPTR_MAX ULONG_MAX + +/* 7.18.2.5. Limits of greatest-width integer types */ + +# ifndef INTMAX_MAX +# undef INTMAX_MIN +# ifdef INT64_MAX +# define INTMAX_MIN INT64_MIN +# define INTMAX_MAX INT64_MAX +# else +# define INTMAX_MIN INT32_MIN +# define INTMAX_MAX INT32_MAX +# endif +# endif + +# ifndef UINTMAX_MAX +# ifdef UINT64_MAX +# define UINTMAX_MAX UINT64_MAX +# else +# define UINTMAX_MAX UINT32_MAX +# endif +# endif + +/* 7.18.3. Limits of other integer types */ + +/* ptrdiff_t limits */ +# undef PTRDIFF_MIN +# undef PTRDIFF_MAX +# if @APPLE_UNIVERSAL_BUILD@ +# ifdef _LP64 +# define PTRDIFF_MIN _STDINT_SIGNED_MIN (64, 0l) +# define PTRDIFF_MAX _STDINT_MAX (1, 64, 0l) +# else +# define PTRDIFF_MIN _STDINT_SIGNED_MIN (32, 0) +# define PTRDIFF_MAX _STDINT_MAX (1, 32, 0) +# endif +# else +# define PTRDIFF_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) +# define PTRDIFF_MAX \ + _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) +# endif + +/* sig_atomic_t limits */ +# undef SIG_ATOMIC_MIN +# undef SIG_ATOMIC_MAX +# if @HAVE_SIGNED_SIG_ATOMIC_T@ +# define SIG_ATOMIC_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_SIG_ATOMIC_T@, 0@SIG_ATOMIC_T_SUFFIX@) +# else +# define SIG_ATOMIC_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_SIG_ATOMIC_T@, 0@SIG_ATOMIC_T_SUFFIX@) +# endif +# define SIG_ATOMIC_MAX \ + _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ + 0@SIG_ATOMIC_T_SUFFIX@) + + +/* size_t limit */ +# undef SIZE_MAX +# if @APPLE_UNIVERSAL_BUILD@ +# ifdef _LP64 +# define SIZE_MAX _STDINT_MAX (0, 64, 0ul) +# else +# define SIZE_MAX _STDINT_MAX (0, 32, 0ul) +# endif +# else +# define SIZE_MAX _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, 0@SIZE_T_SUFFIX@) +# endif + +/* wchar_t limits */ +/* Get WCHAR_MIN, WCHAR_MAX. + This include is not on the top, above, because on OSF/1 4.0 we have a + sequence of nested includes + <wchar.h> -> <stdio.h> -> <getopt.h> -> <stdlib.h>, and the latter includes + <stdint.h> and assumes its types are already defined. */ +# if @HAVE_WCHAR_H@ && ! (defined WCHAR_MIN && defined WCHAR_MAX) + /* BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be + included before <wchar.h>. */ +# include <stddef.h> +# include <stdio.h> +# include <time.h> +# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H +# include <wchar.h> +# undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H +# endif +# undef WCHAR_MIN +# undef WCHAR_MAX +# if @HAVE_SIGNED_WCHAR_T@ +# define WCHAR_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) +# else +# define WCHAR_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) +# endif +# define WCHAR_MAX \ + _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) + +/* wint_t limits */ +# undef WINT_MIN +# undef WINT_MAX +# if @HAVE_SIGNED_WINT_T@ +# define WINT_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +# else +# define WINT_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +# endif +# define WINT_MAX \ + _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) + +/* 7.18.4. Macros for integer constants */ + +/* 7.18.4.1. Macros for minimum-width integer constants */ +/* According to ISO C 99 Technical Corrigendum 1 */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */ + +# undef INT8_C +# undef UINT8_C +# define INT8_C(x) x +# define UINT8_C(x) x + +# undef INT16_C +# undef UINT16_C +# define INT16_C(x) x +# define UINT16_C(x) x + +# undef INT32_C +# undef UINT32_C +# define INT32_C(x) x +# define UINT32_C(x) x ## U + +# undef INT64_C +# undef UINT64_C +# if LONG_MAX >> 31 >> 31 == 1 +# define INT64_C(x) x##L +# elif defined _MSC_VER +# define INT64_C(x) x##i64 +# elif @HAVE_LONG_LONG_INT@ +# define INT64_C(x) x##LL +# endif +# if ULONG_MAX >> 31 >> 31 >> 1 == 1 +# define UINT64_C(x) x##UL +# elif defined _MSC_VER +# define UINT64_C(x) x##ui64 +# elif @HAVE_UNSIGNED_LONG_LONG_INT@ +# define UINT64_C(x) x##ULL +# endif + +/* 7.18.4.2. Macros for greatest-width integer constants */ + +# ifndef INTMAX_C +# if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 +# define INTMAX_C(x) x##LL +# elif defined GL_INT64_T +# define INTMAX_C(x) INT64_C(x) +# else +# define INTMAX_C(x) x##L +# endif +# endif + +# ifndef UINTMAX_C +# if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 +# define UINTMAX_C(x) x##ULL +# elif defined GL_UINT64_T +# define UINTMAX_C(x) UINT64_C(x) +# else +# define UINTMAX_C(x) x##UL +# endif +# endif + +#endif /* !@HAVE_C99_STDINT_H@ */ + +/* Macros specified by ISO/IEC TS 18661-1:2014. */ + +#if (!defined UINTMAX_WIDTH \ + && (defined _GNU_SOURCE || defined __STDC_WANT_IEC_60559_BFP_EXT__)) +# ifdef INT8_MAX +# define INT8_WIDTH _GL_INTEGER_WIDTH (INT8_MIN, INT8_MAX) +# endif +# ifdef UINT8_MAX +# define UINT8_WIDTH _GL_INTEGER_WIDTH (0, UINT8_MAX) +# endif +# ifdef INT16_MAX +# define INT16_WIDTH _GL_INTEGER_WIDTH (INT16_MIN, INT16_MAX) +# endif +# ifdef UINT16_MAX +# define UINT16_WIDTH _GL_INTEGER_WIDTH (0, UINT16_MAX) +# endif +# ifdef INT32_MAX +# define INT32_WIDTH _GL_INTEGER_WIDTH (INT32_MIN, INT32_MAX) +# endif +# ifdef UINT32_MAX +# define UINT32_WIDTH _GL_INTEGER_WIDTH (0, UINT32_MAX) +# endif +# ifdef INT64_MAX +# define INT64_WIDTH _GL_INTEGER_WIDTH (INT64_MIN, INT64_MAX) +# endif +# ifdef UINT64_MAX +# define UINT64_WIDTH _GL_INTEGER_WIDTH (0, UINT64_MAX) +# endif +# define INT_LEAST8_WIDTH _GL_INTEGER_WIDTH (INT_LEAST8_MIN, INT_LEAST8_MAX) +# define UINT_LEAST8_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST8_MAX) +# define INT_LEAST16_WIDTH _GL_INTEGER_WIDTH (INT_LEAST16_MIN, INT_LEAST16_MAX) +# define UINT_LEAST16_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST16_MAX) +# define INT_LEAST32_WIDTH _GL_INTEGER_WIDTH (INT_LEAST32_MIN, INT_LEAST32_MAX) +# define UINT_LEAST32_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST32_MAX) +# define INT_LEAST64_WIDTH _GL_INTEGER_WIDTH (INT_LEAST64_MIN, INT_LEAST64_MAX) +# define UINT_LEAST64_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST64_MAX) +# define INT_FAST8_WIDTH _GL_INTEGER_WIDTH (INT_FAST8_MIN, INT_FAST8_MAX) +# define UINT_FAST8_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST8_MAX) +# define INT_FAST16_WIDTH _GL_INTEGER_WIDTH (INT_FAST16_MIN, INT_FAST16_MAX) +# define UINT_FAST16_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST16_MAX) +# define INT_FAST32_WIDTH _GL_INTEGER_WIDTH (INT_FAST32_MIN, INT_FAST32_MAX) +# define UINT_FAST32_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST32_MAX) +# define INT_FAST64_WIDTH _GL_INTEGER_WIDTH (INT_FAST64_MIN, INT_FAST64_MAX) +# define UINT_FAST64_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST64_MAX) +# define INTPTR_WIDTH _GL_INTEGER_WIDTH (INTPTR_MIN, INTPTR_MAX) +# define UINTPTR_WIDTH _GL_INTEGER_WIDTH (0, UINTPTR_MAX) +# define INTMAX_WIDTH _GL_INTEGER_WIDTH (INTMAX_MIN, INTMAX_MAX) +# define UINTMAX_WIDTH _GL_INTEGER_WIDTH (0, UINTMAX_MAX) +# define PTRDIFF_WIDTH _GL_INTEGER_WIDTH (PTRDIFF_MIN, PTRDIFF_MAX) +# define SIZE_WIDTH _GL_INTEGER_WIDTH (0, SIZE_MAX) +# define WCHAR_WIDTH _GL_INTEGER_WIDTH (WCHAR_MIN, WCHAR_MAX) +# ifdef WINT_MAX +# define WINT_WIDTH _GL_INTEGER_WIDTH (WINT_MIN, WINT_MAX) +# endif +# ifdef SIG_ATOMIC_MAX +# define SIG_ATOMIC_WIDTH _GL_INTEGER_WIDTH (SIG_ATOMIC_MIN, SIG_ATOMIC_MAX) +# endif +#endif /* !WINT_WIDTH && (_GNU_SOURCE || __STDC_WANT_IEC_60559_BFP_EXT__) */ + +#endif /* _@GUARD_PREFIX@_STDINT_H */ +#endif /* !(defined __ANDROID__ && ...) */ +#endif /* !defined _@GUARD_PREFIX@_STDINT_H && !defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H */ diff --git a/grub-core/lib/gnulib/stdio.in.h b/grub-core/lib/gnulib/stdio.in.h new file mode 100644 index 0000000..acf29c4 --- /dev/null +++ b/grub-core/lib/gnulib/stdio.in.h @@ -0,0 +1,1377 @@ +/* A GNU-like <stdio.h>. + + Copyright (C) 2004, 2007-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_FILE || defined __need___FILE || defined _GL_ALREADY_INCLUDING_STDIO_H +/* Special invocation convention: + - Inside glibc header files. + - On OSF/1 5.1 we have a sequence of nested includes + <stdio.h> -> <getopt.h> -> <ctype.h> -> <sys/localedef.h> -> + <sys/lc_core.h> -> <nl_types.h> -> <mesg.h> -> <stdio.h>. + In this situation, the functions are not yet declared, therefore we cannot + provide the C++ aliases. */ + +#@INCLUDE_NEXT@ @NEXT_STDIO_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_STDIO_H + +#define _GL_ALREADY_INCLUDING_STDIO_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STDIO_H@ + +#undef _GL_ALREADY_INCLUDING_STDIO_H + +#ifndef _@GUARD_PREFIX@_STDIO_H +#define _@GUARD_PREFIX@_STDIO_H + +/* Get va_list. Needed on many systems, including glibc 2.8. */ +#include <stdarg.h> + +#include <stddef.h> + +/* Get off_t and ssize_t. Needed on many systems, including glibc 2.8 + and eglibc 2.11.2. + May also define off_t to a 64-bit type on native Windows. */ +#include <sys/types.h> + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The __-protected variants of the attributes 'format' and 'printf' are + accepted by gcc versions 2.6.4 (effectively 2.7) and later. + We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because + gnulib and libintl do '#define printf __printf__' when they override + the 'printf' function. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +#endif + +/* _GL_ATTRIBUTE_FORMAT_PRINTF + indicates to GCC that the function takes a format string and arguments, + where the format string directives are the ones standardized by ISO C99 + and POSIX. */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__gnu_printf__, formatstring_parameter, first_argument)) +#else +# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument)) +#endif + +/* _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_PRINTF, + except that it indicates to GCC that the supported format string directives + are the ones of the system printf(), rather than the ones standardized by + ISO C99 and POSIX. */ +#if GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU +# define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT_PRINTF (formatstring_parameter, first_argument) +#else +# define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument)) +#endif + +/* _GL_ATTRIBUTE_FORMAT_SCANF + indicates to GCC that the function takes a format string and arguments, + where the format string directives are the ones standardized by ISO C99 + and POSIX. */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +# define _GL_ATTRIBUTE_FORMAT_SCANF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__gnu_scanf__, formatstring_parameter, first_argument)) +#else +# define _GL_ATTRIBUTE_FORMAT_SCANF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__scanf__, formatstring_parameter, first_argument)) +#endif + +/* _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_SCANF, + except that it indicates to GCC that the supported format string directives + are the ones of the system scanf(), rather than the ones standardized by + ISO C99 and POSIX. */ +#define _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__scanf__, formatstring_parameter, first_argument)) + +/* Solaris 10 and NetBSD 7.0 declare renameat in <unistd.h>, not in <stdio.h>. */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_RENAMEAT@ || defined GNULIB_POSIXCHECK) && (defined __sun || defined __NetBSD__) \ + && ! defined __GLIBC__ +# include <unistd.h> +#endif + +/* MSVC declares 'perror' in <stdlib.h>, not in <stdio.h>. We must include + it before we #define perror rpl_perror. */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_PERROR@ || defined GNULIB_POSIXCHECK) \ + && (defined _WIN32 && ! defined __CYGWIN__) \ + && ! defined __GLIBC__ +# include <stdlib.h> +#endif + +/* MSVC declares 'remove' in <io.h>, not in <stdio.h>. We must include + it before we #define remove rpl_remove. */ +/* MSVC declares 'rename' in <io.h>, not in <stdio.h>. We must include + it before we #define rename rpl_rename. */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_REMOVE@ || @GNULIB_RENAME@ || defined GNULIB_POSIXCHECK) \ + && (defined _WIN32 && ! defined __CYGWIN__) \ + && ! defined __GLIBC__ +# include <io.h> +#endif + + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Macros for stringification. */ +#define _GL_STDIO_STRINGIZE(token) #token +#define _GL_STDIO_MACROEXPAND_AND_STRINGIZE(token) _GL_STDIO_STRINGIZE(token) + +/* When also using extern inline, suppress the use of static inline in + standard headers of problematic Apple configurations, as Libc at + least through Libc-825.26 (2013-04-09) mishandles it; see, e.g., + <https://lists.gnu.org/r/bug-gnulib/2012-12/msg00023.html>. + Perhaps Apple will fix this some day. */ +#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \ + && defined __GNUC__ && defined __STDC__) +# undef putc_unlocked +#endif + +#if @GNULIB_DPRINTF@ +# if @REPLACE_DPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dprintf rpl_dprintf +# endif +_GL_FUNCDECL_RPL (dprintf, int, (int fd, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (dprintf, int, (int fd, const char *format, ...)); +# else +# if !@HAVE_DPRINTF@ +_GL_FUNCDECL_SYS (dprintf, int, (int fd, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (dprintf, int, (int fd, const char *format, ...)); +# endif +_GL_CXXALIASWARN (dprintf); +#elif defined GNULIB_POSIXCHECK +# undef dprintf +# if HAVE_RAW_DECL_DPRINTF +_GL_WARN_ON_USE (dprintf, "dprintf is unportable - " + "use gnulib module dprintf for portability"); +# endif +#endif + +#if @GNULIB_FCLOSE@ +/* Close STREAM and its underlying file descriptor. */ +# if @REPLACE_FCLOSE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fclose rpl_fclose +# endif +_GL_FUNCDECL_RPL (fclose, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fclose, int, (FILE *stream)); +# else +_GL_CXXALIAS_SYS (fclose, int, (FILE *stream)); +# endif +_GL_CXXALIASWARN (fclose); +#elif defined GNULIB_POSIXCHECK +# undef fclose +/* Assume fclose is always declared. */ +_GL_WARN_ON_USE (fclose, "fclose is not always POSIX compliant - " + "use gnulib module fclose for portable POSIX compliance"); +#endif + +#if @GNULIB_FDOPEN@ +# if @REPLACE_FDOPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fdopen +# define fdopen rpl_fdopen +# endif +_GL_FUNCDECL_RPL (fdopen, FILE *, (int fd, const char *mode) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fdopen, FILE *, (int fd, const char *mode)); +# else +_GL_CXXALIAS_SYS (fdopen, FILE *, (int fd, const char *mode)); +# endif +_GL_CXXALIASWARN (fdopen); +#elif defined GNULIB_POSIXCHECK +# undef fdopen +/* Assume fdopen is always declared. */ +_GL_WARN_ON_USE (fdopen, "fdopen on native Windows platforms is not POSIX compliant - " + "use gnulib module fdopen for portability"); +#endif + +#if @GNULIB_FFLUSH@ +/* Flush all pending data on STREAM according to POSIX rules. Both + output and seekable input streams are supported. + Note! LOSS OF DATA can occur if fflush is applied on an input stream + that is _not_seekable_ or on an update stream that is _not_seekable_ + and in which the most recent operation was input. Seekability can + be tested with lseek(fileno(fp),0,SEEK_CUR). */ +# if @REPLACE_FFLUSH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fflush rpl_fflush +# endif +_GL_FUNCDECL_RPL (fflush, int, (FILE *gl_stream)); +_GL_CXXALIAS_RPL (fflush, int, (FILE *gl_stream)); +# else +_GL_CXXALIAS_SYS (fflush, int, (FILE *gl_stream)); +# endif +_GL_CXXALIASWARN (fflush); +#elif defined GNULIB_POSIXCHECK +# undef fflush +/* Assume fflush is always declared. */ +_GL_WARN_ON_USE (fflush, "fflush is not always POSIX compliant - " + "use gnulib module fflush for portable POSIX compliance"); +#endif + +#if @GNULIB_FGETC@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fgetc +# define fgetc rpl_fgetc +# endif +_GL_FUNCDECL_RPL (fgetc, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fgetc, int, (FILE *stream)); +# else +_GL_CXXALIAS_SYS (fgetc, int, (FILE *stream)); +# endif +_GL_CXXALIASWARN (fgetc); +#endif + +#if @GNULIB_FGETS@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fgets +# define fgets rpl_fgets +# endif +_GL_FUNCDECL_RPL (fgets, char *, (char *s, int n, FILE *stream) + _GL_ARG_NONNULL ((1, 3))); +_GL_CXXALIAS_RPL (fgets, char *, (char *s, int n, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fgets, char *, (char *s, int n, FILE *stream)); +# endif +_GL_CXXALIASWARN (fgets); +#endif + +#if @GNULIB_FOPEN@ +# if @REPLACE_FOPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fopen +# define fopen rpl_fopen +# endif +_GL_FUNCDECL_RPL (fopen, FILE *, (const char *filename, const char *mode) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (fopen, FILE *, (const char *filename, const char *mode)); +# else +_GL_CXXALIAS_SYS (fopen, FILE *, (const char *filename, const char *mode)); +# endif +_GL_CXXALIASWARN (fopen); +#elif defined GNULIB_POSIXCHECK +# undef fopen +/* Assume fopen is always declared. */ +_GL_WARN_ON_USE (fopen, "fopen on native Windows platforms is not POSIX compliant - " + "use gnulib module fopen for portability"); +#endif + +#if @GNULIB_FPRINTF_POSIX@ || @GNULIB_FPRINTF@ +# if (@GNULIB_FPRINTF_POSIX@ && @REPLACE_FPRINTF@) \ + || (@GNULIB_FPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fprintf rpl_fprintf +# endif +# define GNULIB_overrides_fprintf 1 +# if @GNULIB_FPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL (fprintf, int, (FILE *fp, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# else +_GL_FUNCDECL_RPL (fprintf, int, (FILE *fp, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_RPL (fprintf, int, (FILE *fp, const char *format, ...)); +# else +_GL_CXXALIAS_SYS (fprintf, int, (FILE *fp, const char *format, ...)); +# endif +_GL_CXXALIASWARN (fprintf); +#endif +#if !@GNULIB_FPRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_fprintf +# undef fprintf +# endif +/* Assume fprintf is always declared. */ +_GL_WARN_ON_USE (fprintf, "fprintf is not always POSIX compliant - " + "use gnulib module fprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_FPURGE@ +/* Discard all pending buffered I/O data on STREAM. + STREAM must not be wide-character oriented. + When discarding pending output, the file position is set back to where it + was before the write calls. When discarding pending input, the file + position is advanced to match the end of the previously read input. + Return 0 if successful. Upon error, return -1 and set errno. */ +# if @REPLACE_FPURGE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fpurge rpl_fpurge +# endif +_GL_FUNCDECL_RPL (fpurge, int, (FILE *gl_stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fpurge, int, (FILE *gl_stream)); +# else +# if !@HAVE_DECL_FPURGE@ +_GL_FUNCDECL_SYS (fpurge, int, (FILE *gl_stream) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (fpurge, int, (FILE *gl_stream)); +# endif +_GL_CXXALIASWARN (fpurge); +#elif defined GNULIB_POSIXCHECK +# undef fpurge +# if HAVE_RAW_DECL_FPURGE +_GL_WARN_ON_USE (fpurge, "fpurge is not always present - " + "use gnulib module fpurge for portability"); +# endif +#endif + +#if @GNULIB_FPUTC@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fputc +# define fputc rpl_fputc +# endif +_GL_FUNCDECL_RPL (fputc, int, (int c, FILE *stream) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fputc, int, (int c, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fputc, int, (int c, FILE *stream)); +# endif +_GL_CXXALIASWARN (fputc); +#endif + +#if @GNULIB_FPUTS@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fputs +# define fputs rpl_fputs +# endif +_GL_FUNCDECL_RPL (fputs, int, (const char *string, FILE *stream) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (fputs, int, (const char *string, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fputs, int, (const char *string, FILE *stream)); +# endif +_GL_CXXALIASWARN (fputs); +#endif + +#if @GNULIB_FREAD@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fread +# define fread rpl_fread +# endif +_GL_FUNCDECL_RPL (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream) + _GL_ARG_NONNULL ((4))); +_GL_CXXALIAS_RPL (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream)); +# endif +_GL_CXXALIASWARN (fread); +#endif + +#if @GNULIB_FREOPEN@ +# if @REPLACE_FREOPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef freopen +# define freopen rpl_freopen +# endif +_GL_FUNCDECL_RPL (freopen, FILE *, + (const char *filename, const char *mode, FILE *stream) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (freopen, FILE *, + (const char *filename, const char *mode, FILE *stream)); +# else +_GL_CXXALIAS_SYS (freopen, FILE *, + (const char *filename, const char *mode, FILE *stream)); +# endif +_GL_CXXALIASWARN (freopen); +#elif defined GNULIB_POSIXCHECK +# undef freopen +/* Assume freopen is always declared. */ +_GL_WARN_ON_USE (freopen, + "freopen on native Windows platforms is not POSIX compliant - " + "use gnulib module freopen for portability"); +#endif + +#if @GNULIB_FSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fscanf +# define fscanf rpl_fscanf +# endif +_GL_FUNCDECL_RPL (fscanf, int, (FILE *stream, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (fscanf, int, (FILE *stream, const char *format, ...)); +# else +_GL_CXXALIAS_SYS (fscanf, int, (FILE *stream, const char *format, ...)); +# endif +_GL_CXXALIASWARN (fscanf); +#endif + + +/* Set up the following warnings, based on which modules are in use. + GNU Coding Standards discourage the use of fseek, since it imposes + an arbitrary limitation on some 32-bit hosts. Remember that the + fseek module depends on the fseeko module, so we only have three + cases to consider: + + 1. The developer is not using either module. Issue a warning under + GNULIB_POSIXCHECK for both functions, to remind them that both + functions have bugs on some systems. _GL_NO_LARGE_FILES has no + impact on this warning. + + 2. The developer is using both modules. They may be unaware of the + arbitrary limitations of fseek, so issue a warning under + GNULIB_POSIXCHECK. On the other hand, they may be using both + modules intentionally, so the developer can define + _GL_NO_LARGE_FILES in the compilation units where the use of fseek + is safe, to silence the warning. + + 3. The developer is using the fseeko module, but not fseek. Gnulib + guarantees that fseek will still work around platform bugs in that + case, but we presume that the developer is aware of the pitfalls of + fseek and was trying to avoid it, so issue a warning even when + GNULIB_POSIXCHECK is undefined. Again, _GL_NO_LARGE_FILES can be + defined to silence the warning in particular compilation units. + In C++ compilations with GNULIB_NAMESPACE, in order to avoid that + fseek gets defined as a macro, it is recommended that the developer + uses the fseek module, even if he is not calling the fseek function. + + Most gnulib clients that perform stream operations should fall into + category 3. */ + +#if @GNULIB_FSEEK@ +# if defined GNULIB_POSIXCHECK && !defined _GL_NO_LARGE_FILES +# define _GL_FSEEK_WARN /* Category 2, above. */ +# undef fseek +# endif +# if @REPLACE_FSEEK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fseek +# define fseek rpl_fseek +# endif +_GL_FUNCDECL_RPL (fseek, int, (FILE *fp, long offset, int whence) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fseek, int, (FILE *fp, long offset, int whence)); +# else +_GL_CXXALIAS_SYS (fseek, int, (FILE *fp, long offset, int whence)); +# endif +_GL_CXXALIASWARN (fseek); +#endif + +#if @GNULIB_FSEEKO@ +# if !@GNULIB_FSEEK@ && !defined _GL_NO_LARGE_FILES +# define _GL_FSEEK_WARN /* Category 3, above. */ +# undef fseek +# endif +# if @REPLACE_FSEEKO@ +/* Provide an fseeko function that is aware of a preceding fflush(), and which + detects pipes. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fseeko +# define fseeko rpl_fseeko +# endif +_GL_FUNCDECL_RPL (fseeko, int, (FILE *fp, off_t offset, int whence) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fseeko, int, (FILE *fp, off_t offset, int whence)); +# else +# if ! @HAVE_DECL_FSEEKO@ +_GL_FUNCDECL_SYS (fseeko, int, (FILE *fp, off_t offset, int whence) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (fseeko, int, (FILE *fp, off_t offset, int whence)); +# endif +_GL_CXXALIASWARN (fseeko); +#elif defined GNULIB_POSIXCHECK +# define _GL_FSEEK_WARN /* Category 1, above. */ +# undef fseek +# undef fseeko +# if HAVE_RAW_DECL_FSEEKO +_GL_WARN_ON_USE (fseeko, "fseeko is unportable - " + "use gnulib module fseeko for portability"); +# endif +#endif + +#ifdef _GL_FSEEK_WARN +# undef _GL_FSEEK_WARN +/* Here, either fseek is undefined (but C89 guarantees that it is + declared), or it is defined as rpl_fseek (declared above). */ +_GL_WARN_ON_USE (fseek, "fseek cannot handle files larger than 4 GB " + "on 32-bit platforms - " + "use fseeko function for handling of large files"); +#endif + + +/* ftell, ftello. See the comments on fseek/fseeko. */ + +#if @GNULIB_FTELL@ +# if defined GNULIB_POSIXCHECK && !defined _GL_NO_LARGE_FILES +# define _GL_FTELL_WARN /* Category 2, above. */ +# undef ftell +# endif +# if @REPLACE_FTELL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ftell +# define ftell rpl_ftell +# endif +_GL_FUNCDECL_RPL (ftell, long, (FILE *fp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (ftell, long, (FILE *fp)); +# else +_GL_CXXALIAS_SYS (ftell, long, (FILE *fp)); +# endif +_GL_CXXALIASWARN (ftell); +#endif + +#if @GNULIB_FTELLO@ +# if !@GNULIB_FTELL@ && !defined _GL_NO_LARGE_FILES +# define _GL_FTELL_WARN /* Category 3, above. */ +# undef ftell +# endif +# if @REPLACE_FTELLO@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ftello +# define ftello rpl_ftello +# endif +_GL_FUNCDECL_RPL (ftello, off_t, (FILE *fp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (ftello, off_t, (FILE *fp)); +# else +# if ! @HAVE_DECL_FTELLO@ +_GL_FUNCDECL_SYS (ftello, off_t, (FILE *fp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (ftello, off_t, (FILE *fp)); +# endif +_GL_CXXALIASWARN (ftello); +#elif defined GNULIB_POSIXCHECK +# define _GL_FTELL_WARN /* Category 1, above. */ +# undef ftell +# undef ftello +# if HAVE_RAW_DECL_FTELLO +_GL_WARN_ON_USE (ftello, "ftello is unportable - " + "use gnulib module ftello for portability"); +# endif +#endif + +#ifdef _GL_FTELL_WARN +# undef _GL_FTELL_WARN +/* Here, either ftell is undefined (but C89 guarantees that it is + declared), or it is defined as rpl_ftell (declared above). */ +_GL_WARN_ON_USE (ftell, "ftell cannot handle files larger than 4 GB " + "on 32-bit platforms - " + "use ftello function for handling of large files"); +#endif + + +#if @GNULIB_FWRITE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fwrite +# define fwrite rpl_fwrite +# endif +_GL_FUNCDECL_RPL (fwrite, size_t, + (const void *ptr, size_t s, size_t n, FILE *stream) + _GL_ARG_NONNULL ((1, 4))); +_GL_CXXALIAS_RPL (fwrite, size_t, + (const void *ptr, size_t s, size_t n, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fwrite, size_t, + (const void *ptr, size_t s, size_t n, FILE *stream)); + +/* Work around bug 11959 when fortifying glibc 2.4 through 2.15 + <https://sourceware.org/bugzilla/show_bug.cgi?id=11959>, + which sometimes causes an unwanted diagnostic for fwrite calls. + This affects only function declaration attributes under certain + versions of gcc and clang, and is not needed for C++. */ +# if (0 < __USE_FORTIFY_LEVEL \ + && __GLIBC__ == 2 && 4 <= __GLIBC_MINOR__ && __GLIBC_MINOR__ <= 15 \ + && 3 < __GNUC__ + (4 <= __GNUC_MINOR__) \ + && !defined __cplusplus) +# undef fwrite +# undef fwrite_unlocked +extern size_t __REDIRECT (rpl_fwrite, + (const void *__restrict, size_t, size_t, + FILE *__restrict), + fwrite); +extern size_t __REDIRECT (rpl_fwrite_unlocked, + (const void *__restrict, size_t, size_t, + FILE *__restrict), + fwrite_unlocked); +# define fwrite rpl_fwrite +# define fwrite_unlocked rpl_fwrite_unlocked +# endif +# endif +_GL_CXXALIASWARN (fwrite); +#endif + +#if @GNULIB_GETC@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getc +# define getc rpl_fgetc +# endif +_GL_FUNCDECL_RPL (fgetc, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL_1 (getc, rpl_fgetc, int, (FILE *stream)); +# else +_GL_CXXALIAS_SYS (getc, int, (FILE *stream)); +# endif +_GL_CXXALIASWARN (getc); +#endif + +#if @GNULIB_GETCHAR@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getchar +# define getchar rpl_getchar +# endif +_GL_FUNCDECL_RPL (getchar, int, (void)); +_GL_CXXALIAS_RPL (getchar, int, (void)); +# else +_GL_CXXALIAS_SYS (getchar, int, (void)); +# endif +_GL_CXXALIASWARN (getchar); +#endif + +#if @GNULIB_GETDELIM@ +/* Read input, up to (and including) the next occurrence of DELIMITER, from + STREAM, store it in *LINEPTR (and NUL-terminate it). + *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE + bytes of space. It is realloc'd as necessary. + Return the number of bytes read and stored at *LINEPTR (not including the + NUL terminator), or -1 on error or EOF. */ +# if @REPLACE_GETDELIM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getdelim +# define getdelim rpl_getdelim +# endif +_GL_FUNCDECL_RPL (getdelim, ssize_t, + (char **lineptr, size_t *linesize, int delimiter, + FILE *stream) + _GL_ARG_NONNULL ((1, 2, 4))); +_GL_CXXALIAS_RPL (getdelim, ssize_t, + (char **lineptr, size_t *linesize, int delimiter, + FILE *stream)); +# else +# if !@HAVE_DECL_GETDELIM@ +_GL_FUNCDECL_SYS (getdelim, ssize_t, + (char **lineptr, size_t *linesize, int delimiter, + FILE *stream) + _GL_ARG_NONNULL ((1, 2, 4))); +# endif +_GL_CXXALIAS_SYS (getdelim, ssize_t, + (char **lineptr, size_t *linesize, int delimiter, + FILE *stream)); +# endif +_GL_CXXALIASWARN (getdelim); +#elif defined GNULIB_POSIXCHECK +# undef getdelim +# if HAVE_RAW_DECL_GETDELIM +_GL_WARN_ON_USE (getdelim, "getdelim is unportable - " + "use gnulib module getdelim for portability"); +# endif +#endif + +#if @GNULIB_GETLINE@ +/* Read a line, up to (and including) the next newline, from STREAM, store it + in *LINEPTR (and NUL-terminate it). + *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE + bytes of space. It is realloc'd as necessary. + Return the number of bytes read and stored at *LINEPTR (not including the + NUL terminator), or -1 on error or EOF. */ +# if @REPLACE_GETLINE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getline +# define getline rpl_getline +# endif +_GL_FUNCDECL_RPL (getline, ssize_t, + (char **lineptr, size_t *linesize, FILE *stream) + _GL_ARG_NONNULL ((1, 2, 3))); +_GL_CXXALIAS_RPL (getline, ssize_t, + (char **lineptr, size_t *linesize, FILE *stream)); +# else +# if !@HAVE_DECL_GETLINE@ +_GL_FUNCDECL_SYS (getline, ssize_t, + (char **lineptr, size_t *linesize, FILE *stream) + _GL_ARG_NONNULL ((1, 2, 3))); +# endif +_GL_CXXALIAS_SYS (getline, ssize_t, + (char **lineptr, size_t *linesize, FILE *stream)); +# endif +# if @HAVE_DECL_GETLINE@ +_GL_CXXALIASWARN (getline); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getline +# if HAVE_RAW_DECL_GETLINE +_GL_WARN_ON_USE (getline, "getline is unportable - " + "use gnulib module getline for portability"); +# endif +#endif + +/* It is very rare that the developer ever has full control of stdin, + so any use of gets warrants an unconditional warning; besides, C11 + removed it. */ +#undef gets +#if HAVE_RAW_DECL_GETS && !defined __cplusplus +_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); +#endif + +#if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@ +struct obstack; +/* Grow an obstack with formatted output. Return the number of + bytes added to OBS. No trailing nul byte is added, and the + object should be closed with obstack_finish before use. Upon + memory allocation error, call obstack_alloc_failed_handler. Upon + other error, return -1. */ +# if @REPLACE_OBSTACK_PRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define obstack_printf rpl_obstack_printf +# endif +_GL_FUNCDECL_RPL (obstack_printf, int, + (struct obstack *obs, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (obstack_printf, int, + (struct obstack *obs, const char *format, ...)); +# else +# if !@HAVE_DECL_OBSTACK_PRINTF@ +_GL_FUNCDECL_SYS (obstack_printf, int, + (struct obstack *obs, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (obstack_printf, int, + (struct obstack *obs, const char *format, ...)); +# endif +_GL_CXXALIASWARN (obstack_printf); +# if @REPLACE_OBSTACK_PRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define obstack_vprintf rpl_obstack_vprintf +# endif +_GL_FUNCDECL_RPL (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args)); +# else +# if !@HAVE_DECL_OBSTACK_PRINTF@ +_GL_FUNCDECL_SYS (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (obstack_vprintf); +#endif + +#if @GNULIB_PCLOSE@ +# if !@HAVE_PCLOSE@ +_GL_FUNCDECL_SYS (pclose, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (pclose, int, (FILE *stream)); +_GL_CXXALIASWARN (pclose); +#elif defined GNULIB_POSIXCHECK +# undef pclose +# if HAVE_RAW_DECL_PCLOSE +_GL_WARN_ON_USE (pclose, "pclose is unportable - " + "use gnulib module pclose for more portability"); +# endif +#endif + +#if @GNULIB_PERROR@ +/* Print a message to standard error, describing the value of ERRNO, + (if STRING is not NULL and not empty) prefixed with STRING and ": ", + and terminated with a newline. */ +# if @REPLACE_PERROR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define perror rpl_perror +# endif +_GL_FUNCDECL_RPL (perror, void, (const char *string)); +_GL_CXXALIAS_RPL (perror, void, (const char *string)); +# else +_GL_CXXALIAS_SYS (perror, void, (const char *string)); +# endif +_GL_CXXALIASWARN (perror); +#elif defined GNULIB_POSIXCHECK +# undef perror +/* Assume perror is always declared. */ +_GL_WARN_ON_USE (perror, "perror is not always POSIX compliant - " + "use gnulib module perror for portability"); +#endif + +#if @GNULIB_POPEN@ +# if @REPLACE_POPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef popen +# define popen rpl_popen +# endif +_GL_FUNCDECL_RPL (popen, FILE *, (const char *cmd, const char *mode) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (popen, FILE *, (const char *cmd, const char *mode)); +# else +# if !@HAVE_POPEN@ +_GL_FUNCDECL_SYS (popen, FILE *, (const char *cmd, const char *mode) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (popen, FILE *, (const char *cmd, const char *mode)); +# endif +_GL_CXXALIASWARN (popen); +#elif defined GNULIB_POSIXCHECK +# undef popen +# if HAVE_RAW_DECL_POPEN +_GL_WARN_ON_USE (popen, "popen is buggy on some platforms - " + "use gnulib module popen or pipe for more portability"); +# endif +#endif + +#if @GNULIB_PRINTF_POSIX@ || @GNULIB_PRINTF@ +# if (@GNULIB_PRINTF_POSIX@ && @REPLACE_PRINTF@) \ + || (@GNULIB_PRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if defined __GNUC__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +/* Don't break __attribute__((format(printf,M,N))). */ +# define printf __printf__ +# endif +# if @GNULIB_PRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL_1 (__printf__, int, + (const char *format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf)) + _GL_ATTRIBUTE_FORMAT_PRINTF (1, 2) + _GL_ARG_NONNULL ((1))); +# else +_GL_FUNCDECL_RPL_1 (__printf__, int, + (const char *format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf)) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_RPL_1 (printf, __printf__, int, (const char *format, ...)); +# else +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define printf rpl_printf +# endif +_GL_FUNCDECL_RPL (printf, int, + (const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (1, 2) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (printf, int, (const char *format, ...)); +# endif +# define GNULIB_overrides_printf 1 +# else +_GL_CXXALIAS_SYS (printf, int, (const char *format, ...)); +# endif +_GL_CXXALIASWARN (printf); +#endif +#if !@GNULIB_PRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_printf +# undef printf +# endif +/* Assume printf is always declared. */ +_GL_WARN_ON_USE (printf, "printf is not always POSIX compliant - " + "use gnulib module printf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_PUTC@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putc +# define putc rpl_fputc +# endif +_GL_FUNCDECL_RPL (fputc, int, (int c, FILE *stream) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL_1 (putc, rpl_fputc, int, (int c, FILE *stream)); +# else +_GL_CXXALIAS_SYS (putc, int, (int c, FILE *stream)); +# endif +_GL_CXXALIASWARN (putc); +#endif + +#if @GNULIB_PUTCHAR@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putchar +# define putchar rpl_putchar +# endif +_GL_FUNCDECL_RPL (putchar, int, (int c)); +_GL_CXXALIAS_RPL (putchar, int, (int c)); +# else +_GL_CXXALIAS_SYS (putchar, int, (int c)); +# endif +_GL_CXXALIASWARN (putchar); +#endif + +#if @GNULIB_PUTS@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef puts +# define puts rpl_puts +# endif +_GL_FUNCDECL_RPL (puts, int, (const char *string) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (puts, int, (const char *string)); +# else +_GL_CXXALIAS_SYS (puts, int, (const char *string)); +# endif +_GL_CXXALIASWARN (puts); +#endif + +#if @GNULIB_REMOVE@ +# if @REPLACE_REMOVE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef remove +# define remove rpl_remove +# endif +_GL_FUNCDECL_RPL (remove, int, (const char *name) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (remove, int, (const char *name)); +# else +_GL_CXXALIAS_SYS (remove, int, (const char *name)); +# endif +_GL_CXXALIASWARN (remove); +#elif defined GNULIB_POSIXCHECK +# undef remove +/* Assume remove is always declared. */ +_GL_WARN_ON_USE (remove, "remove cannot handle directories on some platforms - " + "use gnulib module remove for more portability"); +#endif + +#if @GNULIB_RENAME@ +# if @REPLACE_RENAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef rename +# define rename rpl_rename +# endif +_GL_FUNCDECL_RPL (rename, int, + (const char *old_filename, const char *new_filename) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (rename, int, + (const char *old_filename, const char *new_filename)); +# else +_GL_CXXALIAS_SYS (rename, int, + (const char *old_filename, const char *new_filename)); +# endif +_GL_CXXALIASWARN (rename); +#elif defined GNULIB_POSIXCHECK +# undef rename +/* Assume rename is always declared. */ +_GL_WARN_ON_USE (rename, "rename is buggy on some platforms - " + "use gnulib module rename for more portability"); +#endif + +#if @GNULIB_RENAMEAT@ +# if @REPLACE_RENAMEAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef renameat +# define renameat rpl_renameat +# endif +_GL_FUNCDECL_RPL (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2) + _GL_ARG_NONNULL ((2, 4))); +_GL_CXXALIAS_RPL (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2)); +# else +# if !@HAVE_RENAMEAT@ +_GL_FUNCDECL_SYS (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2) + _GL_ARG_NONNULL ((2, 4))); +# endif +_GL_CXXALIAS_SYS (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2)); +# endif +_GL_CXXALIASWARN (renameat); +#elif defined GNULIB_POSIXCHECK +# undef renameat +# if HAVE_RAW_DECL_RENAMEAT +_GL_WARN_ON_USE (renameat, "renameat is not portable - " + "use gnulib module renameat for portability"); +# endif +#endif + +#if @GNULIB_SCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if defined __GNUC__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef scanf +/* Don't break __attribute__((format(scanf,M,N))). */ +# define scanf __scanf__ +# endif +_GL_FUNCDECL_RPL_1 (__scanf__, int, + (const char *format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_scanf)) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL_1 (scanf, __scanf__, int, (const char *format, ...)); +# else +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef scanf +# define scanf rpl_scanf +# endif +_GL_FUNCDECL_RPL (scanf, int, (const char *format, ...) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (scanf, int, (const char *format, ...)); +# endif +# else +_GL_CXXALIAS_SYS (scanf, int, (const char *format, ...)); +# endif +_GL_CXXALIASWARN (scanf); +#endif + +#if @GNULIB_SNPRINTF@ +# if @REPLACE_SNPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define snprintf rpl_snprintf +# endif +_GL_FUNCDECL_RPL (snprintf, int, + (char *str, size_t size, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (3, 4) + _GL_ARG_NONNULL ((3))); +_GL_CXXALIAS_RPL (snprintf, int, + (char *str, size_t size, const char *format, ...)); +# else +# if !@HAVE_DECL_SNPRINTF@ +_GL_FUNCDECL_SYS (snprintf, int, + (char *str, size_t size, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (3, 4) + _GL_ARG_NONNULL ((3))); +# endif +_GL_CXXALIAS_SYS (snprintf, int, + (char *str, size_t size, const char *format, ...)); +# endif +_GL_CXXALIASWARN (snprintf); +#elif defined GNULIB_POSIXCHECK +# undef snprintf +# if HAVE_RAW_DECL_SNPRINTF +_GL_WARN_ON_USE (snprintf, "snprintf is unportable - " + "use gnulib module snprintf for portability"); +# endif +#endif + +/* Some people would argue that all sprintf uses should be warned about + (for example, OpenBSD issues a link warning for it), + since it can cause security holes due to buffer overruns. + However, we believe that sprintf can be used safely, and is more + efficient than snprintf in those safe cases; and as proof of our + belief, we use sprintf in several gnulib modules. So this header + intentionally avoids adding a warning to sprintf except when + GNULIB_POSIXCHECK is defined. */ + +#if @GNULIB_SPRINTF_POSIX@ +# if @REPLACE_SPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define sprintf rpl_sprintf +# endif +_GL_FUNCDECL_RPL (sprintf, int, (char *str, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (sprintf, int, (char *str, const char *format, ...)); +# else +_GL_CXXALIAS_SYS (sprintf, int, (char *str, const char *format, ...)); +# endif +_GL_CXXALIASWARN (sprintf); +#elif defined GNULIB_POSIXCHECK +# undef sprintf +/* Assume sprintf is always declared. */ +_GL_WARN_ON_USE (sprintf, "sprintf is not always POSIX compliant - " + "use gnulib module sprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_TMPFILE@ +# if @REPLACE_TMPFILE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define tmpfile rpl_tmpfile +# endif +_GL_FUNCDECL_RPL (tmpfile, FILE *, (void)); +_GL_CXXALIAS_RPL (tmpfile, FILE *, (void)); +# else +_GL_CXXALIAS_SYS (tmpfile, FILE *, (void)); +# endif +_GL_CXXALIASWARN (tmpfile); +#elif defined GNULIB_POSIXCHECK +# undef tmpfile +# if HAVE_RAW_DECL_TMPFILE +_GL_WARN_ON_USE (tmpfile, "tmpfile is not usable on mingw - " + "use gnulib module tmpfile for portability"); +# endif +#endif + +#if @GNULIB_VASPRINTF@ +/* Write formatted output to a string dynamically allocated with malloc(). + If the memory allocation succeeds, store the address of the string in + *RESULT and return the number of resulting bytes, excluding the trailing + NUL. Upon memory allocation error, or some other error, return -1. */ +# if @REPLACE_VASPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define asprintf rpl_asprintf +# endif +_GL_FUNCDECL_RPL (asprintf, int, + (char **result, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (asprintf, int, + (char **result, const char *format, ...)); +# else +# if !@HAVE_VASPRINTF@ +_GL_FUNCDECL_SYS (asprintf, int, + (char **result, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (asprintf, int, + (char **result, const char *format, ...)); +# endif +_GL_CXXALIASWARN (asprintf); +# if @REPLACE_VASPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vasprintf rpl_vasprintf +# endif +_GL_FUNCDECL_RPL (vasprintf, int, + (char **result, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (vasprintf, int, + (char **result, const char *format, va_list args)); +# else +# if !@HAVE_VASPRINTF@ +_GL_FUNCDECL_SYS (vasprintf, int, + (char **result, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (vasprintf, int, + (char **result, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vasprintf); +#endif + +#if @GNULIB_VDPRINTF@ +# if @REPLACE_VDPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vdprintf rpl_vdprintf +# endif +_GL_FUNCDECL_RPL (vdprintf, int, (int fd, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (vdprintf, int, (int fd, const char *format, va_list args)); +# else +# if !@HAVE_VDPRINTF@ +_GL_FUNCDECL_SYS (vdprintf, int, (int fd, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((2))); +# endif +/* Need to cast, because on Solaris, the third parameter will likely be + __va_list args. */ +_GL_CXXALIAS_SYS_CAST (vdprintf, int, + (int fd, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vdprintf); +#elif defined GNULIB_POSIXCHECK +# undef vdprintf +# if HAVE_RAW_DECL_VDPRINTF +_GL_WARN_ON_USE (vdprintf, "vdprintf is unportable - " + "use gnulib module vdprintf for portability"); +# endif +#endif + +#if @GNULIB_VFPRINTF_POSIX@ || @GNULIB_VFPRINTF@ +# if (@GNULIB_VFPRINTF_POSIX@ && @REPLACE_VFPRINTF@) \ + || (@GNULIB_VFPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vfprintf rpl_vfprintf +# endif +# define GNULIB_overrides_vfprintf 1 +# if @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# else +_GL_FUNCDECL_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args)); +# else +/* Need to cast, because on Solaris, the third parameter is + __va_list args + and GCC's fixincludes did not change this to __gnuc_va_list. */ +_GL_CXXALIAS_SYS_CAST (vfprintf, int, + (FILE *fp, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vfprintf); +#endif +#if !@GNULIB_VFPRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_vfprintf +# undef vfprintf +# endif +/* Assume vfprintf is always declared. */ +_GL_WARN_ON_USE (vfprintf, "vfprintf is not always POSIX compliant - " + "use gnulib module vfprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_VFSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef vfscanf +# define vfscanf rpl_vfscanf +# endif +_GL_FUNCDECL_RPL (vfscanf, int, + (FILE *stream, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (vfscanf, int, + (FILE *stream, const char *format, va_list args)); +# else +_GL_CXXALIAS_SYS (vfscanf, int, + (FILE *stream, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vfscanf); +#endif + +#if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VPRINTF@ +# if (@GNULIB_VPRINTF_POSIX@ && @REPLACE_VPRINTF@) \ + || (@GNULIB_VPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vprintf rpl_vprintf +# endif +# define GNULIB_overrides_vprintf 1 +# if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL (vprintf, int, (const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (1, 0) + _GL_ARG_NONNULL ((1))); +# else +_GL_FUNCDECL_RPL (vprintf, int, (const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 0) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_RPL (vprintf, int, (const char *format, va_list args)); +# else +/* Need to cast, because on Solaris, the second parameter is + __va_list args + and GCC's fixincludes did not change this to __gnuc_va_list. */ +_GL_CXXALIAS_SYS_CAST (vprintf, int, (const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vprintf); +#endif +#if !@GNULIB_VPRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_vprintf +# undef vprintf +# endif +/* Assume vprintf is always declared. */ +_GL_WARN_ON_USE (vprintf, "vprintf is not always POSIX compliant - " + "use gnulib module vprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_VSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef vscanf +# define vscanf rpl_vscanf +# endif +_GL_FUNCDECL_RPL (vscanf, int, (const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 0) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (vscanf, int, (const char *format, va_list args)); +# else +_GL_CXXALIAS_SYS (vscanf, int, (const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vscanf); +#endif + +#if @GNULIB_VSNPRINTF@ +# if @REPLACE_VSNPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vsnprintf rpl_vsnprintf +# endif +_GL_FUNCDECL_RPL (vsnprintf, int, + (char *str, size_t size, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) + _GL_ARG_NONNULL ((3))); +_GL_CXXALIAS_RPL (vsnprintf, int, + (char *str, size_t size, const char *format, va_list args)); +# else +# if !@HAVE_DECL_VSNPRINTF@ +_GL_FUNCDECL_SYS (vsnprintf, int, + (char *str, size_t size, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0) + _GL_ARG_NONNULL ((3))); +# endif +_GL_CXXALIAS_SYS (vsnprintf, int, + (char *str, size_t size, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vsnprintf); +#elif defined GNULIB_POSIXCHECK +# undef vsnprintf +# if HAVE_RAW_DECL_VSNPRINTF +_GL_WARN_ON_USE (vsnprintf, "vsnprintf is unportable - " + "use gnulib module vsnprintf for portability"); +# endif +#endif + +#if @GNULIB_VSPRINTF_POSIX@ +# if @REPLACE_VSPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vsprintf rpl_vsprintf +# endif +_GL_FUNCDECL_RPL (vsprintf, int, + (char *str, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (vsprintf, int, + (char *str, const char *format, va_list args)); +# else +/* Need to cast, because on Solaris, the third parameter is + __va_list args + and GCC's fixincludes did not change this to __gnuc_va_list. */ +_GL_CXXALIAS_SYS_CAST (vsprintf, int, + (char *str, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vsprintf); +#elif defined GNULIB_POSIXCHECK +# undef vsprintf +/* Assume vsprintf is always declared. */ +_GL_WARN_ON_USE (vsprintf, "vsprintf is not always POSIX compliant - " + "use gnulib module vsprintf-posix for portable " + "POSIX compliance"); +#endif + +#endif /* _@GUARD_PREFIX@_STDIO_H */ +#endif /* _@GUARD_PREFIX@_STDIO_H */ +#endif diff --git a/grub-core/lib/gnulib/stdlib.in.h b/grub-core/lib/gnulib/stdlib.in.h new file mode 100644 index 0000000..d80d7ec --- /dev/null +++ b/grub-core/lib/gnulib/stdlib.in.h @@ -0,0 +1,1013 @@ +/* A GNU-like <stdlib.h>. + + Copyright (C) 1995, 2001-2004, 2006-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_system_stdlib_h || defined __need_malloc_and_calloc +/* Special invocation conventions inside some gnulib header files, + and inside some glibc header files, respectively. */ + +#@INCLUDE_NEXT@ @NEXT_STDLIB_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_STDLIB_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STDLIB_H@ + +#ifndef _@GUARD_PREFIX@_STDLIB_H +#define _@GUARD_PREFIX@_STDLIB_H + +/* NetBSD 5.0 mis-defines NULL. */ +#include <stddef.h> + +/* MirBSD 10 defines WEXITSTATUS in <sys/wait.h>, not in <stdlib.h>. */ +#if @GNULIB_SYSTEM_POSIX@ && !defined WEXITSTATUS +# include <sys/wait.h> +#endif + +/* Solaris declares getloadavg() in <sys/loadavg.h>. */ +#if (@GNULIB_GETLOADAVG@ || defined GNULIB_POSIXCHECK) && @HAVE_SYS_LOADAVG_H@ +/* OpenIndiana has a bug: <sys/time.h> must be included before + <sys/loadavg.h>. */ +# include <sys/time.h> +# include <sys/loadavg.h> +#endif + +/* Native Windows platforms declare mktemp() in <io.h>. */ +#if 0 && (defined _WIN32 && ! defined __CYGWIN__) +# include <io.h> +#endif + +#if @GNULIB_RANDOM_R@ + +/* OSF/1 5.1 declares 'struct random_data' in <random.h>, which is included + from <stdlib.h> if _REENTRANT is defined. Include it whenever we need + 'struct random_data'. */ +# if @HAVE_RANDOM_H@ +# include <random.h> +# endif + +# if !@HAVE_STRUCT_RANDOM_DATA@ || @REPLACE_RANDOM_R@ || !@HAVE_RANDOM_R@ +# include <stdint.h> +# endif + +# if !@HAVE_STRUCT_RANDOM_DATA@ +/* Define 'struct random_data'. + But allow multiple gnulib generated <stdlib.h> replacements to coexist. */ +# if !GNULIB_defined_struct_random_data +struct random_data +{ + int32_t *fptr; /* Front pointer. */ + int32_t *rptr; /* Rear pointer. */ + int32_t *state; /* Array of state values. */ + int rand_type; /* Type of random number generator. */ + int rand_deg; /* Degree of random number generator. */ + int rand_sep; /* Distance between front and rear. */ + int32_t *end_ptr; /* Pointer behind state table. */ +}; +# define GNULIB_defined_struct_random_data 1 +# endif +# endif +#endif + +#if (@GNULIB_MKSTEMP@ || @GNULIB_MKSTEMPS@ || @GNULIB_MKOSTEMP@ || @GNULIB_MKOSTEMPS@ || @GNULIB_GETSUBOPT@ || defined GNULIB_POSIXCHECK) && ! defined __GLIBC__ && !(defined _WIN32 && ! defined __CYGWIN__) +/* On Mac OS X 10.3, only <unistd.h> declares mkstemp. */ +/* On Mac OS X 10.5, only <unistd.h> declares mkstemps. */ +/* On Mac OS X 10.13, only <unistd.h> declares mkostemp and mkostemps. */ +/* On Cygwin 1.7.1, only <unistd.h> declares getsubopt. */ +/* But avoid namespace pollution on glibc systems and native Windows. */ +# include <unistd.h> +#endif + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +# define _GL_ATTRIBUTE_PURE /* empty */ +#endif + +/* The definition of _Noreturn is copied here. */ + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Some systems do not define EXIT_*, despite otherwise supporting C89. */ +#ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +#endif +/* Tandem/NSK and other platforms that define EXIT_FAILURE as -1 interfere + with proper operation of xargs. */ +#ifndef EXIT_FAILURE +# define EXIT_FAILURE 1 +#elif EXIT_FAILURE != 1 +# undef EXIT_FAILURE +# define EXIT_FAILURE 1 +#endif + + +#if @GNULIB__EXIT@ +/* Terminate the current process with the given return code, without running + the 'atexit' handlers. */ +# if !@HAVE__EXIT@ +_GL_FUNCDECL_SYS (_Exit, _Noreturn void, (int status)); +# endif +_GL_CXXALIAS_SYS (_Exit, void, (int status)); +_GL_CXXALIASWARN (_Exit); +#elif defined GNULIB_POSIXCHECK +# undef _Exit +# if HAVE_RAW_DECL__EXIT +_GL_WARN_ON_USE (_Exit, "_Exit is unportable - " + "use gnulib module _Exit for portability"); +# endif +#endif + + +#if @GNULIB_ATOLL@ +/* Parse a signed decimal integer. + Returns the value of the integer. Errors are not detected. */ +# if !@HAVE_ATOLL@ +_GL_FUNCDECL_SYS (atoll, long long, (const char *string) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (atoll, long long, (const char *string)); +_GL_CXXALIASWARN (atoll); +#elif defined GNULIB_POSIXCHECK +# undef atoll +# if HAVE_RAW_DECL_ATOLL +_GL_WARN_ON_USE (atoll, "atoll is unportable - " + "use gnulib module atoll for portability"); +# endif +#endif + +#if @GNULIB_CALLOC_POSIX@ +# if @REPLACE_CALLOC@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef calloc +# define calloc rpl_calloc +# endif +_GL_FUNCDECL_RPL (calloc, void *, (size_t nmemb, size_t size)); +_GL_CXXALIAS_RPL (calloc, void *, (size_t nmemb, size_t size)); +# else +_GL_CXXALIAS_SYS (calloc, void *, (size_t nmemb, size_t size)); +# endif +_GL_CXXALIASWARN (calloc); +#elif defined GNULIB_POSIXCHECK +# undef calloc +/* Assume calloc is always declared. */ +_GL_WARN_ON_USE (calloc, "calloc is not POSIX compliant everywhere - " + "use gnulib module calloc-posix for portability"); +#endif + +#if @GNULIB_CANONICALIZE_FILE_NAME@ +# if @REPLACE_CANONICALIZE_FILE_NAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define canonicalize_file_name rpl_canonicalize_file_name +# endif +_GL_FUNCDECL_RPL (canonicalize_file_name, char *, (const char *name) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (canonicalize_file_name, char *, (const char *name)); +# else +# if !@HAVE_CANONICALIZE_FILE_NAME@ +_GL_FUNCDECL_SYS (canonicalize_file_name, char *, (const char *name) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (canonicalize_file_name, char *, (const char *name)); +# endif +_GL_CXXALIASWARN (canonicalize_file_name); +#elif defined GNULIB_POSIXCHECK +# undef canonicalize_file_name +# if HAVE_RAW_DECL_CANONICALIZE_FILE_NAME +_GL_WARN_ON_USE (canonicalize_file_name, + "canonicalize_file_name is unportable - " + "use gnulib module canonicalize-lgpl for portability"); +# endif +#endif + +#if @GNULIB_GETLOADAVG@ +/* Store max(NELEM,3) load average numbers in LOADAVG[]. + The three numbers are the load average of the last 1 minute, the last 5 + minutes, and the last 15 minutes, respectively. + LOADAVG is an array of NELEM numbers. */ +# if !@HAVE_DECL_GETLOADAVG@ +_GL_FUNCDECL_SYS (getloadavg, int, (double loadavg[], int nelem) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (getloadavg, int, (double loadavg[], int nelem)); +_GL_CXXALIASWARN (getloadavg); +#elif defined GNULIB_POSIXCHECK +# undef getloadavg +# if HAVE_RAW_DECL_GETLOADAVG +_GL_WARN_ON_USE (getloadavg, "getloadavg is not portable - " + "use gnulib module getloadavg for portability"); +# endif +#endif + +#if @GNULIB_GETSUBOPT@ +/* Assuming *OPTIONP is a comma separated list of elements of the form + "token" or "token=value", getsubopt parses the first of these elements. + If the first element refers to a "token" that is member of the given + NULL-terminated array of tokens: + - It replaces the comma with a NUL byte, updates *OPTIONP to point past + the first option and the comma, sets *VALUEP to the value of the + element (or NULL if it doesn't contain an "=" sign), + - It returns the index of the "token" in the given array of tokens. + Otherwise it returns -1, and *OPTIONP and *VALUEP are undefined. + For more details see the POSIX:2001 specification. + http://www.opengroup.org/susv3xsh/getsubopt.html */ +# if !@HAVE_GETSUBOPT@ +_GL_FUNCDECL_SYS (getsubopt, int, + (char **optionp, char *const *tokens, char **valuep) + _GL_ARG_NONNULL ((1, 2, 3))); +# endif +_GL_CXXALIAS_SYS (getsubopt, int, + (char **optionp, char *const *tokens, char **valuep)); +_GL_CXXALIASWARN (getsubopt); +#elif defined GNULIB_POSIXCHECK +# undef getsubopt +# if HAVE_RAW_DECL_GETSUBOPT +_GL_WARN_ON_USE (getsubopt, "getsubopt is unportable - " + "use gnulib module getsubopt for portability"); +# endif +#endif + +#if @GNULIB_GRANTPT@ +/* Change the ownership and access permission of the slave side of the + pseudo-terminal whose master side is specified by FD. */ +# if !@HAVE_GRANTPT@ +_GL_FUNCDECL_SYS (grantpt, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (grantpt, int, (int fd)); +_GL_CXXALIASWARN (grantpt); +#elif defined GNULIB_POSIXCHECK +# undef grantpt +# if HAVE_RAW_DECL_GRANTPT +_GL_WARN_ON_USE (grantpt, "grantpt is not portable - " + "use gnulib module grantpt for portability"); +# endif +#endif + +/* If _GL_USE_STDLIB_ALLOC is nonzero, the including module does not + rely on GNU or POSIX semantics for malloc and realloc (for example, + by never specifying a zero size), so it does not need malloc or + realloc to be redefined. */ +#if @GNULIB_MALLOC_POSIX@ +# if @REPLACE_MALLOC@ +# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \ + || _GL_USE_STDLIB_ALLOC) +# undef malloc +# define malloc rpl_malloc +# endif +_GL_FUNCDECL_RPL (malloc, void *, (size_t size)); +_GL_CXXALIAS_RPL (malloc, void *, (size_t size)); +# else +_GL_CXXALIAS_SYS (malloc, void *, (size_t size)); +# endif +_GL_CXXALIASWARN (malloc); +#elif defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC +# undef malloc +/* Assume malloc is always declared. */ +_GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - " + "use gnulib module malloc-posix for portability"); +#endif + +/* Convert a multibyte character to a wide character. */ +#if @GNULIB_MBTOWC@ +# if @REPLACE_MBTOWC@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbtowc +# define mbtowc rpl_mbtowc +# endif +_GL_FUNCDECL_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n)); +_GL_CXXALIAS_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n)); +# else +_GL_CXXALIAS_SYS (mbtowc, int, (wchar_t *pwc, const char *s, size_t n)); +# endif +_GL_CXXALIASWARN (mbtowc); +#endif + +#if @GNULIB_MKDTEMP@ +/* Create a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the directory name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique name. + The directory is created mode 700. */ +# if !@HAVE_MKDTEMP@ +_GL_FUNCDECL_SYS (mkdtemp, char *, (char * /*template*/) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkdtemp, char *, (char * /*template*/)); +_GL_CXXALIASWARN (mkdtemp); +#elif defined GNULIB_POSIXCHECK +# undef mkdtemp +# if HAVE_RAW_DECL_MKDTEMP +_GL_WARN_ON_USE (mkdtemp, "mkdtemp is unportable - " + "use gnulib module mkdtemp for portability"); +# endif +#endif + +#if @GNULIB_MKOSTEMP@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The flags are a bitmask, possibly including O_CLOEXEC (defined in <fcntl.h>) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + The file is then created, with the specified flags, ensuring it didn't exist + before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if !@HAVE_MKOSTEMP@ +_GL_FUNCDECL_SYS (mkostemp, int, (char * /*template*/, int /*flags*/) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkostemp, int, (char * /*template*/, int /*flags*/)); +_GL_CXXALIASWARN (mkostemp); +#elif defined GNULIB_POSIXCHECK +# undef mkostemp +# if HAVE_RAW_DECL_MKOSTEMP +_GL_WARN_ON_USE (mkostemp, "mkostemp is unportable - " + "use gnulib module mkostemp for portability"); +# endif +#endif + +#if @GNULIB_MKOSTEMPS@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE before a suffix of length + SUFFIXLEN must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The flags are a bitmask, possibly including O_CLOEXEC (defined in <fcntl.h>) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + The file is then created, with the specified flags, ensuring it didn't exist + before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if !@HAVE_MKOSTEMPS@ +_GL_FUNCDECL_SYS (mkostemps, int, + (char * /*template*/, int /*suffixlen*/, int /*flags*/) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkostemps, int, + (char * /*template*/, int /*suffixlen*/, int /*flags*/)); +_GL_CXXALIASWARN (mkostemps); +#elif defined GNULIB_POSIXCHECK +# undef mkostemps +# if HAVE_RAW_DECL_MKOSTEMPS +_GL_WARN_ON_USE (mkostemps, "mkostemps is unportable - " + "use gnulib module mkostemps for portability"); +# endif +#endif + +#if @GNULIB_MKSTEMP@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The file is then created, ensuring it didn't exist before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if @REPLACE_MKSTEMP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mkstemp rpl_mkstemp +# endif +_GL_FUNCDECL_RPL (mkstemp, int, (char * /*template*/) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mkstemp, int, (char * /*template*/)); +# else +# if ! @HAVE_MKSTEMP@ +_GL_FUNCDECL_SYS (mkstemp, int, (char * /*template*/) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkstemp, int, (char * /*template*/)); +# endif +_GL_CXXALIASWARN (mkstemp); +#elif defined GNULIB_POSIXCHECK +# undef mkstemp +# if HAVE_RAW_DECL_MKSTEMP +_GL_WARN_ON_USE (mkstemp, "mkstemp is unportable - " + "use gnulib module mkstemp for portability"); +# endif +#endif + +#if @GNULIB_MKSTEMPS@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE prior to a suffix of length + SUFFIXLEN must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The file is then created, ensuring it didn't exist before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if !@HAVE_MKSTEMPS@ +_GL_FUNCDECL_SYS (mkstemps, int, (char * /*template*/, int /*suffixlen*/) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkstemps, int, (char * /*template*/, int /*suffixlen*/)); +_GL_CXXALIASWARN (mkstemps); +#elif defined GNULIB_POSIXCHECK +# undef mkstemps +# if HAVE_RAW_DECL_MKSTEMPS +_GL_WARN_ON_USE (mkstemps, "mkstemps is unportable - " + "use gnulib module mkstemps for portability"); +# endif +#endif + +#if @GNULIB_POSIX_OPENPT@ +/* Return an FD open to the master side of a pseudo-terminal. Flags should + include O_RDWR, and may also include O_NOCTTY. */ +# if !@HAVE_POSIX_OPENPT@ +_GL_FUNCDECL_SYS (posix_openpt, int, (int flags)); +# endif +_GL_CXXALIAS_SYS (posix_openpt, int, (int flags)); +_GL_CXXALIASWARN (posix_openpt); +#elif defined GNULIB_POSIXCHECK +# undef posix_openpt +# if HAVE_RAW_DECL_POSIX_OPENPT +_GL_WARN_ON_USE (posix_openpt, "posix_openpt is not portable - " + "use gnulib module posix_openpt for portability"); +# endif +#endif + +#if @GNULIB_PTSNAME@ +/* Return the pathname of the pseudo-terminal slave associated with + the master FD is open on, or NULL on errors. */ +# if @REPLACE_PTSNAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ptsname +# define ptsname rpl_ptsname +# endif +_GL_FUNCDECL_RPL (ptsname, char *, (int fd)); +_GL_CXXALIAS_RPL (ptsname, char *, (int fd)); +# else +# if !@HAVE_PTSNAME@ +_GL_FUNCDECL_SYS (ptsname, char *, (int fd)); +# endif +_GL_CXXALIAS_SYS (ptsname, char *, (int fd)); +# endif +_GL_CXXALIASWARN (ptsname); +#elif defined GNULIB_POSIXCHECK +# undef ptsname +# if HAVE_RAW_DECL_PTSNAME +_GL_WARN_ON_USE (ptsname, "ptsname is not portable - " + "use gnulib module ptsname for portability"); +# endif +#endif + +#if @GNULIB_PTSNAME_R@ +/* Set the pathname of the pseudo-terminal slave associated with + the master FD is open on and return 0, or set errno and return + non-zero on errors. */ +# if @REPLACE_PTSNAME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ptsname_r +# define ptsname_r rpl_ptsname_r +# endif +_GL_FUNCDECL_RPL (ptsname_r, int, (int fd, char *buf, size_t len)); +_GL_CXXALIAS_RPL (ptsname_r, int, (int fd, char *buf, size_t len)); +# else +# if !@HAVE_PTSNAME_R@ +_GL_FUNCDECL_SYS (ptsname_r, int, (int fd, char *buf, size_t len)); +# endif +_GL_CXXALIAS_SYS (ptsname_r, int, (int fd, char *buf, size_t len)); +# endif +_GL_CXXALIASWARN (ptsname_r); +#elif defined GNULIB_POSIXCHECK +# undef ptsname_r +# if HAVE_RAW_DECL_PTSNAME_R +_GL_WARN_ON_USE (ptsname_r, "ptsname_r is not portable - " + "use gnulib module ptsname_r for portability"); +# endif +#endif + +#if @GNULIB_PUTENV@ +# if @REPLACE_PUTENV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putenv +# define putenv rpl_putenv +# endif +_GL_FUNCDECL_RPL (putenv, int, (char *string) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (putenv, int, (char *string)); +# else +_GL_CXXALIAS_SYS (putenv, int, (char *string)); +# endif +_GL_CXXALIASWARN (putenv); +#endif + +#if @GNULIB_QSORT_R@ +/* Sort an array of NMEMB elements, starting at address BASE, each element + occupying SIZE bytes, in ascending order according to the comparison + function COMPARE. */ +# if @REPLACE_QSORT_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef qsort_r +# define qsort_r rpl_qsort_r +# endif +_GL_FUNCDECL_RPL (qsort_r, void, (void *base, size_t nmemb, size_t size, + int (*compare) (void const *, void const *, + void *), + void *arg) _GL_ARG_NONNULL ((1, 4))); +_GL_CXXALIAS_RPL (qsort_r, void, (void *base, size_t nmemb, size_t size, + int (*compare) (void const *, void const *, + void *), + void *arg)); +# else +# if !@HAVE_QSORT_R@ +_GL_FUNCDECL_SYS (qsort_r, void, (void *base, size_t nmemb, size_t size, + int (*compare) (void const *, void const *, + void *), + void *arg) _GL_ARG_NONNULL ((1, 4))); +# endif +_GL_CXXALIAS_SYS (qsort_r, void, (void *base, size_t nmemb, size_t size, + int (*compare) (void const *, void const *, + void *), + void *arg)); +# endif +_GL_CXXALIASWARN (qsort_r); +#elif defined GNULIB_POSIXCHECK +# undef qsort_r +# if HAVE_RAW_DECL_QSORT_R +_GL_WARN_ON_USE (qsort_r, "qsort_r is not portable - " + "use gnulib module qsort_r for portability"); +# endif +#endif + + +#if @GNULIB_RANDOM_R@ +# if !@HAVE_RANDOM_R@ +# ifndef RAND_MAX +# define RAND_MAX 2147483647 +# endif +# endif +#endif + + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (random, long, (void)); +# endif +_GL_CXXALIAS_SYS (random, long, (void)); +_GL_CXXALIASWARN (random); +#elif defined GNULIB_POSIXCHECK +# undef random +# if HAVE_RAW_DECL_RANDOM +_GL_WARN_ON_USE (random, "random is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (srandom, void, (unsigned int seed)); +# endif +_GL_CXXALIAS_SYS (srandom, void, (unsigned int seed)); +_GL_CXXALIASWARN (srandom); +#elif defined GNULIB_POSIXCHECK +# undef srandom +# if HAVE_RAW_DECL_SRANDOM +_GL_WARN_ON_USE (srandom, "srandom is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ || !@HAVE_DECL_INITSTATE@ +_GL_FUNCDECL_SYS (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size)); +_GL_CXXALIASWARN (initstate); +#elif defined GNULIB_POSIXCHECK +# undef initstate +# if HAVE_RAW_DECL_INITSTATE_R +_GL_WARN_ON_USE (initstate, "initstate is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if !@HAVE_RANDOM@ || !@HAVE_DECL_SETSTATE@ +_GL_FUNCDECL_SYS (setstate, char *, (char *arg_state) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (setstate, char *, (char *arg_state)); +_GL_CXXALIASWARN (setstate); +#elif defined GNULIB_POSIXCHECK +# undef setstate +# if HAVE_RAW_DECL_SETSTATE_R +_GL_WARN_ON_USE (setstate, "setstate is unportable - " + "use gnulib module random for portability"); +# endif +#endif + + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef random_r +# define random_r rpl_random_r +# endif +_GL_FUNCDECL_RPL (random_r, int, (struct random_data *buf, int32_t *result) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (random_r, int, (struct random_data *buf, int32_t *result)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (random_r, int, (struct random_data *buf, int32_t *result) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (random_r, int, (struct random_data *buf, int32_t *result)); +# endif +_GL_CXXALIASWARN (random_r); +#elif defined GNULIB_POSIXCHECK +# undef random_r +# if HAVE_RAW_DECL_RANDOM_R +_GL_WARN_ON_USE (random_r, "random_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef srandom_r +# define srandom_r rpl_srandom_r +# endif +_GL_FUNCDECL_RPL (srandom_r, int, + (unsigned int seed, struct random_data *rand_state) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (srandom_r, int, + (unsigned int seed, struct random_data *rand_state)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (srandom_r, int, + (unsigned int seed, struct random_data *rand_state) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (srandom_r, int, + (unsigned int seed, struct random_data *rand_state)); +# endif +_GL_CXXALIASWARN (srandom_r); +#elif defined GNULIB_POSIXCHECK +# undef srandom_r +# if HAVE_RAW_DECL_SRANDOM_R +_GL_WARN_ON_USE (srandom_r, "srandom_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef initstate_r +# define initstate_r rpl_initstate_r +# endif +_GL_FUNCDECL_RPL (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state) + _GL_ARG_NONNULL ((2, 4))); +_GL_CXXALIAS_RPL (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state) + _GL_ARG_NONNULL ((2, 4))); +# endif +_GL_CXXALIAS_SYS (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state)); +# endif +_GL_CXXALIASWARN (initstate_r); +#elif defined GNULIB_POSIXCHECK +# undef initstate_r +# if HAVE_RAW_DECL_INITSTATE_R +_GL_WARN_ON_USE (initstate_r, "initstate_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef setstate_r +# define setstate_r rpl_setstate_r +# endif +_GL_FUNCDECL_RPL (setstate_r, int, + (char *arg_state, struct random_data *rand_state) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (setstate_r, int, + (char *arg_state, struct random_data *rand_state)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (setstate_r, int, + (char *arg_state, struct random_data *rand_state) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (setstate_r, int, + (char *arg_state, struct random_data *rand_state)); +# endif +_GL_CXXALIASWARN (setstate_r); +#elif defined GNULIB_POSIXCHECK +# undef setstate_r +# if HAVE_RAW_DECL_SETSTATE_R +_GL_WARN_ON_USE (setstate_r, "setstate_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + + +#if @GNULIB_REALLOC_POSIX@ +# if @REPLACE_REALLOC@ +# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \ + || _GL_USE_STDLIB_ALLOC) +# undef realloc +# define realloc rpl_realloc +# endif +_GL_FUNCDECL_RPL (realloc, void *, (void *ptr, size_t size)); +_GL_CXXALIAS_RPL (realloc, void *, (void *ptr, size_t size)); +# else +_GL_CXXALIAS_SYS (realloc, void *, (void *ptr, size_t size)); +# endif +_GL_CXXALIASWARN (realloc); +#elif defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC +# undef realloc +/* Assume realloc is always declared. */ +_GL_WARN_ON_USE (realloc, "realloc is not POSIX compliant everywhere - " + "use gnulib module realloc-posix for portability"); +#endif + + +#if @GNULIB_REALLOCARRAY@ +# if ! @HAVE_REALLOCARRAY@ +_GL_FUNCDECL_SYS (reallocarray, void *, + (void *ptr, size_t nmemb, size_t size)); +# endif +_GL_CXXALIAS_SYS (reallocarray, void *, + (void *ptr, size_t nmemb, size_t size)); +_GL_CXXALIASWARN (reallocarray); +#elif defined GNULIB_POSIXCHECK +# undef reallocarray +# if HAVE_RAW_DECL_REALLOCARRAY +_GL_WARN_ON_USE (reallocarray, "reallocarray is not portable - " + "use gnulib module reallocarray for portability"); +# endif +#endif + +#if @GNULIB_REALPATH@ +# if @REPLACE_REALPATH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define realpath rpl_realpath +# endif +_GL_FUNCDECL_RPL (realpath, char *, (const char *name, char *resolved) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (realpath, char *, (const char *name, char *resolved)); +# else +# if !@HAVE_REALPATH@ +_GL_FUNCDECL_SYS (realpath, char *, (const char *name, char *resolved) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (realpath, char *, (const char *name, char *resolved)); +# endif +_GL_CXXALIASWARN (realpath); +#elif defined GNULIB_POSIXCHECK +# undef realpath +# if HAVE_RAW_DECL_REALPATH +_GL_WARN_ON_USE (realpath, "realpath is unportable - use gnulib module " + "canonicalize or canonicalize-lgpl for portability"); +# endif +#endif + +#if @GNULIB_RPMATCH@ +/* Test a user response to a question. + Return 1 if it is affirmative, 0 if it is negative, or -1 if not clear. */ +# if !@HAVE_RPMATCH@ +_GL_FUNCDECL_SYS (rpmatch, int, (const char *response) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (rpmatch, int, (const char *response)); +_GL_CXXALIASWARN (rpmatch); +#elif defined GNULIB_POSIXCHECK +# undef rpmatch +# if HAVE_RAW_DECL_RPMATCH +_GL_WARN_ON_USE (rpmatch, "rpmatch is unportable - " + "use gnulib module rpmatch for portability"); +# endif +#endif + +#if @GNULIB_SECURE_GETENV@ +/* Look up NAME in the environment, returning 0 in insecure situations. */ +# if !@HAVE_SECURE_GETENV@ +_GL_FUNCDECL_SYS (secure_getenv, char *, + (char const *name) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (secure_getenv, char *, (char const *name)); +_GL_CXXALIASWARN (secure_getenv); +#elif defined GNULIB_POSIXCHECK +# undef secure_getenv +# if HAVE_RAW_DECL_SECURE_GETENV +_GL_WARN_ON_USE (secure_getenv, "secure_getenv is unportable - " + "use gnulib module secure_getenv for portability"); +# endif +#endif + +#if @GNULIB_SETENV@ +/* Set NAME to VALUE in the environment. + If REPLACE is nonzero, overwrite an existing value. */ +# if @REPLACE_SETENV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef setenv +# define setenv rpl_setenv +# endif +_GL_FUNCDECL_RPL (setenv, int, + (const char *name, const char *value, int replace) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (setenv, int, + (const char *name, const char *value, int replace)); +# else +# if !@HAVE_DECL_SETENV@ +_GL_FUNCDECL_SYS (setenv, int, + (const char *name, const char *value, int replace) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (setenv, int, + (const char *name, const char *value, int replace)); +# endif +# if !(@REPLACE_SETENV@ && !@HAVE_DECL_SETENV@) +_GL_CXXALIASWARN (setenv); +# endif +#elif defined GNULIB_POSIXCHECK +# undef setenv +# if HAVE_RAW_DECL_SETENV +_GL_WARN_ON_USE (setenv, "setenv is unportable - " + "use gnulib module setenv for portability"); +# endif +#endif + +#if @GNULIB_STRTOD@ + /* Parse a double from STRING, updating ENDP if appropriate. */ +# if @REPLACE_STRTOD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strtod rpl_strtod +# endif +_GL_FUNCDECL_RPL (strtod, double, (const char *str, char **endp) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strtod, double, (const char *str, char **endp)); +# else +# if !@HAVE_STRTOD@ +_GL_FUNCDECL_SYS (strtod, double, (const char *str, char **endp) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtod, double, (const char *str, char **endp)); +# endif +_GL_CXXALIASWARN (strtod); +#elif defined GNULIB_POSIXCHECK +# undef strtod +# if HAVE_RAW_DECL_STRTOD +_GL_WARN_ON_USE (strtod, "strtod is unportable - " + "use gnulib module strtod for portability"); +# endif +#endif + +#if @GNULIB_STRTOLL@ +/* Parse a signed integer whose textual representation starts at STRING. + The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0, + it may be decimal or octal (with prefix "0") or hexadecimal (with prefix + "0x"). + If ENDPTR is not NULL, the address of the first byte after the integer is + stored in *ENDPTR. + Upon overflow, the return value is LLONG_MAX or LLONG_MIN, and errno is set + to ERANGE. */ +# if !@HAVE_STRTOLL@ +_GL_FUNCDECL_SYS (strtoll, long long, + (const char *string, char **endptr, int base) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtoll, long long, + (const char *string, char **endptr, int base)); +_GL_CXXALIASWARN (strtoll); +#elif defined GNULIB_POSIXCHECK +# undef strtoll +# if HAVE_RAW_DECL_STRTOLL +_GL_WARN_ON_USE (strtoll, "strtoll is unportable - " + "use gnulib module strtoll for portability"); +# endif +#endif + +#if @GNULIB_STRTOULL@ +/* Parse an unsigned integer whose textual representation starts at STRING. + The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0, + it may be decimal or octal (with prefix "0") or hexadecimal (with prefix + "0x"). + If ENDPTR is not NULL, the address of the first byte after the integer is + stored in *ENDPTR. + Upon overflow, the return value is ULLONG_MAX, and errno is set to + ERANGE. */ +# if !@HAVE_STRTOULL@ +_GL_FUNCDECL_SYS (strtoull, unsigned long long, + (const char *string, char **endptr, int base) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtoull, unsigned long long, + (const char *string, char **endptr, int base)); +_GL_CXXALIASWARN (strtoull); +#elif defined GNULIB_POSIXCHECK +# undef strtoull +# if HAVE_RAW_DECL_STRTOULL +_GL_WARN_ON_USE (strtoull, "strtoull is unportable - " + "use gnulib module strtoull for portability"); +# endif +#endif + +#if @GNULIB_UNLOCKPT@ +/* Unlock the slave side of the pseudo-terminal whose master side is specified + by FD, so that it can be opened. */ +# if !@HAVE_UNLOCKPT@ +_GL_FUNCDECL_SYS (unlockpt, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (unlockpt, int, (int fd)); +_GL_CXXALIASWARN (unlockpt); +#elif defined GNULIB_POSIXCHECK +# undef unlockpt +# if HAVE_RAW_DECL_UNLOCKPT +_GL_WARN_ON_USE (unlockpt, "unlockpt is not portable - " + "use gnulib module unlockpt for portability"); +# endif +#endif + +#if @GNULIB_UNSETENV@ +/* Remove the variable NAME from the environment. */ +# if @REPLACE_UNSETENV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef unsetenv +# define unsetenv rpl_unsetenv +# endif +_GL_FUNCDECL_RPL (unsetenv, int, (const char *name) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (unsetenv, int, (const char *name)); +# else +# if !@HAVE_DECL_UNSETENV@ +_GL_FUNCDECL_SYS (unsetenv, int, (const char *name) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (unsetenv, int, (const char *name)); +# endif +# if !(@REPLACE_UNSETENV@ && !@HAVE_DECL_UNSETENV@) +_GL_CXXALIASWARN (unsetenv); +# endif +#elif defined GNULIB_POSIXCHECK +# undef unsetenv +# if HAVE_RAW_DECL_UNSETENV +_GL_WARN_ON_USE (unsetenv, "unsetenv is unportable - " + "use gnulib module unsetenv for portability"); +# endif +#endif + +/* Convert a wide character to a multibyte character. */ +#if @GNULIB_WCTOMB@ +# if @REPLACE_WCTOMB@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wctomb +# define wctomb rpl_wctomb +# endif +_GL_FUNCDECL_RPL (wctomb, int, (char *s, wchar_t wc)); +_GL_CXXALIAS_RPL (wctomb, int, (char *s, wchar_t wc)); +# else +_GL_CXXALIAS_SYS (wctomb, int, (char *s, wchar_t wc)); +# endif +_GL_CXXALIASWARN (wctomb); +#endif + + +#endif /* _@GUARD_PREFIX@_STDLIB_H */ +#endif /* _@GUARD_PREFIX@_STDLIB_H */ +#endif diff --git a/grub-core/lib/gnulib/strcasecmp.c b/grub-core/lib/gnulib/strcasecmp.c new file mode 100644 index 0000000..6cd0e1e --- /dev/null +++ b/grub-core/lib/gnulib/strcasecmp.c @@ -0,0 +1,62 @@ +/* Case-insensitive string comparison function. + Copyright (C) 1998-1999, 2005-2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <string.h> + +#include <ctype.h> +#include <limits.h> + +#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) + +/* Compare strings S1 and S2, ignoring case, returning less than, equal to or + greater than zero if S1 is lexicographically less than, equal to or greater + than S2. + Note: This function does not work with multibyte strings! */ + +int +strcasecmp (const char *s1, const char *s2) +{ + const unsigned char *p1 = (const unsigned char *) s1; + const unsigned char *p2 = (const unsigned char *) s2; + unsigned char c1, c2; + + if (p1 == p2) + return 0; + + do + { + c1 = TOLOWER (*p1); + c2 = TOLOWER (*p2); + + if (c1 == '\0') + break; + + ++p1; + ++p2; + } + while (c1 == c2); + + if (UCHAR_MAX <= INT_MAX) + return c1 - c2; + else + /* On machines where 'char' and 'int' are types of the same size, the + difference of two 'unsigned char' values - including the sign bit - + doesn't fit in an 'int'. */ + return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); +} diff --git a/grub-core/lib/gnulib/strchrnul.c b/grub-core/lib/gnulib/strchrnul.c new file mode 100644 index 0000000..0f5dd81 --- /dev/null +++ b/grub-core/lib/gnulib/strchrnul.c @@ -0,0 +1,142 @@ +/* Searching in a string. + Copyright (C) 2003, 2007-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <string.h> + +/* Find the first occurrence of C in S or the final NUL byte. */ +char * +strchrnul (const char *s, int c_in) +{ + /* On 32-bit hardware, choosing longword to be a 32-bit unsigned + long instead of a 64-bit uintmax_t tends to give better + performance. On 64-bit hardware, unsigned long is generally 64 + bits already. Change this typedef to experiment with + performance. */ + typedef unsigned long int longword; + + const unsigned char *char_ptr; + const longword *longword_ptr; + longword repeated_one; + longword repeated_c; + unsigned char c; + + c = (unsigned char) c_in; + if (!c) + return rawmemchr (s, 0); + + /* Handle the first few bytes by reading one byte at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + (size_t) char_ptr % sizeof (longword) != 0; + ++char_ptr) + if (!*char_ptr || *char_ptr == c) + return (char *) char_ptr; + + longword_ptr = (const longword *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to any size longwords. */ + + /* Compute auxiliary longword values: + repeated_one is a value which has a 1 in every byte. + repeated_c has c in every byte. */ + repeated_one = 0x01010101; + repeated_c = c | (c << 8); + repeated_c |= repeated_c << 16; + if (0xffffffffU < (longword) -1) + { + repeated_one |= repeated_one << 31 << 1; + repeated_c |= repeated_c << 31 << 1; + if (8 < sizeof (longword)) + { + size_t i; + + for (i = 64; i < sizeof (longword) * 8; i *= 2) + { + repeated_one |= repeated_one << i; + repeated_c |= repeated_c << i; + } + } + } + + /* Instead of the traditional loop which tests each byte, we will + test a longword at a time. The tricky part is testing if *any of + the four* bytes in the longword in question are equal to NUL or + c. We first use an xor with repeated_c. This reduces the task + to testing whether *any of the four* bytes in longword1 or + longword2 is zero. + + Let's consider longword1. We compute tmp = + ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). + That is, we perform the following operations: + 1. Subtract repeated_one. + 2. & ~longword1. + 3. & a mask consisting of 0x80 in every byte. + Consider what happens in each byte: + - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, + and step 3 transforms it into 0x80. A carry can also be propagated + to more significant bytes. + - If a byte of longword1 is nonzero, let its lowest 1 bit be at + position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, + the byte ends in a single bit of value 0 and k bits of value 1. + After step 2, the result is just k bits of value 1: 2^k - 1. After + step 3, the result is 0. And no carry is produced. + So, if longword1 has only non-zero bytes, tmp is zero. + Whereas if longword1 has a zero byte, call j the position of the least + significant zero byte. Then the result has a zero at positions 0, ..., + j-1 and a 0x80 at position j. We cannot predict the result at the more + significant bytes (positions j+1..3), but it does not matter since we + already have a non-zero bit at position 8*j+7. + + The test whether any byte in longword1 or longword2 is zero is equivalent + to testing whether tmp1 is nonzero or tmp2 is nonzero. We can combine + this into a single test, whether (tmp1 | tmp2) is nonzero. + + This test can read more than one byte beyond the end of a string, + depending on where the terminating NUL is encountered. However, + this is considered safe since the initialization phase ensured + that the read will be aligned, therefore, the read will not cross + page boundaries and will not cause a fault. */ + + while (1) + { + longword longword1 = *longword_ptr ^ repeated_c; + longword longword2 = *longword_ptr; + + if (((((longword1 - repeated_one) & ~longword1) + | ((longword2 - repeated_one) & ~longword2)) + & (repeated_one << 7)) != 0) + break; + longword_ptr++; + } + + char_ptr = (const unsigned char *) longword_ptr; + + /* At this point, we know that one of the sizeof (longword) bytes + starting at char_ptr is == 0 or == c. On little-endian machines, + we could determine the first such byte without any further memory + accesses, just by looking at the tmp result from the last loop + iteration. But this does not work on big-endian machines. + Choose code that works in both cases. */ + + char_ptr = (unsigned char *) longword_ptr; + while (*char_ptr && (*char_ptr != c)) + char_ptr++; + return (char *) char_ptr; +} diff --git a/grub-core/lib/gnulib/strchrnul.valgrind b/grub-core/lib/gnulib/strchrnul.valgrind new file mode 100644 index 0000000..b14fa13 --- /dev/null +++ b/grub-core/lib/gnulib/strchrnul.valgrind @@ -0,0 +1,12 @@ +# Suppress a valgrind message about use of uninitialized memory in strchrnul(). +# This use is OK because it provides only a speedup. +{ + strchrnul-value4 + Memcheck:Value4 + fun:strchrnul +} +{ + strchrnul-value8 + Memcheck:Value8 + fun:strchrnul +} diff --git a/grub-core/lib/gnulib/strdup.c b/grub-core/lib/gnulib/strdup.c new file mode 100644 index 0000000..717cf65 --- /dev/null +++ b/grub-core/lib/gnulib/strdup.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1991, 1996-1998, 2002-2004, 2006-2007, 2009-2019 Free Software + Foundation, Inc. + + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _LIBC +# include <config.h> +#endif + +/* Get specification. */ +#include <string.h> + +#include <stdlib.h> + +#undef __strdup +#ifdef _LIBC +# undef strdup +#endif + +#ifndef weak_alias +# define __strdup strdup +#endif + +/* Duplicate S, returning an identical malloc'd string. */ +char * +__strdup (const char *s) +{ + size_t len = strlen (s) + 1; + void *new = malloc (len); + + if (new == NULL) + return NULL; + + return (char *) memcpy (new, s, len); +} +#ifdef libc_hidden_def +libc_hidden_def (__strdup) +#endif +#ifdef weak_alias +weak_alias (__strdup, strdup) +#endif diff --git a/grub-core/lib/gnulib/streq.h b/grub-core/lib/gnulib/streq.h new file mode 100644 index 0000000..326537b --- /dev/null +++ b/grub-core/lib/gnulib/streq.h @@ -0,0 +1,176 @@ +/* Optimized string comparison. + Copyright (C) 2001-2002, 2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>. */ + +#ifndef _GL_STREQ_H +#define _GL_STREQ_H + +#include <string.h> + +/* STREQ_OPT allows to optimize string comparison with a small literal string. + STREQ_OPT (s, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) + is semantically equivalent to + strcmp (s, "EUC-KR") == 0 + just faster. */ + +/* Help GCC to generate good code for string comparisons with + immediate strings. */ +#if defined (__GNUC__) && defined (__OPTIMIZE__) + +static inline int +streq9 (const char *s1, const char *s2) +{ + return strcmp (s1 + 9, s2 + 9) == 0; +} + +static inline int +streq8 (const char *s1, const char *s2, char s28) +{ + if (s1[8] == s28) + { + if (s28 == 0) + return 1; + else + return streq9 (s1, s2); + } + else + return 0; +} + +static inline int +streq7 (const char *s1, const char *s2, char s27, char s28) +{ + if (s1[7] == s27) + { + if (s27 == 0) + return 1; + else + return streq8 (s1, s2, s28); + } + else + return 0; +} + +static inline int +streq6 (const char *s1, const char *s2, char s26, char s27, char s28) +{ + if (s1[6] == s26) + { + if (s26 == 0) + return 1; + else + return streq7 (s1, s2, s27, s28); + } + else + return 0; +} + +static inline int +streq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28) +{ + if (s1[5] == s25) + { + if (s25 == 0) + return 1; + else + return streq6 (s1, s2, s26, s27, s28); + } + else + return 0; +} + +static inline int +streq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28) +{ + if (s1[4] == s24) + { + if (s24 == 0) + return 1; + else + return streq5 (s1, s2, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +streq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (s1[3] == s23) + { + if (s23 == 0) + return 1; + else + return streq4 (s1, s2, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +streq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (s1[2] == s22) + { + if (s22 == 0) + return 1; + else + return streq3 (s1, s2, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +streq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (s1[1] == s21) + { + if (s21 == 0) + return 1; + else + return streq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +static inline int +streq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28) +{ + if (s1[0] == s20) + { + if (s20 == 0) + return 1; + else + return streq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28); + } + else + return 0; +} + +#define STREQ_OPT(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ + streq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28) + +#else + +#define STREQ_OPT(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ + (strcmp (s1, s2) == 0) + +#endif + +#endif /* _GL_STREQ_H */ diff --git a/grub-core/lib/gnulib/strerror-override.c b/grub-core/lib/gnulib/strerror-override.c new file mode 100644 index 0000000..558a010 --- /dev/null +++ b/grub-core/lib/gnulib/strerror-override.c @@ -0,0 +1,302 @@ +/* strerror-override.c --- POSIX compatible system error routine + + Copyright (C) 2010-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2010. */ + +#include <config.h> + +#include "strerror-override.h" + +#include <errno.h> + +#if GNULIB_defined_EWINSOCK /* native Windows platforms */ +# if HAVE_WINSOCK2_H +# include <winsock2.h> +# endif +#endif + +/* If ERRNUM maps to an errno value defined by gnulib, return a string + describing the error. Otherwise return NULL. */ +const char * +strerror_override (int errnum) +{ + /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */ + switch (errnum) + { +#if REPLACE_STRERROR_0 + case 0: + return "Success"; +#endif + +#if GNULIB_defined_ESOCK /* native Windows platforms with older <errno.h> */ + case EINPROGRESS: + return "Operation now in progress"; + case EALREADY: + return "Operation already in progress"; + case ENOTSOCK: + return "Socket operation on non-socket"; + case EDESTADDRREQ: + return "Destination address required"; + case EMSGSIZE: + return "Message too long"; + case EPROTOTYPE: + return "Protocol wrong type for socket"; + case ENOPROTOOPT: + return "Protocol not available"; + case EPROTONOSUPPORT: + return "Protocol not supported"; + case EOPNOTSUPP: + return "Operation not supported"; + case EAFNOSUPPORT: + return "Address family not supported by protocol"; + case EADDRINUSE: + return "Address already in use"; + case EADDRNOTAVAIL: + return "Cannot assign requested address"; + case ENETDOWN: + return "Network is down"; + case ENETUNREACH: + return "Network is unreachable"; + case ECONNRESET: + return "Connection reset by peer"; + case ENOBUFS: + return "No buffer space available"; + case EISCONN: + return "Transport endpoint is already connected"; + case ENOTCONN: + return "Transport endpoint is not connected"; + case ETIMEDOUT: + return "Connection timed out"; + case ECONNREFUSED: + return "Connection refused"; + case ELOOP: + return "Too many levels of symbolic links"; + case EHOSTUNREACH: + return "No route to host"; + case EWOULDBLOCK: + return "Operation would block"; +#endif +#if GNULIB_defined_ESTREAMS /* native Windows platforms with older <errno.h> */ + case ETXTBSY: + return "Text file busy"; + case ENODATA: + return "No data available"; + case ENOSR: + return "Out of streams resources"; + case ENOSTR: + return "Device not a stream"; + case ETIME: + return "Timer expired"; + case EOTHER: + return "Other error"; +#endif +#if GNULIB_defined_EWINSOCK /* native Windows platforms */ + case ESOCKTNOSUPPORT: + return "Socket type not supported"; + case EPFNOSUPPORT: + return "Protocol family not supported"; + case ESHUTDOWN: + return "Cannot send after transport endpoint shutdown"; + case ETOOMANYREFS: + return "Too many references: cannot splice"; + case EHOSTDOWN: + return "Host is down"; + case EPROCLIM: + return "Too many processes"; + case EUSERS: + return "Too many users"; + case EDQUOT: + return "Disk quota exceeded"; + case ESTALE: + return "Stale NFS file handle"; + case EREMOTE: + return "Object is remote"; +# if HAVE_WINSOCK2_H + /* WSA_INVALID_HANDLE maps to EBADF */ + /* WSA_NOT_ENOUGH_MEMORY maps to ENOMEM */ + /* WSA_INVALID_PARAMETER maps to EINVAL */ + case WSA_OPERATION_ABORTED: + return "Overlapped operation aborted"; + case WSA_IO_INCOMPLETE: + return "Overlapped I/O event object not in signaled state"; + case WSA_IO_PENDING: + return "Overlapped operations will complete later"; + /* WSAEINTR maps to EINTR */ + /* WSAEBADF maps to EBADF */ + /* WSAEACCES maps to EACCES */ + /* WSAEFAULT maps to EFAULT */ + /* WSAEINVAL maps to EINVAL */ + /* WSAEMFILE maps to EMFILE */ + /* WSAEWOULDBLOCK maps to EWOULDBLOCK */ + /* WSAEINPROGRESS maps to EINPROGRESS */ + /* WSAEALREADY maps to EALREADY */ + /* WSAENOTSOCK maps to ENOTSOCK */ + /* WSAEDESTADDRREQ maps to EDESTADDRREQ */ + /* WSAEMSGSIZE maps to EMSGSIZE */ + /* WSAEPROTOTYPE maps to EPROTOTYPE */ + /* WSAENOPROTOOPT maps to ENOPROTOOPT */ + /* WSAEPROTONOSUPPORT maps to EPROTONOSUPPORT */ + /* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */ + /* WSAEOPNOTSUPP maps to EOPNOTSUPP */ + /* WSAEPFNOSUPPORT is EPFNOSUPPORT */ + /* WSAEAFNOSUPPORT maps to EAFNOSUPPORT */ + /* WSAEADDRINUSE maps to EADDRINUSE */ + /* WSAEADDRNOTAVAIL maps to EADDRNOTAVAIL */ + /* WSAENETDOWN maps to ENETDOWN */ + /* WSAENETUNREACH maps to ENETUNREACH */ + /* WSAENETRESET maps to ENETRESET */ + /* WSAECONNABORTED maps to ECONNABORTED */ + /* WSAECONNRESET maps to ECONNRESET */ + /* WSAENOBUFS maps to ENOBUFS */ + /* WSAEISCONN maps to EISCONN */ + /* WSAENOTCONN maps to ENOTCONN */ + /* WSAESHUTDOWN is ESHUTDOWN */ + /* WSAETOOMANYREFS is ETOOMANYREFS */ + /* WSAETIMEDOUT maps to ETIMEDOUT */ + /* WSAECONNREFUSED maps to ECONNREFUSED */ + /* WSAELOOP maps to ELOOP */ + /* WSAENAMETOOLONG maps to ENAMETOOLONG */ + /* WSAEHOSTDOWN is EHOSTDOWN */ + /* WSAEHOSTUNREACH maps to EHOSTUNREACH */ + /* WSAENOTEMPTY maps to ENOTEMPTY */ + /* WSAEPROCLIM is EPROCLIM */ + /* WSAEUSERS is EUSERS */ + /* WSAEDQUOT is EDQUOT */ + /* WSAESTALE is ESTALE */ + /* WSAEREMOTE is EREMOTE */ + case WSASYSNOTREADY: + return "Network subsystem is unavailable"; + case WSAVERNOTSUPPORTED: + return "Winsock.dll version out of range"; + case WSANOTINITIALISED: + return "Successful WSAStartup not yet performed"; + case WSAEDISCON: + return "Graceful shutdown in progress"; + case WSAENOMORE: case WSA_E_NO_MORE: + return "No more results"; + case WSAECANCELLED: case WSA_E_CANCELLED: + return "Call was canceled"; + case WSAEINVALIDPROCTABLE: + return "Procedure call table is invalid"; + case WSAEINVALIDPROVIDER: + return "Service provider is invalid"; + case WSAEPROVIDERFAILEDINIT: + return "Service provider failed to initialize"; + case WSASYSCALLFAILURE: + return "System call failure"; + case WSASERVICE_NOT_FOUND: + return "Service not found"; + case WSATYPE_NOT_FOUND: + return "Class type not found"; + case WSAEREFUSED: + return "Database query was refused"; + case WSAHOST_NOT_FOUND: + return "Host not found"; + case WSATRY_AGAIN: + return "Nonauthoritative host not found"; + case WSANO_RECOVERY: + return "Nonrecoverable error"; + case WSANO_DATA: + return "Valid name, no data record of requested type"; + /* WSA_QOS_* omitted */ +# endif +#endif + +#if GNULIB_defined_ENOMSG + case ENOMSG: + return "No message of desired type"; +#endif + +#if GNULIB_defined_EIDRM + case EIDRM: + return "Identifier removed"; +#endif + +#if GNULIB_defined_ENOLINK + case ENOLINK: + return "Link has been severed"; +#endif + +#if GNULIB_defined_EPROTO + case EPROTO: + return "Protocol error"; +#endif + +#if GNULIB_defined_EMULTIHOP + case EMULTIHOP: + return "Multihop attempted"; +#endif + +#if GNULIB_defined_EBADMSG + case EBADMSG: + return "Bad message"; +#endif + +#if GNULIB_defined_EOVERFLOW + case EOVERFLOW: + return "Value too large for defined data type"; +#endif + +#if GNULIB_defined_ENOTSUP + case ENOTSUP: + return "Not supported"; +#endif + +#if GNULIB_defined_ENETRESET + case ENETRESET: + return "Network dropped connection on reset"; +#endif + +#if GNULIB_defined_ECONNABORTED + case ECONNABORTED: + return "Software caused connection abort"; +#endif + +#if GNULIB_defined_ESTALE + case ESTALE: + return "Stale NFS file handle"; +#endif + +#if GNULIB_defined_EDQUOT + case EDQUOT: + return "Disk quota exceeded"; +#endif + +#if GNULIB_defined_ECANCELED + case ECANCELED: + return "Operation canceled"; +#endif + +#if GNULIB_defined_EOWNERDEAD + case EOWNERDEAD: + return "Owner died"; +#endif + +#if GNULIB_defined_ENOTRECOVERABLE + case ENOTRECOVERABLE: + return "State not recoverable"; +#endif + +#if GNULIB_defined_EILSEQ + case EILSEQ: + return "Invalid or incomplete multibyte or wide character"; +#endif + + default: + return NULL; + } +} diff --git a/grub-core/lib/gnulib/strerror-override.h b/grub-core/lib/gnulib/strerror-override.h new file mode 100644 index 0000000..255febc --- /dev/null +++ b/grub-core/lib/gnulib/strerror-override.h @@ -0,0 +1,56 @@ +/* strerror-override.h --- POSIX compatible system error routine + + Copyright (C) 2010-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _GL_STRERROR_OVERRIDE_H +# define _GL_STRERROR_OVERRIDE_H + +# include <errno.h> +# include <stddef.h> + +/* Reasonable buffer size that should never trigger ERANGE; if this + proves too small, we intentionally abort(), to remind us to fix + this value. */ +# define STACKBUF_LEN 256 + +/* If ERRNUM maps to an errno value defined by gnulib, return a string + describing the error. Otherwise return NULL. */ +# if REPLACE_STRERROR_0 \ + || GNULIB_defined_ESOCK \ + || GNULIB_defined_ESTREAMS \ + || GNULIB_defined_EWINSOCK \ + || GNULIB_defined_ENOMSG \ + || GNULIB_defined_EIDRM \ + || GNULIB_defined_ENOLINK \ + || GNULIB_defined_EPROTO \ + || GNULIB_defined_EMULTIHOP \ + || GNULIB_defined_EBADMSG \ + || GNULIB_defined_EOVERFLOW \ + || GNULIB_defined_ENOTSUP \ + || GNULIB_defined_ENETRESET \ + || GNULIB_defined_ECONNABORTED \ + || GNULIB_defined_ESTALE \ + || GNULIB_defined_EDQUOT \ + || GNULIB_defined_ECANCELED \ + || GNULIB_defined_EOWNERDEAD \ + || GNULIB_defined_ENOTRECOVERABLE \ + || GNULIB_defined_EILSEQ +extern const char *strerror_override (int errnum) _GL_ATTRIBUTE_CONST; +# else +# define strerror_override(ignored) NULL +# endif + +#endif /* _GL_STRERROR_OVERRIDE_H */ diff --git a/grub-core/lib/gnulib/strerror.c b/grub-core/lib/gnulib/strerror.c new file mode 100644 index 0000000..f5900fd --- /dev/null +++ b/grub-core/lib/gnulib/strerror.c @@ -0,0 +1,71 @@ +/* strerror.c --- POSIX compatible system error routine + + Copyright (C) 2007-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <string.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "intprops.h" +#include "strerror-override.h" +#include "verify.h" + +/* Use the system functions, not the gnulib overrides in this file. */ +#undef sprintf + +char * +strerror (int n) +#undef strerror +{ + static char buf[STACKBUF_LEN]; + size_t len; + + /* Cast away const, due to the historical signature of strerror; + callers should not be modifying the string. */ + const char *msg = strerror_override (n); + if (msg) + return (char *) msg; + + msg = strerror (n); + + /* Our strerror_r implementation might use the system's strerror + buffer, so all other clients of strerror have to see the error + copied into a buffer that we manage. This is not thread-safe, + even if the system strerror is, but portable programs shouldn't + be using strerror if they care about thread-safety. */ + if (!msg || !*msg) + { + static char const fmt[] = "Unknown error %d"; + verify (sizeof buf >= sizeof (fmt) + INT_STRLEN_BOUND (n)); + sprintf (buf, fmt, n); + errno = EINVAL; + return buf; + } + + /* Fix STACKBUF_LEN if this ever aborts. */ + len = strlen (msg); + if (sizeof buf <= len) + abort (); + + memcpy (buf, msg, len + 1); + return buf; +} diff --git a/grub-core/lib/gnulib/string.in.h b/grub-core/lib/gnulib/string.in.h new file mode 100644 index 0000000..4a9292f --- /dev/null +++ b/grub-core/lib/gnulib/string.in.h @@ -0,0 +1,1063 @@ +/* A GNU-like <string.h>. + + Copyright (C) 1995-1996, 2001-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined _GL_ALREADY_INCLUDING_STRING_H +/* Special invocation convention: + - On OS X/NetBSD we have a sequence of nested includes + <string.h> -> <strings.h> -> "string.h" + In this situation system _chk variants due to -D_FORTIFY_SOURCE + might be used after any replacements defined here. */ + +#@INCLUDE_NEXT@ @NEXT_STRING_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_STRING_H + +#define _GL_ALREADY_INCLUDING_STRING_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STRING_H@ + +#undef _GL_ALREADY_INCLUDING_STRING_H + +#ifndef _@GUARD_PREFIX@_STRING_H +#define _@GUARD_PREFIX@_STRING_H + +/* NetBSD 5.0 mis-defines NULL. */ +#include <stddef.h> + +/* MirBSD defines mbslen as a macro. */ +#if @GNULIB_MBSLEN@ && defined __MirBSD__ +# include <wchar.h> +#endif + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +# define _GL_ATTRIBUTE_PURE /* empty */ +#endif + +/* NetBSD 5.0 declares strsignal in <unistd.h>, not in <string.h>. */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_STRSIGNAL@ || defined GNULIB_POSIXCHECK) && defined __NetBSD__ \ + && ! defined __GLIBC__ +# include <unistd.h> +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Clear a block of memory. The compiler will not delete a call to + this function, even if the block is dead after the call. */ +#if @GNULIB_EXPLICIT_BZERO@ +# if ! @HAVE_EXPLICIT_BZERO@ +_GL_FUNCDECL_SYS (explicit_bzero, void, + (void *__dest, size_t __n) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (explicit_bzero, void, (void *__dest, size_t __n)); +_GL_CXXALIASWARN (explicit_bzero); +#elif defined GNULIB_POSIXCHECK +# undef explicit_bzero +# if HAVE_RAW_DECL_EXPLICIT_BZERO +_GL_WARN_ON_USE (explicit_bzero, "explicit_bzero is unportable - " + "use gnulib module explicit_bzero for portability"); +# endif +#endif + +/* Find the index of the least-significant set bit. */ +#if @GNULIB_FFSL@ +# if !@HAVE_FFSL@ +_GL_FUNCDECL_SYS (ffsl, int, (long int i)); +# endif +_GL_CXXALIAS_SYS (ffsl, int, (long int i)); +_GL_CXXALIASWARN (ffsl); +#elif defined GNULIB_POSIXCHECK +# undef ffsl +# if HAVE_RAW_DECL_FFSL +_GL_WARN_ON_USE (ffsl, "ffsl is not portable - use the ffsl module"); +# endif +#endif + + +/* Find the index of the least-significant set bit. */ +#if @GNULIB_FFSLL@ +# if !@HAVE_FFSLL@ +_GL_FUNCDECL_SYS (ffsll, int, (long long int i)); +# endif +_GL_CXXALIAS_SYS (ffsll, int, (long long int i)); +_GL_CXXALIASWARN (ffsll); +#elif defined GNULIB_POSIXCHECK +# undef ffsll +# if HAVE_RAW_DECL_FFSLL +_GL_WARN_ON_USE (ffsll, "ffsll is not portable - use the ffsll module"); +# endif +#endif + + +/* Return the first instance of C within N bytes of S, or NULL. */ +#if @GNULIB_MEMCHR@ +# if @REPLACE_MEMCHR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define memchr rpl_memchr +# endif +_GL_FUNCDECL_RPL (memchr, void *, (void const *__s, int __c, size_t __n) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (memchr, void *, (void const *__s, int __c, size_t __n)); +# else +# if ! @HAVE_MEMCHR@ +_GL_FUNCDECL_SYS (memchr, void *, (void const *__s, int __c, size_t __n) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C" { const void * std::memchr (const void *, int, size_t); } + extern "C++" { void * std::memchr (void *, int, size_t); } */ +_GL_CXXALIAS_SYS_CAST2 (memchr, + void *, (void const *__s, int __c, size_t __n), + void const *, (void const *__s, int __c, size_t __n)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n)); +_GL_CXXALIASWARN1 (memchr, void const *, + (void const *__s, int __c, size_t __n)); +# else +_GL_CXXALIASWARN (memchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef memchr +/* Assume memchr is always declared. */ +_GL_WARN_ON_USE (memchr, "memchr has platform-specific bugs - " + "use gnulib module memchr for portability" ); +#endif + +/* Return the first occurrence of NEEDLE in HAYSTACK. */ +#if @GNULIB_MEMMEM@ +# if @REPLACE_MEMMEM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define memmem rpl_memmem +# endif +_GL_FUNCDECL_RPL (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 3))); +_GL_CXXALIAS_RPL (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len)); +# else +# if ! @HAVE_DECL_MEMMEM@ +_GL_FUNCDECL_SYS (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 3))); +# endif +_GL_CXXALIAS_SYS (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len)); +# endif +_GL_CXXALIASWARN (memmem); +#elif defined GNULIB_POSIXCHECK +# undef memmem +# if HAVE_RAW_DECL_MEMMEM +_GL_WARN_ON_USE (memmem, "memmem is unportable and often quadratic - " + "use gnulib module memmem-simple for portability, " + "and module memmem for speed" ); +# endif +#endif + +/* Copy N bytes of SRC to DEST, return pointer to bytes after the + last written byte. */ +#if @GNULIB_MEMPCPY@ +# if ! @HAVE_MEMPCPY@ +_GL_FUNCDECL_SYS (mempcpy, void *, + (void *restrict __dest, void const *restrict __src, + size_t __n) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (mempcpy, void *, + (void *restrict __dest, void const *restrict __src, + size_t __n)); +_GL_CXXALIASWARN (mempcpy); +#elif defined GNULIB_POSIXCHECK +# undef mempcpy +# if HAVE_RAW_DECL_MEMPCPY +_GL_WARN_ON_USE (mempcpy, "mempcpy is unportable - " + "use gnulib module mempcpy for portability"); +# endif +#endif + +/* Search backwards through a block for a byte (specified as an int). */ +#if @GNULIB_MEMRCHR@ +# if ! @HAVE_DECL_MEMRCHR@ +_GL_FUNCDECL_SYS (memrchr, void *, (void const *, int, size_t) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const void * std::memrchr (const void *, int, size_t); } + extern "C++" { void * std::memrchr (void *, int, size_t); } */ +_GL_CXXALIAS_SYS_CAST2 (memrchr, + void *, (void const *, int, size_t), + void const *, (void const *, int, size_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t)); +_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t)); +# else +_GL_CXXALIASWARN (memrchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef memrchr +# if HAVE_RAW_DECL_MEMRCHR +_GL_WARN_ON_USE (memrchr, "memrchr is unportable - " + "use gnulib module memrchr for portability"); +# endif +#endif + +/* Find the first occurrence of C in S. More efficient than + memchr(S,C,N), at the expense of undefined behavior if C does not + occur within N bytes. */ +#if @GNULIB_RAWMEMCHR@ +# if ! @HAVE_RAWMEMCHR@ +_GL_FUNCDECL_SYS (rawmemchr, void *, (void const *__s, int __c_in) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const void * std::rawmemchr (const void *, int); } + extern "C++" { void * std::rawmemchr (void *, int); } */ +_GL_CXXALIAS_SYS_CAST2 (rawmemchr, + void *, (void const *__s, int __c_in), + void const *, (void const *__s, int __c_in)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in)); +_GL_CXXALIASWARN1 (rawmemchr, void const *, (void const *__s, int __c_in)); +# else +_GL_CXXALIASWARN (rawmemchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef rawmemchr +# if HAVE_RAW_DECL_RAWMEMCHR +_GL_WARN_ON_USE (rawmemchr, "rawmemchr is unportable - " + "use gnulib module rawmemchr for portability"); +# endif +#endif + +/* Copy SRC to DST, returning the address of the terminating '\0' in DST. */ +#if @GNULIB_STPCPY@ +# if ! @HAVE_STPCPY@ +_GL_FUNCDECL_SYS (stpcpy, char *, + (char *restrict __dst, char const *restrict __src) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (stpcpy, char *, + (char *restrict __dst, char const *restrict __src)); +_GL_CXXALIASWARN (stpcpy); +#elif defined GNULIB_POSIXCHECK +# undef stpcpy +# if HAVE_RAW_DECL_STPCPY +_GL_WARN_ON_USE (stpcpy, "stpcpy is unportable - " + "use gnulib module stpcpy for portability"); +# endif +#endif + +/* Copy no more than N bytes of SRC to DST, returning a pointer past the + last non-NUL byte written into DST. */ +#if @GNULIB_STPNCPY@ +# if @REPLACE_STPNCPY@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef stpncpy +# define stpncpy rpl_stpncpy +# endif +_GL_FUNCDECL_RPL (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n)); +# else +# if ! @HAVE_STPNCPY@ +_GL_FUNCDECL_SYS (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n)); +# endif +_GL_CXXALIASWARN (stpncpy); +#elif defined GNULIB_POSIXCHECK +# undef stpncpy +# if HAVE_RAW_DECL_STPNCPY +_GL_WARN_ON_USE (stpncpy, "stpncpy is unportable - " + "use gnulib module stpncpy for portability"); +# endif +#endif + +#if defined GNULIB_POSIXCHECK +/* strchr() does not work with multibyte strings if the locale encoding is + GB18030 and the character to be searched is a digit. */ +# undef strchr +/* Assume strchr is always declared. */ +_GL_WARN_ON_USE (strchr, "strchr cannot work correctly on character strings " + "in some multibyte locales - " + "use mbschr if you care about internationalization"); +#endif + +/* Find the first occurrence of C in S or the final NUL byte. */ +#if @GNULIB_STRCHRNUL@ +# if @REPLACE_STRCHRNUL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strchrnul rpl_strchrnul +# endif +_GL_FUNCDECL_RPL (strchrnul, char *, (const char *__s, int __c_in) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strchrnul, char *, + (const char *str, int ch)); +# else +# if ! @HAVE_STRCHRNUL@ +_GL_FUNCDECL_SYS (strchrnul, char *, (char const *__s, int __c_in) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const char * std::strchrnul (const char *, int); } + extern "C++" { char * std::strchrnul (char *, int); } */ +_GL_CXXALIAS_SYS_CAST2 (strchrnul, + char *, (char const *__s, int __c_in), + char const *, (char const *__s, int __c_in)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in)); +_GL_CXXALIASWARN1 (strchrnul, char const *, (char const *__s, int __c_in)); +# else +_GL_CXXALIASWARN (strchrnul); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strchrnul +# if HAVE_RAW_DECL_STRCHRNUL +_GL_WARN_ON_USE (strchrnul, "strchrnul is unportable - " + "use gnulib module strchrnul for portability"); +# endif +#endif + +/* Duplicate S, returning an identical malloc'd string. */ +#if @GNULIB_STRDUP@ +# if @REPLACE_STRDUP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strdup +# define strdup rpl_strdup +# endif +_GL_FUNCDECL_RPL (strdup, char *, (char const *__s) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strdup, char *, (char const *__s)); +# else +# if defined __cplusplus && defined GNULIB_NAMESPACE && defined strdup + /* strdup exists as a function and as a macro. Get rid of the macro. */ +# undef strdup +# endif +# if !(@HAVE_DECL_STRDUP@ || defined strdup) +_GL_FUNCDECL_SYS (strdup, char *, (char const *__s) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strdup, char *, (char const *__s)); +# endif +_GL_CXXALIASWARN (strdup); +#elif defined GNULIB_POSIXCHECK +# undef strdup +# if HAVE_RAW_DECL_STRDUP +_GL_WARN_ON_USE (strdup, "strdup is unportable - " + "use gnulib module strdup for portability"); +# endif +#endif + +/* Append no more than N characters from SRC onto DEST. */ +#if @GNULIB_STRNCAT@ +# if @REPLACE_STRNCAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strncat +# define strncat rpl_strncat +# endif +_GL_FUNCDECL_RPL (strncat, char *, (char *dest, const char *src, size_t n) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (strncat, char *, (char *dest, const char *src, size_t n)); +# else +_GL_CXXALIAS_SYS (strncat, char *, (char *dest, const char *src, size_t n)); +# endif +_GL_CXXALIASWARN (strncat); +#elif defined GNULIB_POSIXCHECK +# undef strncat +# if HAVE_RAW_DECL_STRNCAT +_GL_WARN_ON_USE (strncat, "strncat is unportable - " + "use gnulib module strncat for portability"); +# endif +#endif + +/* Return a newly allocated copy of at most N bytes of STRING. */ +#if @GNULIB_STRNDUP@ +# if @REPLACE_STRNDUP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strndup +# define strndup rpl_strndup +# endif +_GL_FUNCDECL_RPL (strndup, char *, (char const *__s, size_t __n) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strndup, char *, (char const *__s, size_t __n)); +# else +# if ! @HAVE_DECL_STRNDUP@ +_GL_FUNCDECL_SYS (strndup, char *, (char const *__s, size_t __n) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strndup, char *, (char const *__s, size_t __n)); +# endif +_GL_CXXALIASWARN (strndup); +#elif defined GNULIB_POSIXCHECK +# undef strndup +# if HAVE_RAW_DECL_STRNDUP +_GL_WARN_ON_USE (strndup, "strndup is unportable - " + "use gnulib module strndup for portability"); +# endif +#endif + +/* Find the length (number of bytes) of STRING, but scan at most + MAXLEN bytes. If no '\0' terminator is found in that many bytes, + return MAXLEN. */ +#if @GNULIB_STRNLEN@ +# if @REPLACE_STRNLEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strnlen +# define strnlen rpl_strnlen +# endif +_GL_FUNCDECL_RPL (strnlen, size_t, (char const *__s, size_t __maxlen) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strnlen, size_t, (char const *__s, size_t __maxlen)); +# else +# if ! @HAVE_DECL_STRNLEN@ +_GL_FUNCDECL_SYS (strnlen, size_t, (char const *__s, size_t __maxlen) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strnlen, size_t, (char const *__s, size_t __maxlen)); +# endif +_GL_CXXALIASWARN (strnlen); +#elif defined GNULIB_POSIXCHECK +# undef strnlen +# if HAVE_RAW_DECL_STRNLEN +_GL_WARN_ON_USE (strnlen, "strnlen is unportable - " + "use gnulib module strnlen for portability"); +# endif +#endif + +#if defined GNULIB_POSIXCHECK +/* strcspn() assumes the second argument is a list of single-byte characters. + Even in this simple case, it does not work with multibyte strings if the + locale encoding is GB18030 and one of the characters to be searched is a + digit. */ +# undef strcspn +/* Assume strcspn is always declared. */ +_GL_WARN_ON_USE (strcspn, "strcspn cannot work correctly on character strings " + "in multibyte locales - " + "use mbscspn if you care about internationalization"); +#endif + +/* Find the first occurrence in S of any character in ACCEPT. */ +#if @GNULIB_STRPBRK@ +# if ! @HAVE_STRPBRK@ +_GL_FUNCDECL_SYS (strpbrk, char *, (char const *__s, char const *__accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C" { const char * strpbrk (const char *, const char *); } + extern "C++" { char * strpbrk (char *, const char *); } */ +_GL_CXXALIAS_SYS_CAST2 (strpbrk, + char *, (char const *__s, char const *__accept), + const char *, (char const *__s, char const *__accept)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept)); +_GL_CXXALIASWARN1 (strpbrk, char const *, + (char const *__s, char const *__accept)); +# else +_GL_CXXALIASWARN (strpbrk); +# endif +# if defined GNULIB_POSIXCHECK +/* strpbrk() assumes the second argument is a list of single-byte characters. + Even in this simple case, it does not work with multibyte strings if the + locale encoding is GB18030 and one of the characters to be searched is a + digit. */ +# undef strpbrk +_GL_WARN_ON_USE (strpbrk, "strpbrk cannot work correctly on character strings " + "in multibyte locales - " + "use mbspbrk if you care about internationalization"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strpbrk +# if HAVE_RAW_DECL_STRPBRK +_GL_WARN_ON_USE (strpbrk, "strpbrk is unportable - " + "use gnulib module strpbrk for portability"); +# endif +#endif + +#if defined GNULIB_POSIXCHECK +/* strspn() assumes the second argument is a list of single-byte characters. + Even in this simple case, it cannot work with multibyte strings. */ +# undef strspn +/* Assume strspn is always declared. */ +_GL_WARN_ON_USE (strspn, "strspn cannot work correctly on character strings " + "in multibyte locales - " + "use mbsspn if you care about internationalization"); +#endif + +#if defined GNULIB_POSIXCHECK +/* strrchr() does not work with multibyte strings if the locale encoding is + GB18030 and the character to be searched is a digit. */ +# undef strrchr +/* Assume strrchr is always declared. */ +_GL_WARN_ON_USE (strrchr, "strrchr cannot work correctly on character strings " + "in some multibyte locales - " + "use mbsrchr if you care about internationalization"); +#endif + +/* Search the next delimiter (char listed in DELIM) starting at *STRINGP. + If one is found, overwrite it with a NUL, and advance *STRINGP + to point to the next char after it. Otherwise, set *STRINGP to NULL. + If *STRINGP was already NULL, nothing happens. + Return the old value of *STRINGP. + + This is a variant of strtok() that is multithread-safe and supports + empty fields. + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + Caveat: It doesn't work with multibyte strings unless all of the delimiter + characters are ASCII characters < 0x30. + + See also strtok_r(). */ +#if @GNULIB_STRSEP@ +# if ! @HAVE_STRSEP@ +_GL_FUNCDECL_SYS (strsep, char *, + (char **restrict __stringp, char const *restrict __delim) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (strsep, char *, + (char **restrict __stringp, char const *restrict __delim)); +_GL_CXXALIASWARN (strsep); +# if defined GNULIB_POSIXCHECK +# undef strsep +_GL_WARN_ON_USE (strsep, "strsep cannot work correctly on character strings " + "in multibyte locales - " + "use mbssep if you care about internationalization"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strsep +# if HAVE_RAW_DECL_STRSEP +_GL_WARN_ON_USE (strsep, "strsep is unportable - " + "use gnulib module strsep for portability"); +# endif +#endif + +#if @GNULIB_STRSTR@ +# if @REPLACE_STRSTR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strstr rpl_strstr +# endif +_GL_FUNCDECL_RPL (strstr, char *, (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (strstr, char *, (const char *haystack, const char *needle)); +# else + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const char * strstr (const char *, const char *); } + extern "C++" { char * strstr (char *, const char *); } */ +_GL_CXXALIAS_SYS_CAST2 (strstr, + char *, (const char *haystack, const char *needle), + const char *, (const char *haystack, const char *needle)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (strstr, char *, (char *haystack, const char *needle)); +_GL_CXXALIASWARN1 (strstr, const char *, + (const char *haystack, const char *needle)); +# else +_GL_CXXALIASWARN (strstr); +# endif +#elif defined GNULIB_POSIXCHECK +/* strstr() does not work with multibyte strings if the locale encoding is + different from UTF-8: + POSIX says that it operates on "strings", and "string" in POSIX is defined + as a sequence of bytes, not of characters. */ +# undef strstr +/* Assume strstr is always declared. */ +_GL_WARN_ON_USE (strstr, "strstr is quadratic on many systems, and cannot " + "work correctly on character strings in most " + "multibyte locales - " + "use mbsstr if you care about internationalization, " + "or use strstr if you care about speed"); +#endif + +/* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive + comparison. */ +#if @GNULIB_STRCASESTR@ +# if @REPLACE_STRCASESTR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strcasestr rpl_strcasestr +# endif +_GL_FUNCDECL_RPL (strcasestr, char *, + (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (strcasestr, char *, + (const char *haystack, const char *needle)); +# else +# if ! @HAVE_STRCASESTR@ +_GL_FUNCDECL_SYS (strcasestr, char *, + (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const char * strcasestr (const char *, const char *); } + extern "C++" { char * strcasestr (char *, const char *); } */ +_GL_CXXALIAS_SYS_CAST2 (strcasestr, + char *, (const char *haystack, const char *needle), + const char *, (const char *haystack, const char *needle)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (strcasestr, char *, (char *haystack, const char *needle)); +_GL_CXXALIASWARN1 (strcasestr, const char *, + (const char *haystack, const char *needle)); +# else +_GL_CXXALIASWARN (strcasestr); +# endif +#elif defined GNULIB_POSIXCHECK +/* strcasestr() does not work with multibyte strings: + It is a glibc extension, and glibc implements it only for unibyte + locales. */ +# undef strcasestr +# if HAVE_RAW_DECL_STRCASESTR +_GL_WARN_ON_USE (strcasestr, "strcasestr does work correctly on character " + "strings in multibyte locales - " + "use mbscasestr if you care about " + "internationalization, or use c-strcasestr if you want " + "a locale independent function"); +# endif +#endif + +/* Parse S into tokens separated by characters in DELIM. + If S is NULL, the saved pointer in SAVE_PTR is used as + the next starting point. For example: + char s[] = "-abc-=-def"; + char *sp; + x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def" + x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL + x = strtok_r(NULL, "=", &sp); // x = NULL + // s = "abc\0-def\0" + + This is a variant of strtok() that is multithread-safe. + + For the POSIX documentation for this function, see: + http://www.opengroup.org/susv3xsh/strtok.html + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + Caveat: It doesn't work with multibyte strings unless all of the delimiter + characters are ASCII characters < 0x30. + + See also strsep(). */ +#if @GNULIB_STRTOK_R@ +# if @REPLACE_STRTOK_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strtok_r +# define strtok_r rpl_strtok_r +# endif +_GL_FUNCDECL_RPL (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr)); +# else +# if @UNDEFINE_STRTOK_R@ || defined GNULIB_POSIXCHECK +# undef strtok_r +# endif +# if ! @HAVE_DECL_STRTOK_R@ +_GL_FUNCDECL_SYS (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr) + _GL_ARG_NONNULL ((2, 3))); +# endif +_GL_CXXALIAS_SYS (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr)); +# endif +_GL_CXXALIASWARN (strtok_r); +# if defined GNULIB_POSIXCHECK +_GL_WARN_ON_USE (strtok_r, "strtok_r cannot work correctly on character " + "strings in multibyte locales - " + "use mbstok_r if you care about internationalization"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strtok_r +# if HAVE_RAW_DECL_STRTOK_R +_GL_WARN_ON_USE (strtok_r, "strtok_r is unportable - " + "use gnulib module strtok_r for portability"); +# endif +#endif + + +/* The following functions are not specified by POSIX. They are gnulib + extensions. */ + +#if @GNULIB_MBSLEN@ +/* Return the number of multibyte characters in the character string STRING. + This considers multibyte characters, unlike strlen, which counts bytes. */ +# ifdef __MirBSD__ /* MirBSD defines mbslen as a macro. Override it. */ +# undef mbslen +# endif +# if @HAVE_MBSLEN@ /* AIX, OSF/1, MirBSD define mbslen already in libc. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbslen rpl_mbslen +# endif +_GL_FUNCDECL_RPL (mbslen, size_t, (const char *string) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mbslen, size_t, (const char *string)); +# else +_GL_FUNCDECL_SYS (mbslen, size_t, (const char *string) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (mbslen, size_t, (const char *string)); +# endif +_GL_CXXALIASWARN (mbslen); +#endif + +#if @GNULIB_MBSNLEN@ +/* Return the number of multibyte characters in the character string starting + at STRING and ending at STRING + LEN. */ +_GL_EXTERN_C size_t mbsnlen (const char *string, size_t len) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1)); +#endif + +#if @GNULIB_MBSCHR@ +/* Locate the first single-byte character C in the character string STRING, + and return a pointer to it. Return NULL if C is not found in STRING. + Unlike strchr(), this function works correctly in multibyte locales with + encodings such as GB18030. */ +# if defined __hpux +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbschr rpl_mbschr /* avoid collision with HP-UX function */ +# endif +_GL_FUNCDECL_RPL (mbschr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mbschr, char *, (const char *string, int c)); +# else +_GL_FUNCDECL_SYS (mbschr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (mbschr, char *, (const char *string, int c)); +# endif +_GL_CXXALIASWARN (mbschr); +#endif + +#if @GNULIB_MBSRCHR@ +/* Locate the last single-byte character C in the character string STRING, + and return a pointer to it. Return NULL if C is not found in STRING. + Unlike strrchr(), this function works correctly in multibyte locales with + encodings such as GB18030. */ +# if defined __hpux || defined __INTERIX +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbsrchr rpl_mbsrchr /* avoid collision with system function */ +# endif +_GL_FUNCDECL_RPL (mbsrchr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mbsrchr, char *, (const char *string, int c)); +# else +_GL_FUNCDECL_SYS (mbsrchr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (mbsrchr, char *, (const char *string, int c)); +# endif +_GL_CXXALIASWARN (mbsrchr); +#endif + +#if @GNULIB_MBSSTR@ +/* Find the first occurrence of the character string NEEDLE in the character + string HAYSTACK. Return NULL if NEEDLE is not found in HAYSTACK. + Unlike strstr(), this function works correctly in multibyte locales with + encodings different from UTF-8. */ +_GL_EXTERN_C char * mbsstr (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSCASECMP@ +/* Compare the character strings S1 and S2, ignoring case, returning less than, + equal to or greater than zero if S1 is lexicographically less than, equal to + or greater than S2. + Note: This function may, in multibyte locales, return 0 for strings of + different lengths! + Unlike strcasecmp(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C int mbscasecmp (const char *s1, const char *s2) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSNCASECMP@ +/* Compare the initial segment of the character string S1 consisting of at most + N characters with the initial segment of the character string S2 consisting + of at most N characters, ignoring case, returning less than, equal to or + greater than zero if the initial segment of S1 is lexicographically less + than, equal to or greater than the initial segment of S2. + Note: This function may, in multibyte locales, return 0 for initial segments + of different lengths! + Unlike strncasecmp(), this function works correctly in multibyte locales. + But beware that N is not a byte count but a character count! */ +_GL_EXTERN_C int mbsncasecmp (const char *s1, const char *s2, size_t n) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSPCASECMP@ +/* Compare the initial segment of the character string STRING consisting of + at most mbslen (PREFIX) characters with the character string PREFIX, + ignoring case. If the two match, return a pointer to the first byte + after this prefix in STRING. Otherwise, return NULL. + Note: This function may, in multibyte locales, return non-NULL if STRING + is of smaller length than PREFIX! + Unlike strncasecmp(), this function works correctly in multibyte + locales. */ +_GL_EXTERN_C char * mbspcasecmp (const char *string, const char *prefix) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSCASESTR@ +/* Find the first occurrence of the character string NEEDLE in the character + string HAYSTACK, using case-insensitive comparison. + Note: This function may, in multibyte locales, return success even if + strlen (haystack) < strlen (needle) ! + Unlike strcasestr(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C char * mbscasestr (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSCSPN@ +/* Find the first occurrence in the character string STRING of any character + in the character string ACCEPT. Return the number of bytes from the + beginning of the string to this occurrence, or to the end of the string + if none exists. + Unlike strcspn(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C size_t mbscspn (const char *string, const char *accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSPBRK@ +/* Find the first occurrence in the character string STRING of any character + in the character string ACCEPT. Return the pointer to it, or NULL if none + exists. + Unlike strpbrk(), this function works correctly in multibyte locales. */ +# if defined __hpux +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbspbrk rpl_mbspbrk /* avoid collision with HP-UX function */ +# endif +_GL_FUNCDECL_RPL (mbspbrk, char *, (const char *string, const char *accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (mbspbrk, char *, (const char *string, const char *accept)); +# else +_GL_FUNCDECL_SYS (mbspbrk, char *, (const char *string, const char *accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_SYS (mbspbrk, char *, (const char *string, const char *accept)); +# endif +_GL_CXXALIASWARN (mbspbrk); +#endif + +#if @GNULIB_MBSSPN@ +/* Find the first occurrence in the character string STRING of any character + not in the character string REJECT. Return the number of bytes from the + beginning of the string to this occurrence, or to the end of the string + if none exists. + Unlike strspn(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C size_t mbsspn (const char *string, const char *reject) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSSEP@ +/* Search the next delimiter (multibyte character listed in the character + string DELIM) starting at the character string *STRINGP. + If one is found, overwrite it with a NUL, and advance *STRINGP to point + to the next multibyte character after it. Otherwise, set *STRINGP to NULL. + If *STRINGP was already NULL, nothing happens. + Return the old value of *STRINGP. + + This is a variant of mbstok_r() that supports empty fields. + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + + See also mbstok_r(). */ +_GL_EXTERN_C char * mbssep (char **stringp, const char *delim) + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSTOK_R@ +/* Parse the character string STRING into tokens separated by characters in + the character string DELIM. + If STRING is NULL, the saved pointer in SAVE_PTR is used as + the next starting point. For example: + char s[] = "-abc-=-def"; + char *sp; + x = mbstok_r(s, "-", &sp); // x = "abc", sp = "=-def" + x = mbstok_r(NULL, "-=", &sp); // x = "def", sp = NULL + x = mbstok_r(NULL, "=", &sp); // x = NULL + // s = "abc\0-def\0" + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + + See also mbssep(). */ +_GL_EXTERN_C char * mbstok_r (char *string, const char *delim, char **save_ptr) + _GL_ARG_NONNULL ((2, 3)); +#endif + +/* Map any int, typically from errno, into an error message. */ +#if @GNULIB_STRERROR@ +# if @REPLACE_STRERROR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strerror +# define strerror rpl_strerror +# endif +_GL_FUNCDECL_RPL (strerror, char *, (int)); +_GL_CXXALIAS_RPL (strerror, char *, (int)); +# else +_GL_CXXALIAS_SYS (strerror, char *, (int)); +# endif +_GL_CXXALIASWARN (strerror); +#elif defined GNULIB_POSIXCHECK +# undef strerror +/* Assume strerror is always declared. */ +_GL_WARN_ON_USE (strerror, "strerror is unportable - " + "use gnulib module strerror to guarantee non-NULL result"); +#endif + +/* Map any int, typically from errno, into an error message. Multithread-safe. + Uses the POSIX declaration, not the glibc declaration. */ +#if @GNULIB_STRERROR_R@ +# if @REPLACE_STRERROR_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strerror_r +# define strerror_r rpl_strerror_r +# endif +_GL_FUNCDECL_RPL (strerror_r, int, (int errnum, char *buf, size_t buflen) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (strerror_r, int, (int errnum, char *buf, size_t buflen)); +# else +# if !@HAVE_DECL_STRERROR_R@ +_GL_FUNCDECL_SYS (strerror_r, int, (int errnum, char *buf, size_t buflen) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (strerror_r, int, (int errnum, char *buf, size_t buflen)); +# endif +# if @HAVE_DECL_STRERROR_R@ +_GL_CXXALIASWARN (strerror_r); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strerror_r +# if HAVE_RAW_DECL_STRERROR_R +_GL_WARN_ON_USE (strerror_r, "strerror_r is unportable - " + "use gnulib module strerror_r-posix for portability"); +# endif +#endif + +#if @GNULIB_STRSIGNAL@ +# if @REPLACE_STRSIGNAL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strsignal rpl_strsignal +# endif +_GL_FUNCDECL_RPL (strsignal, char *, (int __sig)); +_GL_CXXALIAS_RPL (strsignal, char *, (int __sig)); +# else +# if ! @HAVE_DECL_STRSIGNAL@ +_GL_FUNCDECL_SYS (strsignal, char *, (int __sig)); +# endif +/* Need to cast, because on Cygwin 1.5.x systems, the return type is + 'const char *'. */ +_GL_CXXALIAS_SYS_CAST (strsignal, char *, (int __sig)); +# endif +_GL_CXXALIASWARN (strsignal); +#elif defined GNULIB_POSIXCHECK +# undef strsignal +# if HAVE_RAW_DECL_STRSIGNAL +_GL_WARN_ON_USE (strsignal, "strsignal is unportable - " + "use gnulib module strsignal for portability"); +# endif +#endif + +#if @GNULIB_STRVERSCMP@ +# if !@HAVE_STRVERSCMP@ +_GL_FUNCDECL_SYS (strverscmp, int, (const char *, const char *) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (strverscmp, int, (const char *, const char *)); +_GL_CXXALIASWARN (strverscmp); +#elif defined GNULIB_POSIXCHECK +# undef strverscmp +# if HAVE_RAW_DECL_STRVERSCMP +_GL_WARN_ON_USE (strverscmp, "strverscmp is unportable - " + "use gnulib module strverscmp for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_STRING_H */ +#endif /* _@GUARD_PREFIX@_STRING_H */ +#endif diff --git a/grub-core/lib/gnulib/strings.in.h b/grub-core/lib/gnulib/strings.in.h new file mode 100644 index 0000000..21b1a85 --- /dev/null +++ b/grub-core/lib/gnulib/strings.in.h @@ -0,0 +1,122 @@ +/* A substitute <strings.h>. + + Copyright (C) 2007-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _@GUARD_PREFIX@_STRINGS_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* Minix 3.1.8 has a bug: <sys/types.h> must be included before <strings.h>. + But avoid namespace pollution on glibc systems. */ +#if defined __minix && !defined __GLIBC__ +# include <sys/types.h> +#endif + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_STRINGS_H@ +# @INCLUDE_NEXT@ @NEXT_STRINGS_H@ +#endif + +#ifndef _@GUARD_PREFIX@_STRINGS_H +#define _@GUARD_PREFIX@_STRINGS_H + +#if ! @HAVE_DECL_STRNCASECMP@ +/* Get size_t. */ +# include <stddef.h> +#endif + + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +#ifdef __cplusplus +extern "C" { +#endif + + + /* Find the index of the least-significant set bit. */ +#if @GNULIB_FFS@ +# if !@HAVE_FFS@ +_GL_FUNCDECL_SYS (ffs, int, (int i)); +# endif +_GL_CXXALIAS_SYS (ffs, int, (int i)); +_GL_CXXALIASWARN (ffs); +#elif defined GNULIB_POSIXCHECK +# undef ffs +# if HAVE_RAW_DECL_FFS +_GL_WARN_ON_USE (ffs, "ffs is not portable - use the ffs module"); +# endif +#endif + +/* Compare strings S1 and S2, ignoring case, returning less than, equal to or + greater than zero if S1 is lexicographically less than, equal to or greater + than S2. + Note: This function does not work in multibyte locales. */ +#if ! @HAVE_STRCASECMP@ +extern int strcasecmp (char const *s1, char const *s2) + _GL_ARG_NONNULL ((1, 2)); +#endif +#if defined GNULIB_POSIXCHECK +/* strcasecmp() does not work with multibyte strings: + POSIX says that it operates on "strings", and "string" in POSIX is defined + as a sequence of bytes, not of characters. */ +# undef strcasecmp +# if HAVE_RAW_DECL_STRCASECMP +_GL_WARN_ON_USE (strcasecmp, "strcasecmp cannot work correctly on character " + "strings in multibyte locales - " + "use mbscasecmp if you care about " + "internationalization, or use c_strcasecmp , " + "gnulib module c-strcase) if you want a locale " + "independent function"); +# endif +#endif + +/* Compare no more than N bytes of strings S1 and S2, ignoring case, + returning less than, equal to or greater than zero if S1 is + lexicographically less than, equal to or greater than S2. + Note: This function cannot work correctly in multibyte locales. */ +#if ! @HAVE_DECL_STRNCASECMP@ +extern int strncasecmp (char const *s1, char const *s2, size_t n) + _GL_ARG_NONNULL ((1, 2)); +#endif +#if defined GNULIB_POSIXCHECK +/* strncasecmp() does not work with multibyte strings: + POSIX says that it operates on "strings", and "string" in POSIX is defined + as a sequence of bytes, not of characters. */ +# undef strncasecmp +# if HAVE_RAW_DECL_STRNCASECMP +_GL_WARN_ON_USE (strncasecmp, "strncasecmp cannot work correctly on character " + "strings in multibyte locales - " + "use mbsncasecmp or mbspcasecmp if you care about " + "internationalization, or use c_strncasecmp , " + "gnulib module c-strcase) if you want a locale " + "independent function"); +# endif +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _@GUARD_PREFIX@_STRING_H */ +#endif /* _@GUARD_PREFIX@_STRING_H */ diff --git a/grub-core/lib/gnulib/stripslash.c b/grub-core/lib/gnulib/stripslash.c new file mode 100644 index 0000000..dfc15b4 --- /dev/null +++ b/grub-core/lib/gnulib/stripslash.c @@ -0,0 +1,45 @@ +/* stripslash.c -- remove redundant trailing slashes from a file name + + Copyright (C) 1990, 2001, 2003-2006, 2009-2019 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "dirname.h" + +/* Remove trailing slashes from FILE. Return true if a trailing slash + was removed. This is useful when using file name completion from a + shell that adds a "/" after directory names (such as tcsh and + bash), because on symlinks to directories, several system calls + have different semantics according to whether a trailing slash is + present. */ + +bool +strip_trailing_slashes (char *file) +{ + char *base = last_component (file); + char *base_lim; + bool had_slash; + + /* last_component returns "" for file system roots, but we need to turn + "///" into "/". */ + if (! *base) + base = file; + base_lim = base + base_len (base); + had_slash = (*base_lim != '\0'); + *base_lim = '\0'; + return had_slash; +} diff --git a/grub-core/lib/gnulib/strncasecmp.c b/grub-core/lib/gnulib/strncasecmp.c new file mode 100644 index 0000000..034011c --- /dev/null +++ b/grub-core/lib/gnulib/strncasecmp.c @@ -0,0 +1,62 @@ +/* strncasecmp.c -- case insensitive string comparator + Copyright (C) 1998-1999, 2005-2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <string.h> + +#include <ctype.h> +#include <limits.h> + +#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) + +/* Compare no more than N bytes of strings S1 and S2, ignoring case, + returning less than, equal to or greater than zero if S1 is + lexicographically less than, equal to or greater than S2. + Note: This function cannot work correctly in multibyte locales. */ + +int +strncasecmp (const char *s1, const char *s2, size_t n) +{ + register const unsigned char *p1 = (const unsigned char *) s1; + register const unsigned char *p2 = (const unsigned char *) s2; + unsigned char c1, c2; + + if (p1 == p2 || n == 0) + return 0; + + do + { + c1 = TOLOWER (*p1); + c2 = TOLOWER (*p2); + + if (--n == 0 || c1 == '\0') + break; + + ++p1; + ++p2; + } + while (c1 == c2); + + if (UCHAR_MAX <= INT_MAX) + return c1 - c2; + else + /* On machines where 'char' and 'int' are types of the same size, the + difference of two 'unsigned char' values - including the sign bit - + doesn't fit in an 'int'. */ + return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); +} diff --git a/grub-core/lib/gnulib/strndup.c b/grub-core/lib/gnulib/strndup.c new file mode 100644 index 0000000..5b74828 --- /dev/null +++ b/grub-core/lib/gnulib/strndup.c @@ -0,0 +1,36 @@ +/* A replacement function, for systems that lack strndup. + + Copyright (C) 1996-1998, 2001-2003, 2005-2007, 2009-2019 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include <string.h> + +#include <stdlib.h> + +char * +strndup (char const *s, size_t n) +{ + size_t len = strnlen (s, n); + char *new = malloc (len + 1); + + if (new == NULL) + return NULL; + + new[len] = '\0'; + return memcpy (new, s, len); +} diff --git a/grub-core/lib/gnulib/strnlen.c b/grub-core/lib/gnulib/strnlen.c new file mode 100644 index 0000000..9fb6635 --- /dev/null +++ b/grub-core/lib/gnulib/strnlen.c @@ -0,0 +1,30 @@ +/* Find the length of STRING, but scan at most MAXLEN characters. + Copyright (C) 2005-2007, 2009-2019 Free Software Foundation, Inc. + Written by Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include <string.h> + +/* Find the length of STRING, but scan at most MAXLEN characters. + If no '\0' terminator is found in that many characters, return MAXLEN. */ + +size_t +strnlen (const char *string, size_t maxlen) +{ + const char *end = memchr (string, '\0', maxlen); + return end ? (size_t) (end - string) : maxlen; +} diff --git a/grub-core/lib/gnulib/strnlen1.c b/grub-core/lib/gnulib/strnlen1.c new file mode 100644 index 0000000..666a557 --- /dev/null +++ b/grub-core/lib/gnulib/strnlen1.c @@ -0,0 +1,35 @@ +/* Find the length of STRING + 1, but scan at most MAXLEN bytes. + Copyright (C) 2005-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "strnlen1.h" + +#include <string.h> + +/* Find the length of STRING + 1, but scan at most MAXLEN bytes. + If no '\0' terminator is found in that many characters, return MAXLEN. */ +/* This is the same as strnlen (string, maxlen - 1) + 1. */ +size_t +strnlen1 (const char *string, size_t maxlen) +{ + const char *end = (const char *) memchr (string, '\0', maxlen); + if (end != NULL) + return end - string + 1; + else + return maxlen; +} diff --git a/grub-core/lib/gnulib/strnlen1.h b/grub-core/lib/gnulib/strnlen1.h new file mode 100644 index 0000000..5d95244 --- /dev/null +++ b/grub-core/lib/gnulib/strnlen1.h @@ -0,0 +1,40 @@ +/* Find the length of STRING + 1, but scan at most MAXLEN bytes. + Copyright (C) 2005, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _STRNLEN1_H +#define _STRNLEN1_H + +#include <stddef.h> + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Find the length of STRING + 1, but scan at most MAXLEN bytes. + If no '\0' terminator is found in that many characters, return MAXLEN. */ +/* This is the same as strnlen (string, maxlen - 1) + 1. */ +extern size_t strnlen1 (const char *string, size_t maxlen) + _GL_ATTRIBUTE_PURE; + + +#ifdef __cplusplus +} +#endif + + +#endif /* _STRNLEN1_H */ diff --git a/grub-core/lib/gnulib/sys_stat.in.h b/grub-core/lib/gnulib/sys_stat.in.h new file mode 100644 index 0000000..58fa93f --- /dev/null +++ b/grub-core/lib/gnulib/sys_stat.in.h @@ -0,0 +1,816 @@ +/* Provide a more complete sys/stat.h header file. + Copyright (C) 2005-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Eric Blake, Paul Eggert, and Jim Meyering. */ + +/* This file is supposed to be used on platforms where <sys/stat.h> is + incomplete. It is intended to provide definitions and prototypes + needed by an application. Start with what the system provides. */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_system_sys_stat_h +/* Special invocation convention. */ + +#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_SYS_STAT_H + +/* Get nlink_t. + May also define off_t to a 64-bit type on native Windows. */ +#include <sys/types.h> + +/* Get struct timespec. */ +#include <time.h> + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@ + +#ifndef _@GUARD_PREFIX@_SYS_STAT_H +#define _@GUARD_PREFIX@_SYS_STAT_H + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Before doing "#define mkdir rpl_mkdir" below, we need to include all + headers that may declare mkdir(). Native Windows platforms declare mkdir + in <io.h> and/or <direct.h>, not in <unistd.h>. */ +#if defined _WIN32 && ! defined __CYGWIN__ +# include <io.h> /* mingw32, mingw64 */ +# include <direct.h> /* mingw64, MSVC 9 */ +#endif + +/* Native Windows platforms declare umask() in <io.h>. */ +#if 0 && (defined _WIN32 && ! defined __CYGWIN__) +# include <io.h> +#endif + +/* Large File Support on native Windows. */ +#if @WINDOWS_64_BIT_ST_SIZE@ +# define stat _stati64 +#endif + +/* Optionally, override 'struct stat' on native Windows. */ +#if @GNULIB_OVERRIDES_STRUCT_STAT@ + +# undef stat +# if @GNULIB_STAT@ +# define stat rpl_stat +# else + /* Provoke a clear link error if stat() is used as a function and + module 'stat' is not in use. */ +# define stat stat_used_without_requesting_gnulib_module_stat +# endif + +# if !GNULIB_defined_struct_stat +struct stat +{ + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; +# if 0 + uid_t st_uid; +# else /* uid_t is not defined by default on native Windows. */ + short st_uid; +# endif +# if 0 + gid_t st_gid; +# else /* gid_t is not defined by default on native Windows. */ + short st_gid; +# endif + dev_t st_rdev; + off_t st_size; +# if 0 + blksize_t st_blksize; + blkcnt_t st_blocks; +# endif + +# if @WINDOWS_STAT_TIMESPEC@ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +# else + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +# endif +}; +# if @WINDOWS_STAT_TIMESPEC@ +# define st_atime st_atim.tv_sec +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec + /* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_STAT_TIMESPEC 1 +# endif +# define GNULIB_defined_struct_stat 1 +# endif + +/* Other possible values of st_mode. */ +# if 0 +# define _S_IFBLK 0x6000 +# endif +# if 0 +# define _S_IFLNK 0xA000 +# endif +# if 0 +# define _S_IFSOCK 0xC000 +# endif + +#endif + +#ifndef S_IFIFO +# ifdef _S_IFIFO +# define S_IFIFO _S_IFIFO +# endif +#endif + +#ifndef S_IFMT +# define S_IFMT 0170000 +#endif + +#if STAT_MACROS_BROKEN +# undef S_ISBLK +# undef S_ISCHR +# undef S_ISDIR +# undef S_ISFIFO +# undef S_ISLNK +# undef S_ISNAM +# undef S_ISMPB +# undef S_ISMPC +# undef S_ISNWK +# undef S_ISREG +# undef S_ISSOCK +#endif + +#ifndef S_ISBLK +# ifdef S_IFBLK +# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +# else +# define S_ISBLK(m) 0 +# endif +#endif + +#ifndef S_ISCHR +# ifdef S_IFCHR +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +# else +# define S_ISCHR(m) 0 +# endif +#endif + +#ifndef S_ISDIR +# ifdef S_IFDIR +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# else +# define S_ISDIR(m) 0 +# endif +#endif + +#ifndef S_ISDOOR /* Solaris 2.5 and up */ +# define S_ISDOOR(m) 0 +#endif + +#ifndef S_ISFIFO +# ifdef S_IFIFO +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +# else +# define S_ISFIFO(m) 0 +# endif +#endif + +#ifndef S_ISLNK +# ifdef S_IFLNK +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +# else +# define S_ISLNK(m) 0 +# endif +#endif + +#ifndef S_ISMPB /* V7 */ +# ifdef S_IFMPB +# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) +# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) +# else +# define S_ISMPB(m) 0 +# define S_ISMPC(m) 0 +# endif +#endif + +#ifndef S_ISMPX /* AIX */ +# define S_ISMPX(m) 0 +#endif + +#ifndef S_ISNAM /* Xenix */ +# ifdef S_IFNAM +# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM) +# else +# define S_ISNAM(m) 0 +# endif +#endif + +#ifndef S_ISNWK /* HP/UX */ +# ifdef S_IFNWK +# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) +# else +# define S_ISNWK(m) 0 +# endif +#endif + +#ifndef S_ISPORT /* Solaris 10 and up */ +# define S_ISPORT(m) 0 +#endif + +#ifndef S_ISREG +# ifdef S_IFREG +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +# else +# define S_ISREG(m) 0 +# endif +#endif + +#ifndef S_ISSOCK +# ifdef S_IFSOCK +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +# else +# define S_ISSOCK(m) 0 +# endif +#endif + + +#ifndef S_TYPEISMQ +# define S_TYPEISMQ(p) 0 +#endif + +#ifndef S_TYPEISTMO +# define S_TYPEISTMO(p) 0 +#endif + + +#ifndef S_TYPEISSEM +# ifdef S_INSEM +# define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM) +# else +# define S_TYPEISSEM(p) 0 +# endif +#endif + +#ifndef S_TYPEISSHM +# ifdef S_INSHD +# define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD) +# else +# define S_TYPEISSHM(p) 0 +# endif +#endif + +/* high performance ("contiguous data") */ +#ifndef S_ISCTG +# define S_ISCTG(p) 0 +#endif + +/* Cray DMF (data migration facility): off line, with data */ +#ifndef S_ISOFD +# define S_ISOFD(p) 0 +#endif + +/* Cray DMF (data migration facility): off line, with no data */ +#ifndef S_ISOFL +# define S_ISOFL(p) 0 +#endif + +/* 4.4BSD whiteout */ +#ifndef S_ISWHT +# define S_ISWHT(m) 0 +#endif + +/* If any of the following are undefined, + define them to their de facto standard values. */ +#if !S_ISUID +# define S_ISUID 04000 +#endif +#if !S_ISGID +# define S_ISGID 02000 +#endif + +/* S_ISVTX is a common extension to POSIX. */ +#ifndef S_ISVTX +# define S_ISVTX 01000 +#endif + +#if !S_IRUSR && S_IREAD +# define S_IRUSR S_IREAD +#endif +#if !S_IRUSR +# define S_IRUSR 00400 +#endif +#if !S_IRGRP +# define S_IRGRP (S_IRUSR >> 3) +#endif +#if !S_IROTH +# define S_IROTH (S_IRUSR >> 6) +#endif + +#if !S_IWUSR && S_IWRITE +# define S_IWUSR S_IWRITE +#endif +#if !S_IWUSR +# define S_IWUSR 00200 +#endif +#if !S_IWGRP +# define S_IWGRP (S_IWUSR >> 3) +#endif +#if !S_IWOTH +# define S_IWOTH (S_IWUSR >> 6) +#endif + +#if !S_IXUSR && S_IEXEC +# define S_IXUSR S_IEXEC +#endif +#if !S_IXUSR +# define S_IXUSR 00100 +#endif +#if !S_IXGRP +# define S_IXGRP (S_IXUSR >> 3) +#endif +#if !S_IXOTH +# define S_IXOTH (S_IXUSR >> 6) +#endif + +#if !S_IRWXU +# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) +#endif +#if !S_IRWXG +# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) +#endif +#if !S_IRWXO +# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#endif + +/* S_IXUGO is a common extension to POSIX. */ +#if !S_IXUGO +# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) +#endif + +#ifndef S_IRWXUGO +# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) +#endif + +/* Macros for futimens and utimensat. */ +#ifndef UTIME_NOW +# define UTIME_NOW (-1) +# define UTIME_OMIT (-2) +#endif + + +#if @GNULIB_FCHMODAT@ +# if !@HAVE_FCHMODAT@ +_GL_FUNCDECL_SYS (fchmodat, int, + (int fd, char const *file, mode_t mode, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (fchmodat, int, + (int fd, char const *file, mode_t mode, int flag)); +_GL_CXXALIASWARN (fchmodat); +#elif defined GNULIB_POSIXCHECK +# undef fchmodat +# if HAVE_RAW_DECL_FCHMODAT +_GL_WARN_ON_USE (fchmodat, "fchmodat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_FSTAT@ +# if @REPLACE_FSTAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fstat +# define fstat rpl_fstat +# endif +_GL_FUNCDECL_RPL (fstat, int, (int fd, struct stat *buf) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fstat, int, (int fd, struct stat *buf)); +# else +_GL_CXXALIAS_SYS (fstat, int, (int fd, struct stat *buf)); +# endif +_GL_CXXALIASWARN (fstat); +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef fstat +# define fstat fstat_used_without_requesting_gnulib_module_fstat +#elif @WINDOWS_64_BIT_ST_SIZE@ +/* Above, we define stat to _stati64. */ +# define fstat _fstati64 +#elif defined GNULIB_POSIXCHECK +# undef fstat +# if HAVE_RAW_DECL_FSTAT +_GL_WARN_ON_USE (fstat, "fstat has portability problems - " + "use gnulib module fstat for portability"); +# endif +#endif + + +#if @GNULIB_FSTATAT@ +# if @REPLACE_FSTATAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fstatat +# define fstatat rpl_fstatat +# endif +_GL_FUNCDECL_RPL (fstatat, int, + (int fd, char const *name, struct stat *st, int flags) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (fstatat, int, + (int fd, char const *name, struct stat *st, int flags)); +# else +# if !@HAVE_FSTATAT@ +_GL_FUNCDECL_SYS (fstatat, int, + (int fd, char const *name, struct stat *st, int flags) + _GL_ARG_NONNULL ((2, 3))); +# endif +_GL_CXXALIAS_SYS (fstatat, int, + (int fd, char const *name, struct stat *st, int flags)); +# endif +_GL_CXXALIASWARN (fstatat); +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef fstatat +# define fstatat fstatat_used_without_requesting_gnulib_module_fstatat +#elif defined GNULIB_POSIXCHECK +# undef fstatat +# if HAVE_RAW_DECL_FSTATAT +_GL_WARN_ON_USE (fstatat, "fstatat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_FUTIMENS@ +/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our futimens + implementation relies on futimesat, which on Solaris 10 makes an invocation + to futimens that is meant to invoke the libc's futimens(), not gnulib's + futimens(). */ +# if @REPLACE_FUTIMENS@ || (!@HAVE_FUTIMENS@ && defined __sun) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef futimens +# define futimens rpl_futimens +# endif +_GL_FUNCDECL_RPL (futimens, int, (int fd, struct timespec const times[2])); +_GL_CXXALIAS_RPL (futimens, int, (int fd, struct timespec const times[2])); +# else +# if !@HAVE_FUTIMENS@ +_GL_FUNCDECL_SYS (futimens, int, (int fd, struct timespec const times[2])); +# endif +_GL_CXXALIAS_SYS (futimens, int, (int fd, struct timespec const times[2])); +# endif +# if @HAVE_FUTIMENS@ +_GL_CXXALIASWARN (futimens); +# endif +#elif defined GNULIB_POSIXCHECK +# undef futimens +# if HAVE_RAW_DECL_FUTIMENS +_GL_WARN_ON_USE (futimens, "futimens is not portable - " + "use gnulib module futimens for portability"); +# endif +#endif + + +#if @GNULIB_LCHMOD@ +/* Change the mode of FILENAME to MODE, without dereferencing it if FILENAME + denotes a symbolic link. */ +# if !@HAVE_LCHMOD@ +/* The lchmod replacement follows symbolic links. Callers should take + this into account; lchmod should be applied only to arguments that + are known to not be symbolic links. On hosts that lack lchmod, + this can lead to race conditions between the check and the + invocation of lchmod, but we know of no workarounds that are + reliable in general. You might try requesting support for lchmod + from your operating system supplier. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define lchmod chmod +# endif +/* Need to cast, because on mingw, the second parameter of chmod is + int mode. */ +_GL_CXXALIAS_RPL_CAST_1 (lchmod, chmod, int, + (const char *filename, mode_t mode)); +# else +# if 0 /* assume already declared */ +_GL_FUNCDECL_SYS (lchmod, int, (const char *filename, mode_t mode) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (lchmod, int, (const char *filename, mode_t mode)); +# endif +# if @HAVE_LCHMOD@ +_GL_CXXALIASWARN (lchmod); +# endif +#elif defined GNULIB_POSIXCHECK +# undef lchmod +# if HAVE_RAW_DECL_LCHMOD +_GL_WARN_ON_USE (lchmod, "lchmod is unportable - " + "use gnulib module lchmod for portability"); +# endif +#endif + + +#if @GNULIB_LSTAT@ +# if ! @HAVE_LSTAT@ +/* mingw does not support symlinks, therefore it does not have lstat. But + without links, stat does just fine. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define lstat stat +# endif +_GL_CXXALIAS_RPL_1 (lstat, stat, int, (const char *name, struct stat *buf)); +# elif @REPLACE_LSTAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef lstat +# define lstat rpl_lstat +# endif +_GL_FUNCDECL_RPL (lstat, int, (const char *name, struct stat *buf) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (lstat, int, (const char *name, struct stat *buf)); +# else +_GL_CXXALIAS_SYS (lstat, int, (const char *name, struct stat *buf)); +# endif +# if @HAVE_LSTAT@ +_GL_CXXALIASWARN (lstat); +# endif +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef lstat +# define lstat lstat_used_without_requesting_gnulib_module_lstat +#elif defined GNULIB_POSIXCHECK +# undef lstat +# if HAVE_RAW_DECL_LSTAT +_GL_WARN_ON_USE (lstat, "lstat is unportable - " + "use gnulib module lstat for portability"); +# endif +#endif + + +#if @REPLACE_MKDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mkdir +# define mkdir rpl_mkdir +# endif +_GL_FUNCDECL_RPL (mkdir, int, (char const *name, mode_t mode) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); +#else +/* mingw's _mkdir() function has 1 argument, but we pass 2 arguments. + Additionally, it declares _mkdir (and depending on compile flags, an + alias mkdir), only in the nonstandard includes <direct.h> and <io.h>, + which are included above. */ +# if defined _WIN32 && ! defined __CYGWIN__ + +# if !GNULIB_defined_rpl_mkdir +static int +rpl_mkdir (char const *name, mode_t mode) +{ + return _mkdir (name); +} +# define GNULIB_defined_rpl_mkdir 1 +# endif + +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mkdir rpl_mkdir +# endif +_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); +# else +_GL_CXXALIAS_SYS (mkdir, int, (char const *name, mode_t mode)); +# endif +#endif +_GL_CXXALIASWARN (mkdir); + + +#if @GNULIB_MKDIRAT@ +# if !@HAVE_MKDIRAT@ +_GL_FUNCDECL_SYS (mkdirat, int, (int fd, char const *file, mode_t mode) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mkdirat, int, (int fd, char const *file, mode_t mode)); +_GL_CXXALIASWARN (mkdirat); +#elif defined GNULIB_POSIXCHECK +# undef mkdirat +# if HAVE_RAW_DECL_MKDIRAT +_GL_WARN_ON_USE (mkdirat, "mkdirat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_MKFIFO@ +# if @REPLACE_MKFIFO@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mkfifo +# define mkfifo rpl_mkfifo +# endif +_GL_FUNCDECL_RPL (mkfifo, int, (char const *file, mode_t mode) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mkfifo, int, (char const *file, mode_t mode)); +# else +# if !@HAVE_MKFIFO@ +_GL_FUNCDECL_SYS (mkfifo, int, (char const *file, mode_t mode) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkfifo, int, (char const *file, mode_t mode)); +# endif +_GL_CXXALIASWARN (mkfifo); +#elif defined GNULIB_POSIXCHECK +# undef mkfifo +# if HAVE_RAW_DECL_MKFIFO +_GL_WARN_ON_USE (mkfifo, "mkfifo is not portable - " + "use gnulib module mkfifo for portability"); +# endif +#endif + + +#if @GNULIB_MKFIFOAT@ +# if !@HAVE_MKFIFOAT@ +_GL_FUNCDECL_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode)); +_GL_CXXALIASWARN (mkfifoat); +#elif defined GNULIB_POSIXCHECK +# undef mkfifoat +# if HAVE_RAW_DECL_MKFIFOAT +_GL_WARN_ON_USE (mkfifoat, "mkfifoat is not portable - " + "use gnulib module mkfifoat for portability"); +# endif +#endif + + +#if @GNULIB_MKNOD@ +# if @REPLACE_MKNOD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mknod +# define mknod rpl_mknod +# endif +_GL_FUNCDECL_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev)); +# else +# if !@HAVE_MKNOD@ +_GL_FUNCDECL_SYS (mknod, int, (char const *file, mode_t mode, dev_t dev) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on OSF/1 5.1, the third parameter is '...'. */ +_GL_CXXALIAS_SYS_CAST (mknod, int, (char const *file, mode_t mode, dev_t dev)); +# endif +_GL_CXXALIASWARN (mknod); +#elif defined GNULIB_POSIXCHECK +# undef mknod +# if HAVE_RAW_DECL_MKNOD +_GL_WARN_ON_USE (mknod, "mknod is not portable - " + "use gnulib module mknod for portability"); +# endif +#endif + + +#if @GNULIB_MKNODAT@ +# if !@HAVE_MKNODAT@ +_GL_FUNCDECL_SYS (mknodat, int, + (int fd, char const *file, mode_t mode, dev_t dev) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mknodat, int, + (int fd, char const *file, mode_t mode, dev_t dev)); +_GL_CXXALIASWARN (mknodat); +#elif defined GNULIB_POSIXCHECK +# undef mknodat +# if HAVE_RAW_DECL_MKNODAT +_GL_WARN_ON_USE (mknodat, "mknodat is not portable - " + "use gnulib module mkfifoat for portability"); +# endif +#endif + + +#if @GNULIB_STAT@ +# if @REPLACE_STAT@ +# if !@GNULIB_OVERRIDES_STRUCT_STAT@ + /* We can't use the object-like #define stat rpl_stat, because of + struct stat. This means that rpl_stat will not be used if the user + does (stat)(a,b). Oh well. */ +# if defined _AIX && defined stat && defined _LARGE_FILES + /* With _LARGE_FILES defined, AIX (only) defines stat to stat64, + so we have to replace stat64() instead of stat(). */ +# undef stat64 +# define stat64(name, st) rpl_stat (name, st) +# elif @WINDOWS_64_BIT_ST_SIZE@ + /* Above, we define stat to _stati64. */ +# if defined __MINGW32__ && defined _stati64 +# ifndef _USE_32BIT_TIME_T + /* The system headers define _stati64 to _stat64. */ +# undef _stat64 +# define _stat64(name, st) rpl_stat (name, st) +# endif +# elif defined _MSC_VER && defined _stati64 +# ifdef _USE_32BIT_TIME_T + /* The system headers define _stati64 to _stat32i64. */ +# undef _stat32i64 +# define _stat32i64(name, st) rpl_stat (name, st) +# else + /* The system headers define _stati64 to _stat64. */ +# undef _stat64 +# define _stat64(name, st) rpl_stat (name, st) +# endif +# else +# undef _stati64 +# define _stati64(name, st) rpl_stat (name, st) +# endif +# elif defined __MINGW32__ && defined stat +# ifdef _USE_32BIT_TIME_T + /* The system headers define stat to _stat32i64. */ +# undef _stat32i64 +# define _stat32i64(name, st) rpl_stat (name, st) +# else + /* The system headers define stat to _stat64. */ +# undef _stat64 +# define _stat64(name, st) rpl_stat (name, st) +# endif +# elif defined _MSC_VER && defined stat +# ifdef _USE_32BIT_TIME_T + /* The system headers define stat to _stat32. */ +# undef _stat32 +# define _stat32(name, st) rpl_stat (name, st) +# else + /* The system headers define stat to _stat64i32. */ +# undef _stat64i32 +# define _stat64i32(name, st) rpl_stat (name, st) +# endif +# else /* !(_AIX || __MINGW32__ || _MSC_VER) */ +# undef stat +# define stat(name, st) rpl_stat (name, st) +# endif /* !_LARGE_FILES */ +# endif /* !@GNULIB_OVERRIDES_STRUCT_STAT@ */ +_GL_EXTERN_C int stat (const char *name, struct stat *buf) + _GL_ARG_NONNULL ((1, 2)); +# endif +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +/* see above: + #define stat stat_used_without_requesting_gnulib_module_stat + */ +#elif defined GNULIB_POSIXCHECK +# undef stat +# if HAVE_RAW_DECL_STAT +_GL_WARN_ON_USE (stat, "stat is unportable - " + "use gnulib module stat for portability"); +# endif +#endif + + +#if @GNULIB_UTIMENSAT@ +/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our utimensat + implementation relies on futimesat, which on Solaris 10 makes an invocation + to utimensat that is meant to invoke the libc's utimensat(), not gnulib's + utimensat(). */ +# if @REPLACE_UTIMENSAT@ || (!@HAVE_UTIMENSAT@ && defined __sun) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef utimensat +# define utimensat rpl_utimensat +# endif +_GL_FUNCDECL_RPL (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag)); +# else +# if !@HAVE_UTIMENSAT@ +_GL_FUNCDECL_SYS (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag)); +# endif +# if @HAVE_UTIMENSAT@ +_GL_CXXALIASWARN (utimensat); +# endif +#elif defined GNULIB_POSIXCHECK +# undef utimensat +# if HAVE_RAW_DECL_UTIMENSAT +_GL_WARN_ON_USE (utimensat, "utimensat is not portable - " + "use gnulib module utimensat for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_SYS_STAT_H */ +#endif /* _@GUARD_PREFIX@_SYS_STAT_H */ +#endif diff --git a/grub-core/lib/gnulib/sys_types.in.h b/grub-core/lib/gnulib/sys_types.in.h new file mode 100644 index 0000000..237e206 --- /dev/null +++ b/grub-core/lib/gnulib/sys_types.in.h @@ -0,0 +1,106 @@ +/* Provide a more complete sys/types.h. + + Copyright (C) 2011-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined _WIN32 && !defined __CYGWIN__ \ + && (defined __need_off_t || defined __need___off64_t \ + || defined __need_ssize_t || defined __need_time_t) + +/* Special invocation convention inside mingw header files. */ + +#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_SYS_TYPES_H + +/* The include_next requires a split double-inclusion guard. */ +# define _GL_INCLUDING_SYS_TYPES_H +#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@ +# undef _GL_INCLUDING_SYS_TYPES_H + +#ifndef _@GUARD_PREFIX@_SYS_TYPES_H +#define _@GUARD_PREFIX@_SYS_TYPES_H + +/* Override off_t if Large File Support is requested on native Windows. */ +#if @WINDOWS_64_BIT_OFF_T@ +/* Same as int64_t in <stdint.h>. */ +# if defined _MSC_VER +# define off_t __int64 +# else +# define off_t long long int +# endif +/* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_64_BIT_OFF_T 1 +#endif + +/* Override dev_t and ino_t if distinguishable inodes support is requested + on native Windows. */ +#if @WINDOWS_STAT_INODES@ + +# if @WINDOWS_STAT_INODES@ == 2 +/* Experimental, not useful in Windows 10. */ + +/* Define dev_t to a 64-bit type. */ +# if !defined GNULIB_defined_dev_t +typedef unsigned long long int rpl_dev_t; +# undef dev_t +# define dev_t rpl_dev_t +# define GNULIB_defined_dev_t 1 +# endif + +/* Define ino_t to a 128-bit type. */ +# if !defined GNULIB_defined_ino_t +/* MSVC does not have a 128-bit integer type. + GCC has a 128-bit integer type __int128, but only on 64-bit targets. */ +typedef struct { unsigned long long int _gl_ino[2]; } rpl_ino_t; +# undef ino_t +# define ino_t rpl_ino_t +# define GNULIB_defined_ino_t 1 +# endif + +# else /* @WINDOWS_STAT_INODES@ == 1 */ + +/* Define ino_t to a 64-bit type. */ +# if !defined GNULIB_defined_ino_t +typedef unsigned long long int rpl_ino_t; +# undef ino_t +# define ino_t rpl_ino_t +# define GNULIB_defined_ino_t 1 +# endif + +# endif + +/* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_STAT_INODES @WINDOWS_STAT_INODES@ + +#endif + +/* MSVC 9 defines size_t in <stddef.h>, not in <sys/types.h>. */ +/* But avoid namespace pollution on glibc systems. */ +#if (defined _WIN32 && ! defined __CYGWIN__) && ! defined __GLIBC__ +# include <stddef.h> +#endif + +#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ +#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ +#endif /* __need_XXX */ diff --git a/grub-core/lib/gnulib/sysexits.in.h b/grub-core/lib/gnulib/sysexits.in.h new file mode 100644 index 0000000..7043a0a --- /dev/null +++ b/grub-core/lib/gnulib/sysexits.in.h @@ -0,0 +1,72 @@ +/* exit() exit codes for some BSD system programs. + Copyright (C) 2003, 2006-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Simon Josefsson based on sysexits(3) man page */ + +#ifndef _@GUARD_PREFIX@_SYSEXITS_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if @HAVE_SYSEXITS_H@ + +/* IRIX 6.5 has an <unistd.h> that defines a macro EX_OK with a nonzero + value. Override it. See + <https://lists.gnu.org/r/bug-gnulib/2007-03/msg00361.html> */ +# ifdef __sgi +# include <unistd.h> +# undef EX_OK +# endif + +/* The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_SYSEXITS_H@ + +/* HP-UX 11 <sysexits.h> ends at EX_NOPERM. */ +# ifndef EX_CONFIG +# define EX_CONFIG 78 +# endif + +#endif + +#ifndef _@GUARD_PREFIX@_SYSEXITS_H +#define _@GUARD_PREFIX@_SYSEXITS_H + +#if !@HAVE_SYSEXITS_H@ + +# define EX_OK 0 /* same value as EXIT_SUCCESS */ + +# define EX_USAGE 64 +# define EX_DATAERR 65 +# define EX_NOINPUT 66 +# define EX_NOUSER 67 +# define EX_NOHOST 68 +# define EX_UNAVAILABLE 69 +# define EX_SOFTWARE 70 +# define EX_OSERR 71 +# define EX_OSFILE 72 +# define EX_CANTCREAT 73 +# define EX_IOERR 74 +# define EX_TEMPFAIL 75 +# define EX_PROTOCOL 76 +# define EX_NOPERM 77 +# define EX_CONFIG 78 + +#endif + +#endif /* _@GUARD_PREFIX@_SYSEXITS_H */ +#endif /* _@GUARD_PREFIX@_SYSEXITS_H */ diff --git a/grub-core/lib/gnulib/time.in.h b/grub-core/lib/gnulib/time.in.h new file mode 100644 index 0000000..dd3b212 --- /dev/null +++ b/grub-core/lib/gnulib/time.in.h @@ -0,0 +1,350 @@ +/* A more-standard <time.h>. + + Copyright (C) 2007-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* Don't get in the way of glibc when it includes time.h merely to + declare a few standard symbols, rather than to declare all the + symbols. (However, skip this for MinGW as it treats __need_time_t + incompatibly.) Also, Solaris 8 <time.h> eventually includes itself + recursively; if that is happening, just include the system <time.h> + without adding our own declarations. */ +#if (((defined __need_time_t || defined __need_clock_t \ + || defined __need_timespec) \ + && !defined __MINGW32__) \ + || defined _@GUARD_PREFIX@_TIME_H) + +# @INCLUDE_NEXT@ @NEXT_TIME_H@ + +#else + +# define _@GUARD_PREFIX@_TIME_H + +# @INCLUDE_NEXT@ @NEXT_TIME_H@ + +/* NetBSD 5.0 mis-defines NULL. */ +# include <stddef.h> + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Some systems don't define struct timespec (e.g., AIX 4.1). + Or they define it with the wrong member names or define it in <sys/time.h> + (e.g., FreeBSD circa 1997). Stock Mingw prior to 3.0 does not define it, + but the pthreads-win32 library defines it in <pthread.h>. */ +# if ! @TIME_H_DEFINES_STRUCT_TIMESPEC@ +# if @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +# include <sys/time.h> +# elif @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +# include <pthread.h> +# elif @UNISTD_H_DEFINES_STRUCT_TIMESPEC@ +# include <unistd.h> +# else + +# ifdef __cplusplus +extern "C" { +# endif + +# if !GNULIB_defined_struct_timespec +# undef timespec +# define timespec rpl_timespec +struct timespec +{ + time_t tv_sec; + long int tv_nsec; +}; +# define GNULIB_defined_struct_timespec 1 +# endif + +# ifdef __cplusplus +} +# endif + +# endif +# endif + +# if !GNULIB_defined_struct_time_t_must_be_integral +/* Per http://austingroupbugs.net/view.php?id=327, POSIX requires + time_t to be an integer type, even though C99 permits floating + point. We don't know of any implementation that uses floating + point, and it is much easier to write code that doesn't have to + worry about that corner case, so we force the issue. */ +struct __time_t_must_be_integral { + unsigned int __floating_time_t_unsupported : (time_t) 1; +}; +# define GNULIB_defined_struct_time_t_must_be_integral 1 +# endif + +/* Sleep for at least RQTP seconds unless interrupted, If interrupted, + return -1 and store the remaining time into RMTP. See + <http://www.opengroup.org/susv3xsh/nanosleep.html>. */ +# if @GNULIB_NANOSLEEP@ +# if @REPLACE_NANOSLEEP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define nanosleep rpl_nanosleep +# endif +_GL_FUNCDECL_RPL (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp)); +# else +# if ! @HAVE_NANOSLEEP@ +_GL_FUNCDECL_SYS (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp)); +# endif +_GL_CXXALIASWARN (nanosleep); +# endif + +/* Initialize time conversion information. */ +# if @GNULIB_TZSET@ +# if @REPLACE_TZSET@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef tzset +# define tzset rpl_tzset +# endif +_GL_FUNCDECL_RPL (tzset, void, (void)); +_GL_CXXALIAS_RPL (tzset, void, (void)); +# else +# if ! @HAVE_TZSET@ +_GL_FUNCDECL_SYS (tzset, void, (void)); +# endif +_GL_CXXALIAS_SYS (tzset, void, (void)); +# endif +_GL_CXXALIASWARN (tzset); +# endif + +/* Return the 'time_t' representation of TP and normalize TP. */ +# if @GNULIB_MKTIME@ +# if @REPLACE_MKTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mktime rpl_mktime +# endif +_GL_FUNCDECL_RPL (mktime, time_t, (struct tm *__tp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mktime, time_t, (struct tm *__tp)); +# else +_GL_CXXALIAS_SYS (mktime, time_t, (struct tm *__tp)); +# endif +_GL_CXXALIASWARN (mktime); +# endif + +/* Convert TIMER to RESULT, assuming local time and UTC respectively. See + <http://www.opengroup.org/susv3xsh/localtime_r.html> and + <http://www.opengroup.org/susv3xsh/gmtime_r.html>. */ +# if @GNULIB_TIME_R@ +# if @REPLACE_LOCALTIME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef localtime_r +# define localtime_r rpl_localtime_r +# endif +_GL_FUNCDECL_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# else +# if ! @HAVE_DECL_LOCALTIME_R@ +_GL_FUNCDECL_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# endif +# if @HAVE_DECL_LOCALTIME_R@ +_GL_CXXALIASWARN (localtime_r); +# endif +# if @REPLACE_LOCALTIME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gmtime_r +# define gmtime_r rpl_gmtime_r +# endif +_GL_FUNCDECL_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# else +# if ! @HAVE_DECL_LOCALTIME_R@ +_GL_FUNCDECL_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# endif +# if @HAVE_DECL_LOCALTIME_R@ +_GL_CXXALIASWARN (gmtime_r); +# endif +# endif + +/* Convert TIMER to RESULT, assuming local time and UTC respectively. See + <http://www.opengroup.org/susv3xsh/localtime.html> and + <http://www.opengroup.org/susv3xsh/gmtime.html>. */ +# if @GNULIB_LOCALTIME@ || @REPLACE_LOCALTIME@ +# if @REPLACE_LOCALTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef localtime +# define localtime rpl_localtime +# endif +_GL_FUNCDECL_RPL (localtime, struct tm *, (time_t const *__timer) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (localtime, struct tm *, (time_t const *__timer)); +# else +_GL_CXXALIAS_SYS (localtime, struct tm *, (time_t const *__timer)); +# endif +_GL_CXXALIASWARN (localtime); +# endif + +# if 0 || @REPLACE_GMTIME@ +# if @REPLACE_GMTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gmtime +# define gmtime rpl_gmtime +# endif +_GL_FUNCDECL_RPL (gmtime, struct tm *, (time_t const *__timer) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (gmtime, struct tm *, (time_t const *__timer)); +# else +_GL_CXXALIAS_SYS (gmtime, struct tm *, (time_t const *__timer)); +# endif +_GL_CXXALIASWARN (gmtime); +# endif + +/* Parse BUF as a timestamp, assuming FORMAT specifies its layout, and store + the resulting broken-down time into TM. See + <http://www.opengroup.org/susv3xsh/strptime.html>. */ +# if @GNULIB_STRPTIME@ +# if ! @HAVE_STRPTIME@ +_GL_FUNCDECL_SYS (strptime, char *, (char const *restrict __buf, + char const *restrict __format, + struct tm *restrict __tm) + _GL_ARG_NONNULL ((1, 2, 3))); +# endif +_GL_CXXALIAS_SYS (strptime, char *, (char const *restrict __buf, + char const *restrict __format, + struct tm *restrict __tm)); +_GL_CXXALIASWARN (strptime); +# endif + +/* Convert *TP to a date and time string. See + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/ctime.html>. */ +# if @GNULIB_CTIME@ +# if @REPLACE_CTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define ctime rpl_ctime +# endif +_GL_FUNCDECL_RPL (ctime, char *, (time_t const *__tp) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (ctime, char *, (time_t const *__tp)); +# else +_GL_CXXALIAS_SYS (ctime, char *, (time_t const *__tp)); +# endif +_GL_CXXALIASWARN (ctime); +# endif + +/* Convert *TP to a date and time string. See + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/strftime.html>. */ +# if @GNULIB_STRFTIME@ +# if @REPLACE_STRFTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strftime rpl_strftime +# endif +_GL_FUNCDECL_RPL (strftime, size_t, (char *__buf, size_t __bufsize, + const char *__fmt, const struct tm *__tp) + _GL_ARG_NONNULL ((1, 3, 4))); +_GL_CXXALIAS_RPL (strftime, size_t, (char *__buf, size_t __bufsize, + const char *__fmt, const struct tm *__tp)); +# else +_GL_CXXALIAS_SYS (strftime, size_t, (char *__buf, size_t __bufsize, + const char *__fmt, const struct tm *__tp)); +# endif +_GL_CXXALIASWARN (strftime); +# endif + +# if defined _GNU_SOURCE && @GNULIB_TIME_RZ@ && ! @HAVE_TIMEZONE_T@ +typedef struct tm_zone *timezone_t; +_GL_FUNCDECL_SYS (tzalloc, timezone_t, (char const *__name)); +_GL_CXXALIAS_SYS (tzalloc, timezone_t, (char const *__name)); +_GL_FUNCDECL_SYS (tzfree, void, (timezone_t __tz)); +_GL_CXXALIAS_SYS (tzfree, void, (timezone_t __tz)); +_GL_FUNCDECL_SYS (localtime_rz, struct tm *, + (timezone_t __tz, time_t const *restrict __timer, + struct tm *restrict __result) _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_SYS (localtime_rz, struct tm *, + (timezone_t __tz, time_t const *restrict __timer, + struct tm *restrict __result)); +_GL_FUNCDECL_SYS (mktime_z, time_t, + (timezone_t __tz, struct tm *restrict __result) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_SYS (mktime_z, time_t, + (timezone_t __tz, struct tm *restrict __result)); +# endif + +/* Convert TM to a time_t value, assuming UTC. */ +# if @GNULIB_TIMEGM@ +# if @REPLACE_TIMEGM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef timegm +# define timegm rpl_timegm +# endif +_GL_FUNCDECL_RPL (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (timegm, time_t, (struct tm *__tm)); +# else +# if ! @HAVE_TIMEGM@ +_GL_FUNCDECL_SYS (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (timegm, time_t, (struct tm *__tm)); +# endif +_GL_CXXALIASWARN (timegm); +# endif + +/* Encourage applications to avoid unsafe functions that can overrun + buffers when given outlandish struct tm values. Portable + applications should use strftime (or even sprintf) instead. */ +# if defined GNULIB_POSIXCHECK +# undef asctime +_GL_WARN_ON_USE (asctime, "asctime can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif +# if defined GNULIB_POSIXCHECK +# undef asctime_r +_GL_WARN_ON_USE (asctime, "asctime_r can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif +# if defined GNULIB_POSIXCHECK +# undef ctime +_GL_WARN_ON_USE (asctime, "ctime can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif +# if defined GNULIB_POSIXCHECK +# undef ctime_r +_GL_WARN_ON_USE (asctime, "ctime_r can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif + +#endif diff --git a/grub-core/lib/gnulib/unistd--.h b/grub-core/lib/gnulib/unistd--.h new file mode 100644 index 0000000..1268854 --- /dev/null +++ b/grub-core/lib/gnulib/unistd--.h @@ -0,0 +1,32 @@ +/* Like unistd.h, but redefine some names to avoid glitches. + + Copyright (C) 2005, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +#include <unistd.h> +#include "unistd-safer.h" + +#undef dup +#define dup dup_safer + +#undef pipe +#define pipe pipe_safer + +#if GNULIB_PIPE2_SAFER +# undef pipe2 +# define pipe2 pipe2_safer +#endif diff --git a/grub-core/lib/gnulib/unistd-safer.h b/grub-core/lib/gnulib/unistd-safer.h new file mode 100644 index 0000000..8eebffc --- /dev/null +++ b/grub-core/lib/gnulib/unistd-safer.h @@ -0,0 +1,31 @@ +/* Invoke unistd-like functions, but avoid some glitches. + + Copyright (C) 2001, 2003, 2005, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert and Eric Blake. */ + +int dup_safer (int); +int fd_safer (int); +int pipe_safer (int[2]); + +#if GNULIB_FD_SAFER_FLAG +int dup_safer_flag (int, int); +int fd_safer_flag (int, int); +#endif + +#if GNULIB_PIPE2_SAFER +int pipe2_safer (int[2], int); +#endif diff --git a/grub-core/lib/gnulib/unistd.c b/grub-core/lib/gnulib/unistd.c new file mode 100644 index 0000000..72bad1c --- /dev/null +++ b/grub-core/lib/gnulib/unistd.c @@ -0,0 +1,4 @@ +#include <config.h> +#define _GL_UNISTD_INLINE _GL_EXTERN_INLINE +#include "unistd.h" +typedef int dummy; diff --git a/grub-core/lib/gnulib/unistd.in.h b/grub-core/lib/gnulib/unistd.in.h new file mode 100644 index 0000000..a10ca28 --- /dev/null +++ b/grub-core/lib/gnulib/unistd.in.h @@ -0,0 +1,1668 @@ +/* Substitute for and wrapper around <unistd.h>. + Copyright (C) 2003-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _@GUARD_PREFIX@_UNISTD_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#ifdef _GL_INCLUDING_UNISTD_H +/* Special invocation convention: + - On Mac OS X 10.3.9 we have a sequence of nested includes + <unistd.h> -> <signal.h> -> <pthread.h> -> <unistd.h> + In this situation, the functions are not yet declared, therefore we cannot + provide the C++ aliases. */ + +#@INCLUDE_NEXT@ @NEXT_UNISTD_H@ + +#else +/* Normal invocation convention. */ + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_UNISTD_H@ +# define _GL_INCLUDING_UNISTD_H +# @INCLUDE_NEXT@ @NEXT_UNISTD_H@ +# undef _GL_INCLUDING_UNISTD_H +#endif + +/* Get all possible declarations of gethostname(). */ +#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ \ + && !defined _GL_INCLUDING_WINSOCK2_H +# define _GL_INCLUDING_WINSOCK2_H +# include <winsock2.h> +# undef _GL_INCLUDING_WINSOCK2_H +#endif + +#if !defined _@GUARD_PREFIX@_UNISTD_H && !defined _GL_INCLUDING_WINSOCK2_H +#define _@GUARD_PREFIX@_UNISTD_H + +/* NetBSD 5.0 mis-defines NULL. Also get size_t. */ +#include <stddef.h> + +/* mingw doesn't define the SEEK_* or *_FILENO macros in <unistd.h>. */ +/* MSVC declares 'unlink' in <stdio.h>, not in <unistd.h>. We must include + it before we #define unlink rpl_unlink. */ +/* Cygwin 1.7.1 declares symlinkat in <stdio.h>, not in <unistd.h>. */ +/* But avoid namespace pollution on glibc systems. */ +#if (!(defined SEEK_CUR && defined SEEK_END && defined SEEK_SET) \ + || ((@GNULIB_UNLINK@ || defined GNULIB_POSIXCHECK) \ + && (defined _WIN32 && ! defined __CYGWIN__)) \ + || ((@GNULIB_SYMLINKAT@ || defined GNULIB_POSIXCHECK) \ + && defined __CYGWIN__)) \ + && ! defined __GLIBC__ +# include <stdio.h> +#endif + +/* Cygwin 1.7.1 declares unlinkat in <fcntl.h>, not in <unistd.h>. */ +/* But avoid namespace pollution on glibc systems. */ +#if (@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) && defined __CYGWIN__ \ + && ! defined __GLIBC__ +# include <fcntl.h> +#endif + +/* mingw fails to declare _exit in <unistd.h>. */ +/* mingw, MSVC, BeOS, Haiku declare environ in <stdlib.h>, not in + <unistd.h>. */ +/* Solaris declares getcwd not only in <unistd.h> but also in <stdlib.h>. */ +/* OSF Tru64 Unix cannot see gnulib rpl_strtod when system <stdlib.h> is + included here. */ +/* But avoid namespace pollution on glibc systems. */ +#if !defined __GLIBC__ && !defined __osf__ +# define __need_system_stdlib_h +# include <stdlib.h> +# undef __need_system_stdlib_h +#endif + +/* Native Windows platforms declare chdir, getcwd, rmdir in + <io.h> and/or <direct.h>, not in <unistd.h>. + They also declare access(), chmod(), close(), dup(), dup2(), isatty(), + lseek(), read(), unlink(), write() in <io.h>. */ +#if ((@GNULIB_CHDIR@ || @GNULIB_GETCWD@ || @GNULIB_RMDIR@ \ + || defined GNULIB_POSIXCHECK) \ + && (defined _WIN32 && ! defined __CYGWIN__)) +# include <io.h> /* mingw32, mingw64 */ +# include <direct.h> /* mingw64, MSVC 9 */ +#elif (@GNULIB_CLOSE@ || @GNULIB_DUP@ || @GNULIB_DUP2@ || @GNULIB_ISATTY@ \ + || @GNULIB_LSEEK@ || @GNULIB_READ@ || @GNULIB_UNLINK@ || @GNULIB_WRITE@ \ + || defined GNULIB_POSIXCHECK) \ + && (defined _WIN32 && ! defined __CYGWIN__) +# include <io.h> +#endif + +/* AIX and OSF/1 5.1 declare getdomainname in <netdb.h>, not in <unistd.h>. + NonStop Kernel declares gethostname in <netdb.h>, not in <unistd.h>. */ +/* But avoid namespace pollution on glibc systems. */ +#if ((@GNULIB_GETDOMAINNAME@ && (defined _AIX || defined __osf__)) \ + || (@GNULIB_GETHOSTNAME@ && defined __TANDEM)) \ + && !defined __GLIBC__ +# include <netdb.h> +#endif + +/* MSVC defines off_t in <sys/types.h>. + May also define off_t to a 64-bit type on native Windows. */ +#if !@HAVE_UNISTD_H@ || @WINDOWS_64_BIT_OFF_T@ +/* Get off_t. */ +# include <sys/types.h> +#endif + +#if (@GNULIB_READ@ || @GNULIB_WRITE@ \ + || @GNULIB_READLINK@ || @GNULIB_READLINKAT@ \ + || @GNULIB_PREAD@ || @GNULIB_PWRITE@ || defined GNULIB_POSIXCHECK) +/* Get ssize_t. */ +# include <sys/types.h> +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Get getopt(), optarg, optind, opterr, optopt. */ +#if @GNULIB_UNISTD_H_GETOPT@ && !defined _GL_SYSTEM_GETOPT +# include <getopt-cdefs.h> +# include <getopt-pfx-core.h> +#endif + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_UNISTD_INLINE +# define _GL_UNISTD_INLINE _GL_INLINE +#endif + +/* Hide some function declarations from <winsock2.h>. */ + +#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ +# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef socket +# define socket socket_used_without_including_sys_socket_h +# undef connect +# define connect connect_used_without_including_sys_socket_h +# undef accept +# define accept accept_used_without_including_sys_socket_h +# undef bind +# define bind bind_used_without_including_sys_socket_h +# undef getpeername +# define getpeername getpeername_used_without_including_sys_socket_h +# undef getsockname +# define getsockname getsockname_used_without_including_sys_socket_h +# undef getsockopt +# define getsockopt getsockopt_used_without_including_sys_socket_h +# undef listen +# define listen listen_used_without_including_sys_socket_h +# undef recv +# define recv recv_used_without_including_sys_socket_h +# undef send +# define send send_used_without_including_sys_socket_h +# undef recvfrom +# define recvfrom recvfrom_used_without_including_sys_socket_h +# undef sendto +# define sendto sendto_used_without_including_sys_socket_h +# undef setsockopt +# define setsockopt setsockopt_used_without_including_sys_socket_h +# undef shutdown +# define shutdown shutdown_used_without_including_sys_socket_h +# else + _GL_WARN_ON_USE (socket, + "socket() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (connect, + "connect() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (accept, + "accept() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (bind, + "bind() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (getpeername, + "getpeername() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (getsockname, + "getsockname() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (getsockopt, + "getsockopt() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (listen, + "listen() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (recv, + "recv() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (send, + "send() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (recvfrom, + "recvfrom() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (sendto, + "sendto() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (setsockopt, + "setsockopt() used without including <sys/socket.h>"); + _GL_WARN_ON_USE (shutdown, + "shutdown() used without including <sys/socket.h>"); +# endif +# endif +# if !defined _@GUARD_PREFIX@_SYS_SELECT_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef select +# define select select_used_without_including_sys_select_h +# else + _GL_WARN_ON_USE (select, + "select() used without including <sys/select.h>"); +# endif +# endif +#endif + + +/* OS/2 EMX lacks these macros. */ +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif + +/* Ensure *_OK macros exist. */ +#ifndef F_OK +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 +#endif + + +/* Declare overridden functions. */ + + +#if defined GNULIB_POSIXCHECK +/* The access() function is a security risk. */ +_GL_WARN_ON_USE (access, "the access function is a security risk - " + "use the gnulib module faccessat instead"); +#endif + + +#if @GNULIB_CHDIR@ +_GL_CXXALIAS_SYS (chdir, int, (const char *file) _GL_ARG_NONNULL ((1))); +_GL_CXXALIASWARN (chdir); +#elif defined GNULIB_POSIXCHECK +# undef chdir +# if HAVE_RAW_DECL_CHDIR +_GL_WARN_ON_USE (chown, "chdir is not always in <unistd.h> - " + "use gnulib module chdir for portability"); +# endif +#endif + + +#if @GNULIB_CHOWN@ +/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE + to GID (if GID is not -1). Follow symbolic links. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html. */ +# if @REPLACE_CHOWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef chown +# define chown rpl_chown +# endif +_GL_FUNCDECL_RPL (chown, int, (const char *file, uid_t uid, gid_t gid) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (chown, int, (const char *file, uid_t uid, gid_t gid)); +# else +# if !@HAVE_CHOWN@ +_GL_FUNCDECL_SYS (chown, int, (const char *file, uid_t uid, gid_t gid) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (chown, int, (const char *file, uid_t uid, gid_t gid)); +# endif +_GL_CXXALIASWARN (chown); +#elif defined GNULIB_POSIXCHECK +# undef chown +# if HAVE_RAW_DECL_CHOWN +_GL_WARN_ON_USE (chown, "chown fails to follow symlinks on some systems and " + "doesn't treat a uid or gid of -1 on some systems - " + "use gnulib module chown for portability"); +# endif +#endif + + +#if @GNULIB_CLOSE@ +# if @REPLACE_CLOSE@ +/* Automatically included by modules that need a replacement for close. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef close +# define close rpl_close +# endif +_GL_FUNCDECL_RPL (close, int, (int fd)); +_GL_CXXALIAS_RPL (close, int, (int fd)); +# else +_GL_CXXALIAS_SYS (close, int, (int fd)); +# endif +_GL_CXXALIASWARN (close); +#elif @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +# undef close +# define close close_used_without_requesting_gnulib_module_close +#elif defined GNULIB_POSIXCHECK +# undef close +/* Assume close is always declared. */ +_GL_WARN_ON_USE (close, "close does not portably work on sockets - " + "use gnulib module close for portability"); +#endif + + +#if @GNULIB_DUP@ +# if @REPLACE_DUP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dup rpl_dup +# endif +_GL_FUNCDECL_RPL (dup, int, (int oldfd)); +_GL_CXXALIAS_RPL (dup, int, (int oldfd)); +# else +_GL_CXXALIAS_SYS (dup, int, (int oldfd)); +# endif +_GL_CXXALIASWARN (dup); +#elif defined GNULIB_POSIXCHECK +# undef dup +# if HAVE_RAW_DECL_DUP +_GL_WARN_ON_USE (dup, "dup is unportable - " + "use gnulib module dup for portability"); +# endif +#endif + + +#if @GNULIB_DUP2@ +/* Copy the file descriptor OLDFD into file descriptor NEWFD. Do nothing if + NEWFD = OLDFD, otherwise close NEWFD first if it is open. + Return newfd if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup2.html>. */ +# if @REPLACE_DUP2@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dup2 rpl_dup2 +# endif +_GL_FUNCDECL_RPL (dup2, int, (int oldfd, int newfd)); +_GL_CXXALIAS_RPL (dup2, int, (int oldfd, int newfd)); +# else +# if !@HAVE_DUP2@ +_GL_FUNCDECL_SYS (dup2, int, (int oldfd, int newfd)); +# endif +_GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd)); +# endif +_GL_CXXALIASWARN (dup2); +#elif defined GNULIB_POSIXCHECK +# undef dup2 +# if HAVE_RAW_DECL_DUP2 +_GL_WARN_ON_USE (dup2, "dup2 is unportable - " + "use gnulib module dup2 for portability"); +# endif +#endif + + +#if @GNULIB_DUP3@ +/* Copy the file descriptor OLDFD into file descriptor NEWFD, with the + specified flags. + The flags are a bitmask, possibly including O_CLOEXEC (defined in <fcntl.h>) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + Close NEWFD first if it is open. + Return newfd if successful, otherwise -1 and errno set. + See the Linux man page at + <https://www.kernel.org/doc/man-pages/online/pages/man2/dup3.2.html>. */ +# if @HAVE_DUP3@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dup3 rpl_dup3 +# endif +_GL_FUNCDECL_RPL (dup3, int, (int oldfd, int newfd, int flags)); +_GL_CXXALIAS_RPL (dup3, int, (int oldfd, int newfd, int flags)); +# else +_GL_FUNCDECL_SYS (dup3, int, (int oldfd, int newfd, int flags)); +_GL_CXXALIAS_SYS (dup3, int, (int oldfd, int newfd, int flags)); +# endif +_GL_CXXALIASWARN (dup3); +#elif defined GNULIB_POSIXCHECK +# undef dup3 +# if HAVE_RAW_DECL_DUP3 +_GL_WARN_ON_USE (dup3, "dup3 is unportable - " + "use gnulib module dup3 for portability"); +# endif +#endif + + +#if @GNULIB_ENVIRON@ +# if defined __CYGWIN__ && !defined __i386__ +/* The 'environ' variable is defined in a DLL. Therefore its declaration needs + the '__declspec(dllimport)' attribute, but the system's <unistd.h> lacks it. + This leads to a link error on 64-bit Cygwin when the option + -Wl,--disable-auto-import is in use. */ +_GL_EXTERN_C __declspec(dllimport) char **environ; +# endif +# if !@HAVE_DECL_ENVIRON@ +/* Set of environment variables and values. An array of strings of the form + "VARIABLE=VALUE", terminated with a NULL. */ +# if defined __APPLE__ && defined __MACH__ +# include <TargetConditionals.h> +# if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR +# define _GL_USE_CRT_EXTERNS +# endif +# endif +# ifdef _GL_USE_CRT_EXTERNS +# include <crt_externs.h> +# define environ (*_NSGetEnviron ()) +# else +# ifdef __cplusplus +extern "C" { +# endif +extern char **environ; +# ifdef __cplusplus +} +# endif +# endif +# endif +#elif defined GNULIB_POSIXCHECK +# if HAVE_RAW_DECL_ENVIRON +_GL_UNISTD_INLINE char *** +_GL_WARN_ON_USE_ATTRIBUTE ("environ is unportable - " + "use gnulib module environ for portability") +rpl_environ (void) +{ + return &environ; +} +# undef environ +# define environ (*rpl_environ ()) +# endif +#endif + + +#if @GNULIB_EUIDACCESS@ +/* Like access(), except that it uses the effective user id and group id of + the current process. */ +# if !@HAVE_EUIDACCESS@ +_GL_FUNCDECL_SYS (euidaccess, int, (const char *filename, int mode) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (euidaccess, int, (const char *filename, int mode)); +_GL_CXXALIASWARN (euidaccess); +# if defined GNULIB_POSIXCHECK +/* Like access(), this function is a security risk. */ +_GL_WARN_ON_USE (euidaccess, "the euidaccess function is a security risk - " + "use the gnulib module faccessat instead"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef euidaccess +# if HAVE_RAW_DECL_EUIDACCESS +_GL_WARN_ON_USE (euidaccess, "euidaccess is unportable - " + "use gnulib module euidaccess for portability"); +# endif +#endif + + +#if @GNULIB_FACCESSAT@ +# if @REPLACE_FACCESSAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef faccessat +# define faccessat rpl_faccessat +# endif +_GL_FUNCDECL_RPL (faccessat, int, + (int fd, char const *name, int mode, int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (faccessat, int, + (int fd, char const *name, int mode, int flag)); +# else +# if !@HAVE_FACCESSAT@ +_GL_FUNCDECL_SYS (faccessat, int, + (int fd, char const *file, int mode, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (faccessat, int, + (int fd, char const *file, int mode, int flag)); +# endif +_GL_CXXALIASWARN (faccessat); +#elif defined GNULIB_POSIXCHECK +# undef faccessat +# if HAVE_RAW_DECL_FACCESSAT +_GL_WARN_ON_USE (faccessat, "faccessat is not portable - " + "use gnulib module faccessat for portability"); +# endif +#endif + + +#if @GNULIB_FCHDIR@ +/* Change the process' current working directory to the directory on which + the given file descriptor is open. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html>. */ +# if ! @HAVE_FCHDIR@ +_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); + +/* Gnulib internal hooks needed to maintain the fchdir metadata. */ +_GL_EXTERN_C int _gl_register_fd (int fd, const char *filename) + _GL_ARG_NONNULL ((2)); +_GL_EXTERN_C void _gl_unregister_fd (int fd); +_GL_EXTERN_C int _gl_register_dup (int oldfd, int newfd); +_GL_EXTERN_C const char *_gl_directory_name (int fd); + +# else +# if !@HAVE_DECL_FCHDIR@ +_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); +# endif +# endif +_GL_CXXALIAS_SYS (fchdir, int, (int /*fd*/)); +_GL_CXXALIASWARN (fchdir); +#elif defined GNULIB_POSIXCHECK +# undef fchdir +# if HAVE_RAW_DECL_FCHDIR +_GL_WARN_ON_USE (fchdir, "fchdir is unportable - " + "use gnulib module fchdir for portability"); +# endif +#endif + + +#if @GNULIB_FCHOWNAT@ +# if @REPLACE_FCHOWNAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fchownat +# define fchownat rpl_fchownat +# endif +_GL_FUNCDECL_RPL (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag)); +# else +# if !@HAVE_FCHOWNAT@ +_GL_FUNCDECL_SYS (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag)); +# endif +_GL_CXXALIASWARN (fchownat); +#elif defined GNULIB_POSIXCHECK +# undef fchownat +# if HAVE_RAW_DECL_FCHOWNAT +_GL_WARN_ON_USE (fchownat, "fchownat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_FDATASYNC@ +/* Synchronize changes to a file. + Return 0 if successful, otherwise -1 and errno set. + See POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html>. */ +# if !@HAVE_FDATASYNC@ || !@HAVE_DECL_FDATASYNC@ +_GL_FUNCDECL_SYS (fdatasync, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (fdatasync, int, (int fd)); +_GL_CXXALIASWARN (fdatasync); +#elif defined GNULIB_POSIXCHECK +# undef fdatasync +# if HAVE_RAW_DECL_FDATASYNC +_GL_WARN_ON_USE (fdatasync, "fdatasync is unportable - " + "use gnulib module fdatasync for portability"); +# endif +#endif + + +#if @GNULIB_FSYNC@ +/* Synchronize changes, including metadata, to a file. + Return 0 if successful, otherwise -1 and errno set. + See POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html>. */ +# if !@HAVE_FSYNC@ +_GL_FUNCDECL_SYS (fsync, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (fsync, int, (int fd)); +_GL_CXXALIASWARN (fsync); +#elif defined GNULIB_POSIXCHECK +# undef fsync +# if HAVE_RAW_DECL_FSYNC +_GL_WARN_ON_USE (fsync, "fsync is unportable - " + "use gnulib module fsync for portability"); +# endif +#endif + + +#if @GNULIB_FTRUNCATE@ +/* Change the size of the file to which FD is opened to become equal to LENGTH. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html>. */ +# if @REPLACE_FTRUNCATE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ftruncate +# define ftruncate rpl_ftruncate +# endif +_GL_FUNCDECL_RPL (ftruncate, int, (int fd, off_t length)); +_GL_CXXALIAS_RPL (ftruncate, int, (int fd, off_t length)); +# else +# if !@HAVE_FTRUNCATE@ +_GL_FUNCDECL_SYS (ftruncate, int, (int fd, off_t length)); +# endif +_GL_CXXALIAS_SYS (ftruncate, int, (int fd, off_t length)); +# endif +_GL_CXXALIASWARN (ftruncate); +#elif defined GNULIB_POSIXCHECK +# undef ftruncate +# if HAVE_RAW_DECL_FTRUNCATE +_GL_WARN_ON_USE (ftruncate, "ftruncate is unportable - " + "use gnulib module ftruncate for portability"); +# endif +#endif + + +#if @GNULIB_GETCWD@ +/* Get the name of the current working directory, and put it in SIZE bytes + of BUF. + Return BUF if successful, or NULL if the directory couldn't be determined + or SIZE was too small. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html>. + Additionally, the gnulib module 'getcwd' guarantees the following GNU + extension: If BUF is NULL, an array is allocated with 'malloc'; the array + is SIZE bytes long, unless SIZE == 0, in which case it is as big as + necessary. */ +# if @REPLACE_GETCWD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getcwd rpl_getcwd +# endif +_GL_FUNCDECL_RPL (getcwd, char *, (char *buf, size_t size)); +_GL_CXXALIAS_RPL (getcwd, char *, (char *buf, size_t size)); +# else +/* Need to cast, because on mingw, the second parameter is + int size. */ +_GL_CXXALIAS_SYS_CAST (getcwd, char *, (char *buf, size_t size)); +# endif +_GL_CXXALIASWARN (getcwd); +#elif defined GNULIB_POSIXCHECK +# undef getcwd +# if HAVE_RAW_DECL_GETCWD +_GL_WARN_ON_USE (getcwd, "getcwd is unportable - " + "use gnulib module getcwd for portability"); +# endif +#endif + + +#if @GNULIB_GETDOMAINNAME@ +/* Return the NIS domain name of the machine. + WARNING! The NIS domain name is unrelated to the fully qualified host name + of the machine. It is also unrelated to email addresses. + WARNING! The NIS domain name is usually the empty string or "(none)" when + not using NIS. + + Put up to LEN bytes of the NIS domain name into NAME. + Null terminate it if the name is shorter than LEN. + If the NIS domain name is longer than LEN, set errno = EINVAL and return -1. + Return 0 if successful, otherwise set errno and return -1. */ +# if @REPLACE_GETDOMAINNAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getdomainname +# define getdomainname rpl_getdomainname +# endif +_GL_FUNCDECL_RPL (getdomainname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getdomainname, int, (char *name, size_t len)); +# else +# if !@HAVE_DECL_GETDOMAINNAME@ +_GL_FUNCDECL_SYS (getdomainname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (getdomainname, int, (char *name, size_t len)); +# endif +_GL_CXXALIASWARN (getdomainname); +#elif defined GNULIB_POSIXCHECK +# undef getdomainname +# if HAVE_RAW_DECL_GETDOMAINNAME +_GL_WARN_ON_USE (getdomainname, "getdomainname is unportable - " + "use gnulib module getdomainname for portability"); +# endif +#endif + + +#if @GNULIB_GETDTABLESIZE@ +/* Return the maximum number of file descriptors in the current process. + In POSIX, this is same as sysconf (_SC_OPEN_MAX). */ +# if @REPLACE_GETDTABLESIZE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getdtablesize +# define getdtablesize rpl_getdtablesize +# endif +_GL_FUNCDECL_RPL (getdtablesize, int, (void)); +_GL_CXXALIAS_RPL (getdtablesize, int, (void)); +# else +# if !@HAVE_GETDTABLESIZE@ +_GL_FUNCDECL_SYS (getdtablesize, int, (void)); +# endif +_GL_CXXALIAS_SYS (getdtablesize, int, (void)); +# endif +_GL_CXXALIASWARN (getdtablesize); +#elif defined GNULIB_POSIXCHECK +# undef getdtablesize +# if HAVE_RAW_DECL_GETDTABLESIZE +_GL_WARN_ON_USE (getdtablesize, "getdtablesize is unportable - " + "use gnulib module getdtablesize for portability"); +# endif +#endif + + +#if @GNULIB_GETGROUPS@ +/* Return the supplemental groups that the current process belongs to. + It is unspecified whether the effective group id is in the list. + If N is 0, return the group count; otherwise, N describes how many + entries are available in GROUPS. Return -1 and set errno if N is + not 0 and not large enough. Fails with ENOSYS on some systems. */ +# if @REPLACE_GETGROUPS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getgroups +# define getgroups rpl_getgroups +# endif +_GL_FUNCDECL_RPL (getgroups, int, (int n, gid_t *groups)); +_GL_CXXALIAS_RPL (getgroups, int, (int n, gid_t *groups)); +# else +# if !@HAVE_GETGROUPS@ +_GL_FUNCDECL_SYS (getgroups, int, (int n, gid_t *groups)); +# endif +_GL_CXXALIAS_SYS (getgroups, int, (int n, gid_t *groups)); +# endif +_GL_CXXALIASWARN (getgroups); +#elif defined GNULIB_POSIXCHECK +# undef getgroups +# if HAVE_RAW_DECL_GETGROUPS +_GL_WARN_ON_USE (getgroups, "getgroups is unportable - " + "use gnulib module getgroups for portability"); +# endif +#endif + + +#if @GNULIB_GETHOSTNAME@ +/* Return the standard host name of the machine. + WARNING! The host name may or may not be fully qualified. + + Put up to LEN bytes of the host name into NAME. + Null terminate it if the name is shorter than LEN. + If the host name is longer than LEN, set errno = EINVAL and return -1. + Return 0 if successful, otherwise set errno and return -1. */ +# if @UNISTD_H_HAVE_WINSOCK2_H@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gethostname +# define gethostname rpl_gethostname +# endif +_GL_FUNCDECL_RPL (gethostname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (gethostname, int, (char *name, size_t len)); +# else +# if !@HAVE_GETHOSTNAME@ +_GL_FUNCDECL_SYS (gethostname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on Solaris 10 and OSF/1 5.1 systems, the second + parameter is + int len. */ +_GL_CXXALIAS_SYS_CAST (gethostname, int, (char *name, size_t len)); +# endif +_GL_CXXALIASWARN (gethostname); +#elif @UNISTD_H_HAVE_WINSOCK2_H@ +# undef gethostname +# define gethostname gethostname_used_without_requesting_gnulib_module_gethostname +#elif defined GNULIB_POSIXCHECK +# undef gethostname +# if HAVE_RAW_DECL_GETHOSTNAME +_GL_WARN_ON_USE (gethostname, "gethostname is unportable - " + "use gnulib module gethostname for portability"); +# endif +#endif + + +#if @GNULIB_GETLOGIN@ +/* Returns the user's login name, or NULL if it cannot be found. Upon error, + returns NULL with errno set. + + See <http://www.opengroup.org/susv3xsh/getlogin.html>. + + Most programs don't need to use this function, because the information is + available through environment variables: + ${LOGNAME-$USER} on Unix platforms, + $USERNAME on native Windows platforms. + */ +# if !@HAVE_DECL_GETLOGIN@ +_GL_FUNCDECL_SYS (getlogin, char *, (void)); +# endif +_GL_CXXALIAS_SYS (getlogin, char *, (void)); +_GL_CXXALIASWARN (getlogin); +#elif defined GNULIB_POSIXCHECK +# undef getlogin +# if HAVE_RAW_DECL_GETLOGIN +_GL_WARN_ON_USE (getlogin, "getlogin is unportable - " + "use gnulib module getlogin for portability"); +# endif +#endif + + +#if @GNULIB_GETLOGIN_R@ +/* Copies the user's login name to NAME. + The array pointed to by NAME has room for SIZE bytes. + + Returns 0 if successful. Upon error, an error number is returned, or -1 in + the case that the login name cannot be found but no specific error is + provided (this case is hopefully rare but is left open by the POSIX spec). + + See <http://www.opengroup.org/susv3xsh/getlogin.html>. + + Most programs don't need to use this function, because the information is + available through environment variables: + ${LOGNAME-$USER} on Unix platforms, + $USERNAME on native Windows platforms. + */ +# if @REPLACE_GETLOGIN_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getlogin_r rpl_getlogin_r +# endif +_GL_FUNCDECL_RPL (getlogin_r, int, (char *name, size_t size) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getlogin_r, int, (char *name, size_t size)); +# else +# if !@HAVE_DECL_GETLOGIN_R@ +_GL_FUNCDECL_SYS (getlogin_r, int, (char *name, size_t size) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on Solaris 10 systems, the second argument is + int size. */ +_GL_CXXALIAS_SYS_CAST (getlogin_r, int, (char *name, size_t size)); +# endif +_GL_CXXALIASWARN (getlogin_r); +#elif defined GNULIB_POSIXCHECK +# undef getlogin_r +# if HAVE_RAW_DECL_GETLOGIN_R +_GL_WARN_ON_USE (getlogin_r, "getlogin_r is unportable - " + "use gnulib module getlogin_r for portability"); +# endif +#endif + + +#if @GNULIB_GETPAGESIZE@ +# if @REPLACE_GETPAGESIZE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getpagesize rpl_getpagesize +# endif +_GL_FUNCDECL_RPL (getpagesize, int, (void)); +_GL_CXXALIAS_RPL (getpagesize, int, (void)); +# else +# if !@HAVE_GETPAGESIZE@ +# if !defined getpagesize +/* This is for POSIX systems. */ +# if !defined _gl_getpagesize && defined _SC_PAGESIZE +# if ! (defined __VMS && __VMS_VER < 70000000) +# define _gl_getpagesize() sysconf (_SC_PAGESIZE) +# endif +# endif +/* This is for older VMS. */ +# if !defined _gl_getpagesize && defined __VMS +# ifdef __ALPHA +# define _gl_getpagesize() 8192 +# else +# define _gl_getpagesize() 512 +# endif +# endif +/* This is for BeOS. */ +# if !defined _gl_getpagesize && @HAVE_OS_H@ +# include <OS.h> +# if defined B_PAGE_SIZE +# define _gl_getpagesize() B_PAGE_SIZE +# endif +# endif +/* This is for AmigaOS4.0. */ +# if !defined _gl_getpagesize && defined __amigaos4__ +# define _gl_getpagesize() 2048 +# endif +/* This is for older Unix systems. */ +# if !defined _gl_getpagesize && @HAVE_SYS_PARAM_H@ +# include <sys/param.h> +# ifdef EXEC_PAGESIZE +# define _gl_getpagesize() EXEC_PAGESIZE +# else +# ifdef NBPG +# ifndef CLSIZE +# define CLSIZE 1 +# endif +# define _gl_getpagesize() (NBPG * CLSIZE) +# else +# ifdef NBPC +# define _gl_getpagesize() NBPC +# endif +# endif +# endif +# endif +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getpagesize() _gl_getpagesize () +# else +# if !GNULIB_defined_getpagesize_function +_GL_UNISTD_INLINE int +getpagesize () +{ + return _gl_getpagesize (); +} +# define GNULIB_defined_getpagesize_function 1 +# endif +# endif +# endif +# endif +/* Need to cast, because on Cygwin 1.5.x systems, the return type is size_t. */ +_GL_CXXALIAS_SYS_CAST (getpagesize, int, (void)); +# endif +# if @HAVE_DECL_GETPAGESIZE@ +_GL_CXXALIASWARN (getpagesize); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getpagesize +# if HAVE_RAW_DECL_GETPAGESIZE +_GL_WARN_ON_USE (getpagesize, "getpagesize is unportable - " + "use gnulib module getpagesize for portability"); +# endif +#endif + + +#if @GNULIB_GETPASS@ +/* Function getpass() from module 'getpass': + Read a password from /dev/tty or stdin. + Function getpass() from module 'getpass-gnu': + Read a password of arbitrary length from /dev/tty or stdin. */ +# if @REPLACE_GETPASS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getpass +# define getpass rpl_getpass +# endif +_GL_FUNCDECL_RPL (getpass, char *, (const char *prompt) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getpass, char *, (const char *prompt)); +# else +# if !@HAVE_GETPASS@ +_GL_FUNCDECL_SYS (getpass, char *, (const char *prompt) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (getpass, char *, (const char *prompt)); +# endif +_GL_CXXALIASWARN (getpass); +#elif defined GNULIB_POSIXCHECK +# undef getpass +# if HAVE_RAW_DECL_GETPASS +_GL_WARN_ON_USE (getpass, "getpass is unportable - " + "use gnulib module getpass or getpass-gnu for portability"); +# endif +#endif + + +#if @GNULIB_GETUSERSHELL@ +/* Return the next valid login shell on the system, or NULL when the end of + the list has been reached. */ +# if !@HAVE_DECL_GETUSERSHELL@ +_GL_FUNCDECL_SYS (getusershell, char *, (void)); +# endif +_GL_CXXALIAS_SYS (getusershell, char *, (void)); +_GL_CXXALIASWARN (getusershell); +#elif defined GNULIB_POSIXCHECK +# undef getusershell +# if HAVE_RAW_DECL_GETUSERSHELL +_GL_WARN_ON_USE (getusershell, "getusershell is unportable - " + "use gnulib module getusershell for portability"); +# endif +#endif + +#if @GNULIB_GETUSERSHELL@ +/* Rewind to pointer that is advanced at each getusershell() call. */ +# if !@HAVE_DECL_GETUSERSHELL@ +_GL_FUNCDECL_SYS (setusershell, void, (void)); +# endif +_GL_CXXALIAS_SYS (setusershell, void, (void)); +_GL_CXXALIASWARN (setusershell); +#elif defined GNULIB_POSIXCHECK +# undef setusershell +# if HAVE_RAW_DECL_SETUSERSHELL +_GL_WARN_ON_USE (setusershell, "setusershell is unportable - " + "use gnulib module getusershell for portability"); +# endif +#endif + +#if @GNULIB_GETUSERSHELL@ +/* Free the pointer that is advanced at each getusershell() call and + associated resources. */ +# if !@HAVE_DECL_GETUSERSHELL@ +_GL_FUNCDECL_SYS (endusershell, void, (void)); +# endif +_GL_CXXALIAS_SYS (endusershell, void, (void)); +_GL_CXXALIASWARN (endusershell); +#elif defined GNULIB_POSIXCHECK +# undef endusershell +# if HAVE_RAW_DECL_ENDUSERSHELL +_GL_WARN_ON_USE (endusershell, "endusershell is unportable - " + "use gnulib module getusershell for portability"); +# endif +#endif + + +#if @GNULIB_GROUP_MEMBER@ +/* Determine whether group id is in calling user's group list. */ +# if !@HAVE_GROUP_MEMBER@ +_GL_FUNCDECL_SYS (group_member, int, (gid_t gid)); +# endif +_GL_CXXALIAS_SYS (group_member, int, (gid_t gid)); +_GL_CXXALIASWARN (group_member); +#elif defined GNULIB_POSIXCHECK +# undef group_member +# if HAVE_RAW_DECL_GROUP_MEMBER +_GL_WARN_ON_USE (group_member, "group_member is unportable - " + "use gnulib module group-member for portability"); +# endif +#endif + + +#if @GNULIB_ISATTY@ +# if @REPLACE_ISATTY@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef isatty +# define isatty rpl_isatty +# endif +_GL_FUNCDECL_RPL (isatty, int, (int fd)); +_GL_CXXALIAS_RPL (isatty, int, (int fd)); +# else +_GL_CXXALIAS_SYS (isatty, int, (int fd)); +# endif +_GL_CXXALIASWARN (isatty); +#elif defined GNULIB_POSIXCHECK +# undef isatty +# if HAVE_RAW_DECL_ISATTY +_GL_WARN_ON_USE (isatty, "isatty has portability problems on native Windows - " + "use gnulib module isatty for portability"); +# endif +#endif + + +#if @GNULIB_LCHOWN@ +/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE + to GID (if GID is not -1). Do not follow symbolic links. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/lchown.html>. */ +# if @REPLACE_LCHOWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef lchown +# define lchown rpl_lchown +# endif +_GL_FUNCDECL_RPL (lchown, int, (char const *file, uid_t owner, gid_t group) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (lchown, int, (char const *file, uid_t owner, gid_t group)); +# else +# if !@HAVE_LCHOWN@ +_GL_FUNCDECL_SYS (lchown, int, (char const *file, uid_t owner, gid_t group) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (lchown, int, (char const *file, uid_t owner, gid_t group)); +# endif +_GL_CXXALIASWARN (lchown); +#elif defined GNULIB_POSIXCHECK +# undef lchown +# if HAVE_RAW_DECL_LCHOWN +_GL_WARN_ON_USE (lchown, "lchown is unportable to pre-POSIX.1-2001 systems - " + "use gnulib module lchown for portability"); +# endif +#endif + + +#if @GNULIB_LINK@ +/* Create a new hard link for an existing file. + Return 0 if successful, otherwise -1 and errno set. + See POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html>. */ +# if @REPLACE_LINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define link rpl_link +# endif +_GL_FUNCDECL_RPL (link, int, (const char *path1, const char *path2) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (link, int, (const char *path1, const char *path2)); +# else +# if !@HAVE_LINK@ +_GL_FUNCDECL_SYS (link, int, (const char *path1, const char *path2) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (link, int, (const char *path1, const char *path2)); +# endif +_GL_CXXALIASWARN (link); +#elif defined GNULIB_POSIXCHECK +# undef link +# if HAVE_RAW_DECL_LINK +_GL_WARN_ON_USE (link, "link is unportable - " + "use gnulib module link for portability"); +# endif +#endif + + +#if @GNULIB_LINKAT@ +/* Create a new hard link for an existing file, relative to two + directories. FLAG controls whether symlinks are followed. + Return 0 if successful, otherwise -1 and errno set. */ +# if @REPLACE_LINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef linkat +# define linkat rpl_linkat +# endif +_GL_FUNCDECL_RPL (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag) + _GL_ARG_NONNULL ((2, 4))); +_GL_CXXALIAS_RPL (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag)); +# else +# if !@HAVE_LINKAT@ +_GL_FUNCDECL_SYS (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag) + _GL_ARG_NONNULL ((2, 4))); +# endif +_GL_CXXALIAS_SYS (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag)); +# endif +_GL_CXXALIASWARN (linkat); +#elif defined GNULIB_POSIXCHECK +# undef linkat +# if HAVE_RAW_DECL_LINKAT +_GL_WARN_ON_USE (linkat, "linkat is unportable - " + "use gnulib module linkat for portability"); +# endif +#endif + + +#if @GNULIB_LSEEK@ +/* Set the offset of FD relative to SEEK_SET, SEEK_CUR, or SEEK_END. + Return the new offset if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html>. */ +# if @REPLACE_LSEEK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define lseek rpl_lseek +# endif +_GL_FUNCDECL_RPL (lseek, off_t, (int fd, off_t offset, int whence)); +_GL_CXXALIAS_RPL (lseek, off_t, (int fd, off_t offset, int whence)); +# else +_GL_CXXALIAS_SYS (lseek, off_t, (int fd, off_t offset, int whence)); +# endif +_GL_CXXALIASWARN (lseek); +#elif defined GNULIB_POSIXCHECK +# undef lseek +# if HAVE_RAW_DECL_LSEEK +_GL_WARN_ON_USE (lseek, "lseek does not fail with ESPIPE on pipes on some " + "systems - use gnulib module lseek for portability"); +# endif +#endif + + +#if @GNULIB_PIPE@ +/* Create a pipe, defaulting to O_BINARY mode. + Store the read-end as fd[0] and the write-end as fd[1]. + Return 0 upon success, or -1 with errno set upon failure. */ +# if !@HAVE_PIPE@ +_GL_FUNCDECL_SYS (pipe, int, (int fd[2]) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (pipe, int, (int fd[2])); +_GL_CXXALIASWARN (pipe); +#elif defined GNULIB_POSIXCHECK +# undef pipe +# if HAVE_RAW_DECL_PIPE +_GL_WARN_ON_USE (pipe, "pipe is unportable - " + "use gnulib module pipe-posix for portability"); +# endif +#endif + + +#if @GNULIB_PIPE2@ +/* Create a pipe, applying the given flags when opening the read-end of the + pipe and the write-end of the pipe. + The flags are a bitmask, possibly including O_CLOEXEC (defined in <fcntl.h>) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + Store the read-end as fd[0] and the write-end as fd[1]. + Return 0 upon success, or -1 with errno set upon failure. + See also the Linux man page at + <https://www.kernel.org/doc/man-pages/online/pages/man2/pipe2.2.html>. */ +# if @HAVE_PIPE2@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define pipe2 rpl_pipe2 +# endif +_GL_FUNCDECL_RPL (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (pipe2, int, (int fd[2], int flags)); +# else +_GL_FUNCDECL_SYS (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (pipe2, int, (int fd[2], int flags)); +# endif +_GL_CXXALIASWARN (pipe2); +#elif defined GNULIB_POSIXCHECK +# undef pipe2 +# if HAVE_RAW_DECL_PIPE2 +_GL_WARN_ON_USE (pipe2, "pipe2 is unportable - " + "use gnulib module pipe2 for portability"); +# endif +#endif + + +#if @GNULIB_PREAD@ +/* Read at most BUFSIZE bytes from FD into BUF, starting at OFFSET. + Return the number of bytes placed into BUF if successful, otherwise + set errno and return -1. 0 indicates EOF. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html>. */ +# if @REPLACE_PREAD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pread +# define pread rpl_pread +# endif +_GL_FUNCDECL_RPL (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset)); +# else +# if !@HAVE_PREAD@ +_GL_FUNCDECL_SYS (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset)); +# endif +_GL_CXXALIASWARN (pread); +#elif defined GNULIB_POSIXCHECK +# undef pread +# if HAVE_RAW_DECL_PREAD +_GL_WARN_ON_USE (pread, "pread is unportable - " + "use gnulib module pread for portability"); +# endif +#endif + + +#if @GNULIB_PWRITE@ +/* Write at most BUFSIZE bytes from BUF into FD, starting at OFFSET. + Return the number of bytes written if successful, otherwise + set errno and return -1. 0 indicates nothing written. See the + POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html>. */ +# if @REPLACE_PWRITE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pwrite +# define pwrite rpl_pwrite +# endif +_GL_FUNCDECL_RPL (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset)); +# else +# if !@HAVE_PWRITE@ +_GL_FUNCDECL_SYS (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset)); +# endif +_GL_CXXALIASWARN (pwrite); +#elif defined GNULIB_POSIXCHECK +# undef pwrite +# if HAVE_RAW_DECL_PWRITE +_GL_WARN_ON_USE (pwrite, "pwrite is unportable - " + "use gnulib module pwrite for portability"); +# endif +#endif + + +#if @GNULIB_READ@ +/* Read up to COUNT bytes from file descriptor FD into the buffer starting + at BUF. See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html>. */ +# if @REPLACE_READ@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef read +# define read rpl_read +# endif +_GL_FUNCDECL_RPL (read, ssize_t, (int fd, void *buf, size_t count) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (read, ssize_t, (int fd, void *buf, size_t count)); +# else +/* Need to cast, because on mingw, the third parameter is + unsigned int count + and the return type is 'int'. */ +_GL_CXXALIAS_SYS_CAST (read, ssize_t, (int fd, void *buf, size_t count)); +# endif +_GL_CXXALIASWARN (read); +#endif + + +#if @GNULIB_READLINK@ +/* Read the contents of the symbolic link FILE and place the first BUFSIZE + bytes of it into BUF. Return the number of bytes placed into BUF if + successful, otherwise -1 and errno set. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>. */ +# if @REPLACE_READLINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define readlink rpl_readlink +# endif +_GL_FUNCDECL_RPL (readlink, ssize_t, + (const char *file, char *buf, size_t bufsize) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (readlink, ssize_t, + (const char *file, char *buf, size_t bufsize)); +# else +# if !@HAVE_READLINK@ +_GL_FUNCDECL_SYS (readlink, ssize_t, + (const char *file, char *buf, size_t bufsize) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (readlink, ssize_t, + (const char *file, char *buf, size_t bufsize)); +# endif +_GL_CXXALIASWARN (readlink); +#elif defined GNULIB_POSIXCHECK +# undef readlink +# if HAVE_RAW_DECL_READLINK +_GL_WARN_ON_USE (readlink, "readlink is unportable - " + "use gnulib module readlink for portability"); +# endif +#endif + + +#if @GNULIB_READLINKAT@ +# if @REPLACE_READLINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define readlinkat rpl_readlinkat +# endif +_GL_FUNCDECL_RPL (readlinkat, ssize_t, + (int fd, char const *file, char *buf, size_t len) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (readlinkat, ssize_t, + (int fd, char const *file, char *buf, size_t len)); +# else +# if !@HAVE_READLINKAT@ +_GL_FUNCDECL_SYS (readlinkat, ssize_t, + (int fd, char const *file, char *buf, size_t len) + _GL_ARG_NONNULL ((2, 3))); +# endif +_GL_CXXALIAS_SYS (readlinkat, ssize_t, + (int fd, char const *file, char *buf, size_t len)); +# endif +_GL_CXXALIASWARN (readlinkat); +#elif defined GNULIB_POSIXCHECK +# undef readlinkat +# if HAVE_RAW_DECL_READLINKAT +_GL_WARN_ON_USE (readlinkat, "readlinkat is not portable - " + "use gnulib module readlinkat for portability"); +# endif +#endif + + +#if @GNULIB_RMDIR@ +/* Remove the directory DIR. */ +# if @REPLACE_RMDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define rmdir rpl_rmdir +# endif +_GL_FUNCDECL_RPL (rmdir, int, (char const *name) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (rmdir, int, (char const *name)); +# else +_GL_CXXALIAS_SYS (rmdir, int, (char const *name)); +# endif +_GL_CXXALIASWARN (rmdir); +#elif defined GNULIB_POSIXCHECK +# undef rmdir +# if HAVE_RAW_DECL_RMDIR +_GL_WARN_ON_USE (rmdir, "rmdir is unportable - " + "use gnulib module rmdir for portability"); +# endif +#endif + + +#if @GNULIB_SETHOSTNAME@ +/* Set the host name of the machine. + The host name may or may not be fully qualified. + + Put LEN bytes of NAME into the host name. + Return 0 if successful, otherwise, set errno and return -1. + + Platforms with no ability to set the hostname return -1 and set + errno = ENOSYS. */ +# if !@HAVE_SETHOSTNAME@ || !@HAVE_DECL_SETHOSTNAME@ +_GL_FUNCDECL_SYS (sethostname, int, (const char *name, size_t len) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on Solaris 11 2011-10, Mac OS X 10.5, IRIX 6.5 + and FreeBSD 6.4 the second parameter is int. On Solaris 11 + 2011-10, the first parameter is not const. */ +_GL_CXXALIAS_SYS_CAST (sethostname, int, (const char *name, size_t len)); +_GL_CXXALIASWARN (sethostname); +#elif defined GNULIB_POSIXCHECK +# undef sethostname +# if HAVE_RAW_DECL_SETHOSTNAME +_GL_WARN_ON_USE (sethostname, "sethostname is unportable - " + "use gnulib module sethostname for portability"); +# endif +#endif + + +#if @GNULIB_SLEEP@ +/* Pause the execution of the current thread for N seconds. + Returns the number of seconds left to sleep. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/sleep.html>. */ +# if @REPLACE_SLEEP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef sleep +# define sleep rpl_sleep +# endif +_GL_FUNCDECL_RPL (sleep, unsigned int, (unsigned int n)); +_GL_CXXALIAS_RPL (sleep, unsigned int, (unsigned int n)); +# else +# if !@HAVE_SLEEP@ +_GL_FUNCDECL_SYS (sleep, unsigned int, (unsigned int n)); +# endif +_GL_CXXALIAS_SYS (sleep, unsigned int, (unsigned int n)); +# endif +_GL_CXXALIASWARN (sleep); +#elif defined GNULIB_POSIXCHECK +# undef sleep +# if HAVE_RAW_DECL_SLEEP +_GL_WARN_ON_USE (sleep, "sleep is unportable - " + "use gnulib module sleep for portability"); +# endif +#endif + + +#if @GNULIB_SYMLINK@ +# if @REPLACE_SYMLINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef symlink +# define symlink rpl_symlink +# endif +_GL_FUNCDECL_RPL (symlink, int, (char const *contents, char const *file) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (symlink, int, (char const *contents, char const *file)); +# else +# if !@HAVE_SYMLINK@ +_GL_FUNCDECL_SYS (symlink, int, (char const *contents, char const *file) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (symlink, int, (char const *contents, char const *file)); +# endif +_GL_CXXALIASWARN (symlink); +#elif defined GNULIB_POSIXCHECK +# undef symlink +# if HAVE_RAW_DECL_SYMLINK +_GL_WARN_ON_USE (symlink, "symlink is not portable - " + "use gnulib module symlink for portability"); +# endif +#endif + + +#if @GNULIB_SYMLINKAT@ +# if @REPLACE_SYMLINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef symlinkat +# define symlinkat rpl_symlinkat +# endif +_GL_FUNCDECL_RPL (symlinkat, int, + (char const *contents, int fd, char const *file) + _GL_ARG_NONNULL ((1, 3))); +_GL_CXXALIAS_RPL (symlinkat, int, + (char const *contents, int fd, char const *file)); +# else +# if !@HAVE_SYMLINKAT@ +_GL_FUNCDECL_SYS (symlinkat, int, + (char const *contents, int fd, char const *file) + _GL_ARG_NONNULL ((1, 3))); +# endif +_GL_CXXALIAS_SYS (symlinkat, int, + (char const *contents, int fd, char const *file)); +# endif +_GL_CXXALIASWARN (symlinkat); +#elif defined GNULIB_POSIXCHECK +# undef symlinkat +# if HAVE_RAW_DECL_SYMLINKAT +_GL_WARN_ON_USE (symlinkat, "symlinkat is not portable - " + "use gnulib module symlinkat for portability"); +# endif +#endif + + +#if @GNULIB_TRUNCATE@ +/* Change the size of the file designated by FILENAME to become equal to LENGTH. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html>. */ +# if @REPLACE_TRUNCATE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef truncate +# define truncate rpl_truncate +# endif +_GL_FUNCDECL_RPL (truncate, int, (const char *filename, off_t length) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (truncate, int, (const char *filename, off_t length)); +# else +# if !@HAVE_DECL_TRUNCATE@ +_GL_FUNCDECL_SYS (truncate, int, (const char *filename, off_t length) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (truncate, int, (const char *filename, off_t length)); +# endif +_GL_CXXALIASWARN (truncate); +#elif defined GNULIB_POSIXCHECK +# undef truncate +# if HAVE_RAW_DECL_TRUNCATE +_GL_WARN_ON_USE (truncate, "truncate is unportable - " + "use gnulib module truncate for portability"); +# endif +#endif + + +#if @GNULIB_TTYNAME_R@ +/* Store at most BUFLEN characters of the pathname of the terminal FD is + open on in BUF. Return 0 on success, otherwise an error number. */ +# if @REPLACE_TTYNAME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ttyname_r +# define ttyname_r rpl_ttyname_r +# endif +_GL_FUNCDECL_RPL (ttyname_r, int, + (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (ttyname_r, int, + (int fd, char *buf, size_t buflen)); +# else +# if !@HAVE_DECL_TTYNAME_R@ +_GL_FUNCDECL_SYS (ttyname_r, int, + (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (ttyname_r, int, + (int fd, char *buf, size_t buflen)); +# endif +_GL_CXXALIASWARN (ttyname_r); +#elif defined GNULIB_POSIXCHECK +# undef ttyname_r +# if HAVE_RAW_DECL_TTYNAME_R +_GL_WARN_ON_USE (ttyname_r, "ttyname_r is not portable - " + "use gnulib module ttyname_r for portability"); +# endif +#endif + + +#if @GNULIB_UNLINK@ +# if @REPLACE_UNLINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef unlink +# define unlink rpl_unlink +# endif +_GL_FUNCDECL_RPL (unlink, int, (char const *file) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (unlink, int, (char const *file)); +# else +_GL_CXXALIAS_SYS (unlink, int, (char const *file)); +# endif +_GL_CXXALIASWARN (unlink); +#elif defined GNULIB_POSIXCHECK +# undef unlink +# if HAVE_RAW_DECL_UNLINK +_GL_WARN_ON_USE (unlink, "unlink is not portable - " + "use gnulib module unlink for portability"); +# endif +#endif + + +#if @GNULIB_UNLINKAT@ +# if @REPLACE_UNLINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef unlinkat +# define unlinkat rpl_unlinkat +# endif +_GL_FUNCDECL_RPL (unlinkat, int, (int fd, char const *file, int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (unlinkat, int, (int fd, char const *file, int flag)); +# else +# if !@HAVE_UNLINKAT@ +_GL_FUNCDECL_SYS (unlinkat, int, (int fd, char const *file, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (unlinkat, int, (int fd, char const *file, int flag)); +# endif +_GL_CXXALIASWARN (unlinkat); +#elif defined GNULIB_POSIXCHECK +# undef unlinkat +# if HAVE_RAW_DECL_UNLINKAT +_GL_WARN_ON_USE (unlinkat, "unlinkat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_USLEEP@ +/* Pause the execution of the current thread for N microseconds. + Returns 0 on completion, or -1 on range error. + See the POSIX:2001 specification + <http://www.opengroup.org/susv3xsh/usleep.html>. */ +# if @REPLACE_USLEEP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef usleep +# define usleep rpl_usleep +# endif +_GL_FUNCDECL_RPL (usleep, int, (useconds_t n)); +_GL_CXXALIAS_RPL (usleep, int, (useconds_t n)); +# else +# if !@HAVE_USLEEP@ +_GL_FUNCDECL_SYS (usleep, int, (useconds_t n)); +# endif +_GL_CXXALIAS_SYS (usleep, int, (useconds_t n)); +# endif +_GL_CXXALIASWARN (usleep); +#elif defined GNULIB_POSIXCHECK +# undef usleep +# if HAVE_RAW_DECL_USLEEP +_GL_WARN_ON_USE (usleep, "usleep is unportable - " + "use gnulib module usleep for portability"); +# endif +#endif + + +#if @GNULIB_WRITE@ +/* Write up to COUNT bytes starting at BUF to file descriptor FD. + See the POSIX:2008 specification + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html>. */ +# if @REPLACE_WRITE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef write +# define write rpl_write +# endif +_GL_FUNCDECL_RPL (write, ssize_t, (int fd, const void *buf, size_t count) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (write, ssize_t, (int fd, const void *buf, size_t count)); +# else +/* Need to cast, because on mingw, the third parameter is + unsigned int count + and the return type is 'int'. */ +_GL_CXXALIAS_SYS_CAST (write, ssize_t, (int fd, const void *buf, size_t count)); +# endif +_GL_CXXALIASWARN (write); +#endif + +_GL_INLINE_HEADER_END + +#endif /* _@GUARD_PREFIX@_UNISTD_H */ +#endif /* _GL_INCLUDING_UNISTD_H */ +#endif /* _@GUARD_PREFIX@_UNISTD_H */ diff --git a/grub-core/lib/gnulib/unitypes.in.h b/grub-core/lib/gnulib/unitypes.in.h new file mode 100644 index 0000000..631654b --- /dev/null +++ b/grub-core/lib/gnulib/unitypes.in.h @@ -0,0 +1,46 @@ +/* Elementary types and macros for the GNU UniString library. + Copyright (C) 2002, 2005-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _UNITYPES_H +#define _UNITYPES_H + +/* Get uint8_t, uint16_t, uint32_t. */ +#include <stdint.h> + +/* Type representing a Unicode character. */ +typedef uint32_t ucs4_t; + +/* Attribute of a function whose result depends only on the arguments + (not pointers!) and which has no side effects. */ +#ifndef _UC_ATTRIBUTE_CONST +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) +# define _UC_ATTRIBUTE_CONST __attribute__ ((__const__)) +# else +# define _UC_ATTRIBUTE_CONST +# endif +#endif + +/* Attribute of a function whose result depends only on the arguments + (possibly pointers) and global memory, and which has no side effects. */ +#ifndef _UC_ATTRIBUTE_PURE +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# define _UC_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define _UC_ATTRIBUTE_PURE +# endif +#endif + +#endif /* _UNITYPES_H */ diff --git a/grub-core/lib/gnulib/uniwidth.in.h b/grub-core/lib/gnulib/uniwidth.in.h new file mode 100644 index 0000000..80c5eea --- /dev/null +++ b/grub-core/lib/gnulib/uniwidth.in.h @@ -0,0 +1,72 @@ +/* Display width functions. + Copyright (C) 2001-2002, 2005, 2007, 2009-2019 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _UNIWIDTH_H +#define _UNIWIDTH_H + +#include "unitypes.h" + +/* Get size_t. */ +#include <stddef.h> + +/* Get locale_charset() declaration. */ +#include "localcharset.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Display width. */ + +/* These functions are locale dependent. The encoding argument identifies + the encoding (e.g. "ISO-8859-2" for Polish). */ + +/* Determine number of column positions required for UC. */ +extern int + uc_width (ucs4_t uc, const char *encoding) + _UC_ATTRIBUTE_PURE; + +/* Determine number of column positions required for first N units + (or fewer if S ends before this) in S. */ +extern int + u8_width (const uint8_t *s, size_t n, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u16_width (const uint16_t *s, size_t n, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u32_width (const uint32_t *s, size_t n, const char *encoding) + _UC_ATTRIBUTE_PURE; + +/* Determine number of column positions required for S. */ +extern int + u8_strwidth (const uint8_t *s, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u16_strwidth (const uint16_t *s, const char *encoding) + _UC_ATTRIBUTE_PURE; +extern int + u32_strwidth (const uint32_t *s, const char *encoding) + _UC_ATTRIBUTE_PURE; + + +#ifdef __cplusplus +} +#endif + +#endif /* _UNIWIDTH_H */ diff --git a/grub-core/lib/gnulib/uniwidth/cjk.h b/grub-core/lib/gnulib/uniwidth/cjk.h new file mode 100644 index 0000000..9870422 --- /dev/null +++ b/grub-core/lib/gnulib/uniwidth/cjk.h @@ -0,0 +1,37 @@ +/* Test for CJK encoding. + Copyright (C) 2001-2002, 2005-2007, 2009-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include "streq.h" + +static int +is_cjk_encoding (const char *encoding) +{ + if (0 + /* Legacy Japanese encodings */ + || STREQ_OPT (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0) + /* Legacy Chinese encodings */ + || STREQ_OPT (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0) + || STREQ_OPT (encoding, "GBK", 'G', 'B', 'K', 0, 0, 0, 0, 0, 0) + || STREQ_OPT (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0) + || STREQ_OPT (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0) + /* Legacy Korean encodings */ + || STREQ_OPT (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) + || STREQ_OPT (encoding, "CP949", 'C', 'P', '9', '4', '9', 0, 0, 0, 0) + || STREQ_OPT (encoding, "JOHAB", 'J', 'O', 'H', 'A', 'B', 0, 0, 0, 0)) + return 1; + return 0; +} diff --git a/grub-core/lib/gnulib/uniwidth/width.c b/grub-core/lib/gnulib/uniwidth/width.c new file mode 100644 index 0000000..a7f59b1 --- /dev/null +++ b/grub-core/lib/gnulib/uniwidth/width.c @@ -0,0 +1,468 @@ +/* Determine display width of Unicode character. + Copyright (C) 2001-2002, 2006-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "uniwidth.h" + +#include "cjk.h" + +/* + * Non-spacing attribute table. + * Consists of: + * - Non-spacing characters; generated from PropList.txt or + * "grep '^[^;]*;[^;]*;[^;]*;[^;]*;NSM;' UnicodeData.txt" + * - Format control characters; generated from + * "grep '^[^;]*;[^;]*;Cf;' UnicodeData.txt" + * - Zero width characters; generated from + * "grep '^[^;]*;ZERO WIDTH ' UnicodeData.txt" + */ +static const unsigned char nonspacing_table_data[38*64] = { + /* 0x0000-0x01ff */ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0x0000-0x003f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x0040-0x007f */ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, /* 0x0080-0x00bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00c0-0x00ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0100-0x013f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0140-0x017f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0180-0x01bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x01c0-0x01ff */ + /* 0x0200-0x03ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0200-0x023f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0240-0x027f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0280-0x02bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x02c0-0x02ff */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x0300-0x033f */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, /* 0x0340-0x037f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0380-0x03bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x03c0-0x03ff */ + /* 0x0400-0x05ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0400-0x043f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0440-0x047f */ + 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0480-0x04bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04c0-0x04ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0500-0x053f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0540-0x057f */ + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xbf, /* 0x0580-0x05bf */ + 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x05c0-0x05ff */ + /* 0x0600-0x07ff */ + 0x3f, 0x00, 0xff, 0x17, 0x00, 0x00, 0x00, 0x00, /* 0x0600-0x063f */ + 0x00, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, /* 0x0640-0x067f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0680-0x06bf */ + 0x00, 0x00, 0xc0, 0xbf, 0x9f, 0x3d, 0x00, 0x00, /* 0x06c0-0x06ff */ + 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, /* 0x0700-0x073f */ + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0740-0x077f */ + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, /* 0x0780-0x07bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, /* 0x07c0-0x07ff */ + /* 0x0800-0x09ff */ + 0x00, 0x00, 0xc0, 0xfb, 0xef, 0x3e, 0x00, 0x00, /* 0x0800-0x083f */ + 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, /* 0x0840-0x087f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0880-0x08bf */ + 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x08c0-0x08ff */ + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, /* 0x0900-0x093f */ + 0xfe, 0x21, 0xfe, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0940-0x097f */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0980-0x09bf */ + 0x1e, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x09c0-0x09ff */ + /* 0x0a00-0x0bff */ + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0a00-0x0a3f */ + 0x86, 0x39, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, /* 0x0a40-0x0a7f */ + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0a80-0x0abf */ + 0xbe, 0x21, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0ac0-0x0aff */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, /* 0x0b00-0x0b3f */ + 0x1e, 0x20, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0b40-0x0b7f */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b80-0x0bbf */ + 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0bc0-0x0bff */ + /* 0x0c00-0x0dff */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, /* 0x0c00-0x0c3f */ + 0xc1, 0x3d, 0x60, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0c40-0x0c7f */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0c80-0x0cbf */ + 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0cc0-0x0cff */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d00-0x0d3f */ + 0x1e, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0d40-0x0d7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d80-0x0dbf */ + 0x00, 0x04, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0dc0-0x0dff */ + /* 0x0e00-0x0fff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x07, /* 0x0e00-0x0e3f */ + 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e40-0x0e7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x1b, /* 0x0e80-0x0ebf */ + 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0ec0-0x0eff */ + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xa0, 0x02, /* 0x0f00-0x0f3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, /* 0x0f40-0x0f7f */ + 0xdf, 0xe0, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x1f, /* 0x0f80-0x0fbf */ + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0fc0-0x0fff */ + /* 0x1000-0x11ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfd, 0x66, /* 0x1000-0x103f */ + 0x00, 0x00, 0x00, 0xc3, 0x01, 0x00, 0x1e, 0x00, /* 0x1040-0x107f */ + 0x64, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, /* 0x1080-0x10bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10c0-0x10ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1100-0x113f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1140-0x117f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1180-0x11bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11c0-0x11ff */ + /* 0x1200-0x13ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1200-0x123f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1240-0x127f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1280-0x12bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x12c0-0x12ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1300-0x133f */ + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, /* 0x1340-0x137f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1380-0x13bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x13c0-0x13ff */ + /* 0x1600-0x17ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1600-0x163f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1640-0x167f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1680-0x16bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16c0-0x16ff */ + 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, /* 0x1700-0x173f */ + 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, /* 0x1740-0x177f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x3f, /* 0x1780-0x17bf */ + 0x40, 0xfe, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x00, /* 0x17c0-0x17ff */ + /* 0x1800-0x19ff */ + 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1800-0x183f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1840-0x187f */ + 0x60, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x1880-0x18bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18c0-0x18ff */ + 0x00, 0x00, 0x00, 0x00, 0x87, 0x01, 0x04, 0x0e, /* 0x1900-0x193f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1940-0x197f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1980-0x19bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x19c0-0x19ff */ + /* 0x1a00-0x1bff */ + 0x00, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, /* 0x1a00-0x1a3f */ + 0x00, 0x00, 0x40, 0x7f, 0xe5, 0x1f, 0xf8, 0x9f, /* 0x1a40-0x1a7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, /* 0x1a80-0x1abf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1ac0-0x1aff */ + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x17, /* 0x1b00-0x1b3f */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, /* 0x1b40-0x1b7f */ + 0x03, 0x00, 0x00, 0x00, 0x3c, 0x3b, 0x00, 0x00, /* 0x1b80-0x1bbf */ + 0x00, 0x00, 0x00, 0x00, 0x40, 0xa3, 0x03, 0x00, /* 0x1bc0-0x1bff */ + /* 0x1c00-0x1dff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xcf, 0x00, /* 0x1c00-0x1c3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c40-0x1c7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c80-0x1cbf */ + 0x00, 0x00, 0xf7, 0xff, 0xfd, 0x21, 0x10, 0x03, /* 0x1cc0-0x1cff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d00-0x1d3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d40-0x1d7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d80-0x1dbf */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xf8, /* 0x1dc0-0x1dff */ + /* 0x2000-0x21ff */ + 0x00, 0xf8, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, /* 0x2000-0x203f */ + 0x00, 0x00, 0x00, 0x00, 0xdf, 0xff, 0x00, 0x00, /* 0x2040-0x207f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2080-0x20bf */ + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, /* 0x20c0-0x20ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2100-0x213f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2140-0x217f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2180-0x21bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x21c0-0x21ff */ + /* 0x2c00-0x2dff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c00-0x2c3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c40-0x2c7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c80-0x2cbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, /* 0x2cc0-0x2cff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d00-0x2d3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x2d40-0x2d7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d80-0x2dbf */ + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, /* 0x2dc0-0x2dff */ + /* 0x3000-0x31ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, /* 0x3000-0x303f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3040-0x307f */ + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, /* 0x3080-0x30bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30c0-0x30ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3100-0x313f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3140-0x317f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3180-0x31bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x31c0-0x31ff */ + /* 0xa600-0xa7ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa600-0xa63f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf7, 0x3f, /* 0xa640-0xa67f */ + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, /* 0xa680-0xa6bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, /* 0xa6c0-0xa6ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa700-0xa73f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa740-0xa77f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa780-0xa7bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa7c0-0xa7ff */ + /* 0xa800-0xa9ff */ + 0x44, 0x08, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, /* 0xa800-0xa83f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa840-0xa87f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa880-0xa8bf */ + 0x30, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, /* 0xa8c0-0xa8ff */ + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, /* 0xa900-0xa93f */ + 0x80, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa940-0xa97f */ + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x13, /* 0xa980-0xa9bf */ + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, /* 0xa9c0-0xa9ff */ + /* 0xaa00-0xabff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x66, 0x00, /* 0xaa00-0xaa3f */ + 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0xaa40-0xaa7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0xc1, /* 0xaa80-0xaabf */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 0x00, /* 0xaac0-0xaaff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab00-0xab3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab40-0xab7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab80-0xabbf */ + 0x00, 0x00, 0x00, 0x00, 0x20, 0x21, 0x00, 0x00, /* 0xabc0-0xabff */ + /* 0xfa00-0xfbff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa00-0xfa3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa40-0xfa7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa80-0xfabf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfac0-0xfaff */ + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, /* 0xfb00-0xfb3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb40-0xfb7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb80-0xfbbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfbc0-0xfbff */ + /* 0xfe00-0xffff */ + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, /* 0xfe00-0xfe3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe40-0xfe7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe80-0xfebf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xfec0-0xfeff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff00-0xff3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff40-0xff7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff80-0xffbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, /* 0xffc0-0xffff */ + /* 0x10000-0x101ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10000-0x1003f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10040-0x1007f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10080-0x100bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x100c0-0x100ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10100-0x1013f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10140-0x1017f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10180-0x101bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, /* 0x101c0-0x101ff */ + /* 0x10200-0x103ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10200-0x1023f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10240-0x1027f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10280-0x102bf */ + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* 0x102c0-0x102ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10300-0x1033f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, /* 0x10340-0x1037f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10380-0x103bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x103c0-0x103ff */ + /* 0x10a00-0x10bff */ + 0x6e, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, /* 0x10a00-0x10a3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10a40-0x10a7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10a80-0x10abf */ + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, /* 0x10ac0-0x10aff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10b00-0x10b3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10b40-0x10b7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10b80-0x10bbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10bc0-0x10bff */ + /* 0x11000-0x111ff */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0x11000-0x1103f */ + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x11040-0x1107f */ + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x26, /* 0x11080-0x110bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x110c0-0x110ff */ + 0x07, 0x00, 0x00, 0x00, 0x80, 0xef, 0x1f, 0x00, /* 0x11100-0x1113f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, /* 0x11140-0x1117f */ + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f, /* 0x11180-0x111bf */ + 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x111c0-0x111ff */ + /* 0x11200-0x113ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xd3, 0x40, /* 0x11200-0x1123f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11240-0x1127f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11280-0x112bf */ + 0x00, 0x00, 0x00, 0x80, 0xf8, 0x07, 0x00, 0x00, /* 0x112c0-0x112ff */ + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x11300-0x1133f */ + 0x01, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x1f, 0x00, /* 0x11340-0x1137f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11380-0x113bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x113c0-0x113ff */ + /* 0x11400-0x115ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0x11400-0x1143f */ + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11440-0x1147f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x85, /* 0x11480-0x114bf */ + 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x114c0-0x114ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11500-0x1153f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11540-0x1157f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xb0, /* 0x11580-0x115bf */ + 0x01, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, /* 0x115c0-0x115ff */ + /* 0x11600-0x117ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa7, /* 0x11600-0x1163f */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11640-0x1167f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xbf, 0x00, /* 0x11680-0x116bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x116c0-0x116ff */ + 0x00, 0x00, 0x00, 0xe0, 0xbc, 0x0f, 0x00, 0x00, /* 0x11700-0x1173f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11740-0x1177f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11780-0x117bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x117c0-0x117ff */ + /* 0x11c00-0x11dff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x3f, /* 0x11c00-0x11c3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11c40-0x11c7f */ + 0x00, 0x00, 0xfc, 0xff, 0xff, 0xfc, 0x6d, 0x00, /* 0x11c80-0x11cbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11cc0-0x11cff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11d00-0x11d3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11d40-0x11d7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11d80-0x11dbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11dc0-0x11dff */ + /* 0x16a00-0x16bff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16a00-0x16a3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16a40-0x16a7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16a80-0x16abf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, /* 0x16ac0-0x16aff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, /* 0x16b00-0x16b3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16b40-0x16b7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16b80-0x16bbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16bc0-0x16bff */ + /* 0x16e00-0x16fff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16e00-0x16e3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16e40-0x16e7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16e80-0x16ebf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16ec0-0x16eff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16f00-0x16f3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16f40-0x16f7f */ + 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16f80-0x16fbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16fc0-0x16fff */ + /* 0x1bc00-0x1bdff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1bc00-0x1bc3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1bc40-0x1bc7f */ + 0x00, 0x00, 0x00, 0x60, 0x0f, 0x00, 0x00, 0x00, /* 0x1bc80-0x1bcbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1bcc0-0x1bcff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1bd00-0x1bd3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1bd40-0x1bd7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1bd80-0x1bdbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1bdc0-0x1bdff */ + /* 0x1d000-0x1d1ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d000-0x1d03f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d040-0x1d07f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d080-0x1d0bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d0c0-0x1d0ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d100-0x1d13f */ + 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xf8, 0xff, /* 0x1d140-0x1d17f */ + 0xe7, 0x0f, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, /* 0x1d180-0x1d1bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d1c0-0x1d1ff */ + /* 0x1d200-0x1d3ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d200-0x1d23f */ + 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d240-0x1d27f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d280-0x1d2bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d2c0-0x1d2ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d300-0x1d33f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d340-0x1d37f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d380-0x1d3bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d3c0-0x1d3ff */ + /* 0x1da00-0x1dbff */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf8, /* 0x1da00-0x1da3f */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x20, 0x00, /* 0x1da40-0x1da7f */ + 0x10, 0x00, 0x00, 0xf8, 0xfe, 0xff, 0x00, 0x00, /* 0x1da80-0x1dabf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1dac0-0x1daff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1db00-0x1db3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1db40-0x1db7f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1db80-0x1dbbf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1dbc0-0x1dbff */ + /* 0x1e000-0x1e1ff */ + 0x7f, 0xff, 0xff, 0xf9, 0xdb, 0x07, 0x00, 0x00, /* 0x1e000-0x1e03f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e040-0x1e07f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e080-0x1e0bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e0c0-0x1e0ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e100-0x1e13f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e140-0x1e17f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e180-0x1e1bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e1c0-0x1e1ff */ + /* 0x1e800-0x1e9ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e800-0x1e83f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e840-0x1e87f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e880-0x1e8bf */ + 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e8c0-0x1e8ff */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e900-0x1e93f */ + 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e940-0x1e97f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e980-0x1e9bf */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0x1e9c0-0x1e9ff */ +}; +static const signed char nonspacing_table_ind[248] = { + 0, 1, 2, 3, 4, 5, 6, 7, /* 0x0000-0x0fff */ + 8, 9, -1, 10, 11, 12, 13, -1, /* 0x1000-0x1fff */ + 14, -1, -1, -1, -1, -1, 15, -1, /* 0x2000-0x2fff */ + 16, -1, -1, -1, -1, -1, -1, -1, /* 0x3000-0x3fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x4000-0x4fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x5000-0x5fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x6000-0x6fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x7000-0x7fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x8000-0x8fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9000-0x9fff */ + -1, -1, -1, 17, 18, 19, -1, -1, /* 0xa000-0xafff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb000-0xbfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc000-0xcfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd000-0xdfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe000-0xefff */ + -1, -1, -1, -1, -1, 20, -1, 21, /* 0xf000-0xffff */ + 22, 23, -1, -1, -1, 24, -1, -1, /* 0x10000-0x10fff */ + 25, 26, 27, 28, -1, -1, 29, -1, /* 0x11000-0x11fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x12000-0x12fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x13000-0x13fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x14000-0x14fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x15000-0x15fff */ + -1, -1, -1, -1, -1, 30, -1, 31, /* 0x16000-0x16fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x17000-0x17fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x18000-0x18fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x19000-0x19fff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1a000-0x1afff */ + -1, -1, -1, -1, -1, -1, 32, -1, /* 0x1b000-0x1bfff */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x1c000-0x1cfff */ + 33, 34, -1, -1, -1, 35, -1, -1, /* 0x1d000-0x1dfff */ + 36, -1, -1, -1, 37, -1, -1, -1 /* 0x1e000-0x1efff */ +}; + +/* Determine number of column positions required for UC. */ +int +uc_width (ucs4_t uc, const char *encoding) +{ + /* Test for non-spacing or control character. */ + if ((uc >> 9) < 248) + { + int ind = nonspacing_table_ind[uc >> 9]; + if (ind >= 0) + if ((nonspacing_table_data[64*ind + ((uc >> 3) & 63)] >> (uc & 7)) & 1) + { + if (uc > 0 && uc < 0xa0) + return -1; + else + return 0; + } + } + else if ((uc >> 9) == (0xe0000 >> 9)) + { + if (uc >= 0xe0100) + { + if (uc <= 0xe01ef) + return 0; + } + else + { + if (uc >= 0xe0020 ? uc <= 0xe007f : uc == 0xe0001) + return 0; + } + } + /* Test for double-width character. + * Generated from "grep '^[^;]\{4,5\};[WF]' EastAsianWidth.txt" + * and "grep '^[^;]\{4,5\};[^WF]' EastAsianWidth.txt" + */ + if (uc >= 0x1100 + && ((uc < 0x1160) /* Hangul Jamo */ + || (uc >= 0x2329 && uc < 0x232b) /* Angle Brackets */ + || (uc >= 0x2e80 && uc < 0xa4d0 /* CJK ... Yi */ + && !(uc == 0x303f) && !(uc >= 0x4dc0 && uc < 0x4e00)) + || (uc >= 0xac00 && uc < 0xd7a4) /* Hangul Syllables */ + || (uc >= 0xf900 && uc < 0xfb00) /* CJK Compatibility Ideographs */ + || (uc >= 0xfe10 && uc < 0xfe20) /* Presentation Forms for Vertical */ + || (uc >= 0xfe30 && uc < 0xfe70) /* CJK Compatibility Forms */ + || (uc >= 0xff00 && uc < 0xff61) /* Fullwidth Forms */ + || (uc >= 0xffe0 && uc < 0xffe7) /* Fullwidth Signs */ + || (uc >= 0x20000 && uc <= 0x2ffff) /* Supplementary Ideographic Plane */ + || (uc >= 0x30000 && uc <= 0x3ffff) /* Tertiary Ideographic Plane */ + ) ) + return 2; + /* In ancient CJK encodings, Cyrillic and most other characters are + double-width as well. */ + if (uc >= 0x00A1 && uc < 0xFF61 && uc != 0x20A9 + && is_cjk_encoding (encoding)) + return 2; + return 1; +} diff --git a/grub-core/lib/gnulib/vasnprintf.c b/grub-core/lib/gnulib/vasnprintf.c new file mode 100644 index 0000000..c475903 --- /dev/null +++ b/grub-core/lib/gnulib/vasnprintf.c @@ -0,0 +1,5621 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 1999, 2002-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* This file can be parametrized with the following macros: + VASNPRINTF The name of the function being defined. + FCHAR_T The element type of the format string. + DCHAR_T The element type of the destination (result) string. + FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters + in the format string are ASCII. MUST be set if + FCHAR_T and DCHAR_T are not the same type. + DIRECTIVE Structure denoting a format directive. + Depends on FCHAR_T. + DIRECTIVES Structure denoting the set of format directives of a + format string. Depends on FCHAR_T. + PRINTF_PARSE Function that parses a format string. + Depends on FCHAR_T. + DCHAR_CPY memcpy like function for DCHAR_T[] arrays. + DCHAR_SET memset like function for DCHAR_T[] arrays. + DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays. + SNPRINTF The system's snprintf (or similar) function. + This may be either snprintf or swprintf. + TCHAR_T The element type of the argument and result string + of the said SNPRINTF function. This may be either + char or wchar_t. The code exploits that + sizeof (TCHAR_T) | sizeof (DCHAR_T) and + alignof (TCHAR_T) <= alignof (DCHAR_T). + DCHAR_IS_TCHAR Set to 1 if DCHAR_T and TCHAR_T are the same type. + DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[]. + DCHAR_IS_UINT8_T Set to 1 if DCHAR_T is uint8_t. + DCHAR_IS_UINT16_T Set to 1 if DCHAR_T is uint16_t. + DCHAR_IS_UINT32_T Set to 1 if DCHAR_T is uint32_t. */ + +/* Tell glibc's <stdio.h> to provide a prototype for snprintf(). + This must come before <config.h> because <config.h> may include + <features.h>, and once <features.h> has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifndef VASNPRINTF +# include <config.h> +#endif +#ifndef IN_LIBINTL +# include <alloca.h> +#endif + +/* Specification. */ +#ifndef VASNPRINTF +# if WIDE_CHAR_VERSION +# include "vasnwprintf.h" +# else +# include "vasnprintf.h" +# endif +#endif + +#include <locale.h> /* localeconv() */ +#include <stdio.h> /* snprintf(), sprintf() */ +#include <stdlib.h> /* abort(), malloc(), realloc(), free() */ +#include <string.h> /* memcpy(), strlen() */ +#include <errno.h> /* errno */ +#include <limits.h> /* CHAR_BIT */ +#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */ +#if HAVE_NL_LANGINFO +# include <langinfo.h> +#endif +#ifndef VASNPRINTF +# if WIDE_CHAR_VERSION +# include "wprintf-parse.h" +# else +# include "printf-parse.h" +# endif +#endif + +/* Checked size_t computations. */ +#include "xsize.h" + +#include "verify.h" + +#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL +# include <math.h> +# include "float+.h" +#endif + +#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL +# include <math.h> +# include "isnand-nolibm.h" +#endif + +#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL +# include <math.h> +# include "isnanl-nolibm.h" +# include "fpucw.h" +#endif + +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL +# include <math.h> +# include "isnand-nolibm.h" +# include "printf-frexp.h" +#endif + +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL +# include <math.h> +# include "isnanl-nolibm.h" +# include "printf-frexpl.h" +# include "fpucw.h" +#endif + +#ifndef FALLTHROUGH +# if __GNUC__ < 7 +# define FALLTHROUGH ((void) 0) +# else +# define FALLTHROUGH __attribute__ ((__fallthrough__)) +# endif +#endif + +/* Default parameters. */ +#ifndef VASNPRINTF +# if WIDE_CHAR_VERSION +# define VASNPRINTF vasnwprintf +# define FCHAR_T wchar_t +# define DCHAR_T wchar_t +# define TCHAR_T wchar_t +# define DCHAR_IS_TCHAR 1 +# define DIRECTIVE wchar_t_directive +# define DIRECTIVES wchar_t_directives +# define PRINTF_PARSE wprintf_parse +# define DCHAR_CPY wmemcpy +# define DCHAR_SET wmemset +# else +# define VASNPRINTF vasnprintf +# define FCHAR_T char +# define DCHAR_T char +# define TCHAR_T char +# define DCHAR_IS_TCHAR 1 +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +# define PRINTF_PARSE printf_parse +# define DCHAR_CPY memcpy +# define DCHAR_SET memset +# endif +#endif +#if WIDE_CHAR_VERSION + /* TCHAR_T is wchar_t. */ +# define USE_SNPRINTF 1 +# if HAVE_DECL__SNWPRINTF + /* On Windows, the function swprintf() has a different signature than + on Unix; we use the function _snwprintf() or - on mingw - snwprintf() + instead. The mingw function snwprintf() has fewer bugs than the + MSVCRT function _snwprintf(), so prefer that. */ +# if defined __MINGW32__ +# define SNPRINTF snwprintf +# else +# define SNPRINTF _snwprintf +# define USE_MSVC__SNPRINTF 1 +# endif +# else + /* Unix. */ +# define SNPRINTF swprintf +# endif +#else + /* TCHAR_T is char. */ + /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'. + But don't use it on BeOS, since BeOS snprintf produces no output if the + size argument is >= 0x3000000. + Also don't use it on Linux libc5, since there snprintf with size = 1 + writes any output without bounds, like sprintf. */ +# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1) +# define USE_SNPRINTF 1 +# else +# define USE_SNPRINTF 0 +# endif +# if HAVE_DECL__SNPRINTF + /* Windows. The mingw function snprintf() has fewer bugs than the MSVCRT + function _snprintf(), so prefer that. */ +# if defined __MINGW32__ +# define SNPRINTF snprintf + /* Here we need to call the native snprintf, not rpl_snprintf. */ +# undef snprintf +# else + /* MSVC versions < 14 did not have snprintf, only _snprintf. */ +# define SNPRINTF _snprintf +# define USE_MSVC__SNPRINTF 1 +# endif +# else + /* Unix. */ +# define SNPRINTF snprintf + /* Here we need to call the native snprintf, not rpl_snprintf. */ +# undef snprintf +# endif +#endif +/* Here we need to call the native sprintf, not rpl_sprintf. */ +#undef sprintf + +/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized" + warnings in this file. Use -Dlint to suppress them. */ +#if defined GCC_LINT || defined lint +# define IF_LINT(Code) Code +#else +# define IF_LINT(Code) /* empty */ +#endif + +/* Avoid some warnings from "gcc -Wshadow". + This file doesn't use the exp() and remainder() functions. */ +#undef exp +#define exp expo +#undef remainder +#define remainder rem + +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && !WIDE_CHAR_VERSION +# if (HAVE_STRNLEN && !defined _AIX) +# define local_strnlen strnlen +# else +# ifndef local_strnlen_defined +# define local_strnlen_defined 1 +static size_t +local_strnlen (const char *string, size_t maxlen) +{ + const char *end = memchr (string, '\0', maxlen); + return end ? (size_t) (end - string) : maxlen; +} +# endif +# endif +#endif + +#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T +# if HAVE_WCSLEN +# define local_wcslen wcslen +# else + /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid + a dependency towards this library, here is a local substitute. + Define this substitute only once, even if this file is included + twice in the same compilation unit. */ +# ifndef local_wcslen_defined +# define local_wcslen_defined 1 +static size_t +local_wcslen (const wchar_t *s) +{ + const wchar_t *ptr; + + for (ptr = s; *ptr != (wchar_t) 0; ptr++) + ; + return ptr - s; +} +# endif +# endif +#endif + +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && HAVE_WCHAR_T && WIDE_CHAR_VERSION +# if HAVE_WCSNLEN +# define local_wcsnlen wcsnlen +# else +# ifndef local_wcsnlen_defined +# define local_wcsnlen_defined 1 +static size_t +local_wcsnlen (const wchar_t *s, size_t maxlen) +{ + const wchar_t *ptr; + + for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--) + ; + return ptr - s; +} +# endif +# endif +#endif + +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL +/* Determine the decimal-point character according to the current locale. */ +# ifndef decimal_point_char_defined +# define decimal_point_char_defined 1 +static char +decimal_point_char (void) +{ + const char *point; + /* Determine it in a multithread-safe way. We know nl_langinfo is + multithread-safe on glibc systems and Mac OS X systems, but is not required + to be multithread-safe by POSIX. sprintf(), however, is multithread-safe. + localeconv() is rarely multithread-safe. */ +# if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__)) + point = nl_langinfo (RADIXCHAR); +# elif 1 + char pointbuf[5]; + sprintf (pointbuf, "%#.0f", 1.0); + point = &pointbuf[1]; +# else + point = localeconv () -> decimal_point; +# endif + /* The decimal point is always a single byte: either '.' or ','. */ + return (point[0] != '\0' ? point[0] : '.'); +} +# endif +#endif + +#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL + +/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */ +static int +is_infinite_or_zero (double x) +{ + return isnand (x) || x + x == x; +} + +#endif + +#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL + +/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */ +static int +is_infinite_or_zerol (long double x) +{ + return isnanl (x) || x + x == x; +} + +#endif + +#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL + +/* Converting 'long double' to decimal without rare rounding bugs requires + real bignums. We use the naming conventions of GNU gmp, but vastly simpler + (and slower) algorithms. */ + +typedef unsigned int mp_limb_t; +# define GMP_LIMB_BITS 32 +verify (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS); + +typedef unsigned long long mp_twolimb_t; +# define GMP_TWOLIMB_BITS 64 +verify (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS); + +/* Representation of a bignum >= 0. */ +typedef struct +{ + size_t nlimbs; + mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc(). */ +} mpn_t; + +/* Compute the product of two bignums >= 0. + Return the allocated memory in case of success, NULL in case of memory + allocation failure. */ +static void * +multiply (mpn_t src1, mpn_t src2, mpn_t *dest) +{ + const mp_limb_t *p1; + const mp_limb_t *p2; + size_t len1; + size_t len2; + + if (src1.nlimbs <= src2.nlimbs) + { + len1 = src1.nlimbs; + p1 = src1.limbs; + len2 = src2.nlimbs; + p2 = src2.limbs; + } + else + { + len1 = src2.nlimbs; + p1 = src2.limbs; + len2 = src1.nlimbs; + p2 = src1.limbs; + } + /* Now 0 <= len1 <= len2. */ + if (len1 == 0) + { + /* src1 or src2 is zero. */ + dest->nlimbs = 0; + dest->limbs = (mp_limb_t *) malloc (1); + } + else + { + /* Here 1 <= len1 <= len2. */ + size_t dlen; + mp_limb_t *dp; + size_t k, i, j; + + dlen = len1 + len2; + dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t)); + if (dp == NULL) + return NULL; + for (k = len2; k > 0; ) + dp[--k] = 0; + for (i = 0; i < len1; i++) + { + mp_limb_t digit1 = p1[i]; + mp_twolimb_t carry = 0; + for (j = 0; j < len2; j++) + { + mp_limb_t digit2 = p2[j]; + carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2; + carry += dp[i + j]; + dp[i + j] = (mp_limb_t) carry; + carry = carry >> GMP_LIMB_BITS; + } + dp[i + len2] = (mp_limb_t) carry; + } + /* Normalise. */ + while (dlen > 0 && dp[dlen - 1] == 0) + dlen--; + dest->nlimbs = dlen; + dest->limbs = dp; + } + return dest->limbs; +} + +/* Compute the quotient of a bignum a >= 0 and a bignum b > 0. + a is written as a = q * b + r with 0 <= r < b. q is the quotient, r + the remainder. + Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd, + q is incremented. + Return the allocated memory in case of success, NULL in case of memory + allocation failure. */ +static void * +divide (mpn_t a, mpn_t b, mpn_t *q) +{ + /* Algorithm: + First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]] + with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS). + If m<n, then q:=0 and r:=a. + If m>=n=1, perform a single-precision division: + r:=0, j:=m, + while j>0 do + {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j = + = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta} + j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j]. + Normalise [q[m-1],...,q[0]], yields q. + If m>=n>1, perform a multiple-precision division: + We have a/b < beta^(m-n+1). + s:=intDsize-1-(highest bit in b[n-1]), 0<=s<intDsize. + Shift a and b left by s bits, copying them. r:=a. + r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2. + For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).} + Compute q* : + q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]). + In case of overflow (q* >= beta) set q* := beta-1. + Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2] + and c3 := b[n-2] * q*. + {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow + occurred. Furthermore 0 <= c3 < beta^2. + If there was overflow and + r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2, + the next test can be skipped.} + While c3 > c2, {Here 0 <= c2 < c3 < beta^2} + Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2]. + If q* > 0: + Put r := r - b * q* * beta^j. In detail: + [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]]. + hence: u:=0, for i:=0 to n-1 do + u := u + q* * b[i], + r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry), + u:=u div beta (+ 1, if carry in subtraction) + r[n+j]:=r[n+j]-u. + {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1 + < q* + 1 <= beta, + the carry u does not overflow.} + If a negative carry occurs, put q* := q* - 1 + and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]]. + Set q[j] := q*. + Normalise [q[m-n],..,q[0]]; this yields the quotient q. + Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the + rest r. + The room for q[j] can be allocated at the memory location of r[n+j]. + Finally, round-to-even: + Shift r left by 1 bit. + If r > b or if r = b and q[0] is odd, q := q+1. + */ + const mp_limb_t *a_ptr = a.limbs; + size_t a_len = a.nlimbs; + const mp_limb_t *b_ptr = b.limbs; + size_t b_len = b.nlimbs; + mp_limb_t *roomptr; + mp_limb_t *tmp_roomptr = NULL; + mp_limb_t *q_ptr; + size_t q_len; + mp_limb_t *r_ptr; + size_t r_len; + + /* Allocate room for a_len+2 digits. + (Need a_len+1 digits for the real division and 1 more digit for the + final rounding of q.) */ + roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t)); + if (roomptr == NULL) + return NULL; + + /* Normalise a. */ + while (a_len > 0 && a_ptr[a_len - 1] == 0) + a_len--; + + /* Normalise b. */ + for (;;) + { + if (b_len == 0) + /* Division by zero. */ + abort (); + if (b_ptr[b_len - 1] == 0) + b_len--; + else + break; + } + + /* Here m = a_len >= 0 and n = b_len > 0. */ + + if (a_len < b_len) + { + /* m<n: trivial case. q=0, r := copy of a. */ + r_ptr = roomptr; + r_len = a_len; + memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t)); + q_ptr = roomptr + a_len; + q_len = 0; + } + else if (b_len == 1) + { + /* n=1: single precision division. + beta^(m-1) <= a < beta^m ==> beta^(m-2) <= a/b < beta^m */ + r_ptr = roomptr; + q_ptr = roomptr + 1; + { + mp_limb_t den = b_ptr[0]; + mp_limb_t remainder = 0; + const mp_limb_t *sourceptr = a_ptr + a_len; + mp_limb_t *destptr = q_ptr + a_len; + size_t count; + for (count = a_len; count > 0; count--) + { + mp_twolimb_t num = + ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr; + *--destptr = num / den; + remainder = num % den; + } + /* Normalise and store r. */ + if (remainder > 0) + { + r_ptr[0] = remainder; + r_len = 1; + } + else + r_len = 0; + /* Normalise q. */ + q_len = a_len; + if (q_ptr[q_len - 1] == 0) + q_len--; + } + } + else + { + /* n>1: multiple precision division. + beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==> + beta^(m-n-1) <= a/b < beta^(m-n+1). */ + /* Determine s. */ + size_t s; + { + mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */ + /* Determine s = GMP_LIMB_BITS - integer_length (msd). + Code copied from gnulib's integer_length.c. */ +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + s = __builtin_clz (msd); +# else +# if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT + if (GMP_LIMB_BITS <= DBL_MANT_BIT) + { + /* Use 'double' operations. + Assumes an IEEE 754 'double' implementation. */ +# define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7) +# define DBL_EXP_BIAS (DBL_EXP_MASK / 2 - 1) +# define NWORDS \ + ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + union { double value; unsigned int word[NWORDS]; } m; + + /* Use a single integer to floating-point conversion. */ + m.value = msd; + + s = GMP_LIMB_BITS + - (((m.word[DBL_EXPBIT0_WORD] >> DBL_EXPBIT0_BIT) & DBL_EXP_MASK) + - DBL_EXP_BIAS); + } + else +# undef NWORDS +# endif + { + s = 31; + if (msd >= 0x10000) + { + msd = msd >> 16; + s -= 16; + } + if (msd >= 0x100) + { + msd = msd >> 8; + s -= 8; + } + if (msd >= 0x10) + { + msd = msd >> 4; + s -= 4; + } + if (msd >= 0x4) + { + msd = msd >> 2; + s -= 2; + } + if (msd >= 0x2) + { + msd = msd >> 1; + s -= 1; + } + } +# endif + } + /* 0 <= s < GMP_LIMB_BITS. + Copy b, shifting it left by s bits. */ + if (s > 0) + { + tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t)); + if (tmp_roomptr == NULL) + { + free (roomptr); + return NULL; + } + { + const mp_limb_t *sourceptr = b_ptr; + mp_limb_t *destptr = tmp_roomptr; + mp_twolimb_t accu = 0; + size_t count; + for (count = b_len; count > 0; count--) + { + accu += (mp_twolimb_t) *sourceptr++ << s; + *destptr++ = (mp_limb_t) accu; + accu = accu >> GMP_LIMB_BITS; + } + /* accu must be zero, since that was how s was determined. */ + if (accu != 0) + abort (); + } + b_ptr = tmp_roomptr; + } + /* Copy a, shifting it left by s bits, yields r. + Memory layout: + At the beginning: r = roomptr[0..a_len], + at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len] */ + r_ptr = roomptr; + if (s == 0) + { + memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t)); + r_ptr[a_len] = 0; + } + else + { + const mp_limb_t *sourceptr = a_ptr; + mp_limb_t *destptr = r_ptr; + mp_twolimb_t accu = 0; + size_t count; + for (count = a_len; count > 0; count--) + { + accu += (mp_twolimb_t) *sourceptr++ << s; + *destptr++ = (mp_limb_t) accu; + accu = accu >> GMP_LIMB_BITS; + } + *destptr++ = (mp_limb_t) accu; + } + q_ptr = roomptr + b_len; + q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */ + { + size_t j = a_len - b_len; /* m-n */ + mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */ + mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */ + mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */ + ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd; + /* Division loop, traversed m-n+1 times. + j counts down, b is unchanged, beta/2 <= b[n-1] < beta. */ + for (;;) + { + mp_limb_t q_star; + mp_limb_t c1; + if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */ + { + /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow. */ + mp_twolimb_t num = + ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS) + | r_ptr[j + b_len - 1]; + q_star = num / b_msd; + c1 = num % b_msd; + } + else + { + /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1]. */ + q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */ + /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta + <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta + <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) + {<= beta !}. + If yes, jump directly to the subtraction loop. + (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta + <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */ + if (r_ptr[j + b_len] > b_msd + || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd) + /* r[j+n] >= b[n-1]+1 or + r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a + carry. */ + goto subtract; + } + /* q_star = q*, + c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta). */ + { + mp_twolimb_t c2 = /* c1*beta+r[j+n-2] */ + ((mp_twolimb_t) c1 << GMP_LIMB_BITS) | r_ptr[j + b_len - 2]; + mp_twolimb_t c3 = /* b[n-2] * q* */ + (mp_twolimb_t) b_2msd * (mp_twolimb_t) q_star; + /* While c2 < c3, increase c2 and decrease c3. + Consider c3-c2. While it is > 0, decrease it by + b[n-1]*beta+b[n-2]. Because of b[n-1]*beta+b[n-2] >= beta^2/2 + this can happen only twice. */ + if (c3 > c2) + { + q_star = q_star - 1; /* q* := q* - 1 */ + if (c3 - c2 > b_msdd) + q_star = q_star - 1; /* q* := q* - 1 */ + } + } + if (q_star > 0) + subtract: + { + /* Subtract r := r - b * q* * beta^j. */ + mp_limb_t cr; + { + const mp_limb_t *sourceptr = b_ptr; + mp_limb_t *destptr = r_ptr + j; + mp_twolimb_t carry = 0; + size_t count; + for (count = b_len; count > 0; count--) + { + /* Here 0 <= carry <= q*. */ + carry = + carry + + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++ + + (mp_limb_t) ~(*destptr); + /* Here 0 <= carry <= beta*q* + beta-1. */ + *destptr++ = ~(mp_limb_t) carry; + carry = carry >> GMP_LIMB_BITS; /* <= q* */ + } + cr = (mp_limb_t) carry; + } + /* Subtract cr from r_ptr[j + b_len], then forget about + r_ptr[j + b_len]. */ + if (cr > r_ptr[j + b_len]) + { + /* Subtraction gave a carry. */ + q_star = q_star - 1; /* q* := q* - 1 */ + /* Add b back. */ + { + const mp_limb_t *sourceptr = b_ptr; + mp_limb_t *destptr = r_ptr + j; + mp_limb_t carry = 0; + size_t count; + for (count = b_len; count > 0; count--) + { + mp_limb_t source1 = *sourceptr++; + mp_limb_t source2 = *destptr; + *destptr++ = source1 + source2 + carry; + carry = + (carry + ? source1 >= (mp_limb_t) ~source2 + : source1 > (mp_limb_t) ~source2); + } + } + /* Forget about the carry and about r[j+n]. */ + } + } + /* q* is determined. Store it as q[j]. */ + q_ptr[j] = q_star; + if (j == 0) + break; + j--; + } + } + r_len = b_len; + /* Normalise q. */ + if (q_ptr[q_len - 1] == 0) + q_len--; +# if 0 /* Not needed here, since we need r only to compare it with b/2, and + b is shifted left by s bits. */ + /* Shift r right by s bits. */ + if (s > 0) + { + mp_limb_t ptr = r_ptr + r_len; + mp_twolimb_t accu = 0; + size_t count; + for (count = r_len; count > 0; count--) + { + accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS; + accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s); + *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS); + } + } +# endif + /* Normalise r. */ + while (r_len > 0 && r_ptr[r_len - 1] == 0) + r_len--; + } + /* Compare r << 1 with b. */ + if (r_len > b_len) + goto increment_q; + { + size_t i; + for (i = b_len;;) + { + mp_limb_t r_i = + (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0) + | (i < r_len ? r_ptr[i] << 1 : 0); + mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0); + if (r_i > b_i) + goto increment_q; + if (r_i < b_i) + goto keep_q; + if (i == 0) + break; + i--; + } + } + if (q_len > 0 && ((q_ptr[0] & 1) != 0)) + /* q is odd. */ + increment_q: + { + size_t i; + for (i = 0; i < q_len; i++) + if (++(q_ptr[i]) != 0) + goto keep_q; + q_ptr[q_len++] = 1; + } + keep_q: + if (tmp_roomptr != NULL) + free (tmp_roomptr); + q->limbs = q_ptr; + q->nlimbs = q_len; + return roomptr; +} + +/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal + representation. + Destroys the contents of a. + Return the allocated memory - containing the decimal digits in low-to-high + order, terminated with a NUL character - in case of success, NULL in case + of memory allocation failure. */ +static char * +convert_to_decimal (mpn_t a, size_t extra_zeroes) +{ + mp_limb_t *a_ptr = a.limbs; + size_t a_len = a.nlimbs; + /* 0.03345 is slightly larger than log(2)/(9*log(10)). */ + size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1); + /* We need extra_zeroes bytes for zeroes, followed by c_len bytes for the + digits of a, followed by 1 byte for the terminating NUL. */ + char *c_ptr = (char *) malloc (xsum (xsum (extra_zeroes, c_len), 1)); + if (c_ptr != NULL) + { + char *d_ptr = c_ptr; + for (; extra_zeroes > 0; extra_zeroes--) + *d_ptr++ = '0'; + while (a_len > 0) + { + /* Divide a by 10^9, in-place. */ + mp_limb_t remainder = 0; + mp_limb_t *ptr = a_ptr + a_len; + size_t count; + for (count = a_len; count > 0; count--) + { + mp_twolimb_t num = + ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr; + *ptr = num / 1000000000; + remainder = num % 1000000000; + } + /* Store the remainder as 9 decimal digits. */ + for (count = 9; count > 0; count--) + { + *d_ptr++ = '0' + (remainder % 10); + remainder = remainder / 10; + } + /* Normalize a. */ + if (a_ptr[a_len - 1] == 0) + a_len--; + } + /* Remove leading zeroes. */ + while (d_ptr > c_ptr && d_ptr[-1] == '0') + d_ptr--; + /* But keep at least one zero. */ + if (d_ptr == c_ptr) + *d_ptr++ = '0'; + /* Terminate the string. */ + *d_ptr = '\0'; + } + return c_ptr; +} + +# if NEED_PRINTF_LONG_DOUBLE + +/* Assuming x is finite and >= 0: + write x as x = 2^e * m, where m is a bignum. + Return the allocated memory in case of success, NULL in case of memory + allocation failure. */ +static void * +decode_long_double (long double x, int *ep, mpn_t *mp) +{ + mpn_t m; + int exp; + long double y; + size_t i; + + /* Allocate memory for result. */ + m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; + m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t)); + if (m.limbs == NULL) + return NULL; + /* Split into exponential part and mantissa. */ + y = frexpl (x, &exp); + if (!(y >= 0.0L && y < 1.0L)) + abort (); + /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the + latter is an integer. */ + /* Convert the mantissa (y * 2^LDBL_MANT_BIT) to a sequence of limbs. + I'm not sure whether it's safe to cast a 'long double' value between + 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only + 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int', + doesn't matter). */ +# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0 +# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2 + { + mp_limb_t hi, lo; + y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2)); + hi = (int) y; + y -= hi; + if (!(y >= 0.0L && y < 1.0L)) + abort (); + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + lo = (int) y; + y -= lo; + if (!(y >= 0.0L && y < 1.0L)) + abort (); + m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo; + } +# else + { + mp_limb_t d; + y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS); + d = (int) y; + y -= d; + if (!(y >= 0.0L && y < 1.0L)) + abort (); + m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d; + } +# endif +# endif + for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; ) + { + mp_limb_t hi, lo; + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + hi = (int) y; + y -= hi; + if (!(y >= 0.0L && y < 1.0L)) + abort (); + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + lo = (int) y; + y -= lo; + if (!(y >= 0.0L && y < 1.0L)) + abort (); + m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo; + } +# if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess + precision. */ + if (!(y == 0.0L)) + abort (); +# endif + /* Normalise. */ + while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0) + m.nlimbs--; + *mp = m; + *ep = exp - LDBL_MANT_BIT; + return m.limbs; +} + +# endif + +# if NEED_PRINTF_DOUBLE + +/* Assuming x is finite and >= 0: + write x as x = 2^e * m, where m is a bignum. + Return the allocated memory in case of success, NULL in case of memory + allocation failure. */ +static void * +decode_double (double x, int *ep, mpn_t *mp) +{ + mpn_t m; + int exp; + double y; + size_t i; + + /* Allocate memory for result. */ + m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; + m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t)); + if (m.limbs == NULL) + return NULL; + /* Split into exponential part and mantissa. */ + y = frexp (x, &exp); + if (!(y >= 0.0 && y < 1.0)) + abort (); + /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * 2^DBL_MANT_BIT), and the + latter is an integer. */ + /* Convert the mantissa (y * 2^DBL_MANT_BIT) to a sequence of limbs. + I'm not sure whether it's safe to cast a 'double' value between + 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only + 'double' values between 0 and 2^16 (to 'unsigned int' or 'int', + doesn't matter). */ +# if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0 +# if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2 + { + mp_limb_t hi, lo; + y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2)); + hi = (int) y; + y -= hi; + if (!(y >= 0.0 && y < 1.0)) + abort (); + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + lo = (int) y; + y -= lo; + if (!(y >= 0.0 && y < 1.0)) + abort (); + m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo; + } +# else + { + mp_limb_t d; + y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS); + d = (int) y; + y -= d; + if (!(y >= 0.0 && y < 1.0)) + abort (); + m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d; + } +# endif +# endif + for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; ) + { + mp_limb_t hi, lo; + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + hi = (int) y; + y -= hi; + if (!(y >= 0.0 && y < 1.0)) + abort (); + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + lo = (int) y; + y -= lo; + if (!(y >= 0.0 && y < 1.0)) + abort (); + m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo; + } + if (!(y == 0.0)) + abort (); + /* Normalise. */ + while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0) + m.nlimbs--; + *mp = m; + *ep = exp - DBL_MANT_BIT; + return m.limbs; +} + +# endif + +/* Assuming x = 2^e * m is finite and >= 0, and n is an integer: + Returns the decimal representation of round (x * 10^n). + Return the allocated memory - containing the decimal digits in low-to-high + order, terminated with a NUL character - in case of success, NULL in case + of memory allocation failure. */ +static char * +scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n) +{ + int s; + size_t extra_zeroes; + unsigned int abs_n; + unsigned int abs_s; + mp_limb_t *pow5_ptr; + size_t pow5_len; + unsigned int s_limbs; + unsigned int s_bits; + mpn_t pow5; + mpn_t z; + void *z_memory; + char *digits; + + if (memory == NULL) + return NULL; + /* x = 2^e * m, hence + y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m) + = round (2^s * 5^n * m). */ + s = e + n; + extra_zeroes = 0; + /* Factor out a common power of 10 if possible. */ + if (s > 0 && n > 0) + { + extra_zeroes = (s < n ? s : n); + s -= extra_zeroes; + n -= extra_zeroes; + } + /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes. + Before converting to decimal, we need to compute + z = round (2^s * 5^n * m). */ + /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same + sign. 2.322 is slightly larger than log(5)/log(2). */ + abs_n = (n >= 0 ? n : -n); + abs_s = (s >= 0 ? s : -s); + pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1 + + abs_s / GMP_LIMB_BITS + 1) + * sizeof (mp_limb_t)); + if (pow5_ptr == NULL) + { + free (memory); + return NULL; + } + /* Initialize with 1. */ + pow5_ptr[0] = 1; + pow5_len = 1; + /* Multiply with 5^|n|. */ + if (abs_n > 0) + { + static mp_limb_t const small_pow5[13 + 1] = + { + 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, + 48828125, 244140625, 1220703125 + }; + unsigned int n13; + for (n13 = 0; n13 <= abs_n; n13 += 13) + { + mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13]; + size_t j; + mp_twolimb_t carry = 0; + for (j = 0; j < pow5_len; j++) + { + mp_limb_t digit2 = pow5_ptr[j]; + carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2; + pow5_ptr[j] = (mp_limb_t) carry; + carry = carry >> GMP_LIMB_BITS; + } + if (carry > 0) + pow5_ptr[pow5_len++] = (mp_limb_t) carry; + } + } + s_limbs = abs_s / GMP_LIMB_BITS; + s_bits = abs_s % GMP_LIMB_BITS; + if (n >= 0 ? s >= 0 : s <= 0) + { + /* Multiply with 2^|s|. */ + if (s_bits > 0) + { + mp_limb_t *ptr = pow5_ptr; + mp_twolimb_t accu = 0; + size_t count; + for (count = pow5_len; count > 0; count--) + { + accu += (mp_twolimb_t) *ptr << s_bits; + *ptr++ = (mp_limb_t) accu; + accu = accu >> GMP_LIMB_BITS; + } + if (accu > 0) + { + *ptr = (mp_limb_t) accu; + pow5_len++; + } + } + if (s_limbs > 0) + { + size_t count; + for (count = pow5_len; count > 0;) + { + count--; + pow5_ptr[s_limbs + count] = pow5_ptr[count]; + } + for (count = s_limbs; count > 0;) + { + count--; + pow5_ptr[count] = 0; + } + pow5_len += s_limbs; + } + pow5.limbs = pow5_ptr; + pow5.nlimbs = pow5_len; + if (n >= 0) + { + /* Multiply m with pow5. No division needed. */ + z_memory = multiply (m, pow5, &z); + } + else + { + /* Divide m by pow5 and round. */ + z_memory = divide (m, pow5, &z); + } + } + else + { + pow5.limbs = pow5_ptr; + pow5.nlimbs = pow5_len; + if (n >= 0) + { + /* n >= 0, s < 0. + Multiply m with pow5, then divide by 2^|s|. */ + mpn_t numerator; + mpn_t denominator; + void *tmp_memory; + tmp_memory = multiply (m, pow5, &numerator); + if (tmp_memory == NULL) + { + free (pow5_ptr); + free (memory); + return NULL; + } + /* Construct 2^|s|. */ + { + mp_limb_t *ptr = pow5_ptr + pow5_len; + size_t i; + for (i = 0; i < s_limbs; i++) + ptr[i] = 0; + ptr[s_limbs] = (mp_limb_t) 1 << s_bits; + denominator.limbs = ptr; + denominator.nlimbs = s_limbs + 1; + } + z_memory = divide (numerator, denominator, &z); + free (tmp_memory); + } + else + { + /* n < 0, s > 0. + Multiply m with 2^s, then divide by pow5. */ + mpn_t numerator; + mp_limb_t *num_ptr; + num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1) + * sizeof (mp_limb_t)); + if (num_ptr == NULL) + { + free (pow5_ptr); + free (memory); + return NULL; + } + { + mp_limb_t *destptr = num_ptr; + { + size_t i; + for (i = 0; i < s_limbs; i++) + *destptr++ = 0; + } + if (s_bits > 0) + { + const mp_limb_t *sourceptr = m.limbs; + mp_twolimb_t accu = 0; + size_t count; + for (count = m.nlimbs; count > 0; count--) + { + accu += (mp_twolimb_t) *sourceptr++ << s_bits; + *destptr++ = (mp_limb_t) accu; + accu = accu >> GMP_LIMB_BITS; + } + if (accu > 0) + *destptr++ = (mp_limb_t) accu; + } + else + { + const mp_limb_t *sourceptr = m.limbs; + size_t count; + for (count = m.nlimbs; count > 0; count--) + *destptr++ = *sourceptr++; + } + numerator.limbs = num_ptr; + numerator.nlimbs = destptr - num_ptr; + } + z_memory = divide (numerator, pow5, &z); + free (num_ptr); + } + } + free (pow5_ptr); + free (memory); + + /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */ + + if (z_memory == NULL) + return NULL; + digits = convert_to_decimal (z, extra_zeroes); + free (z_memory); + return digits; +} + +# if NEED_PRINTF_LONG_DOUBLE + +/* Assuming x is finite and >= 0, and n is an integer: + Returns the decimal representation of round (x * 10^n). + Return the allocated memory - containing the decimal digits in low-to-high + order, terminated with a NUL character - in case of success, NULL in case + of memory allocation failure. */ +static char * +scale10_round_decimal_long_double (long double x, int n) +{ + int e IF_LINT(= 0); + mpn_t m; + void *memory = decode_long_double (x, &e, &m); + return scale10_round_decimal_decoded (e, m, memory, n); +} + +# endif + +# if NEED_PRINTF_DOUBLE + +/* Assuming x is finite and >= 0, and n is an integer: + Returns the decimal representation of round (x * 10^n). + Return the allocated memory - containing the decimal digits in low-to-high + order, terminated with a NUL character - in case of success, NULL in case + of memory allocation failure. */ +static char * +scale10_round_decimal_double (double x, int n) +{ + int e IF_LINT(= 0); + mpn_t m; + void *memory = decode_double (x, &e, &m); + return scale10_round_decimal_decoded (e, m, memory, n); +} + +# endif + +# if NEED_PRINTF_LONG_DOUBLE + +/* Assuming x is finite and > 0: + Return an approximation for n with 10^n <= x < 10^(n+1). + The approximation is usually the right n, but may be off by 1 sometimes. */ +static int +floorlog10l (long double x) +{ + int exp; + long double y; + double z; + double l; + + /* Split into exponential part and mantissa. */ + y = frexpl (x, &exp); + if (!(y >= 0.0L && y < 1.0L)) + abort (); + if (y == 0.0L) + return INT_MIN; + if (y < 0.5L) + { + while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2)))) + { + y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2)); + exp -= GMP_LIMB_BITS; + } + if (y < (1.0L / (1 << 16))) + { + y *= 1.0L * (1 << 16); + exp -= 16; + } + if (y < (1.0L / (1 << 8))) + { + y *= 1.0L * (1 << 8); + exp -= 8; + } + if (y < (1.0L / (1 << 4))) + { + y *= 1.0L * (1 << 4); + exp -= 4; + } + if (y < (1.0L / (1 << 2))) + { + y *= 1.0L * (1 << 2); + exp -= 2; + } + if (y < (1.0L / (1 << 1))) + { + y *= 1.0L * (1 << 1); + exp -= 1; + } + } + if (!(y >= 0.5L && y < 1.0L)) + abort (); + /* Compute an approximation for l = log2(x) = exp + log2(y). */ + l = exp; + z = y; + if (z < 0.70710678118654752444) + { + z *= 1.4142135623730950488; + l -= 0.5; + } + if (z < 0.8408964152537145431) + { + z *= 1.1892071150027210667; + l -= 0.25; + } + if (z < 0.91700404320467123175) + { + z *= 1.0905077326652576592; + l -= 0.125; + } + if (z < 0.9576032806985736469) + { + z *= 1.0442737824274138403; + l -= 0.0625; + } + /* Now 0.95 <= z <= 1.01. */ + z = 1 - z; + /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...) + Four terms are enough to get an approximation with error < 10^-7. */ + l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25))); + /* Finally multiply with log(2)/log(10), yields an approximation for + log10(x). */ + l *= 0.30102999566398119523; + /* Round down to the next integer. */ + return (int) l + (l < 0 ? -1 : 0); +} + +# endif + +# if NEED_PRINTF_DOUBLE + +/* Assuming x is finite and > 0: + Return an approximation for n with 10^n <= x < 10^(n+1). + The approximation is usually the right n, but may be off by 1 sometimes. */ +static int +floorlog10 (double x) +{ + int exp; + double y; + double z; + double l; + + /* Split into exponential part and mantissa. */ + y = frexp (x, &exp); + if (!(y >= 0.0 && y < 1.0)) + abort (); + if (y == 0.0) + return INT_MIN; + if (y < 0.5) + { + while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2)))) + { + y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2)); + exp -= GMP_LIMB_BITS; + } + if (y < (1.0 / (1 << 16))) + { + y *= 1.0 * (1 << 16); + exp -= 16; + } + if (y < (1.0 / (1 << 8))) + { + y *= 1.0 * (1 << 8); + exp -= 8; + } + if (y < (1.0 / (1 << 4))) + { + y *= 1.0 * (1 << 4); + exp -= 4; + } + if (y < (1.0 / (1 << 2))) + { + y *= 1.0 * (1 << 2); + exp -= 2; + } + if (y < (1.0 / (1 << 1))) + { + y *= 1.0 * (1 << 1); + exp -= 1; + } + } + if (!(y >= 0.5 && y < 1.0)) + abort (); + /* Compute an approximation for l = log2(x) = exp + log2(y). */ + l = exp; + z = y; + if (z < 0.70710678118654752444) + { + z *= 1.4142135623730950488; + l -= 0.5; + } + if (z < 0.8408964152537145431) + { + z *= 1.1892071150027210667; + l -= 0.25; + } + if (z < 0.91700404320467123175) + { + z *= 1.0905077326652576592; + l -= 0.125; + } + if (z < 0.9576032806985736469) + { + z *= 1.0442737824274138403; + l -= 0.0625; + } + /* Now 0.95 <= z <= 1.01. */ + z = 1 - z; + /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...) + Four terms are enough to get an approximation with error < 10^-7. */ + l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25))); + /* Finally multiply with log(2)/log(10), yields an approximation for + log10(x). */ + l *= 0.30102999566398119523; + /* Round down to the next integer. */ + return (int) l + (l < 0 ? -1 : 0); +} + +# endif + +/* Tests whether a string of digits consists of exactly PRECISION zeroes and + a single '1' digit. */ +static int +is_borderline (const char *digits, size_t precision) +{ + for (; precision > 0; precision--, digits++) + if (*digits != '0') + return 0; + if (*digits != '1') + return 0; + digits++; + return *digits == '\0'; +} + +#endif + +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF + +/* Use a different function name, to make it possible that the 'wchar_t' + parametrization and the 'char' parametrization get compiled in the same + translation unit. */ +# if WIDE_CHAR_VERSION +# define MAX_ROOM_NEEDED wmax_room_needed +# else +# define MAX_ROOM_NEEDED max_room_needed +# endif + +/* Returns the number of TCHAR_T units needed as temporary space for the result + of sprintf or SNPRINTF of a single conversion directive. */ +static size_t +MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion, + arg_type type, int flags, size_t width, int has_precision, + size_t precision, int pad_ourselves) +{ + size_t tmp_length; + + switch (conversion) + { + case 'd': case 'i': case 'u': +# if HAVE_LONG_LONG_INT + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + ) + + 1; /* turn floor into ceil */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Multiply by 2, as an estimate for FLAG_GROUP. */ + tmp_length = xsum (tmp_length, tmp_length); + /* Add 1, to account for a leading sign. */ + tmp_length = xsum (tmp_length, 1); + break; + + case 'o': +# if HAVE_LONG_LONG_INT + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1; /* turn floor into ceil */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Add 1, to account for a leading sign. */ + tmp_length = xsum (tmp_length, 1); + break; + + case 'x': case 'X': +# if HAVE_LONG_LONG_INT + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Add 2, to account for a leading sign or alternate form. */ + tmp_length = xsum (tmp_length, 2); + break; + + case 'f': case 'F': + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) (LDBL_MAX_EXP + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 10; /* sign, decimal point etc. */ + else + tmp_length = + (unsigned int) (DBL_MAX_EXP + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 10; /* sign, decimal point etc. */ + tmp_length = xsum (tmp_length, precision); + break; + + case 'e': case 'E': case 'g': case 'G': + tmp_length = + 12; /* sign, decimal point, exponent etc. */ + tmp_length = xsum (tmp_length, precision); + break; + + case 'a': case 'A': + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) (LDBL_DIG + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) (DBL_DIG + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Account for sign, decimal point etc. */ + tmp_length = xsum (tmp_length, 12); + break; + + case 'c': +# if HAVE_WINT_T && !WIDE_CHAR_VERSION + if (type == TYPE_WIDE_CHAR) + tmp_length = MB_CUR_MAX; + else +# endif + tmp_length = 1; + break; + + case 's': +# if HAVE_WCHAR_T + if (type == TYPE_WIDE_STRING) + { +# if WIDE_CHAR_VERSION + /* ISO C says about %ls in fwprintf: + "If the precision is not specified or is greater than the size + of the array, the array shall contain a null wide character." + So if there is a precision, we must not use wcslen. */ + const wchar_t *arg = ap->arg[arg_index].a.a_wide_string; + + if (has_precision) + tmp_length = local_wcsnlen (arg, precision); + else + tmp_length = local_wcslen (arg); +# else + /* ISO C says about %ls in fprintf: + "If a precision is specified, no more than that many bytes are + written (including shift sequences, if any), and the array + shall contain a null wide character if, to equal the multibyte + character sequence length given by the precision, the function + would need to access a wide character one past the end of the + array." + So if there is a precision, we must not use wcslen. */ + /* This case has already been handled separately in VASNPRINTF. */ + abort (); +# endif + } + else +# endif + { +# if WIDE_CHAR_VERSION + /* ISO C says about %s in fwprintf: + "If the precision is not specified or is greater than the size + of the converted array, the converted array shall contain a + null wide character." + So if there is a precision, we must not use strlen. */ + /* This case has already been handled separately in VASNPRINTF. */ + abort (); +# else + /* ISO C says about %s in fprintf: + "If the precision is not specified or greater than the size of + the array, the array shall contain a null character." + So if there is a precision, we must not use strlen. */ + const char *arg = ap->arg[arg_index].a.a_string; + + if (has_precision) + tmp_length = local_strnlen (arg, precision); + else + tmp_length = strlen (arg); +# endif + } + break; + + case 'p': + tmp_length = + (unsigned int) (sizeof (void *) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading 0x */ + break; + + default: + abort (); + } + + if (!pad_ourselves) + { +# if ENABLE_UNISTDIO + /* Padding considers the number of characters, therefore the number of + elements after padding may be + > max (tmp_length, width) + but is certainly + <= tmp_length + width. */ + tmp_length = xsum (tmp_length, width); +# else + /* Padding considers the number of elements, says POSIX. */ + if (tmp_length < width) + tmp_length = width; +# endif + } + + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ + + return tmp_length; +} + +#endif + +DCHAR_T * +VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, + const FCHAR_T *format, va_list args) +{ + DIRECTIVES d; + arguments a; + + if (PRINTF_PARSE (format, &d, &a) < 0) + /* errno is already set. */ + return NULL; + +#define CLEANUP() \ + if (d.dir != d.direct_alloc_dir) \ + free (d.dir); \ + if (a.arg != a.direct_alloc_arg) \ + free (a.arg); + + if (PRINTF_FETCHARGS (args, &a) < 0) + { + CLEANUP (); + errno = EINVAL; + return NULL; + } + + { + size_t buf_neededlength; + TCHAR_T *buf; + TCHAR_T *buf_malloced; + const FCHAR_T *cp; + size_t i; + DIRECTIVE *dp; + /* Output string accumulator. */ + DCHAR_T *result; + size_t allocated; + size_t length; + + /* Allocate a small buffer that will hold a directive passed to + sprintf or snprintf. */ + buf_neededlength = + xsum4 (7, d.max_width_length, d.max_precision_length, 6); +#if HAVE_ALLOCA + if (buf_neededlength < 4000 / sizeof (TCHAR_T)) + { + buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T)); + buf_malloced = NULL; + } + else +#endif + { + size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T)); + if (size_overflow_p (buf_memsize)) + goto out_of_memory_1; + buf = (TCHAR_T *) malloc (buf_memsize); + if (buf == NULL) + goto out_of_memory_1; + buf_malloced = buf; + } + + if (resultbuf != NULL) + { + result = resultbuf; + allocated = *lengthp; + } + else + { + result = NULL; + allocated = 0; + } + length = 0; + /* Invariants: + result is either == resultbuf or == NULL or malloc-allocated. + If length > 0, then result != NULL. */ + + /* Ensures that allocated >= needed. Aborts through a jump to + out_of_memory if needed is SIZE_MAX or otherwise too big. */ +#define ENSURE_ALLOCATION(needed) \ + if ((needed) > allocated) \ + { \ + size_t memory_size; \ + DCHAR_T *memory; \ + \ + allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ + if ((needed) > allocated) \ + allocated = (needed); \ + memory_size = xtimes (allocated, sizeof (DCHAR_T)); \ + if (size_overflow_p (memory_size)) \ + goto out_of_memory; \ + if (result == resultbuf || result == NULL) \ + memory = (DCHAR_T *) malloc (memory_size); \ + else \ + memory = (DCHAR_T *) realloc (result, memory_size); \ + if (memory == NULL) \ + goto out_of_memory; \ + if (result == resultbuf && length > 0) \ + DCHAR_CPY (memory, result, length); \ + result = memory; \ + } + + for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) + { + if (cp != dp->dir_start) + { + size_t n = dp->dir_start - cp; + size_t augmented_length = xsum (length, n); + + ENSURE_ALLOCATION (augmented_length); + /* This copies a piece of FCHAR_T[] into a DCHAR_T[]. Here we + need that the format string contains only ASCII characters + if FCHAR_T and DCHAR_T are not the same type. */ + if (sizeof (FCHAR_T) == sizeof (DCHAR_T)) + { + DCHAR_CPY (result + length, (const DCHAR_T *) cp, n); + length = augmented_length; + } + else + { + do + result[length++] = *cp++; + while (--n > 0); + } + } + if (i == d.count) + break; + + /* Execute a single directive. */ + if (dp->conversion == '%') + { + size_t augmented_length; + + if (!(dp->arg_index == ARG_NONE)) + abort (); + augmented_length = xsum (length, 1); + ENSURE_ALLOCATION (augmented_length); + result[length] = '%'; + length = augmented_length; + } + else + { + if (!(dp->arg_index != ARG_NONE)) + abort (); + + if (dp->conversion == 'n') + { + switch (a.arg[dp->arg_index].type) + { + case TYPE_COUNT_SCHAR_POINTER: + *a.arg[dp->arg_index].a.a_count_schar_pointer = length; + break; + case TYPE_COUNT_SHORT_POINTER: + *a.arg[dp->arg_index].a.a_count_short_pointer = length; + break; + case TYPE_COUNT_INT_POINTER: + *a.arg[dp->arg_index].a.a_count_int_pointer = length; + break; + case TYPE_COUNT_LONGINT_POINTER: + *a.arg[dp->arg_index].a.a_count_longint_pointer = length; + break; +#if HAVE_LONG_LONG_INT + case TYPE_COUNT_LONGLONGINT_POINTER: + *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; + break; +#endif + default: + abort (); + } + } +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + else if (dp->conversion == 'U') + { + arg_type type = a.arg[dp->arg_index].type; + int flags = dp->flags; + int has_width; + size_t width; + int has_precision; + size_t precision; + + has_width = 0; + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = arg; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = -width; + } + } + else + { + const FCHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + has_width = 1; + } + + has_precision = 0; + precision = 0; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const FCHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } + + switch (type) + { + case TYPE_U8_STRING: + { + const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string; + const uint8_t *arg_end; + size_t characters; + + if (has_precision) + { + /* Use only PRECISION characters, from the left. */ + arg_end = arg; + characters = 0; + for (; precision > 0; precision--) + { + int count = u8_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else if (has_width) + { + /* Use the entire string, and count the number of + characters. */ + arg_end = arg; + characters = 0; + for (;;) + { + int count = u8_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else + { + /* Use the entire string. */ + arg_end = arg + u8_strlen (arg); + /* The number of characters doesn't matter. */ + characters = 0; + } + + if (characters < width && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + +# if DCHAR_IS_UINT8_T + { + size_t n = arg_end - arg; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_CPY (result + length, arg, n); + length += n; + } +# else + { /* Convert. */ + DCHAR_T *converted = result + length; + size_t converted_len = allocated - length; +# if DCHAR_IS_TCHAR + /* Convert from UTF-8 to locale encoding. */ + converted = + u8_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + converted, &converted_len); +# else + /* Convert from UTF-8 to UTF-16/UTF-32. */ + converted = + U8_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); +# endif + if (converted == NULL) + { + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + if (converted != result + length) + { + ENSURE_ALLOCATION (xsum (length, converted_len)); + DCHAR_CPY (result + length, converted, converted_len); + free (converted); + } + length += converted_len; + } +# endif + + if (characters < width && (dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } + break; + + case TYPE_U16_STRING: + { + const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string; + const uint16_t *arg_end; + size_t characters; + + if (has_precision) + { + /* Use only PRECISION characters, from the left. */ + arg_end = arg; + characters = 0; + for (; precision > 0; precision--) + { + int count = u16_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else if (has_width) + { + /* Use the entire string, and count the number of + characters. */ + arg_end = arg; + characters = 0; + for (;;) + { + int count = u16_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else + { + /* Use the entire string. */ + arg_end = arg + u16_strlen (arg); + /* The number of characters doesn't matter. */ + characters = 0; + } + + if (characters < width && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + +# if DCHAR_IS_UINT16_T + { + size_t n = arg_end - arg; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_CPY (result + length, arg, n); + length += n; + } +# else + { /* Convert. */ + DCHAR_T *converted = result + length; + size_t converted_len = allocated - length; +# if DCHAR_IS_TCHAR + /* Convert from UTF-16 to locale encoding. */ + converted = + u16_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + converted, &converted_len); +# else + /* Convert from UTF-16 to UTF-8/UTF-32. */ + converted = + U16_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); +# endif + if (converted == NULL) + { + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + if (converted != result + length) + { + ENSURE_ALLOCATION (xsum (length, converted_len)); + DCHAR_CPY (result + length, converted, converted_len); + free (converted); + } + length += converted_len; + } +# endif + + if (characters < width && (dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } + break; + + case TYPE_U32_STRING: + { + const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string; + const uint32_t *arg_end; + size_t characters; + + if (has_precision) + { + /* Use only PRECISION characters, from the left. */ + arg_end = arg; + characters = 0; + for (; precision > 0; precision--) + { + int count = u32_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else if (has_width) + { + /* Use the entire string, and count the number of + characters. */ + arg_end = arg; + characters = 0; + for (;;) + { + int count = u32_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else + { + /* Use the entire string. */ + arg_end = arg + u32_strlen (arg); + /* The number of characters doesn't matter. */ + characters = 0; + } + + if (characters < width && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + +# if DCHAR_IS_UINT32_T + { + size_t n = arg_end - arg; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_CPY (result + length, arg, n); + length += n; + } +# else + { /* Convert. */ + DCHAR_T *converted = result + length; + size_t converted_len = allocated - length; +# if DCHAR_IS_TCHAR + /* Convert from UTF-32 to locale encoding. */ + converted = + u32_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + converted, &converted_len); +# else + /* Convert from UTF-32 to UTF-8/UTF-16. */ + converted = + U32_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); +# endif + if (converted == NULL) + { + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + if (converted != result + length) + { + ENSURE_ALLOCATION (xsum (length, converted_len)); + DCHAR_CPY (result + length, converted, converted_len); + free (converted); + } + length += converted_len; + } +# endif + + if (characters < width && (dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } + break; + + default: + abort (); + } + } +#endif +#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T + else if (dp->conversion == 's' +# if WIDE_CHAR_VERSION + && a.arg[dp->arg_index].type != TYPE_WIDE_STRING +# else + && a.arg[dp->arg_index].type == TYPE_WIDE_STRING +# endif + ) + { + /* The normal handling of the 's' directive below requires + allocating a temporary buffer. The determination of its + length (tmp_length), in the case when a precision is + specified, below requires a conversion between a char[] + string and a wchar_t[] wide string. It could be done, but + we have no guarantee that the implementation of sprintf will + use the exactly same algorithm. Without this guarantee, it + is possible to have buffer overrun bugs. In order to avoid + such bugs, we implement the entire processing of the 's' + directive ourselves. */ + int flags = dp->flags; + int has_width; + size_t width; + int has_precision; + size_t precision; + + has_width = 0; + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = arg; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = -width; + } + } + else + { + const FCHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + has_width = 1; + } + + has_precision = 0; + precision = 6; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const FCHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } + +# if WIDE_CHAR_VERSION + /* %s in vasnwprintf. See the specification of fwprintf. */ + { + const char *arg = a.arg[dp->arg_index].a.a_string; + const char *arg_end; + size_t characters; + + if (has_precision) + { + /* Use only as many bytes as needed to produce PRECISION + wide characters, from the left. */ +# if HAVE_MBRTOWC + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + arg_end = arg; + characters = 0; + for (; precision > 0; precision--) + { + int count; +# if HAVE_MBRTOWC + count = mbrlen (arg_end, MB_CUR_MAX, &state); +# else + count = mblen (arg_end, MB_CUR_MAX); +# endif + if (count == 0) + /* Found the terminating NUL. */ + break; + if (count < 0) + { + /* Invalid or incomplete multibyte character. */ + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else if (has_width) + { + /* Use the entire string, and count the number of wide + characters. */ +# if HAVE_MBRTOWC + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + arg_end = arg; + characters = 0; + for (;;) + { + int count; +# if HAVE_MBRTOWC + count = mbrlen (arg_end, MB_CUR_MAX, &state); +# else + count = mblen (arg_end, MB_CUR_MAX); +# endif + if (count == 0) + /* Found the terminating NUL. */ + break; + if (count < 0) + { + /* Invalid or incomplete multibyte character. */ + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else + { + /* Use the entire string. */ + arg_end = arg + strlen (arg); + /* The number of characters doesn't matter. */ + characters = 0; + } + + if (characters < width && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + + if (has_precision || has_width) + { + /* We know the number of wide characters in advance. */ + size_t remaining; +# if HAVE_MBRTOWC + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + ENSURE_ALLOCATION (xsum (length, characters)); + for (remaining = characters; remaining > 0; remaining--) + { + wchar_t wc; + int count; +# if HAVE_MBRTOWC + count = mbrtowc (&wc, arg, arg_end - arg, &state); +# else + count = mbtowc (&wc, arg, arg_end - arg); +# endif + if (count <= 0) + /* mbrtowc not consistent with mbrlen, or mbtowc + not consistent with mblen. */ + abort (); + result[length++] = wc; + arg += count; + } + if (!(arg == arg_end)) + abort (); + } + else + { +# if HAVE_MBRTOWC + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + while (arg < arg_end) + { + wchar_t wc; + int count; +# if HAVE_MBRTOWC + count = mbrtowc (&wc, arg, arg_end - arg, &state); +# else + count = mbtowc (&wc, arg, arg_end - arg); +# endif + if (count <= 0) + /* mbrtowc not consistent with mbrlen, or mbtowc + not consistent with mblen. */ + abort (); + ENSURE_ALLOCATION (xsum (length, 1)); + result[length++] = wc; + arg += count; + } + } + + if (characters < width && (dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } +# else + /* %ls in vasnprintf. See the specification of fprintf. */ + { + const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; + const wchar_t *arg_end; + size_t characters; +# if !DCHAR_IS_TCHAR + /* This code assumes that TCHAR_T is 'char'. */ + verify (sizeof (TCHAR_T) == 1); + TCHAR_T *tmpsrc; + DCHAR_T *tmpdst; + size_t tmpdst_len; +# endif + size_t w; + + if (has_precision) + { + /* Use only as many wide characters as needed to produce + at most PRECISION bytes, from the left. */ +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + arg_end = arg; + characters = 0; + while (precision > 0) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; + + if (*arg_end == 0) + /* Found the terminating null wide character. */ + break; +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + count = wcrtomb (cbuf, *arg_end, &state); +# else + count = wctomb (cbuf, *arg_end); +# endif + if (count < 0) + { + /* Cannot convert. */ + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + if (precision < (unsigned int) count) + break; + arg_end++; + characters += count; + precision -= count; + } + } +# if DCHAR_IS_TCHAR + else if (has_width) +# else + else +# endif + { + /* Use the entire string, and count the number of + bytes. */ +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + arg_end = arg; + characters = 0; + for (;;) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; + + if (*arg_end == 0) + /* Found the terminating null wide character. */ + break; +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + count = wcrtomb (cbuf, *arg_end, &state); +# else + count = wctomb (cbuf, *arg_end); +# endif + if (count < 0) + { + /* Cannot convert. */ + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end++; + characters += count; + } + } +# if DCHAR_IS_TCHAR + else + { + /* Use the entire string. */ + arg_end = arg + local_wcslen (arg); + /* The number of bytes doesn't matter. */ + characters = 0; + } +# endif + +# if !DCHAR_IS_TCHAR + /* Convert the string into a piece of temporary memory. */ + tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T)); + if (tmpsrc == NULL) + goto out_of_memory; + { + TCHAR_T *tmpptr = tmpsrc; + size_t remaining; +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + for (remaining = characters; remaining > 0; ) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; + + if (*arg == 0) + abort (); +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + count = wcrtomb (cbuf, *arg, &state); +# else + count = wctomb (cbuf, *arg); +# endif + if (count <= 0) + /* Inconsistency. */ + abort (); + memcpy (tmpptr, cbuf, count); + tmpptr += count; + arg++; + remaining -= count; + } + if (!(arg == arg_end)) + abort (); + } + + /* Convert from TCHAR_T[] to DCHAR_T[]. */ + tmpdst = + DCHAR_CONV_FROM_ENCODING (locale_charset (), + iconveh_question_mark, + tmpsrc, characters, + NULL, + NULL, &tmpdst_len); + if (tmpdst == NULL) + { + int saved_errno = errno; + free (tmpsrc); + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + free (tmpsrc); +# endif + + if (has_width) + { +# if ENABLE_UNISTDIO + /* Outside POSIX, it's preferable to compare the width + against the number of _characters_ of the converted + value. */ + w = DCHAR_MBSNLEN (result + length, characters); +# else + /* The width is compared against the number of _bytes_ + of the converted value, says POSIX. */ + w = characters; +# endif + } + else + /* w doesn't matter. */ + w = 0; + + if (w < width && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - w; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + +# if DCHAR_IS_TCHAR + if (has_precision || has_width) + { + /* We know the number of bytes in advance. */ + size_t remaining; +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + ENSURE_ALLOCATION (xsum (length, characters)); + for (remaining = characters; remaining > 0; ) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; + + if (*arg == 0) + abort (); +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + count = wcrtomb (cbuf, *arg, &state); +# else + count = wctomb (cbuf, *arg); +# endif + if (count <= 0) + /* Inconsistency. */ + abort (); + memcpy (result + length, cbuf, count); + length += count; + arg++; + remaining -= count; + } + if (!(arg == arg_end)) + abort (); + } + else + { +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + mbstate_t state; + memset (&state, '\0', sizeof (mbstate_t)); +# endif + while (arg < arg_end) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; + + if (*arg == 0) + abort (); +# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t + count = wcrtomb (cbuf, *arg, &state); +# else + count = wctomb (cbuf, *arg); +# endif + if (count <= 0) + { + /* Cannot convert. */ + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + ENSURE_ALLOCATION (xsum (length, count)); + memcpy (result + length, cbuf, count); + length += count; + arg++; + } + } +# else + ENSURE_ALLOCATION (xsum (length, tmpdst_len)); + DCHAR_CPY (result + length, tmpdst, tmpdst_len); + free (tmpdst); + length += tmpdst_len; +# endif + + if (w < width && (dp->flags & FLAG_LEFT)) + { + size_t n = width - w; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } +# endif + } +#endif +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL + else if ((dp->conversion == 'a' || dp->conversion == 'A') +# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE)) + && (0 +# if NEED_PRINTF_DOUBLE + || a.arg[dp->arg_index].type == TYPE_DOUBLE +# endif +# if NEED_PRINTF_LONG_DOUBLE + || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE +# endif + ) +# endif + ) + { + arg_type type = a.arg[dp->arg_index].type; + int flags = dp->flags; + size_t width; + int has_precision; + size_t precision; + size_t tmp_length; + size_t count; + DCHAR_T tmpbuf[700]; + DCHAR_T *tmp; + DCHAR_T *pad_ptr; + DCHAR_T *p; + + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = arg; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = -width; + } + } + else + { + const FCHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + } + + has_precision = 0; + precision = 0; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const FCHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } + + /* Allocate a temporary buffer of sufficient size. */ + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) ((LDBL_DIG + 1) + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + else + tmp_length = + (unsigned int) ((DBL_DIG + 1) + * 0.831 /* decimal -> hexadecimal */ + ) + + 1; /* turn floor into ceil */ + if (tmp_length < precision) + tmp_length = precision; + /* Account for sign, decimal point etc. */ + tmp_length = xsum (tmp_length, 12); + + if (tmp_length < width) + tmp_length = width; + + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ + + if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T)) + tmp = tmpbuf; + else + { + size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T)); + + if (size_overflow_p (tmp_memsize)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + tmp = (DCHAR_T *) malloc (tmp_memsize); + if (tmp == NULL) + /* Out of memory. */ + goto out_of_memory; + } + + pad_ptr = NULL; + p = tmp; + if (type == TYPE_LONGDOUBLE) + { +# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE + long double arg = a.arg[dp->arg_index].a.a_longdouble; + + if (isnanl (arg)) + { + if (dp->conversion == 'A') + { + *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; + } + else + { + *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; + } + } + else + { + int sign = 0; + DECL_LONG_DOUBLE_ROUNDING + + BEGIN_LONG_DOUBLE_ROUNDING (); + + if (signbit (arg)) /* arg < 0.0L or negative zero */ + { + sign = -1; + arg = -arg; + } + + if (sign < 0) + *p++ = '-'; + else if (flags & FLAG_SHOWSIGN) + *p++ = '+'; + else if (flags & FLAG_SPACE) + *p++ = ' '; + + if (arg > 0.0L && arg + arg == arg) + { + if (dp->conversion == 'A') + { + *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; + } + else + { + *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; + } + } + else + { + int exponent; + long double mantissa; + + if (arg > 0.0L) + mantissa = printf_frexpl (arg, &exponent); + else + { + exponent = 0; + mantissa = 0.0L; + } + + if (has_precision + && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1) + { + /* Round the mantissa. */ + long double tail = mantissa; + size_t q; + + for (q = precision; ; q--) + { + int digit = (int) tail; + tail -= digit; + if (q == 0) + { + if (digit & 1 ? tail >= 0.5L : tail > 0.5L) + tail = 1 - tail; + else + tail = - tail; + break; + } + tail *= 16.0L; + } + if (tail != 0.0L) + for (q = precision; q > 0; q--) + tail *= 0.0625L; + mantissa += tail; + } + + *p++ = '0'; + *p++ = dp->conversion - 'A' + 'X'; + pad_ptr = p; + { + int digit; + + digit = (int) mantissa; + mantissa -= digit; + *p++ = '0' + digit; + if ((flags & FLAG_ALT) + || mantissa > 0.0L || precision > 0) + { + *p++ = decimal_point_char (); + /* This loop terminates because we assume + that FLT_RADIX is a power of 2. */ + while (mantissa > 0.0L) + { + mantissa *= 16.0L; + digit = (int) mantissa; + mantissa -= digit; + *p++ = digit + + (digit < 10 + ? '0' + : dp->conversion - 10); + if (precision > 0) + precision--; + } + while (precision > 0) + { + *p++ = '0'; + precision--; + } + } + } + *p++ = dp->conversion - 'A' + 'P'; +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + { '%', '+', 'd', '\0' }; + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif + } + + END_LONG_DOUBLE_ROUNDING (); + } +# else + abort (); +# endif + } + else + { +# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE + double arg = a.arg[dp->arg_index].a.a_double; + + if (isnand (arg)) + { + if (dp->conversion == 'A') + { + *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; + } + else + { + *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; + } + } + else + { + int sign = 0; + + if (signbit (arg)) /* arg < 0.0 or negative zero */ + { + sign = -1; + arg = -arg; + } + + if (sign < 0) + *p++ = '-'; + else if (flags & FLAG_SHOWSIGN) + *p++ = '+'; + else if (flags & FLAG_SPACE) + *p++ = ' '; + + if (arg > 0.0 && arg + arg == arg) + { + if (dp->conversion == 'A') + { + *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; + } + else + { + *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; + } + } + else + { + int exponent; + double mantissa; + + if (arg > 0.0) + mantissa = printf_frexp (arg, &exponent); + else + { + exponent = 0; + mantissa = 0.0; + } + + if (has_precision + && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1) + { + /* Round the mantissa. */ + double tail = mantissa; + size_t q; + + for (q = precision; ; q--) + { + int digit = (int) tail; + tail -= digit; + if (q == 0) + { + if (digit & 1 ? tail >= 0.5 : tail > 0.5) + tail = 1 - tail; + else + tail = - tail; + break; + } + tail *= 16.0; + } + if (tail != 0.0) + for (q = precision; q > 0; q--) + tail *= 0.0625; + mantissa += tail; + } + + *p++ = '0'; + *p++ = dp->conversion - 'A' + 'X'; + pad_ptr = p; + { + int digit; + + digit = (int) mantissa; + mantissa -= digit; + *p++ = '0' + digit; + if ((flags & FLAG_ALT) + || mantissa > 0.0 || precision > 0) + { + *p++ = decimal_point_char (); + /* This loop terminates because we assume + that FLT_RADIX is a power of 2. */ + while (mantissa > 0.0) + { + mantissa *= 16.0; + digit = (int) mantissa; + mantissa -= digit; + *p++ = digit + + (digit < 10 + ? '0' + : dp->conversion - 10); + if (precision > 0) + precision--; + } + while (precision > 0) + { + *p++ = '0'; + precision--; + } + } + } + *p++ = dp->conversion - 'A' + 'P'; +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + { '%', '+', 'd', '\0' }; + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif + } + } +# else + abort (); +# endif + } + + /* The generated string now extends from tmp to p, with the + zero padding insertion point being at pad_ptr. */ + count = p - tmp; + + if (count < width) + { + size_t pad = width - count; + DCHAR_T *end = p + pad; + + if (flags & FLAG_LEFT) + { + /* Pad with spaces on the right. */ + for (; pad > 0; pad--) + *p++ = ' '; + } + else if ((flags & FLAG_ZERO) && pad_ptr != NULL) + { + /* Pad with zeroes. */ + DCHAR_T *q = end; + + while (p > pad_ptr) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = '0'; + } + else + { + /* Pad with spaces on the left. */ + DCHAR_T *q = end; + + while (p > tmp) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = ' '; + } + + p = end; + } + + count = p - tmp; + + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); + + /* Make room for the result. */ + if (count >= allocated - length) + { + size_t n = xsum (length, count); + + ENSURE_ALLOCATION (n); + } + + /* Append the result. */ + memcpy (result + length, tmp, count * sizeof (DCHAR_T)); + if (tmp != tmpbuf) + free (tmp); + length += count; + } +#endif +#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL + else if ((dp->conversion == 'f' || dp->conversion == 'F' + || dp->conversion == 'e' || dp->conversion == 'E' + || dp->conversion == 'g' || dp->conversion == 'G' + || dp->conversion == 'a' || dp->conversion == 'A') + && (0 +# if NEED_PRINTF_DOUBLE + || a.arg[dp->arg_index].type == TYPE_DOUBLE +# elif NEED_PRINTF_INFINITE_DOUBLE + || (a.arg[dp->arg_index].type == TYPE_DOUBLE + /* The systems (mingw) which produce wrong output + for Inf, -Inf, and NaN also do so for -0.0. + Therefore we treat this case here as well. */ + && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double)) +# endif +# if NEED_PRINTF_LONG_DOUBLE + || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE +# elif NEED_PRINTF_INFINITE_LONG_DOUBLE + || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE + /* Some systems produce wrong output for Inf, + -Inf, and NaN. Some systems in this category + (IRIX 5.3) also do so for -0.0. Therefore we + treat this case here as well. */ + && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble)) +# endif + )) + { +# if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) + arg_type type = a.arg[dp->arg_index].type; +# endif + int flags = dp->flags; + size_t width; + size_t count; + int has_precision; + size_t precision; + size_t tmp_length; + DCHAR_T tmpbuf[700]; + DCHAR_T *tmp; + DCHAR_T *pad_ptr; + DCHAR_T *p; + + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = arg; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = -width; + } + } + else + { + const FCHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + } + + has_precision = 0; + precision = 0; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const FCHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } + + /* POSIX specifies the default precision to be 6 for %f, %F, + %e, %E, but not for %g, %G. Implementations appear to use + the same default precision also for %g, %G. But for %a, %A, + the default precision is 0. */ + if (!has_precision) + if (!(dp->conversion == 'a' || dp->conversion == 'A')) + precision = 6; + + /* Allocate a temporary buffer of sufficient size. */ +# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE + tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1); +# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE + tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0); +# elif NEED_PRINTF_LONG_DOUBLE + tmp_length = LDBL_DIG + 1; +# elif NEED_PRINTF_DOUBLE + tmp_length = DBL_DIG + 1; +# else + tmp_length = 0; +# endif + if (tmp_length < precision) + tmp_length = precision; +# if NEED_PRINTF_LONG_DOUBLE +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE + if (type == TYPE_LONGDOUBLE) +# endif + if (dp->conversion == 'f' || dp->conversion == 'F') + { + long double arg = a.arg[dp->arg_index].a.a_longdouble; + if (!(isnanl (arg) || arg + arg == arg)) + { + /* arg is finite and nonzero. */ + int exponent = floorlog10l (arg < 0 ? -arg : arg); + if (exponent >= 0 && tmp_length < exponent + precision) + tmp_length = exponent + precision; + } + } +# endif +# if NEED_PRINTF_DOUBLE +# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE + if (type == TYPE_DOUBLE) +# endif + if (dp->conversion == 'f' || dp->conversion == 'F') + { + double arg = a.arg[dp->arg_index].a.a_double; + if (!(isnand (arg) || arg + arg == arg)) + { + /* arg is finite and nonzero. */ + int exponent = floorlog10 (arg < 0 ? -arg : arg); + if (exponent >= 0 && tmp_length < exponent + precision) + tmp_length = exponent + precision; + } + } +# endif + /* Account for sign, decimal point etc. */ + tmp_length = xsum (tmp_length, 12); + + if (tmp_length < width) + tmp_length = width; + + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ + + if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T)) + tmp = tmpbuf; + else + { + size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T)); + + if (size_overflow_p (tmp_memsize)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + tmp = (DCHAR_T *) malloc (tmp_memsize); + if (tmp == NULL) + /* Out of memory. */ + goto out_of_memory; + } + + pad_ptr = NULL; + p = tmp; + +# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE + if (type == TYPE_LONGDOUBLE) +# endif + { + long double arg = a.arg[dp->arg_index].a.a_longdouble; + + if (isnanl (arg)) + { + if (dp->conversion >= 'A' && dp->conversion <= 'Z') + { + *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; + } + else + { + *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; + } + } + else + { + int sign = 0; + DECL_LONG_DOUBLE_ROUNDING + + BEGIN_LONG_DOUBLE_ROUNDING (); + + if (signbit (arg)) /* arg < 0.0L or negative zero */ + { + sign = -1; + arg = -arg; + } + + if (sign < 0) + *p++ = '-'; + else if (flags & FLAG_SHOWSIGN) + *p++ = '+'; + else if (flags & FLAG_SPACE) + *p++ = ' '; + + if (arg > 0.0L && arg + arg == arg) + { + if (dp->conversion >= 'A' && dp->conversion <= 'Z') + { + *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; + } + else + { + *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; + } + } + else + { +# if NEED_PRINTF_LONG_DOUBLE + pad_ptr = p; + + if (dp->conversion == 'f' || dp->conversion == 'F') + { + char *digits; + size_t ndigits; + + digits = + scale10_round_decimal_long_double (arg, precision); + if (digits == NULL) + { + END_LONG_DOUBLE_ROUNDING (); + goto out_of_memory; + } + ndigits = strlen (digits); + + if (ndigits > precision) + do + { + --ndigits; + *p++ = digits[ndigits]; + } + while (ndigits > precision); + else + *p++ = '0'; + /* Here ndigits <= precision. */ + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > ndigits; precision--) + *p++ = '0'; + while (ndigits > 0) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + + free (digits); + } + else if (dp->conversion == 'e' || dp->conversion == 'E') + { + int exponent; + + if (arg == 0.0L) + { + exponent = 0; + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + } + else + { + /* arg > 0.0L. */ + int adjusted; + char *digits; + size_t ndigits; + + exponent = floorlog10l (arg); + adjusted = 0; + for (;;) + { + digits = + scale10_round_decimal_long_double (arg, + (int)precision - exponent); + if (digits == NULL) + { + END_LONG_DOUBLE_ROUNDING (); + goto out_of_memory; + } + ndigits = strlen (digits); + + if (ndigits == precision + 1) + break; + if (ndigits < precision + || ndigits > precision + 2) + /* The exponent was not guessed + precisely enough. */ + abort (); + if (adjusted) + /* None of two values of exponent is + the right one. Prevent an endless + loop. */ + abort (); + free (digits); + if (ndigits == precision) + exponent -= 1; + else + exponent += 1; + adjusted = 1; + } + /* Here ndigits = precision+1. */ + if (is_borderline (digits, precision)) + { + /* Maybe the exponent guess was too high + and a smaller exponent can be reached + by turning a 10...0 into 9...9x. */ + char *digits2 = + scale10_round_decimal_long_double (arg, + (int)precision - exponent + 1); + if (digits2 == NULL) + { + free (digits); + END_LONG_DOUBLE_ROUNDING (); + goto out_of_memory; + } + if (strlen (digits2) == precision + 1) + { + free (digits); + digits = digits2; + exponent -= 1; + } + else + free (digits2); + } + /* Here ndigits = precision+1. */ + + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + while (ndigits > 0) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + + free (digits); + } + + *p++ = dp->conversion; /* 'e' or 'E' */ +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + { '%', '+', '.', '2', 'd', '\0' }; + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+.2d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+.2d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif + } + else if (dp->conversion == 'g' || dp->conversion == 'G') + { + if (precision == 0) + precision = 1; + /* precision >= 1. */ + + if (arg == 0.0L) + /* The exponent is 0, >= -4, < precision. + Use fixed-point notation. */ + { + size_t ndigits = precision; + /* Number of trailing zeroes that have to be + dropped. */ + size_t nzeroes = + (flags & FLAG_ALT ? 0 : precision - 1); + + --ndigits; + *p++ = '0'; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = '0'; + } + } + } + else + { + /* arg > 0.0L. */ + int exponent; + int adjusted; + char *digits; + size_t ndigits; + size_t nzeroes; + + exponent = floorlog10l (arg); + adjusted = 0; + for (;;) + { + digits = + scale10_round_decimal_long_double (arg, + (int)(precision - 1) - exponent); + if (digits == NULL) + { + END_LONG_DOUBLE_ROUNDING (); + goto out_of_memory; + } + ndigits = strlen (digits); + + if (ndigits == precision) + break; + if (ndigits < precision - 1 + || ndigits > precision + 1) + /* The exponent was not guessed + precisely enough. */ + abort (); + if (adjusted) + /* None of two values of exponent is + the right one. Prevent an endless + loop. */ + abort (); + free (digits); + if (ndigits < precision) + exponent -= 1; + else + exponent += 1; + adjusted = 1; + } + /* Here ndigits = precision. */ + if (is_borderline (digits, precision - 1)) + { + /* Maybe the exponent guess was too high + and a smaller exponent can be reached + by turning a 10...0 into 9...9x. */ + char *digits2 = + scale10_round_decimal_long_double (arg, + (int)(precision - 1) - exponent + 1); + if (digits2 == NULL) + { + free (digits); + END_LONG_DOUBLE_ROUNDING (); + goto out_of_memory; + } + if (strlen (digits2) == precision) + { + free (digits); + digits = digits2; + exponent -= 1; + } + else + free (digits2); + } + /* Here ndigits = precision. */ + + /* Determine the number of trailing zeroes + that have to be dropped. */ + nzeroes = 0; + if ((flags & FLAG_ALT) == 0) + while (nzeroes < ndigits + && digits[nzeroes] == '0') + nzeroes++; + + /* The exponent is now determined. */ + if (exponent >= -4 + && exponent < (long)precision) + { + /* Fixed-point notation: + max(exponent,0)+1 digits, then the + decimal point, then the remaining + digits without trailing zeroes. */ + if (exponent >= 0) + { + size_t ecount = exponent + 1; + /* Note: count <= precision = ndigits. */ + for (; ecount > 0; ecount--) + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + } + else + { + size_t ecount = -exponent - 1; + *p++ = '0'; + *p++ = decimal_point_char (); + for (; ecount > 0; ecount--) + *p++ = '0'; + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + } + else + { + /* Exponential notation. */ + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */ +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + { '%', '+', '.', '2', 'd', '\0' }; + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+.2d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+.2d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif + } + + free (digits); + } + } + else + abort (); +# else + /* arg is finite. */ + if (!(arg == 0.0L)) + abort (); + + pad_ptr = p; + + if (dp->conversion == 'f' || dp->conversion == 'F') + { + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + } + else if (dp->conversion == 'e' || dp->conversion == 'E') + { + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + *p++ = dp->conversion; /* 'e' or 'E' */ + *p++ = '+'; + *p++ = '0'; + *p++ = '0'; + } + else if (dp->conversion == 'g' || dp->conversion == 'G') + { + *p++ = '0'; + if (flags & FLAG_ALT) + { + size_t ndigits = + (precision > 0 ? precision - 1 : 0); + *p++ = decimal_point_char (); + for (; ndigits > 0; --ndigits) + *p++ = '0'; + } + } + else if (dp->conversion == 'a' || dp->conversion == 'A') + { + *p++ = '0'; + *p++ = dp->conversion - 'A' + 'X'; + pad_ptr = p; + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + *p++ = dp->conversion - 'A' + 'P'; + *p++ = '+'; + *p++ = '0'; + } + else + abort (); +# endif + } + + END_LONG_DOUBLE_ROUNDING (); + } + } +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE + else +# endif +# endif +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE + { + double arg = a.arg[dp->arg_index].a.a_double; + + if (isnand (arg)) + { + if (dp->conversion >= 'A' && dp->conversion <= 'Z') + { + *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; + } + else + { + *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; + } + } + else + { + int sign = 0; + + if (signbit (arg)) /* arg < 0.0 or negative zero */ + { + sign = -1; + arg = -arg; + } + + if (sign < 0) + *p++ = '-'; + else if (flags & FLAG_SHOWSIGN) + *p++ = '+'; + else if (flags & FLAG_SPACE) + *p++ = ' '; + + if (arg > 0.0 && arg + arg == arg) + { + if (dp->conversion >= 'A' && dp->conversion <= 'Z') + { + *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; + } + else + { + *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; + } + } + else + { +# if NEED_PRINTF_DOUBLE + pad_ptr = p; + + if (dp->conversion == 'f' || dp->conversion == 'F') + { + char *digits; + size_t ndigits; + + digits = + scale10_round_decimal_double (arg, precision); + if (digits == NULL) + goto out_of_memory; + ndigits = strlen (digits); + + if (ndigits > precision) + do + { + --ndigits; + *p++ = digits[ndigits]; + } + while (ndigits > precision); + else + *p++ = '0'; + /* Here ndigits <= precision. */ + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > ndigits; precision--) + *p++ = '0'; + while (ndigits > 0) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + + free (digits); + } + else if (dp->conversion == 'e' || dp->conversion == 'E') + { + int exponent; + + if (arg == 0.0) + { + exponent = 0; + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + } + else + { + /* arg > 0.0. */ + int adjusted; + char *digits; + size_t ndigits; + + exponent = floorlog10 (arg); + adjusted = 0; + for (;;) + { + digits = + scale10_round_decimal_double (arg, + (int)precision - exponent); + if (digits == NULL) + goto out_of_memory; + ndigits = strlen (digits); + + if (ndigits == precision + 1) + break; + if (ndigits < precision + || ndigits > precision + 2) + /* The exponent was not guessed + precisely enough. */ + abort (); + if (adjusted) + /* None of two values of exponent is + the right one. Prevent an endless + loop. */ + abort (); + free (digits); + if (ndigits == precision) + exponent -= 1; + else + exponent += 1; + adjusted = 1; + } + /* Here ndigits = precision+1. */ + if (is_borderline (digits, precision)) + { + /* Maybe the exponent guess was too high + and a smaller exponent can be reached + by turning a 10...0 into 9...9x. */ + char *digits2 = + scale10_round_decimal_double (arg, + (int)precision - exponent + 1); + if (digits2 == NULL) + { + free (digits); + goto out_of_memory; + } + if (strlen (digits2) == precision + 1) + { + free (digits); + digits = digits2; + exponent -= 1; + } + else + free (digits2); + } + /* Here ndigits = precision+1. */ + + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + while (ndigits > 0) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + + free (digits); + } + + *p++ = dp->conversion; /* 'e' or 'E' */ +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if defined _WIN32 && ! defined __CYGWIN__ + { '%', '+', '.', '3', 'd', '\0' }; +# else + { '%', '+', '.', '2', 'd', '\0' }; +# endif + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + { + static const char decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if defined _WIN32 && ! defined __CYGWIN__ + "%+.3d"; +# else + "%+.2d"; +# endif + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, decimal_format, exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, decimal_format, exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } + } +# endif + } + else if (dp->conversion == 'g' || dp->conversion == 'G') + { + if (precision == 0) + precision = 1; + /* precision >= 1. */ + + if (arg == 0.0) + /* The exponent is 0, >= -4, < precision. + Use fixed-point notation. */ + { + size_t ndigits = precision; + /* Number of trailing zeroes that have to be + dropped. */ + size_t nzeroes = + (flags & FLAG_ALT ? 0 : precision - 1); + + --ndigits; + *p++ = '0'; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = '0'; + } + } + } + else + { + /* arg > 0.0. */ + int exponent; + int adjusted; + char *digits; + size_t ndigits; + size_t nzeroes; + + exponent = floorlog10 (arg); + adjusted = 0; + for (;;) + { + digits = + scale10_round_decimal_double (arg, + (int)(precision - 1) - exponent); + if (digits == NULL) + goto out_of_memory; + ndigits = strlen (digits); + + if (ndigits == precision) + break; + if (ndigits < precision - 1 + || ndigits > precision + 1) + /* The exponent was not guessed + precisely enough. */ + abort (); + if (adjusted) + /* None of two values of exponent is + the right one. Prevent an endless + loop. */ + abort (); + free (digits); + if (ndigits < precision) + exponent -= 1; + else + exponent += 1; + adjusted = 1; + } + /* Here ndigits = precision. */ + if (is_borderline (digits, precision - 1)) + { + /* Maybe the exponent guess was too high + and a smaller exponent can be reached + by turning a 10...0 into 9...9x. */ + char *digits2 = + scale10_round_decimal_double (arg, + (int)(precision - 1) - exponent + 1); + if (digits2 == NULL) + { + free (digits); + goto out_of_memory; + } + if (strlen (digits2) == precision) + { + free (digits); + digits = digits2; + exponent -= 1; + } + else + free (digits2); + } + /* Here ndigits = precision. */ + + /* Determine the number of trailing zeroes + that have to be dropped. */ + nzeroes = 0; + if ((flags & FLAG_ALT) == 0) + while (nzeroes < ndigits + && digits[nzeroes] == '0') + nzeroes++; + + /* The exponent is now determined. */ + if (exponent >= -4 + && exponent < (long)precision) + { + /* Fixed-point notation: + max(exponent,0)+1 digits, then the + decimal point, then the remaining + digits without trailing zeroes. */ + if (exponent >= 0) + { + size_t ecount = exponent + 1; + /* Note: ecount <= precision = ndigits. */ + for (; ecount > 0; ecount--) + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + } + else + { + size_t ecount = -exponent - 1; + *p++ = '0'; + *p++ = decimal_point_char (); + for (; ecount > 0; ecount--) + *p++ = '0'; + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + } + else + { + /* Exponential notation. */ + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */ +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if defined _WIN32 && ! defined __CYGWIN__ + { '%', '+', '.', '3', 'd', '\0' }; +# else + { '%', '+', '.', '2', 'd', '\0' }; +# endif + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + { + static const char decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if defined _WIN32 && ! defined __CYGWIN__ + "%+.3d"; +# else + "%+.2d"; +# endif + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, decimal_format, exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, decimal_format, exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } + } +# endif + } + + free (digits); + } + } + else + abort (); +# else + /* arg is finite. */ + if (!(arg == 0.0)) + abort (); + + pad_ptr = p; + + if (dp->conversion == 'f' || dp->conversion == 'F') + { + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + } + else if (dp->conversion == 'e' || dp->conversion == 'E') + { + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + *p++ = dp->conversion; /* 'e' or 'E' */ + *p++ = '+'; + /* Produce the same number of exponent digits as + the native printf implementation. */ +# if defined _WIN32 && ! defined __CYGWIN__ + *p++ = '0'; +# endif + *p++ = '0'; + *p++ = '0'; + } + else if (dp->conversion == 'g' || dp->conversion == 'G') + { + *p++ = '0'; + if (flags & FLAG_ALT) + { + size_t ndigits = + (precision > 0 ? precision - 1 : 0); + *p++ = decimal_point_char (); + for (; ndigits > 0; --ndigits) + *p++ = '0'; + } + } + else + abort (); +# endif + } + } + } +# endif + + /* The generated string now extends from tmp to p, with the + zero padding insertion point being at pad_ptr. */ + count = p - tmp; + + if (count < width) + { + size_t pad = width - count; + DCHAR_T *end = p + pad; + + if (flags & FLAG_LEFT) + { + /* Pad with spaces on the right. */ + for (; pad > 0; pad--) + *p++ = ' '; + } + else if ((flags & FLAG_ZERO) && pad_ptr != NULL) + { + /* Pad with zeroes. */ + DCHAR_T *q = end; + + while (p > pad_ptr) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = '0'; + } + else + { + /* Pad with spaces on the left. */ + DCHAR_T *q = end; + + while (p > tmp) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = ' '; + } + + p = end; + } + + count = p - tmp; + + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); + + /* Make room for the result. */ + if (count >= allocated - length) + { + size_t n = xsum (length, count); + + ENSURE_ALLOCATION (n); + } + + /* Append the result. */ + memcpy (result + length, tmp, count * sizeof (DCHAR_T)); + if (tmp != tmpbuf) + free (tmp); + length += count; + } +#endif + else + { + arg_type type = a.arg[dp->arg_index].type; + int flags = dp->flags; +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + int has_width; +#endif +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + size_t width; +#endif +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION + int has_precision; + size_t precision; +#endif +#if NEED_PRINTF_UNBOUNDED_PRECISION + int prec_ourselves; +#else +# define prec_ourselves 0 +#endif +#if NEED_PRINTF_FLAG_LEFTADJUST +# define pad_ourselves 1 +#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + int pad_ourselves; +#else +# define pad_ourselves 0 +#endif + TCHAR_T *fbp; + unsigned int prefix_count; + int prefixes[2] IF_LINT (= { 0 }); + int orig_errno; +#if !USE_SNPRINTF + size_t tmp_length; + TCHAR_T tmpbuf[700]; + TCHAR_T *tmp; +#endif + +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + has_width = 0; +#endif +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = arg; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = -width; + } + } + else + { + const FCHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + has_width = 1; +#endif + } +#endif + +#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION + has_precision = 0; + precision = 6; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const FCHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } +#endif + + /* Decide whether to handle the precision ourselves. */ +#if NEED_PRINTF_UNBOUNDED_PRECISION + switch (dp->conversion) + { + case 'd': case 'i': case 'u': + case 'o': + case 'x': case 'X': case 'p': + prec_ourselves = has_precision && (precision > 0); + break; + default: + prec_ourselves = 0; + break; + } +#endif + + /* Decide whether to perform the padding ourselves. */ +#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION) + switch (dp->conversion) + { +# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO + /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need + to perform the padding after this conversion. Functions + with unistdio extensions perform the padding based on + character count rather than element count. */ + case 'c': case 's': +# endif +# if NEED_PRINTF_FLAG_ZERO + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': + case 'a': case 'A': +# endif + pad_ourselves = 1; + break; + default: + pad_ourselves = prec_ourselves; + break; + } +#endif + +#if !USE_SNPRINTF + /* Allocate a temporary buffer of sufficient size for calling + sprintf. */ + tmp_length = + MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type, + flags, width, has_precision, precision, + pad_ourselves); + + if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T)) + tmp = tmpbuf; + else + { + size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T)); + + if (size_overflow_p (tmp_memsize)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + tmp = (TCHAR_T *) malloc (tmp_memsize); + if (tmp == NULL) + /* Out of memory. */ + goto out_of_memory; + } +#endif + + /* Construct the format string for calling snprintf or + sprintf. */ + fbp = buf; + *fbp++ = '%'; +#if NEED_PRINTF_FLAG_GROUPING + /* The underlying implementation doesn't support the ' flag. + Produce no grouping characters in this case; this is + acceptable because the grouping is locale dependent. */ +#else + if (flags & FLAG_GROUP) + *fbp++ = '\''; +#endif + if (flags & FLAG_LEFT) + *fbp++ = '-'; + if (flags & FLAG_SHOWSIGN) + *fbp++ = '+'; + if (flags & FLAG_SPACE) + *fbp++ = ' '; + if (flags & FLAG_ALT) + *fbp++ = '#'; +#if __GLIBC__ >= 2 && !defined __UCLIBC__ + if (flags & FLAG_LOCALIZED) + *fbp++ = 'I'; +#endif + if (!pad_ourselves) + { + if (flags & FLAG_ZERO) + *fbp++ = '0'; + if (dp->width_start != dp->width_end) + { + size_t n = dp->width_end - dp->width_start; + /* The width specification is known to consist only + of standard ASCII characters. */ + if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) + { + memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T)); + fbp += n; + } + else + { + const FCHAR_T *mp = dp->width_start; + do + *fbp++ = *mp++; + while (--n > 0); + } + } + } + if (!prec_ourselves) + { + if (dp->precision_start != dp->precision_end) + { + size_t n = dp->precision_end - dp->precision_start; + /* The precision specification is known to consist only + of standard ASCII characters. */ + if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) + { + memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T)); + fbp += n; + } + else + { + const FCHAR_T *mp = dp->precision_start; + do + *fbp++ = *mp++; + while (--n > 0); + } + } + } + + switch (type) + { +#if HAVE_LONG_LONG_INT + case TYPE_LONGLONGINT: + case TYPE_ULONGLONGINT: +# if defined _WIN32 && ! defined __CYGWIN__ + *fbp++ = 'I'; + *fbp++ = '6'; + *fbp++ = '4'; + break; +# else + *fbp++ = 'l'; +# endif +#endif + FALLTHROUGH; + case TYPE_LONGINT: + case TYPE_ULONGINT: +#if HAVE_WINT_T + case TYPE_WIDE_CHAR: +#endif +#if HAVE_WCHAR_T + case TYPE_WIDE_STRING: +#endif + *fbp++ = 'l'; + break; + case TYPE_LONGDOUBLE: + *fbp++ = 'L'; + break; + default: + break; + } +#if NEED_PRINTF_DIRECTIVE_F + if (dp->conversion == 'F') + *fbp = 'f'; + else +#endif + *fbp = dp->conversion; +#if USE_SNPRINTF +# if ! (((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) \ + && !defined __UCLIBC__) \ + || (defined __APPLE__ && defined __MACH__) \ + || (defined _WIN32 && ! defined __CYGWIN__)) + fbp[1] = '%'; + fbp[2] = 'n'; + fbp[3] = '\0'; +# else + /* On glibc2 systems from glibc >= 2.3 - probably also older + ones - we know that snprintf's return value conforms to + ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and + gl_SNPRINTF_TRUNCATION_C99 pass. + Therefore we can avoid using %n in this situation. + On glibc2 systems from 2004-10-18 or newer, the use of %n + in format strings in writable memory may crash the program + (if compiled with _FORTIFY_SOURCE=2), so we should avoid it + in this situation. */ + /* On Mac OS X 10.3 or newer, we know that snprintf's return + value conforms to ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 + and gl_SNPRINTF_TRUNCATION_C99 pass. + Therefore we can avoid using %n in this situation. + On Mac OS X 10.13 or newer, the use of %n in format strings + in writable memory by default crashes the program, so we + should avoid it in this situation. */ + /* On native Windows systems (such as mingw), we can avoid using + %n because: + - Although the gl_SNPRINTF_TRUNCATION_C99 test fails, + snprintf does not write more than the specified number + of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes + '4', '5', '6' into buf, not '4', '5', '\0'.) + - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf + allows us to recognize the case of an insufficient + buffer size: it returns -1 in this case. + On native Windows systems (such as mingw) where the OS is + Windows Vista, the use of %n in format strings by default + crashes the program. See + <https://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and + <https://msdn.microsoft.com/en-us/library/ms175782.aspx> + So we should avoid %n in this situation. */ + fbp[1] = '\0'; +# endif +#else + fbp[1] = '\0'; +#endif + + /* Construct the arguments for calling snprintf or sprintf. */ + prefix_count = 0; + if (!pad_ourselves && dp->width_arg_index != ARG_NONE) + { + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; + } + if (!prec_ourselves && dp->precision_arg_index != ARG_NONE) + { + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int; + } + +#if USE_SNPRINTF + /* The SNPRINTF result is appended after result[0..length]. + The latter is an array of DCHAR_T; SNPRINTF appends an + array of TCHAR_T to it. This is possible because + sizeof (TCHAR_T) divides sizeof (DCHAR_T) and + alignof (TCHAR_T) <= alignof (DCHAR_T). */ +# define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T)) + /* Ensure that maxlen below will be >= 2. Needed on BeOS, + where an snprintf() with maxlen==1 acts like sprintf(). */ + ENSURE_ALLOCATION (xsum (length, + (2 + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR)); + /* Prepare checking whether snprintf returns the count + via %n. */ + *(TCHAR_T *) (result + length) = '\0'; +#endif + + orig_errno = errno; + + for (;;) + { + int count = -1; + +#if USE_SNPRINTF + int retcount = 0; + size_t maxlen = allocated - length; + /* SNPRINTF can fail if its second argument is + > INT_MAX. */ + if (maxlen > INT_MAX / TCHARS_PER_DCHAR) + maxlen = INT_MAX / TCHARS_PER_DCHAR; + maxlen = maxlen * TCHARS_PER_DCHAR; +# define SNPRINTF_BUF(arg) \ + switch (prefix_count) \ + { \ + case 0: \ + retcount = SNPRINTF ((TCHAR_T *) (result + length), \ + maxlen, buf, \ + arg, &count); \ + break; \ + case 1: \ + retcount = SNPRINTF ((TCHAR_T *) (result + length), \ + maxlen, buf, \ + prefixes[0], arg, &count); \ + break; \ + case 2: \ + retcount = SNPRINTF ((TCHAR_T *) (result + length), \ + maxlen, buf, \ + prefixes[0], prefixes[1], arg, \ + &count); \ + break; \ + default: \ + abort (); \ + } +#else +# define SNPRINTF_BUF(arg) \ + switch (prefix_count) \ + { \ + case 0: \ + count = sprintf (tmp, buf, arg); \ + break; \ + case 1: \ + count = sprintf (tmp, buf, prefixes[0], arg); \ + break; \ + case 2: \ + count = sprintf (tmp, buf, prefixes[0], prefixes[1],\ + arg); \ + break; \ + default: \ + abort (); \ + } +#endif + + errno = 0; + switch (type) + { + case TYPE_SCHAR: + { + int arg = a.arg[dp->arg_index].a.a_schar; + SNPRINTF_BUF (arg); + } + break; + case TYPE_UCHAR: + { + unsigned int arg = a.arg[dp->arg_index].a.a_uchar; + SNPRINTF_BUF (arg); + } + break; + case TYPE_SHORT: + { + int arg = a.arg[dp->arg_index].a.a_short; + SNPRINTF_BUF (arg); + } + break; + case TYPE_USHORT: + { + unsigned int arg = a.arg[dp->arg_index].a.a_ushort; + SNPRINTF_BUF (arg); + } + break; + case TYPE_INT: + { + int arg = a.arg[dp->arg_index].a.a_int; + SNPRINTF_BUF (arg); + } + break; + case TYPE_UINT: + { + unsigned int arg = a.arg[dp->arg_index].a.a_uint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_LONGINT: + { + long int arg = a.arg[dp->arg_index].a.a_longint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_ULONGINT: + { + unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; + SNPRINTF_BUF (arg); + } + break; +#if HAVE_LONG_LONG_INT + case TYPE_LONGLONGINT: + { + long long int arg = a.arg[dp->arg_index].a.a_longlongint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_ULONGLONGINT: + { + unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_DOUBLE: + { + double arg = a.arg[dp->arg_index].a.a_double; + SNPRINTF_BUF (arg); + } + break; + case TYPE_LONGDOUBLE: + { + long double arg = a.arg[dp->arg_index].a.a_longdouble; + SNPRINTF_BUF (arg); + } + break; + case TYPE_CHAR: + { + int arg = a.arg[dp->arg_index].a.a_char; + SNPRINTF_BUF (arg); + } + break; +#if HAVE_WINT_T + case TYPE_WIDE_CHAR: + { + wint_t arg = a.arg[dp->arg_index].a.a_wide_char; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_STRING: + { + const char *arg = a.arg[dp->arg_index].a.a_string; + SNPRINTF_BUF (arg); + } + break; +#if HAVE_WCHAR_T + case TYPE_WIDE_STRING: + { + const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_POINTER: + { + void *arg = a.arg[dp->arg_index].a.a_pointer; + SNPRINTF_BUF (arg); + } + break; + default: + abort (); + } + +#if USE_SNPRINTF + /* Portability: Not all implementations of snprintf() + are ISO C 99 compliant. Determine the number of + bytes that snprintf() has produced or would have + produced. */ + if (count >= 0) + { + /* Verify that snprintf() has NUL-terminated its + result. */ + if ((unsigned int) count < maxlen + && ((TCHAR_T *) (result + length)) [count] != '\0') + abort (); + /* Portability hack. */ + if (retcount > count) + count = retcount; + } + else + { + /* snprintf() doesn't understand the '%n' + directive. */ + if (fbp[1] != '\0') + { + /* Don't use the '%n' directive; instead, look + at the snprintf() return value. */ + fbp[1] = '\0'; + continue; + } + else + { + /* Look at the snprintf() return value. */ + if (retcount < 0) + { +# if !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF + /* HP-UX 10.20 snprintf() is doubly deficient: + It doesn't understand the '%n' directive, + *and* it returns -1 (rather than the length + that would have been required) when the + buffer is too small. + But a failure at this point can also come + from other reasons than a too small buffer, + such as an invalid wide string argument to + the %ls directive, or possibly an invalid + floating-point argument. */ + size_t tmp_length = + MAX_ROOM_NEEDED (&a, dp->arg_index, + dp->conversion, type, flags, + width, + has_precision, + precision, pad_ourselves); + + if (maxlen < tmp_length) + { + /* Make more room. But try to do through + this reallocation only once. */ + size_t bigger_need = + xsum (length, + xsum (tmp_length, + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR); + /* And always grow proportionally. + (There may be several arguments, each + needing a little more room than the + previous one.) */ + size_t bigger_need2 = + xsum (xtimes (allocated, 2), 12); + if (bigger_need < bigger_need2) + bigger_need = bigger_need2; + ENSURE_ALLOCATION (bigger_need); + continue; + } +# endif + } + else + count = retcount; + } + } +#endif + + /* Attempt to handle failure. */ + if (count < 0) + { + /* SNPRINTF or sprintf failed. Save and use the errno + that it has set, if any. */ + int saved_errno = errno; + if (saved_errno == 0) + { + if (dp->conversion == 'c' || dp->conversion == 's') + saved_errno = EILSEQ; + else + saved_errno = EINVAL; + } + + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + + errno = saved_errno; + return NULL; + } + +#if USE_SNPRINTF + /* Handle overflow of the allocated buffer. + If such an overflow occurs, a C99 compliant snprintf() + returns a count >= maxlen. However, a non-compliant + snprintf() function returns only count = maxlen - 1. To + cover both cases, test whether count >= maxlen - 1. */ + if ((unsigned int) count + 1 >= maxlen) + { + /* If maxlen already has attained its allowed maximum, + allocating more memory will not increase maxlen. + Instead of looping, bail out. */ + if (maxlen == INT_MAX / TCHARS_PER_DCHAR) + goto overflow; + else + { + /* Need at least (count + 1) * sizeof (TCHAR_T) + bytes. (The +1 is for the trailing NUL.) + But ask for (count + 2) * sizeof (TCHAR_T) + bytes, so that in the next round, we likely get + maxlen > (unsigned int) count + 1 + and so we don't get here again. + And allocate proportionally, to avoid looping + eternally if snprintf() reports a too small + count. */ + size_t n = + xmax (xsum (length, + ((unsigned int) count + 2 + + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR), + xtimes (allocated, 2)); + + ENSURE_ALLOCATION (n); + continue; + } + } +#endif + +#if NEED_PRINTF_UNBOUNDED_PRECISION + if (prec_ourselves) + { + /* Handle the precision. */ + TCHAR_T *prec_ptr = +# if USE_SNPRINTF + (TCHAR_T *) (result + length); +# else + tmp; +# endif + size_t prefix_count; + size_t move; + + prefix_count = 0; + /* Put the additional zeroes after the sign. */ + if (count >= 1 + && (*prec_ptr == '-' || *prec_ptr == '+' + || *prec_ptr == ' ')) + prefix_count = 1; + /* Put the additional zeroes after the 0x prefix if + (flags & FLAG_ALT) || (dp->conversion == 'p'). */ + else if (count >= 2 + && prec_ptr[0] == '0' + && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X')) + prefix_count = 2; + + move = count - prefix_count; + if (precision > move) + { + /* Insert zeroes. */ + size_t insert = precision - move; + TCHAR_T *prec_end; + +# if USE_SNPRINTF + size_t n = + xsum (length, + (count + insert + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR); + length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR; + ENSURE_ALLOCATION (n); + length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR; + prec_ptr = (TCHAR_T *) (result + length); +# endif + + prec_end = prec_ptr + count; + prec_ptr += prefix_count; + + while (prec_end > prec_ptr) + { + prec_end--; + prec_end[insert] = prec_end[0]; + } + + prec_end += insert; + do + *--prec_end = '0'; + while (prec_end > prec_ptr); + + count += insert; + } + } +#endif + +#if !USE_SNPRINTF + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); +#endif + +#if !DCHAR_IS_TCHAR + /* Convert from TCHAR_T[] to DCHAR_T[]. */ + if (dp->conversion == 'c' || dp->conversion == 's') + { + /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING + TYPE_WIDE_STRING. + The result string is not certainly ASCII. */ + const TCHAR_T *tmpsrc; + DCHAR_T *tmpdst; + size_t tmpdst_len; + /* This code assumes that TCHAR_T is 'char'. */ + verify (sizeof (TCHAR_T) == 1); +# if USE_SNPRINTF + tmpsrc = (TCHAR_T *) (result + length); +# else + tmpsrc = tmp; +# endif + tmpdst = + DCHAR_CONV_FROM_ENCODING (locale_charset (), + iconveh_question_mark, + tmpsrc, count, + NULL, + NULL, &tmpdst_len); + if (tmpdst == NULL) + { + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + ENSURE_ALLOCATION (xsum (length, tmpdst_len)); + DCHAR_CPY (result + length, tmpdst, tmpdst_len); + free (tmpdst); + count = tmpdst_len; + } + else + { + /* The result string is ASCII. + Simple 1:1 conversion. */ +# if USE_SNPRINTF + /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a + no-op conversion, in-place on the array starting + at (result + length). */ + if (sizeof (DCHAR_T) != sizeof (TCHAR_T)) +# endif + { + const TCHAR_T *tmpsrc; + DCHAR_T *tmpdst; + size_t n; + +# if USE_SNPRINTF + if (result == resultbuf) + { + tmpsrc = (TCHAR_T *) (result + length); + /* ENSURE_ALLOCATION will not move tmpsrc + (because it's part of resultbuf). */ + ENSURE_ALLOCATION (xsum (length, count)); + } + else + { + /* ENSURE_ALLOCATION will move the array + (because it uses realloc(). */ + ENSURE_ALLOCATION (xsum (length, count)); + tmpsrc = (TCHAR_T *) (result + length); + } +# else + tmpsrc = tmp; + ENSURE_ALLOCATION (xsum (length, count)); +# endif + tmpdst = result + length; + /* Copy backwards, because of overlapping. */ + tmpsrc += count; + tmpdst += count; + for (n = count; n > 0; n--) + *--tmpdst = *--tmpsrc; + } + } +#endif + +#if DCHAR_IS_TCHAR && !USE_SNPRINTF + /* Make room for the result. */ + if (count > allocated - length) + { + /* Need at least count elements. But allocate + proportionally. */ + size_t n = + xmax (xsum (length, count), xtimes (allocated, 2)); + + ENSURE_ALLOCATION (n); + } +#endif + + /* Here count <= allocated - length. */ + + /* Perform padding. */ +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + if (pad_ourselves && has_width) + { + size_t w; +# if ENABLE_UNISTDIO + /* Outside POSIX, it's preferable to compare the width + against the number of _characters_ of the converted + value. */ + w = DCHAR_MBSNLEN (result + length, count); +# else + /* The width is compared against the number of _bytes_ + of the converted value, says POSIX. */ + w = count; +# endif + if (w < width) + { + size_t pad = width - w; + + /* Make room for the result. */ + if (xsum (count, pad) > allocated - length) + { + /* Need at least count + pad elements. But + allocate proportionally. */ + size_t n = + xmax (xsum3 (length, count, pad), + xtimes (allocated, 2)); + +# if USE_SNPRINTF + length += count; + ENSURE_ALLOCATION (n); + length -= count; +# else + ENSURE_ALLOCATION (n); +# endif + } + /* Here count + pad <= allocated - length. */ + + { +# if !DCHAR_IS_TCHAR || USE_SNPRINTF + DCHAR_T * const rp = result + length; +# else + DCHAR_T * const rp = tmp; +# endif + DCHAR_T *p = rp + count; + DCHAR_T *end = p + pad; + DCHAR_T *pad_ptr; +# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO + if (dp->conversion == 'c' + || dp->conversion == 's') + /* No zero-padding for string directives. */ + pad_ptr = NULL; + else +# endif + { + pad_ptr = (*rp == '-' ? rp + 1 : rp); + /* No zero-padding of "inf" and "nan". */ + if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z') + || (*pad_ptr >= 'a' && *pad_ptr <= 'z')) + pad_ptr = NULL; + } + /* The generated string now extends from rp to p, + with the zero padding insertion point being at + pad_ptr. */ + + count = count + pad; /* = end - rp */ + + if (flags & FLAG_LEFT) + { + /* Pad with spaces on the right. */ + for (; pad > 0; pad--) + *p++ = ' '; + } + else if ((flags & FLAG_ZERO) && pad_ptr != NULL) + { + /* Pad with zeroes. */ + DCHAR_T *q = end; + + while (p > pad_ptr) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = '0'; + } + else + { + /* Pad with spaces on the left. */ + DCHAR_T *q = end; + + while (p > rp) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = ' '; + } + } + } + } +#endif + + /* Here still count <= allocated - length. */ + +#if !DCHAR_IS_TCHAR || USE_SNPRINTF + /* The snprintf() result did fit. */ +#else + /* Append the sprintf() result. */ + memcpy (result + length, tmp, count * sizeof (DCHAR_T)); +#endif +#if !USE_SNPRINTF + if (tmp != tmpbuf) + free (tmp); +#endif + +#if NEED_PRINTF_DIRECTIVE_F + if (dp->conversion == 'F') + { + /* Convert the %f result to upper case for %F. */ + DCHAR_T *rp = result + length; + size_t rc; + for (rc = count; rc > 0; rc--, rp++) + if (*rp >= 'a' && *rp <= 'z') + *rp = *rp - 'a' + 'A'; + } +#endif + + length += count; + break; + } + errno = orig_errno; +#undef pad_ourselves +#undef prec_ourselves + } + } + } + + /* Add the final NUL. */ + ENSURE_ALLOCATION (xsum (length, 1)); + result[length] = '\0'; + + if (result != resultbuf && length + 1 < allocated) + { + /* Shrink the allocated memory if possible. */ + DCHAR_T *memory; + + memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T)); + if (memory != NULL) + result = memory; + } + + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + *lengthp = length; + /* Note that we can produce a big string of a length > INT_MAX. POSIX + says that snprintf() fails with errno = EOVERFLOW in this case, but + that's only because snprintf() returns an 'int'. This function does + not have this limitation. */ + return result; + +#if USE_SNPRINTF + overflow: + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EOVERFLOW; + return NULL; +#endif + + out_of_memory: + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + out_of_memory_1: + CLEANUP (); + errno = ENOMEM; + return NULL; + } +} + +#undef MAX_ROOM_NEEDED +#undef TCHARS_PER_DCHAR +#undef SNPRINTF +#undef USE_SNPRINTF +#undef DCHAR_SET +#undef DCHAR_CPY +#undef PRINTF_PARSE +#undef DIRECTIVES +#undef DIRECTIVE +#undef DCHAR_IS_TCHAR +#undef TCHAR_T +#undef DCHAR_T +#undef FCHAR_T +#undef VASNPRINTF diff --git a/grub-core/lib/gnulib/vasnprintf.h b/grub-core/lib/gnulib/vasnprintf.h new file mode 100644 index 0000000..5b192b2 --- /dev/null +++ b/grub-core/lib/gnulib/vasnprintf.h @@ -0,0 +1,79 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 2002-2004, 2007-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _VASNPRINTF_H +#define _VASNPRINTF_H + +/* Get va_list. */ +#include <stdarg.h> + +/* Get size_t. */ +#include <stddef.h> + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The __-protected variants of the attributes 'format' and 'printf' are + accepted by gcc versions 2.6.4 (effectively 2.7) and later. + We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because + gnulib and libintl do '#define printf __printf__' when they override + the 'printf' function. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Write formatted output to a string dynamically allocated with malloc(). + You can pass a preallocated buffer for the result in RESULTBUF and its + size in *LENGTHP; otherwise you pass RESULTBUF = NULL. + If successful, return the address of the string (this may be = RESULTBUF + if no dynamic memory allocation was necessary) and set *LENGTHP to the + number of resulting bytes, excluding the trailing NUL. Upon error, set + errno and return NULL. + + When dynamic memory allocation occurs, the preallocated buffer is left + alone (with possibly modified contents). This makes it possible to use + a statically allocated or stack-allocated buffer, like this: + + char buf[100]; + size_t len = sizeof (buf); + char *output = vasnprintf (buf, &len, format, args); + if (output == NULL) + ... error handling ...; + else + { + ... use the output string ...; + if (output != buf) + free (output); + } + */ +#if REPLACE_VASNPRINTF +# define asnprintf rpl_asnprintf +# define vasnprintf rpl_vasnprintf +#endif +extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) + _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 4)); +extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT ((__printf__, 3, 0)); + +#ifdef __cplusplus +} +#endif + +#endif /* _VASNPRINTF_H */ diff --git a/grub-core/lib/gnulib/verify.h b/grub-core/lib/gnulib/verify.h new file mode 100644 index 0000000..b2e5f64 --- /dev/null +++ b/grub-core/lib/gnulib/verify.h @@ -0,0 +1,285 @@ +/* Compile-time assert-like macros. + + Copyright (C) 2005-2006, 2009-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ + +#ifndef _GL_VERIFY_H +#define _GL_VERIFY_H + + +/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert works as per C11. + This is supported by GCC 4.6.0 and later, in C mode, and its use + here generates easier-to-read diagnostics when verify (R) fails. + + Define _GL_HAVE_STATIC_ASSERT to 1 if static_assert works as per C++11. + This will likely be supported by future GCC versions, in C++ mode. + + Use this only with GCC. If we were willing to slow 'configure' + down we could also use it with other compilers, but since this + affects only the quality of diagnostics, why bother? */ +#if (4 < __GNUC__ + (6 <= __GNUC_MINOR__) \ + && (201112L <= __STDC_VERSION__ || !defined __STRICT_ANSI__) \ + && !defined __cplusplus) +# define _GL_HAVE__STATIC_ASSERT 1 +#endif +/* The condition (99 < __GNUC__) is temporary, until we know about the + first G++ release that supports static_assert. */ +#if (99 < __GNUC__) && defined __cplusplus +# define _GL_HAVE_STATIC_ASSERT 1 +#endif + +/* FreeBSD 9.1 <sys/cdefs.h>, included by <stddef.h> and lots of other + system headers, defines a conflicting _Static_assert that is no + better than ours; override it. */ +#ifndef _GL_HAVE_STATIC_ASSERT +# include <stddef.h> +# undef _Static_assert +#endif + +/* Each of these macros verifies that its argument R is nonzero. To + be portable, R should be an integer constant expression. Unlike + assert (R), there is no run-time overhead. + + If _Static_assert works, verify (R) uses it directly. Similarly, + _GL_VERIFY_TRUE works by packaging a _Static_assert inside a struct + that is an operand of sizeof. + + The code below uses several ideas for C++ compilers, and for C + compilers that do not support _Static_assert: + + * The first step is ((R) ? 1 : -1). Given an expression R, of + integral or boolean or floating-point type, this yields an + expression of integral type, whose value is later verified to be + constant and nonnegative. + + * Next this expression W is wrapped in a type + struct _gl_verify_type { + unsigned int _gl_verify_error_if_negative: W; + }. + If W is negative, this yields a compile-time error. No compiler can + deal with a bit-field of negative size. + + One might think that an array size check would have the same + effect, that is, that the type struct { unsigned int dummy[W]; } + would work as well. However, inside a function, some compilers + (such as C++ compilers and GNU C) allow local parameters and + variables inside array size expressions. With these compilers, + an array size check would not properly diagnose this misuse of + the verify macro: + + void function (int n) { verify (n < 0); } + + * For the verify macro, the struct _gl_verify_type will need to + somehow be embedded into a declaration. To be portable, this + declaration must declare an object, a constant, a function, or a + typedef name. If the declared entity uses the type directly, + such as in + + struct dummy {...}; + typedef struct {...} dummy; + extern struct {...} *dummy; + extern void dummy (struct {...} *); + extern struct {...} *dummy (void); + + two uses of the verify macro would yield colliding declarations + if the entity names are not disambiguated. A workaround is to + attach the current line number to the entity name: + + #define _GL_CONCAT0(x, y) x##y + #define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) + extern struct {...} * _GL_CONCAT (dummy, __LINE__); + + But this has the problem that two invocations of verify from + within the same macro would collide, since the __LINE__ value + would be the same for both invocations. (The GCC __COUNTER__ + macro solves this problem, but is not portable.) + + A solution is to use the sizeof operator. It yields a number, + getting rid of the identity of the type. Declarations like + + extern int dummy [sizeof (struct {...})]; + extern void dummy (int [sizeof (struct {...})]); + extern int (*dummy (void)) [sizeof (struct {...})]; + + can be repeated. + + * Should the implementation use a named struct or an unnamed struct? + Which of the following alternatives can be used? + + extern int dummy [sizeof (struct {...})]; + extern int dummy [sizeof (struct _gl_verify_type {...})]; + extern void dummy (int [sizeof (struct {...})]); + extern void dummy (int [sizeof (struct _gl_verify_type {...})]); + extern int (*dummy (void)) [sizeof (struct {...})]; + extern int (*dummy (void)) [sizeof (struct _gl_verify_type {...})]; + + In the second and sixth case, the struct type is exported to the + outer scope; two such declarations therefore collide. GCC warns + about the first, third, and fourth cases. So the only remaining + possibility is the fifth case: + + extern int (*dummy (void)) [sizeof (struct {...})]; + + * GCC warns about duplicate declarations of the dummy function if + -Wredundant-decls is used. GCC 4.3 and later have a builtin + __COUNTER__ macro that can let us generate unique identifiers for + each dummy function, to suppress this warning. + + * This implementation exploits the fact that older versions of GCC, + which do not support _Static_assert, also do not warn about the + last declaration mentioned above. + + * GCC warns if -Wnested-externs is enabled and verify() is used + within a function body; but inside a function, you can always + arrange to use verify_expr() instead. + + * In C++, any struct definition inside sizeof is invalid. + Use a template type to work around the problem. */ + +/* Concatenate two preprocessor tokens. */ +#define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) +#define _GL_CONCAT0(x, y) x##y + +/* _GL_COUNTER is an integer, preferably one that changes each time we + use it. Use __COUNTER__ if it works, falling back on __LINE__ + otherwise. __LINE__ isn't perfect, but it's better than a + constant. */ +#if defined __COUNTER__ && __COUNTER__ != __COUNTER__ +# define _GL_COUNTER __COUNTER__ +#else +# define _GL_COUNTER __LINE__ +#endif + +/* Generate a symbol with the given prefix, making it unique if + possible. */ +#define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER) + +/* Verify requirement R at compile-time, as an integer constant expression + that returns 1. If R is false, fail at compile-time, preferably + with a diagnostic that includes the string-literal DIAGNOSTIC. */ + +#define _GL_VERIFY_TRUE(R, DIAGNOSTIC) \ + (!!sizeof (_GL_VERIFY_TYPE (R, DIAGNOSTIC))) + +#ifdef __cplusplus +# if !GNULIB_defined_struct__gl_verify_type +template <int w> + struct _gl_verify_type { + unsigned int _gl_verify_error_if_negative: w; + }; +# define GNULIB_defined_struct__gl_verify_type 1 +# endif +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + _gl_verify_type<(R) ? 1 : -1> +#elif defined _GL_HAVE__STATIC_ASSERT +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + struct { \ + _Static_assert (R, DIAGNOSTIC); \ + int _gl_dummy; \ + } +#else +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + struct { unsigned int _gl_verify_error_if_negative: (R) ? 1 : -1; } +#endif + +/* Verify requirement R at compile-time, as a declaration without a + trailing ';'. If R is false, fail at compile-time, preferably + with a diagnostic that includes the string-literal DIAGNOSTIC. + + Unfortunately, unlike C11, this implementation must appear as an + ordinary declaration, and cannot appear inside struct { ... }. */ + +#ifdef _GL_HAVE__STATIC_ASSERT +# define _GL_VERIFY _Static_assert +#else +# define _GL_VERIFY(R, DIAGNOSTIC) \ + extern int (*_GL_GENSYM (_gl_verify_function) (void)) \ + [_GL_VERIFY_TRUE (R, DIAGNOSTIC)] +#endif + +/* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h. */ +#ifdef _GL_STATIC_ASSERT_H +# if !defined _GL_HAVE__STATIC_ASSERT && !defined _Static_assert +# define _Static_assert(R, DIAGNOSTIC) _GL_VERIFY (R, DIAGNOSTIC) +# endif +# if !defined _GL_HAVE_STATIC_ASSERT && !defined static_assert +# define static_assert _Static_assert /* C11 requires this #define. */ +# endif +#endif + +/* @assert.h omit start@ */ + +/* Each of these macros verifies that its argument R is nonzero. To + be portable, R should be an integer constant expression. Unlike + assert (R), there is no run-time overhead. + + There are two macros, since no single macro can be used in all + contexts in C. verify_true (R) is for scalar contexts, including + integer constant expression contexts. verify (R) is for declaration + contexts, e.g., the top level. */ + +/* Verify requirement R at compile-time, as an integer constant expression. + Return 1. This is equivalent to verify_expr (R, 1). + + verify_true is obsolescent; please use verify_expr instead. */ + +#define verify_true(R) _GL_VERIFY_TRUE (R, "verify_true (" #R ")") + +/* Verify requirement R at compile-time. Return the value of the + expression E. */ + +#define verify_expr(R, E) \ + (_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E)) + +/* Verify requirement R at compile-time, as a declaration without a + trailing ';'. */ + +#ifdef __GNUC__ +# define verify(R) _GL_VERIFY (R, "verify (" #R ")") +#else +/* PGI barfs if R is long. Play it safe. */ +# define verify(R) _GL_VERIFY (R, "verify (...)") +#endif + +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +/* Assume that R always holds. This lets the compiler optimize + accordingly. R should not have side-effects; it may or may not be + evaluated. Behavior is undefined if R is false. */ + +#if (__has_builtin (__builtin_unreachable) \ + || 4 < __GNUC__ + (5 <= __GNUC_MINOR__)) +# define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) +#elif 1200 <= _MSC_VER +# define assume(R) __assume (R) +#elif ((defined GCC_LINT || defined lint) \ + && (__has_builtin (__builtin_trap) \ + || 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__)))) + /* Doing it this way helps various packages when configured with + --enable-gcc-warnings, which compiles with -Dlint. It's nicer + when 'assume' silences warnings even with older GCCs. */ +# define assume(R) ((R) ? (void) 0 : __builtin_trap ()) +#else + /* Some tools grok NOTREACHED, e.g., Oracle Studio 12.6. */ +# define assume(R) ((R) ? (void) 0 : /*NOTREACHED*/ (void) 0) +#endif + +/* @assert.h omit end@ */ + +#endif diff --git a/grub-core/lib/gnulib/vsnprintf.c b/grub-core/lib/gnulib/vsnprintf.c new file mode 100644 index 0000000..6a209f7 --- /dev/null +++ b/grub-core/lib/gnulib/vsnprintf.c @@ -0,0 +1,70 @@ +/* Formatted output to strings. + Copyright (C) 2004, 2006-2019 Free Software Foundation, Inc. + Written by Simon Josefsson and Yoann Vandoorselaere <yoann@prelude-ids.org>. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* Specification. */ +#include <stdio.h> + +#include <errno.h> +#include <limits.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +#include "vasnprintf.h" + +/* Print formatted output to string STR. Similar to vsprintf, but + additional length SIZE limit how much is written into STR. Returns + string length of formatted string (which may be larger than SIZE). + STR may be NULL, in which case nothing will be written. On error, + return a negative value. */ +int +vsnprintf (char *str, size_t size, const char *format, va_list args) +{ + char *output; + size_t len; + size_t lenbuf = size; + + output = vasnprintf (str, &lenbuf, format, args); + len = lenbuf; + + if (!output) + return -1; + + if (output != str) + { + if (size) + { + size_t pruned_len = (len < size ? len : size - 1); + memcpy (str, output, pruned_len); + str[pruned_len] = '\0'; + } + + free (output); + } + + if (len > INT_MAX) + { + errno = EOVERFLOW; + return -1; + } + + return len; +} diff --git a/grub-core/lib/gnulib/warn-on-use.h b/grub-core/lib/gnulib/warn-on-use.h new file mode 100644 index 0000000..7d11a15 --- /dev/null +++ b/grub-core/lib/gnulib/warn-on-use.h @@ -0,0 +1,131 @@ +/* A C macro for emitting warnings if a function is used. + Copyright (C) 2010-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* _GL_WARN_ON_USE (function, "literal string") issues a declaration + for FUNCTION which will then trigger a compiler warning containing + the text of "literal string" anywhere that function is called, if + supported by the compiler. If the compiler does not support this + feature, the macro expands to an unused extern declaration. + + _GL_WARN_ON_USE_ATTRIBUTE ("literal string") expands to the + attribute used in _GL_WARN_ON_USE. If the compiler does not support + this feature, it expands to empty. + + These macros are useful for marking a function as a potential + portability trap, with the intent that "literal string" include + instructions on the replacement function that should be used + instead. + _GL_WARN_ON_USE is for functions with 'extern' linkage. + _GL_WARN_ON_USE_ATTRIBUTE is for functions with 'static' or 'inline' + linkage. + + However, one of the reasons that a function is a portability trap is + if it has the wrong signature. Declaring FUNCTION with a different + signature in C is a compilation error, so this macro must use the + same type as any existing declaration so that programs that avoid + the problematic FUNCTION do not fail to compile merely because they + included a header that poisoned the function. But this implies that + _GL_WARN_ON_USE is only safe to use if FUNCTION is known to already + have a declaration. Use of this macro implies that there must not + be any other macro hiding the declaration of FUNCTION; but + undefining FUNCTION first is part of the poisoning process anyway + (although for symbols that are provided only via a macro, the result + is a compilation error rather than a warning containing + "literal string"). Also note that in C++, it is only safe to use if + FUNCTION has no overloads. + + For an example, it is possible to poison 'getline' by: + - adding a call to gl_WARN_ON_USE_PREPARE([[#include <stdio.h>]], + [getline]) in configure.ac, which potentially defines + HAVE_RAW_DECL_GETLINE + - adding this code to a header that wraps the system <stdio.h>: + #undef getline + #if HAVE_RAW_DECL_GETLINE + _GL_WARN_ON_USE (getline, "getline is required by POSIX 2008, but" + "not universally present; use the gnulib module getline"); + #endif + + It is not possible to directly poison global variables. But it is + possible to write a wrapper accessor function, and poison that + (less common usage, like &environ, will cause a compilation error + rather than issue the nice warning, but the end result of informing + the developer about their portability problem is still achieved): + #if HAVE_RAW_DECL_ENVIRON + static char *** + rpl_environ (void) { return &environ; } + _GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared"); + # undef environ + # define environ (*rpl_environ ()) + #endif + or better (avoiding contradictory use of 'static' and 'extern'): + #if HAVE_RAW_DECL_ENVIRON + static char *** + _GL_WARN_ON_USE_ATTRIBUTE ("environ is not always properly declared") + rpl_environ (void) { return &environ; } + # undef environ + # define environ (*rpl_environ ()) + #endif + */ +#ifndef _GL_WARN_ON_USE + +# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) +/* A compiler attribute is available in gcc versions 4.3.0 and later. */ +# define _GL_WARN_ON_USE(function, message) \ +extern __typeof__ (function) function __attribute__ ((__warning__ (message))) +# define _GL_WARN_ON_USE_ATTRIBUTE(message) \ + __attribute__ ((__warning__ (message))) +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING +/* Verify the existence of the function. */ +# define _GL_WARN_ON_USE(function, message) \ +extern __typeof__ (function) function +# define _GL_WARN_ON_USE_ATTRIBUTE(message) +# else /* Unsupported. */ +# define _GL_WARN_ON_USE(function, message) \ +_GL_WARN_EXTERN_C int _gl_warn_on_use +# define _GL_WARN_ON_USE_ATTRIBUTE(message) +# endif +#endif + +/* _GL_WARN_ON_USE_CXX (function, rettype, parameters_and_attributes, "string") + is like _GL_WARN_ON_USE (function, "string"), except that the function is + declared with the given prototype, consisting of return type, parameters, + and attributes. + This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does + not work in this case. */ +#ifndef _GL_WARN_ON_USE_CXX +# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) +# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ +extern rettype function parameters_and_attributes \ + __attribute__ ((__warning__ (msg))) +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING +/* Verify the existence of the function. */ +# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ +extern rettype function parameters_and_attributes +# else /* Unsupported. */ +# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ +_GL_WARN_EXTERN_C int _gl_warn_on_use +# endif +#endif + +/* _GL_WARN_EXTERN_C declaration; + performs the declaration with C linkage. */ +#ifndef _GL_WARN_EXTERN_C +# if defined __cplusplus +# define _GL_WARN_EXTERN_C extern "C" +# else +# define _GL_WARN_EXTERN_C extern +# endif +#endif diff --git a/grub-core/lib/gnulib/wchar.in.h b/grub-core/lib/gnulib/wchar.in.h new file mode 100644 index 0000000..17d5691 --- /dev/null +++ b/grub-core/lib/gnulib/wchar.in.h @@ -0,0 +1,1072 @@ +/* A substitute for ISO C99 <wchar.h>, for platforms that have issues. + + Copyright (C) 2007-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Eric Blake. */ + +/* + * ISO C 99 <wchar.h> for platforms that have issues. + * <http://www.opengroup.org/susv3xbd/wchar.h.html> + * + * For now, this just ensures proper prerequisite inclusion order and + * the declaration of wcwidth(). + */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if (((defined __need_mbstate_t || defined __need_wint_t) \ + && !defined __MINGW32__) \ + || (defined __hpux \ + && ((defined _INTTYPES_INCLUDED && !defined strtoimax) \ + || defined _GL_JUST_INCLUDE_SYSTEM_WCHAR_H)) \ + || (defined __MINGW32__ && defined __STRING_H_SOURCED__) \ + || defined _GL_ALREADY_INCLUDING_WCHAR_H) +/* Special invocation convention: + - Inside glibc and uClibc header files, but not MinGW. + - On HP-UX 11.00 we have a sequence of nested includes + <wchar.h> -> <stdlib.h> -> <stdint.h>, and the latter includes <wchar.h>, + once indirectly <stdint.h> -> <sys/types.h> -> <inttypes.h> -> <wchar.h> + and once directly. In both situations 'wint_t' is not yet defined, + therefore we cannot provide the function overrides; instead include only + the system's <wchar.h>. + - With MinGW 3.22, when <string.h> includes <wchar.h>, only some part of + <wchar.h> is actually processed, and that doesn't include 'mbstate_t'. + - On IRIX 6.5, similarly, we have an include <wchar.h> -> <wctype.h>, and + the latter includes <wchar.h>. But here, we have no way to detect whether + <wctype.h> is completely included or is still being included. */ + +#@INCLUDE_NEXT@ @NEXT_WCHAR_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_WCHAR_H + +#define _GL_ALREADY_INCLUDING_WCHAR_H + +#if @HAVE_FEATURES_H@ +# include <features.h> /* for __GLIBC__ */ +#endif + +/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before + <wchar.h>. + BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be + included before <wchar.h>. + In some builds of uClibc, <wchar.h> is nonexistent and wchar_t is defined + by <stddef.h>. + But avoid namespace pollution on glibc systems. */ +#if !(defined __GLIBC__ && !defined __UCLIBC__) +# include <stddef.h> +#endif +#ifndef __GLIBC__ +# include <stdio.h> +# include <time.h> +#endif + +/* Include the original <wchar.h> if it exists. + Some builds of uClibc lack it. */ +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_WCHAR_H@ +# @INCLUDE_NEXT@ @NEXT_WCHAR_H@ +#endif + +#undef _GL_ALREADY_INCLUDING_WCHAR_H + +#ifndef _@GUARD_PREFIX@_WCHAR_H +#define _@GUARD_PREFIX@_WCHAR_H + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +# define _GL_ATTRIBUTE_PURE /* empty */ +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Define wint_t and WEOF. (Also done in wctype.in.h.) */ +#if !@HAVE_WINT_T@ && !defined wint_t +# define wint_t int +# ifndef WEOF +# define WEOF -1 +# endif +#else +/* mingw and MSVC define wint_t as 'unsigned short' in <crtdefs.h> or + <stddef.h>. This is too small: ISO C 99 section 7.24.1.(2) says that + wint_t must be "unchanged by default argument promotions". Override it. */ +# if @GNULIB_OVERRIDES_WINT_T@ +# if !GNULIB_defined_wint_t +# if @HAVE_CRTDEFS_H@ +# include <crtdefs.h> +# else +# include <stddef.h> +# endif +typedef unsigned int rpl_wint_t; +# undef wint_t +# define wint_t rpl_wint_t +# define GNULIB_defined_wint_t 1 +# endif +# endif +# ifndef WEOF +# define WEOF ((wint_t) -1) +# endif +#endif + + +/* Override mbstate_t if it is too small. + On IRIX 6.5, sizeof (mbstate_t) == 1, which is not sufficient for + implementing mbrtowc for encodings like UTF-8. */ +#if !(@HAVE_MBSINIT@ && @HAVE_MBRTOWC@) || @REPLACE_MBSTATE_T@ +# if !GNULIB_defined_mbstate_t +typedef int rpl_mbstate_t; +# undef mbstate_t +# define mbstate_t rpl_mbstate_t +# define GNULIB_defined_mbstate_t 1 +# endif +#endif + + +/* Convert a single-byte character to a wide character. */ +#if @GNULIB_BTOWC@ +# if @REPLACE_BTOWC@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef btowc +# define btowc rpl_btowc +# endif +_GL_FUNCDECL_RPL (btowc, wint_t, (int c) _GL_ATTRIBUTE_PURE); +_GL_CXXALIAS_RPL (btowc, wint_t, (int c)); +# else +# if !@HAVE_BTOWC@ +_GL_FUNCDECL_SYS (btowc, wint_t, (int c) _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (btowc, wint_t, (int c)); +# endif +_GL_CXXALIASWARN (btowc); +#elif defined GNULIB_POSIXCHECK +# undef btowc +# if HAVE_RAW_DECL_BTOWC +_GL_WARN_ON_USE (btowc, "btowc is unportable - " + "use gnulib module btowc for portability"); +# endif +#endif + + +/* Convert a wide character to a single-byte character. */ +#if @GNULIB_WCTOB@ +# if @REPLACE_WCTOB@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wctob +# define wctob rpl_wctob +# endif +_GL_FUNCDECL_RPL (wctob, int, (wint_t wc) _GL_ATTRIBUTE_PURE); +_GL_CXXALIAS_RPL (wctob, int, (wint_t wc)); +# else +# if !defined wctob && !@HAVE_DECL_WCTOB@ +/* wctob is provided by gnulib, or wctob exists but is not declared. */ +_GL_FUNCDECL_SYS (wctob, int, (wint_t wc) _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wctob, int, (wint_t wc)); +# endif +_GL_CXXALIASWARN (wctob); +#elif defined GNULIB_POSIXCHECK +# undef wctob +# if HAVE_RAW_DECL_WCTOB +_GL_WARN_ON_USE (wctob, "wctob is unportable - " + "use gnulib module wctob for portability"); +# endif +#endif + + +/* Test whether *PS is in the initial state. */ +#if @GNULIB_MBSINIT@ +# if @REPLACE_MBSINIT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbsinit +# define mbsinit rpl_mbsinit +# endif +_GL_FUNCDECL_RPL (mbsinit, int, (const mbstate_t *ps)); +_GL_CXXALIAS_RPL (mbsinit, int, (const mbstate_t *ps)); +# else +# if !@HAVE_MBSINIT@ +_GL_FUNCDECL_SYS (mbsinit, int, (const mbstate_t *ps)); +# endif +_GL_CXXALIAS_SYS (mbsinit, int, (const mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (mbsinit); +#elif defined GNULIB_POSIXCHECK +# undef mbsinit +# if HAVE_RAW_DECL_MBSINIT +_GL_WARN_ON_USE (mbsinit, "mbsinit is unportable - " + "use gnulib module mbsinit for portability"); +# endif +#endif + + +/* Convert a multibyte character to a wide character. */ +#if @GNULIB_MBRTOWC@ +# if @REPLACE_MBRTOWC@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbrtowc +# define mbrtowc rpl_mbrtowc +# endif +_GL_FUNCDECL_RPL (mbrtowc, size_t, + (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); +_GL_CXXALIAS_RPL (mbrtowc, size_t, + (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); +# else +# if !@HAVE_MBRTOWC@ +_GL_FUNCDECL_SYS (mbrtowc, size_t, + (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); +# endif +_GL_CXXALIAS_SYS (mbrtowc, size_t, + (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (mbrtowc); +#elif defined GNULIB_POSIXCHECK +# undef mbrtowc +# if HAVE_RAW_DECL_MBRTOWC +_GL_WARN_ON_USE (mbrtowc, "mbrtowc is unportable - " + "use gnulib module mbrtowc for portability"); +# endif +#endif + + +/* Recognize a multibyte character. */ +#if @GNULIB_MBRLEN@ +# if @REPLACE_MBRLEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbrlen +# define mbrlen rpl_mbrlen +# endif +_GL_FUNCDECL_RPL (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); +_GL_CXXALIAS_RPL (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); +# else +# if !@HAVE_MBRLEN@ +_GL_FUNCDECL_SYS (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); +# endif +_GL_CXXALIAS_SYS (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (mbrlen); +#elif defined GNULIB_POSIXCHECK +# undef mbrlen +# if HAVE_RAW_DECL_MBRLEN +_GL_WARN_ON_USE (mbrlen, "mbrlen is unportable - " + "use gnulib module mbrlen for portability"); +# endif +#endif + + +/* Convert a string to a wide string. */ +#if @GNULIB_MBSRTOWCS@ +# if @REPLACE_MBSRTOWCS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbsrtowcs +# define mbsrtowcs rpl_mbsrtowcs +# endif +_GL_FUNCDECL_RPL (mbsrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (mbsrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t len, + mbstate_t *ps)); +# else +# if !@HAVE_MBSRTOWCS@ +_GL_FUNCDECL_SYS (mbsrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mbsrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t len, + mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (mbsrtowcs); +#elif defined GNULIB_POSIXCHECK +# undef mbsrtowcs +# if HAVE_RAW_DECL_MBSRTOWCS +_GL_WARN_ON_USE (mbsrtowcs, "mbsrtowcs is unportable - " + "use gnulib module mbsrtowcs for portability"); +# endif +#endif + + +/* Convert a string to a wide string. */ +#if @GNULIB_MBSNRTOWCS@ +# if @REPLACE_MBSNRTOWCS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbsnrtowcs +# define mbsnrtowcs rpl_mbsnrtowcs +# endif +_GL_FUNCDECL_RPL (mbsnrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t srclen, size_t len, + mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (mbsnrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t srclen, size_t len, + mbstate_t *ps)); +# else +# if !@HAVE_MBSNRTOWCS@ +_GL_FUNCDECL_SYS (mbsnrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t srclen, size_t len, + mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mbsnrtowcs, size_t, + (wchar_t *dest, const char **srcp, size_t srclen, size_t len, + mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (mbsnrtowcs); +#elif defined GNULIB_POSIXCHECK +# undef mbsnrtowcs +# if HAVE_RAW_DECL_MBSNRTOWCS +_GL_WARN_ON_USE (mbsnrtowcs, "mbsnrtowcs is unportable - " + "use gnulib module mbsnrtowcs for portability"); +# endif +#endif + + +/* Convert a wide character to a multibyte character. */ +#if @GNULIB_WCRTOMB@ +# if @REPLACE_WCRTOMB@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcrtomb +# define wcrtomb rpl_wcrtomb +# endif +_GL_FUNCDECL_RPL (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); +_GL_CXXALIAS_RPL (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); +# else +# if !@HAVE_WCRTOMB@ +_GL_FUNCDECL_SYS (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); +# endif +_GL_CXXALIAS_SYS (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (wcrtomb); +#elif defined GNULIB_POSIXCHECK +# undef wcrtomb +# if HAVE_RAW_DECL_WCRTOMB +_GL_WARN_ON_USE (wcrtomb, "wcrtomb is unportable - " + "use gnulib module wcrtomb for portability"); +# endif +#endif + + +/* Convert a wide string to a string. */ +#if @GNULIB_WCSRTOMBS@ +# if @REPLACE_WCSRTOMBS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcsrtombs +# define wcsrtombs rpl_wcsrtombs +# endif +_GL_FUNCDECL_RPL (wcsrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t len, mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (wcsrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t len, + mbstate_t *ps)); +# else +# if !@HAVE_WCSRTOMBS@ +_GL_FUNCDECL_SYS (wcsrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t len, mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (wcsrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t len, + mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (wcsrtombs); +#elif defined GNULIB_POSIXCHECK +# undef wcsrtombs +# if HAVE_RAW_DECL_WCSRTOMBS +_GL_WARN_ON_USE (wcsrtombs, "wcsrtombs is unportable - " + "use gnulib module wcsrtombs for portability"); +# endif +#endif + + +/* Convert a wide string to a string. */ +#if @GNULIB_WCSNRTOMBS@ +# if @REPLACE_WCSNRTOMBS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcsnrtombs +# define wcsnrtombs rpl_wcsnrtombs +# endif +_GL_FUNCDECL_RPL (wcsnrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t srclen, size_t len, + mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (wcsnrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t srclen, size_t len, + mbstate_t *ps)); +# else +# if !@HAVE_WCSNRTOMBS@ +_GL_FUNCDECL_SYS (wcsnrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t srclen, size_t len, + mbstate_t *ps) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (wcsnrtombs, size_t, + (char *dest, const wchar_t **srcp, size_t srclen, size_t len, + mbstate_t *ps)); +# endif +_GL_CXXALIASWARN (wcsnrtombs); +#elif defined GNULIB_POSIXCHECK +# undef wcsnrtombs +# if HAVE_RAW_DECL_WCSNRTOMBS +_GL_WARN_ON_USE (wcsnrtombs, "wcsnrtombs is unportable - " + "use gnulib module wcsnrtombs for portability"); +# endif +#endif + + +/* Return the number of screen columns needed for WC. */ +#if @GNULIB_WCWIDTH@ +# if @REPLACE_WCWIDTH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcwidth +# define wcwidth rpl_wcwidth +# endif +_GL_FUNCDECL_RPL (wcwidth, int, (wchar_t) _GL_ATTRIBUTE_PURE); +_GL_CXXALIAS_RPL (wcwidth, int, (wchar_t)); +# else +# if !@HAVE_DECL_WCWIDTH@ +/* wcwidth exists but is not declared. */ +_GL_FUNCDECL_SYS (wcwidth, int, (wchar_t) _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcwidth, int, (wchar_t)); +# endif +_GL_CXXALIASWARN (wcwidth); +#elif defined GNULIB_POSIXCHECK +# undef wcwidth +# if HAVE_RAW_DECL_WCWIDTH +_GL_WARN_ON_USE (wcwidth, "wcwidth is unportable - " + "use gnulib module wcwidth for portability"); +# endif +#endif + + +/* Search N wide characters of S for C. */ +#if @GNULIB_WMEMCHR@ +# if !@HAVE_WMEMCHR@ +_GL_FUNCDECL_SYS (wmemchr, wchar_t *, (const wchar_t *s, wchar_t c, size_t n) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wmemchr (const wchar_t *, wchar_t, size_t); + wchar_t * std::wmemchr (wchar_t *, wchar_t, size_t); + } */ +_GL_CXXALIAS_SYS_CAST2 (wmemchr, + wchar_t *, (const wchar_t *, wchar_t, size_t), + const wchar_t *, (const wchar_t *, wchar_t, size_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wmemchr, wchar_t *, (wchar_t *s, wchar_t c, size_t n)); +_GL_CXXALIASWARN1 (wmemchr, const wchar_t *, + (const wchar_t *s, wchar_t c, size_t n)); +# else +_GL_CXXALIASWARN (wmemchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wmemchr +# if HAVE_RAW_DECL_WMEMCHR +_GL_WARN_ON_USE (wmemchr, "wmemchr is unportable - " + "use gnulib module wmemchr for portability"); +# endif +#endif + + +/* Compare N wide characters of S1 and S2. */ +#if @GNULIB_WMEMCMP@ +# if !@HAVE_WMEMCMP@ +_GL_FUNCDECL_SYS (wmemcmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wmemcmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wmemcmp); +#elif defined GNULIB_POSIXCHECK +# undef wmemcmp +# if HAVE_RAW_DECL_WMEMCMP +_GL_WARN_ON_USE (wmemcmp, "wmemcmp is unportable - " + "use gnulib module wmemcmp for portability"); +# endif +#endif + + +/* Copy N wide characters of SRC to DEST. */ +#if @GNULIB_WMEMCPY@ +# if !@HAVE_WMEMCPY@ +_GL_FUNCDECL_SYS (wmemcpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wmemcpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wmemcpy); +#elif defined GNULIB_POSIXCHECK +# undef wmemcpy +# if HAVE_RAW_DECL_WMEMCPY +_GL_WARN_ON_USE (wmemcpy, "wmemcpy is unportable - " + "use gnulib module wmemcpy for portability"); +# endif +#endif + + +/* Copy N wide characters of SRC to DEST, guaranteeing correct behavior for + overlapping memory areas. */ +#if @GNULIB_WMEMMOVE@ +# if !@HAVE_WMEMMOVE@ +_GL_FUNCDECL_SYS (wmemmove, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wmemmove, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wmemmove); +#elif defined GNULIB_POSIXCHECK +# undef wmemmove +# if HAVE_RAW_DECL_WMEMMOVE +_GL_WARN_ON_USE (wmemmove, "wmemmove is unportable - " + "use gnulib module wmemmove for portability"); +# endif +#endif + + +/* Set N wide characters of S to C. */ +#if @GNULIB_WMEMSET@ +# if !@HAVE_WMEMSET@ +_GL_FUNCDECL_SYS (wmemset, wchar_t *, (wchar_t *s, wchar_t c, size_t n)); +# endif +_GL_CXXALIAS_SYS (wmemset, wchar_t *, (wchar_t *s, wchar_t c, size_t n)); +_GL_CXXALIASWARN (wmemset); +#elif defined GNULIB_POSIXCHECK +# undef wmemset +# if HAVE_RAW_DECL_WMEMSET +_GL_WARN_ON_USE (wmemset, "wmemset is unportable - " + "use gnulib module wmemset for portability"); +# endif +#endif + + +/* Return the number of wide characters in S. */ +#if @GNULIB_WCSLEN@ +# if !@HAVE_WCSLEN@ +_GL_FUNCDECL_SYS (wcslen, size_t, (const wchar_t *s) _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcslen, size_t, (const wchar_t *s)); +_GL_CXXALIASWARN (wcslen); +#elif defined GNULIB_POSIXCHECK +# undef wcslen +# if HAVE_RAW_DECL_WCSLEN +_GL_WARN_ON_USE (wcslen, "wcslen is unportable - " + "use gnulib module wcslen for portability"); +# endif +#endif + + +/* Return the number of wide characters in S, but at most MAXLEN. */ +#if @GNULIB_WCSNLEN@ +# if !@HAVE_WCSNLEN@ +_GL_FUNCDECL_SYS (wcsnlen, size_t, (const wchar_t *s, size_t maxlen) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsnlen, size_t, (const wchar_t *s, size_t maxlen)); +_GL_CXXALIASWARN (wcsnlen); +#elif defined GNULIB_POSIXCHECK +# undef wcsnlen +# if HAVE_RAW_DECL_WCSNLEN +_GL_WARN_ON_USE (wcsnlen, "wcsnlen is unportable - " + "use gnulib module wcsnlen for portability"); +# endif +#endif + + +/* Copy SRC to DEST. */ +#if @GNULIB_WCSCPY@ +# if !@HAVE_WCSCPY@ +_GL_FUNCDECL_SYS (wcscpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +# endif +_GL_CXXALIAS_SYS (wcscpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +_GL_CXXALIASWARN (wcscpy); +#elif defined GNULIB_POSIXCHECK +# undef wcscpy +# if HAVE_RAW_DECL_WCSCPY +_GL_WARN_ON_USE (wcscpy, "wcscpy is unportable - " + "use gnulib module wcscpy for portability"); +# endif +#endif + + +/* Copy SRC to DEST, returning the address of the terminating L'\0' in DEST. */ +#if @GNULIB_WCPCPY@ +# if !@HAVE_WCPCPY@ +_GL_FUNCDECL_SYS (wcpcpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +# endif +_GL_CXXALIAS_SYS (wcpcpy, wchar_t *, (wchar_t *dest, const wchar_t *src)); +_GL_CXXALIASWARN (wcpcpy); +#elif defined GNULIB_POSIXCHECK +# undef wcpcpy +# if HAVE_RAW_DECL_WCPCPY +_GL_WARN_ON_USE (wcpcpy, "wcpcpy is unportable - " + "use gnulib module wcpcpy for portability"); +# endif +#endif + + +/* Copy no more than N wide characters of SRC to DEST. */ +#if @GNULIB_WCSNCPY@ +# if !@HAVE_WCSNCPY@ +_GL_FUNCDECL_SYS (wcsncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcsncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wcsncpy); +#elif defined GNULIB_POSIXCHECK +# undef wcsncpy +# if HAVE_RAW_DECL_WCSNCPY +_GL_WARN_ON_USE (wcsncpy, "wcsncpy is unportable - " + "use gnulib module wcsncpy for portability"); +# endif +#endif + + +/* Copy no more than N characters of SRC to DEST, returning the address of + the last character written into DEST. */ +#if @GNULIB_WCPNCPY@ +# if !@HAVE_WCPNCPY@ +_GL_FUNCDECL_SYS (wcpncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcpncpy, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wcpncpy); +#elif defined GNULIB_POSIXCHECK +# undef wcpncpy +# if HAVE_RAW_DECL_WCPNCPY +_GL_WARN_ON_USE (wcpncpy, "wcpncpy is unportable - " + "use gnulib module wcpncpy for portability"); +# endif +#endif + + +/* Append SRC onto DEST. */ +#if @GNULIB_WCSCAT@ +# if !@HAVE_WCSCAT@ +_GL_FUNCDECL_SYS (wcscat, wchar_t *, (wchar_t *dest, const wchar_t *src)); +# endif +_GL_CXXALIAS_SYS (wcscat, wchar_t *, (wchar_t *dest, const wchar_t *src)); +_GL_CXXALIASWARN (wcscat); +#elif defined GNULIB_POSIXCHECK +# undef wcscat +# if HAVE_RAW_DECL_WCSCAT +_GL_WARN_ON_USE (wcscat, "wcscat is unportable - " + "use gnulib module wcscat for portability"); +# endif +#endif + + +/* Append no more than N wide characters of SRC onto DEST. */ +#if @GNULIB_WCSNCAT@ +# if !@HAVE_WCSNCAT@ +_GL_FUNCDECL_SYS (wcsncat, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcsncat, wchar_t *, + (wchar_t *dest, const wchar_t *src, size_t n)); +_GL_CXXALIASWARN (wcsncat); +#elif defined GNULIB_POSIXCHECK +# undef wcsncat +# if HAVE_RAW_DECL_WCSNCAT +_GL_WARN_ON_USE (wcsncat, "wcsncat is unportable - " + "use gnulib module wcsncat for portability"); +# endif +#endif + + +/* Compare S1 and S2. */ +#if @GNULIB_WCSCMP@ +# if !@HAVE_WCSCMP@ +_GL_FUNCDECL_SYS (wcscmp, int, (const wchar_t *s1, const wchar_t *s2) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcscmp, int, (const wchar_t *s1, const wchar_t *s2)); +_GL_CXXALIASWARN (wcscmp); +#elif defined GNULIB_POSIXCHECK +# undef wcscmp +# if HAVE_RAW_DECL_WCSCMP +_GL_WARN_ON_USE (wcscmp, "wcscmp is unportable - " + "use gnulib module wcscmp for portability"); +# endif +#endif + + +/* Compare no more than N wide characters of S1 and S2. */ +#if @GNULIB_WCSNCMP@ +# if !@HAVE_WCSNCMP@ +_GL_FUNCDECL_SYS (wcsncmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsncmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wcsncmp); +#elif defined GNULIB_POSIXCHECK +# undef wcsncmp +# if HAVE_RAW_DECL_WCSNCMP +_GL_WARN_ON_USE (wcsncmp, "wcsncmp is unportable - " + "use gnulib module wcsncmp for portability"); +# endif +#endif + + +/* Compare S1 and S2, ignoring case. */ +#if @GNULIB_WCSCASECMP@ +# if !@HAVE_WCSCASECMP@ +_GL_FUNCDECL_SYS (wcscasecmp, int, (const wchar_t *s1, const wchar_t *s2) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcscasecmp, int, (const wchar_t *s1, const wchar_t *s2)); +_GL_CXXALIASWARN (wcscasecmp); +#elif defined GNULIB_POSIXCHECK +# undef wcscasecmp +# if HAVE_RAW_DECL_WCSCASECMP +_GL_WARN_ON_USE (wcscasecmp, "wcscasecmp is unportable - " + "use gnulib module wcscasecmp for portability"); +# endif +#endif + + +/* Compare no more than N chars of S1 and S2, ignoring case. */ +#if @GNULIB_WCSNCASECMP@ +# if !@HAVE_WCSNCASECMP@ +_GL_FUNCDECL_SYS (wcsncasecmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsncasecmp, int, + (const wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wcsncasecmp); +#elif defined GNULIB_POSIXCHECK +# undef wcsncasecmp +# if HAVE_RAW_DECL_WCSNCASECMP +_GL_WARN_ON_USE (wcsncasecmp, "wcsncasecmp is unportable - " + "use gnulib module wcsncasecmp for portability"); +# endif +#endif + + +/* Compare S1 and S2, both interpreted as appropriate to the LC_COLLATE + category of the current locale. */ +#if @GNULIB_WCSCOLL@ +# if !@HAVE_WCSCOLL@ +_GL_FUNCDECL_SYS (wcscoll, int, (const wchar_t *s1, const wchar_t *s2)); +# endif +_GL_CXXALIAS_SYS (wcscoll, int, (const wchar_t *s1, const wchar_t *s2)); +_GL_CXXALIASWARN (wcscoll); +#elif defined GNULIB_POSIXCHECK +# undef wcscoll +# if HAVE_RAW_DECL_WCSCOLL +_GL_WARN_ON_USE (wcscoll, "wcscoll is unportable - " + "use gnulib module wcscoll for portability"); +# endif +#endif + + +/* Transform S2 into array pointed to by S1 such that if wcscmp is applied + to two transformed strings the result is the as applying 'wcscoll' to the + original strings. */ +#if @GNULIB_WCSXFRM@ +# if !@HAVE_WCSXFRM@ +_GL_FUNCDECL_SYS (wcsxfrm, size_t, (wchar_t *s1, const wchar_t *s2, size_t n)); +# endif +_GL_CXXALIAS_SYS (wcsxfrm, size_t, (wchar_t *s1, const wchar_t *s2, size_t n)); +_GL_CXXALIASWARN (wcsxfrm); +#elif defined GNULIB_POSIXCHECK +# undef wcsxfrm +# if HAVE_RAW_DECL_WCSXFRM +_GL_WARN_ON_USE (wcsxfrm, "wcsxfrm is unportable - " + "use gnulib module wcsxfrm for portability"); +# endif +#endif + + +/* Duplicate S, returning an identical malloc'd string. */ +#if @GNULIB_WCSDUP@ +# if !@HAVE_WCSDUP@ +_GL_FUNCDECL_SYS (wcsdup, wchar_t *, (const wchar_t *s)); +# endif +_GL_CXXALIAS_SYS (wcsdup, wchar_t *, (const wchar_t *s)); +_GL_CXXALIASWARN (wcsdup); +#elif defined GNULIB_POSIXCHECK +# undef wcsdup +# if HAVE_RAW_DECL_WCSDUP +_GL_WARN_ON_USE (wcsdup, "wcsdup is unportable - " + "use gnulib module wcsdup for portability"); +# endif +#endif + + +/* Find the first occurrence of WC in WCS. */ +#if @GNULIB_WCSCHR@ +# if !@HAVE_WCSCHR@ +_GL_FUNCDECL_SYS (wcschr, wchar_t *, (const wchar_t *wcs, wchar_t wc) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcschr (const wchar_t *, wchar_t); + wchar_t * std::wcschr (wchar_t *, wchar_t); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcschr, + wchar_t *, (const wchar_t *, wchar_t), + const wchar_t *, (const wchar_t *, wchar_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcschr, wchar_t *, (wchar_t *wcs, wchar_t wc)); +_GL_CXXALIASWARN1 (wcschr, const wchar_t *, (const wchar_t *wcs, wchar_t wc)); +# else +_GL_CXXALIASWARN (wcschr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcschr +# if HAVE_RAW_DECL_WCSCHR +_GL_WARN_ON_USE (wcschr, "wcschr is unportable - " + "use gnulib module wcschr for portability"); +# endif +#endif + + +/* Find the last occurrence of WC in WCS. */ +#if @GNULIB_WCSRCHR@ +# if !@HAVE_WCSRCHR@ +_GL_FUNCDECL_SYS (wcsrchr, wchar_t *, (const wchar_t *wcs, wchar_t wc) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcsrchr (const wchar_t *, wchar_t); + wchar_t * std::wcsrchr (wchar_t *, wchar_t); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcsrchr, + wchar_t *, (const wchar_t *, wchar_t), + const wchar_t *, (const wchar_t *, wchar_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcsrchr, wchar_t *, (wchar_t *wcs, wchar_t wc)); +_GL_CXXALIASWARN1 (wcsrchr, const wchar_t *, (const wchar_t *wcs, wchar_t wc)); +# else +_GL_CXXALIASWARN (wcsrchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcsrchr +# if HAVE_RAW_DECL_WCSRCHR +_GL_WARN_ON_USE (wcsrchr, "wcsrchr is unportable - " + "use gnulib module wcsrchr for portability"); +# endif +#endif + + +/* Return the length of the initial segmet of WCS which consists entirely + of wide characters not in REJECT. */ +#if @GNULIB_WCSCSPN@ +# if !@HAVE_WCSCSPN@ +_GL_FUNCDECL_SYS (wcscspn, size_t, (const wchar_t *wcs, const wchar_t *reject) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcscspn, size_t, (const wchar_t *wcs, const wchar_t *reject)); +_GL_CXXALIASWARN (wcscspn); +#elif defined GNULIB_POSIXCHECK +# undef wcscspn +# if HAVE_RAW_DECL_WCSCSPN +_GL_WARN_ON_USE (wcscspn, "wcscspn is unportable - " + "use gnulib module wcscspn for portability"); +# endif +#endif + + +/* Return the length of the initial segmet of WCS which consists entirely + of wide characters in ACCEPT. */ +#if @GNULIB_WCSSPN@ +# if !@HAVE_WCSSPN@ +_GL_FUNCDECL_SYS (wcsspn, size_t, (const wchar_t *wcs, const wchar_t *accept) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcsspn, size_t, (const wchar_t *wcs, const wchar_t *accept)); +_GL_CXXALIASWARN (wcsspn); +#elif defined GNULIB_POSIXCHECK +# undef wcsspn +# if HAVE_RAW_DECL_WCSSPN +_GL_WARN_ON_USE (wcsspn, "wcsspn is unportable - " + "use gnulib module wcsspn for portability"); +# endif +#endif + + +/* Find the first occurrence in WCS of any character in ACCEPT. */ +#if @GNULIB_WCSPBRK@ +# if !@HAVE_WCSPBRK@ +_GL_FUNCDECL_SYS (wcspbrk, wchar_t *, + (const wchar_t *wcs, const wchar_t *accept) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcspbrk (const wchar_t *, const wchar_t *); + wchar_t * std::wcspbrk (wchar_t *, const wchar_t *); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcspbrk, + wchar_t *, (const wchar_t *, const wchar_t *), + const wchar_t *, (const wchar_t *, const wchar_t *)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcspbrk, wchar_t *, + (wchar_t *wcs, const wchar_t *accept)); +_GL_CXXALIASWARN1 (wcspbrk, const wchar_t *, + (const wchar_t *wcs, const wchar_t *accept)); +# else +_GL_CXXALIASWARN (wcspbrk); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcspbrk +# if HAVE_RAW_DECL_WCSPBRK +_GL_WARN_ON_USE (wcspbrk, "wcspbrk is unportable - " + "use gnulib module wcspbrk for portability"); +# endif +#endif + + +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +#if @GNULIB_WCSSTR@ +# if !@HAVE_WCSSTR@ +_GL_FUNCDECL_SYS (wcsstr, wchar_t *, + (const wchar_t *haystack, const wchar_t *needle) + _GL_ATTRIBUTE_PURE); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { + const wchar_t * std::wcsstr (const wchar_t *, const wchar_t *); + wchar_t * std::wcsstr (wchar_t *, const wchar_t *); + } */ +_GL_CXXALIAS_SYS_CAST2 (wcsstr, + wchar_t *, (const wchar_t *, const wchar_t *), + const wchar_t *, (const wchar_t *, const wchar_t *)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +_GL_CXXALIASWARN1 (wcsstr, wchar_t *, + (wchar_t *haystack, const wchar_t *needle)); +_GL_CXXALIASWARN1 (wcsstr, const wchar_t *, + (const wchar_t *haystack, const wchar_t *needle)); +# else +_GL_CXXALIASWARN (wcsstr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef wcsstr +# if HAVE_RAW_DECL_WCSSTR +_GL_WARN_ON_USE (wcsstr, "wcsstr is unportable - " + "use gnulib module wcsstr for portability"); +# endif +#endif + + +/* Divide WCS into tokens separated by characters in DELIM. */ +#if @GNULIB_WCSTOK@ +# if !@HAVE_WCSTOK@ +_GL_FUNCDECL_SYS (wcstok, wchar_t *, + (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr)); +# endif +_GL_CXXALIAS_SYS (wcstok, wchar_t *, + (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr)); +_GL_CXXALIASWARN (wcstok); +#elif defined GNULIB_POSIXCHECK +# undef wcstok +# if HAVE_RAW_DECL_WCSTOK +_GL_WARN_ON_USE (wcstok, "wcstok is unportable - " + "use gnulib module wcstok for portability"); +# endif +#endif + + +/* Determine number of column positions required for first N wide + characters (or fewer if S ends before this) in S. */ +#if @GNULIB_WCSWIDTH@ +# if @REPLACE_WCSWIDTH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcswidth +# define wcswidth rpl_wcswidth +# endif +_GL_FUNCDECL_RPL (wcswidth, int, (const wchar_t *s, size_t n) + _GL_ATTRIBUTE_PURE); +_GL_CXXALIAS_RPL (wcswidth, int, (const wchar_t *s, size_t n)); +# else +# if !@HAVE_WCSWIDTH@ +_GL_FUNCDECL_SYS (wcswidth, int, (const wchar_t *s, size_t n) + _GL_ATTRIBUTE_PURE); +# endif +_GL_CXXALIAS_SYS (wcswidth, int, (const wchar_t *s, size_t n)); +# endif +_GL_CXXALIASWARN (wcswidth); +#elif defined GNULIB_POSIXCHECK +# undef wcswidth +# if HAVE_RAW_DECL_WCSWIDTH +_GL_WARN_ON_USE (wcswidth, "wcswidth is unportable - " + "use gnulib module wcswidth for portability"); +# endif +#endif + + +/* Convert *TP to a date and time wide string. See + <http://pubs.opengroup.org/onlinepubs/9699919799/functions/wcsftime.html>. */ +#if @GNULIB_WCSFTIME@ +# if @REPLACE_WCSFTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wcsftime +# define wcsftime rpl_wcsftime +# endif +_GL_FUNCDECL_RPL (wcsftime, size_t, (wchar_t *__buf, size_t __bufsize, + const wchar_t *__fmt, const struct tm *__tp) + _GL_ARG_NONNULL ((1, 3, 4))); +_GL_CXXALIAS_RPL (wcsftime, size_t, (wchar_t *__buf, size_t __bufsize, + const wchar_t *__fmt, const struct tm *__tp)); +# else +# if !@HAVE_WCSFTIME@ +_GL_FUNCDECL_SYS (wcsftime, size_t, (wchar_t *__buf, size_t __bufsize, + const wchar_t *__fmt, const struct tm *__tp) + _GL_ARG_NONNULL ((1, 3, 4))); +# endif +_GL_CXXALIAS_SYS (wcsftime, size_t, (wchar_t *__buf, size_t __bufsize, + const wchar_t *__fmt, const struct tm *__tp)); +# endif +_GL_CXXALIASWARN (wcsftime); +#elif defined GNULIB_POSIXCHECK +# undef wcsftime +# if HAVE_RAW_DECL_WCSFTIME +_GL_WARN_ON_USE (wcsftime, "wcsftime is unportable - " + "use gnulib module wcsftime for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_WCHAR_H */ +#endif /* _@GUARD_PREFIX@_WCHAR_H */ +#endif diff --git a/grub-core/lib/gnulib/wcrtomb.c b/grub-core/lib/gnulib/wcrtomb.c new file mode 100644 index 0000000..9fc40cf --- /dev/null +++ b/grub-core/lib/gnulib/wcrtomb.c @@ -0,0 +1,53 @@ +/* Convert wide character to multibyte character. + Copyright (C) 2008-2019 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <wchar.h> + +#include <errno.h> +#include <stdlib.h> + + +size_t +wcrtomb (char *s, wchar_t wc, mbstate_t *ps) +{ + /* This implementation of wcrtomb on top of wctomb() supports only + stateless encodings. ps must be in the initial state. */ + if (ps != NULL && !mbsinit (ps)) + { + errno = EINVAL; + return (size_t)(-1); + } + + if (s == NULL) + /* We know the NUL wide character corresponds to the NUL character. */ + return 1; + else + { + int ret = wctomb (s, wc); + + if (ret >= 0) + return ret; + else + { + errno = EILSEQ; + return (size_t)(-1); + } + } +} diff --git a/grub-core/lib/gnulib/wctype-h.c b/grub-core/lib/gnulib/wctype-h.c new file mode 100644 index 0000000..bb5f847 --- /dev/null +++ b/grub-core/lib/gnulib/wctype-h.c @@ -0,0 +1,4 @@ +/* Normally this would be wctype.c, but that name's already taken. */ +#include <config.h> +#define _GL_WCTYPE_INLINE _GL_EXTERN_INLINE +#include "wctype.h" diff --git a/grub-core/lib/gnulib/wctype.in.h b/grub-core/lib/gnulib/wctype.in.h new file mode 100644 index 0000000..0a7471f --- /dev/null +++ b/grub-core/lib/gnulib/wctype.in.h @@ -0,0 +1,533 @@ +/* A substitute for ISO C99 <wctype.h>, for platforms that lack it. + + Copyright (C) 2006-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible and Paul Eggert. */ + +/* + * ISO C 99 <wctype.h> for platforms that lack it. + * <http://www.opengroup.org/susv3xbd/wctype.h.html> + * + * iswctype, towctrans, towlower, towupper, wctrans, wctype, + * wctrans_t, and wctype_t are not yet implemented. + */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if (defined __MINGW32__ && defined __CTYPE_H_SOURCED__) + +/* Special invocation convention: + - With MinGW 3.22, when <ctype.h> includes <wctype.h>, only some part of + <wctype.h> is being processed, which doesn't include the idempotency + guard. */ + +#@INCLUDE_NEXT@ @NEXT_WCTYPE_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_WCTYPE_H + +#if @HAVE_WINT_T@ +/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. + Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before + <wchar.h>. + BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be + included before <wchar.h>. */ +# include <stddef.h> +# include <stdio.h> +# include <time.h> +# include <wchar.h> +#endif + +/* Native Windows (mingw, MSVC) have declarations of towupper, towlower, and + isw* functions in <ctype.h>, <wchar.h> as well as in <wctype.h>. Include + <ctype.h>, <wchar.h> in advance to avoid rpl_ prefix being added to the + declarations. */ +#if defined _WIN32 && ! defined __CYGWIN__ +# include <ctype.h> +# include <wchar.h> +#endif + +/* Include the original <wctype.h> if it exists. + BeOS 5 has the functions but no <wctype.h>. */ +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_WCTYPE_H@ +# @INCLUDE_NEXT@ @NEXT_WCTYPE_H@ +#endif + +#ifndef _@GUARD_PREFIX@_WCTYPE_H +#define _@GUARD_PREFIX@_WCTYPE_H + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_WCTYPE_INLINE +# define _GL_WCTYPE_INLINE _GL_INLINE +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Solaris 2.6 <wctype.h> includes <widec.h> which includes <euc.h> which + #defines a number of identifiers in the application namespace. Revert + these #defines. */ +#ifdef __sun +# undef multibyte +# undef eucw1 +# undef eucw2 +# undef eucw3 +# undef scrw1 +# undef scrw2 +# undef scrw3 +#endif + +/* Define wint_t and WEOF. (Also done in wchar.in.h.) */ +#if !@HAVE_WINT_T@ && !defined wint_t +# define wint_t int +# ifndef WEOF +# define WEOF -1 +# endif +#else +/* mingw and MSVC define wint_t as 'unsigned short' in <crtdefs.h> or + <stddef.h>. This is too small: ISO C 99 section 7.24.1.(2) says that + wint_t must be "unchanged by default argument promotions". Override it. */ +# if @GNULIB_OVERRIDES_WINT_T@ +# if !GNULIB_defined_wint_t +# if @HAVE_CRTDEFS_H@ +# include <crtdefs.h> +# else +# include <stddef.h> +# endif +typedef unsigned int rpl_wint_t; +# undef wint_t +# define wint_t rpl_wint_t +# define GNULIB_defined_wint_t 1 +# endif +# endif +# ifndef WEOF +# define WEOF ((wint_t) -1) +# endif +#endif + + +#if !GNULIB_defined_wctype_functions + +/* FreeBSD 4.4 to 4.11 has <wctype.h> but lacks the functions. + Linux libc5 has <wctype.h> and the functions but they are broken. + Assume all 11 functions (all isw* except iswblank) are implemented the + same way, or not at all. */ +# if ! @HAVE_ISWCNTRL@ || @REPLACE_ISWCNTRL@ + +/* IRIX 5.3 has macros but no functions, its isw* macros refer to an + undefined variable _ctmp_ and to <ctype.h> macros like _P, and they + refer to system functions like _iswctype that are not in the + standard C library. Rather than try to get ancient buggy + implementations like this to work, just disable them. */ +# undef iswalnum +# undef iswalpha +# undef iswblank +# undef iswcntrl +# undef iswdigit +# undef iswgraph +# undef iswlower +# undef iswprint +# undef iswpunct +# undef iswspace +# undef iswupper +# undef iswxdigit +# undef towlower +# undef towupper + +/* Linux libc5 has <wctype.h> and the functions but they are broken. */ +# if @REPLACE_ISWCNTRL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define iswalnum rpl_iswalnum +# define iswalpha rpl_iswalpha +# define iswblank rpl_iswblank +# define iswcntrl rpl_iswcntrl +# define iswdigit rpl_iswdigit +# define iswgraph rpl_iswgraph +# define iswlower rpl_iswlower +# define iswprint rpl_iswprint +# define iswpunct rpl_iswpunct +# define iswspace rpl_iswspace +# define iswupper rpl_iswupper +# define iswxdigit rpl_iswxdigit +# endif +# endif +# if @REPLACE_TOWLOWER@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define towlower rpl_towlower +# define towupper rpl_towupper +# endif +# endif + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswalnum +# else +iswalnum +# endif + (wint_t wc) +{ + return ((wc >= '0' && wc <= '9') + || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z')); +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswalpha +# else +iswalpha +# endif + (wint_t wc) +{ + return (wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswblank +# else +iswblank +# endif + (wint_t wc) +{ + return wc == ' ' || wc == '\t'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswcntrl +# else +iswcntrl +# endif + (wint_t wc) +{ + return (wc & ~0x1f) == 0 || wc == 0x7f; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswdigit +# else +iswdigit +# endif + (wint_t wc) +{ + return wc >= '0' && wc <= '9'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswgraph +# else +iswgraph +# endif + (wint_t wc) +{ + return wc >= '!' && wc <= '~'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswlower +# else +iswlower +# endif + (wint_t wc) +{ + return wc >= 'a' && wc <= 'z'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswprint +# else +iswprint +# endif + (wint_t wc) +{ + return wc >= ' ' && wc <= '~'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswpunct +# else +iswpunct +# endif + (wint_t wc) +{ + return (wc >= '!' && wc <= '~' + && !((wc >= '0' && wc <= '9') + || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z'))); +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswspace +# else +iswspace +# endif + (wint_t wc) +{ + return (wc == ' ' || wc == '\t' + || wc == '\n' || wc == '\v' || wc == '\f' || wc == '\r'); +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswupper +# else +iswupper +# endif + (wint_t wc) +{ + return wc >= 'A' && wc <= 'Z'; +} + +_GL_WCTYPE_INLINE int +# if @REPLACE_ISWCNTRL@ +rpl_iswxdigit +# else +iswxdigit +# endif + (wint_t wc) +{ + return ((wc >= '0' && wc <= '9') + || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'F')); +} + +_GL_WCTYPE_INLINE wint_t +# if @REPLACE_TOWLOWER@ +rpl_towlower +# else +towlower +# endif + (wint_t wc) +{ + return (wc >= 'A' && wc <= 'Z' ? wc - 'A' + 'a' : wc); +} + +_GL_WCTYPE_INLINE wint_t +# if @REPLACE_TOWLOWER@ +rpl_towupper +# else +towupper +# endif + (wint_t wc) +{ + return (wc >= 'a' && wc <= 'z' ? wc - 'a' + 'A' : wc); +} + +# elif @GNULIB_ISWBLANK@ && (! @HAVE_ISWBLANK@ || @REPLACE_ISWBLANK@) +/* Only the iswblank function is missing. */ + +# if @REPLACE_ISWBLANK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define iswblank rpl_iswblank +# endif +_GL_FUNCDECL_RPL (iswblank, int, (wint_t wc)); +# else +_GL_FUNCDECL_SYS (iswblank, int, (wint_t wc)); +# endif + +# endif + +# if defined __MINGW32__ + +/* On native Windows, wchar_t is uint16_t, and wint_t is uint32_t. + The functions towlower and towupper are implemented in the MSVCRT library + to take a wchar_t argument and return a wchar_t result. mingw declares + these functions to take a wint_t argument and return a wint_t result. + This means that: + 1. When the user passes an argument outside the range 0x0000..0xFFFF, the + function will look only at the lower 16 bits. This is allowed according + to POSIX. + 2. The return value is returned in the lower 16 bits of the result register. + The upper 16 bits are random: whatever happened to be in that part of the + result register. We need to fix this by adding a zero-extend from + wchar_t to wint_t after the call. */ + +_GL_WCTYPE_INLINE wint_t +rpl_towlower (wint_t wc) +{ + return (wint_t) (wchar_t) towlower (wc); +} +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define towlower rpl_towlower +# endif + +_GL_WCTYPE_INLINE wint_t +rpl_towupper (wint_t wc) +{ + return (wint_t) (wchar_t) towupper (wc); +} +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define towupper rpl_towupper +# endif + +# endif /* __MINGW32__ */ + +# define GNULIB_defined_wctype_functions 1 +#endif + +#if @REPLACE_ISWCNTRL@ +_GL_CXXALIAS_RPL (iswalnum, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswalpha, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswcntrl, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswdigit, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswgraph, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswlower, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswprint, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswpunct, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswspace, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswupper, int, (wint_t wc)); +_GL_CXXALIAS_RPL (iswxdigit, int, (wint_t wc)); +#else +_GL_CXXALIAS_SYS (iswalnum, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswalpha, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswcntrl, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswdigit, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswgraph, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswlower, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswprint, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswpunct, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswspace, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswupper, int, (wint_t wc)); +_GL_CXXALIAS_SYS (iswxdigit, int, (wint_t wc)); +#endif +_GL_CXXALIASWARN (iswalnum); +_GL_CXXALIASWARN (iswalpha); +_GL_CXXALIASWARN (iswcntrl); +_GL_CXXALIASWARN (iswdigit); +_GL_CXXALIASWARN (iswgraph); +_GL_CXXALIASWARN (iswlower); +_GL_CXXALIASWARN (iswprint); +_GL_CXXALIASWARN (iswpunct); +_GL_CXXALIASWARN (iswspace); +_GL_CXXALIASWARN (iswupper); +_GL_CXXALIASWARN (iswxdigit); + +#if @GNULIB_ISWBLANK@ +# if @REPLACE_ISWCNTRL@ || @REPLACE_ISWBLANK@ +_GL_CXXALIAS_RPL (iswblank, int, (wint_t wc)); +# else +_GL_CXXALIAS_SYS (iswblank, int, (wint_t wc)); +# endif +_GL_CXXALIASWARN (iswblank); +#endif + +#if !@HAVE_WCTYPE_T@ +# if !GNULIB_defined_wctype_t +typedef void * wctype_t; +# define GNULIB_defined_wctype_t 1 +# endif +#endif + +/* Get a descriptor for a wide character property. */ +#if @GNULIB_WCTYPE@ +# if !@HAVE_WCTYPE_T@ +_GL_FUNCDECL_SYS (wctype, wctype_t, (const char *name)); +# endif +_GL_CXXALIAS_SYS (wctype, wctype_t, (const char *name)); +_GL_CXXALIASWARN (wctype); +#elif defined GNULIB_POSIXCHECK +# undef wctype +# if HAVE_RAW_DECL_WCTYPE +_GL_WARN_ON_USE (wctype, "wctype is unportable - " + "use gnulib module wctype for portability"); +# endif +#endif + +/* Test whether a wide character has a given property. + The argument WC must be either a wchar_t value or WEOF. + The argument DESC must have been returned by the wctype() function. */ +#if @GNULIB_ISWCTYPE@ +# if !@HAVE_WCTYPE_T@ +_GL_FUNCDECL_SYS (iswctype, int, (wint_t wc, wctype_t desc)); +# endif +_GL_CXXALIAS_SYS (iswctype, int, (wint_t wc, wctype_t desc)); +_GL_CXXALIASWARN (iswctype); +#elif defined GNULIB_POSIXCHECK +# undef iswctype +# if HAVE_RAW_DECL_ISWCTYPE +_GL_WARN_ON_USE (iswctype, "iswctype is unportable - " + "use gnulib module iswctype for portability"); +# endif +#endif + +#if @REPLACE_TOWLOWER@ || defined __MINGW32__ +_GL_CXXALIAS_RPL (towlower, wint_t, (wint_t wc)); +_GL_CXXALIAS_RPL (towupper, wint_t, (wint_t wc)); +#else +_GL_CXXALIAS_SYS (towlower, wint_t, (wint_t wc)); +_GL_CXXALIAS_SYS (towupper, wint_t, (wint_t wc)); +#endif +_GL_CXXALIASWARN (towlower); +_GL_CXXALIASWARN (towupper); + +#if !@HAVE_WCTRANS_T@ +# if !GNULIB_defined_wctrans_t +typedef void * wctrans_t; +# define GNULIB_defined_wctrans_t 1 +# endif +#endif + +/* Get a descriptor for a wide character case conversion. */ +#if @GNULIB_WCTRANS@ +# if !@HAVE_WCTRANS_T@ +_GL_FUNCDECL_SYS (wctrans, wctrans_t, (const char *name)); +# endif +_GL_CXXALIAS_SYS (wctrans, wctrans_t, (const char *name)); +_GL_CXXALIASWARN (wctrans); +#elif defined GNULIB_POSIXCHECK +# undef wctrans +# if HAVE_RAW_DECL_WCTRANS +_GL_WARN_ON_USE (wctrans, "wctrans is unportable - " + "use gnulib module wctrans for portability"); +# endif +#endif + +/* Perform a given case conversion on a wide character. + The argument WC must be either a wchar_t value or WEOF. + The argument DESC must have been returned by the wctrans() function. */ +#if @GNULIB_TOWCTRANS@ +# if !@HAVE_WCTRANS_T@ +_GL_FUNCDECL_SYS (towctrans, wint_t, (wint_t wc, wctrans_t desc)); +# endif +_GL_CXXALIAS_SYS (towctrans, wint_t, (wint_t wc, wctrans_t desc)); +_GL_CXXALIASWARN (towctrans); +#elif defined GNULIB_POSIXCHECK +# undef towctrans +# if HAVE_RAW_DECL_TOWCTRANS +_GL_WARN_ON_USE (towctrans, "towctrans is unportable - " + "use gnulib module towctrans for portability"); +# endif +#endif + +_GL_INLINE_HEADER_END + +#endif /* _@GUARD_PREFIX@_WCTYPE_H */ +#endif /* _@GUARD_PREFIX@_WCTYPE_H */ +#endif diff --git a/grub-core/lib/gnulib/wcwidth.c b/grub-core/lib/gnulib/wcwidth.c new file mode 100644 index 0000000..1f081cc --- /dev/null +++ b/grub-core/lib/gnulib/wcwidth.c @@ -0,0 +1,73 @@ +/* Determine the number of screen columns needed for a character. + Copyright (C) 2006-2007, 2010-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <wchar.h> + +/* Get iswprint. */ +#include <wctype.h> + +#include "localcharset.h" +#include "streq.h" +#include "uniwidth.h" + +/* Returns 1 if the current locale is an UTF-8 locale, 0 otherwise. */ +static inline int +is_locale_utf8 (void) +{ + const char *encoding = locale_charset (); + return STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0); +} + +#if GNULIB_WCHAR_SINGLE +/* When we know that the locale does not change, provide a speedup by + caching the value of is_locale_utf8. */ +static int cached_is_locale_utf8 = -1; +static inline int +is_locale_utf8_cached (void) +{ + if (cached_is_locale_utf8 < 0) + cached_is_locale_utf8 = is_locale_utf8 (); + return cached_is_locale_utf8; +} +#else +/* By default, don't make assumptions, hence no caching. */ +# define is_locale_utf8_cached is_locale_utf8 +#endif + +int +wcwidth (wchar_t wc) +#undef wcwidth +{ + /* In UTF-8 locales, use a Unicode aware width function. */ + if (is_locale_utf8_cached ()) + { + /* We assume that in a UTF-8 locale, a wide character is the same as a + Unicode character. */ + return uc_width (wc, "UTF-8"); + } + else + { + /* Otherwise, fall back to the system's wcwidth function. */ +#if HAVE_WCWIDTH + return wcwidth (wc); +#else + return wc == 0 ? 0 : iswprint (wc) ? 1 : -1; +#endif + } +} diff --git a/grub-core/lib/gnulib/xalloc-oversized.h b/grub-core/lib/gnulib/xalloc-oversized.h new file mode 100644 index 0000000..e3068c8 --- /dev/null +++ b/grub-core/lib/gnulib/xalloc-oversized.h @@ -0,0 +1,60 @@ +/* xalloc-oversized.h -- memory allocation size checking + + Copyright (C) 1990-2000, 2003-2004, 2006-2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef XALLOC_OVERSIZED_H_ +#define XALLOC_OVERSIZED_H_ + +#include <stddef.h> +#include <stdint.h> + +/* True if N * S would overflow in a size_t calculation, + or would generate a value larger than PTRDIFF_MAX. + This expands to a constant expression if N and S are both constants. + By gnulib convention, SIZE_MAX represents overflow in size + calculations, so the conservative size_t-based dividend to use here + is SIZE_MAX - 1. */ +#define __xalloc_oversized(n, s) \ + ((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) < (n)) + +#if PTRDIFF_MAX < SIZE_MAX +typedef ptrdiff_t __xalloc_count_type; +#else +typedef size_t __xalloc_count_type; +#endif + +/* Return 1 if an array of N objects, each of size S, cannot exist + reliably due to size or ptrdiff_t arithmetic overflow. S must be + positive and N must be nonnegative. This is a macro, not a + function, so that it works correctly even when SIZE_MAX < N. */ + +#if 7 <= __GNUC__ +# define xalloc_oversized(n, s) \ + __builtin_mul_overflow_p (n, s, (__xalloc_count_type) 1) +#elif 5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__ +# define xalloc_oversized(n, s) \ + (__builtin_constant_p (n) && __builtin_constant_p (s) \ + ? __xalloc_oversized (n, s) \ + : ({ __xalloc_count_type __xalloc_count; \ + __builtin_mul_overflow (n, s, &__xalloc_count); })) + +/* Other compilers use integer division; this may be slower but is + more portable. */ +#else +# define xalloc_oversized(n, s) __xalloc_oversized (n, s) +#endif + +#endif /* !XALLOC_OVERSIZED_H_ */ diff --git a/grub-core/lib/gnulib/xsize.c b/grub-core/lib/gnulib/xsize.c new file mode 100644 index 0000000..4b4914c --- /dev/null +++ b/grub-core/lib/gnulib/xsize.c @@ -0,0 +1,3 @@ +#include <config.h> +#define XSIZE_INLINE _GL_EXTERN_INLINE +#include "xsize.h" diff --git a/grub-core/lib/gnulib/xsize.h b/grub-core/lib/gnulib/xsize.h new file mode 100644 index 0000000..ecfd478 --- /dev/null +++ b/grub-core/lib/gnulib/xsize.h @@ -0,0 +1,117 @@ +/* xsize.h -- Checked size_t computations. + + Copyright (C) 2003, 2008-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _XSIZE_H +#define _XSIZE_H + +/* Get size_t. */ +#include <stddef.h> + +/* Get SIZE_MAX. */ +#include <limits.h> +#if HAVE_STDINT_H +# include <stdint.h> +#endif + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef XSIZE_INLINE +# define XSIZE_INLINE _GL_INLINE +#endif + +/* The size of memory objects is often computed through expressions of + type size_t. Example: + void* p = malloc (header_size + n * element_size). + These computations can lead to overflow. When this happens, malloc() + returns a piece of memory that is way too small, and the program then + crashes while attempting to fill the memory. + To avoid this, the functions and macros in this file check for overflow. + The convention is that SIZE_MAX represents overflow. + malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc + implementation that uses mmap --, it's recommended to use size_overflow_p() + or size_in_bounds_p() before invoking malloc(). + The example thus becomes: + size_t size = xsum (header_size, xtimes (n, element_size)); + void *p = (size_in_bounds_p (size) ? malloc (size) : NULL); +*/ + +/* Convert an arbitrary value >= 0 to type size_t. */ +#define xcast_size_t(N) \ + ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX) + +/* Sum of two sizes, with overflow check. */ +XSIZE_INLINE size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum (size_t size1, size_t size2) +{ + size_t sum = size1 + size2; + return (sum >= size1 ? sum : SIZE_MAX); +} + +/* Sum of three sizes, with overflow check. */ +XSIZE_INLINE size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum3 (size_t size1, size_t size2, size_t size3) +{ + return xsum (xsum (size1, size2), size3); +} + +/* Sum of four sizes, with overflow check. */ +XSIZE_INLINE size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum4 (size_t size1, size_t size2, size_t size3, size_t size4) +{ + return xsum (xsum (xsum (size1, size2), size3), size4); +} + +/* Maximum of two sizes, with overflow check. */ +XSIZE_INLINE size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xmax (size_t size1, size_t size2) +{ + /* No explicit check is needed here, because for any n: + max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */ + return (size1 >= size2 ? size1 : size2); +} + +/* Multiplication of a count with an element size, with overflow check. + The count must be >= 0 and the element size must be > 0. + This is a macro, not a function, so that it works correctly even + when N is of a wider type and N > SIZE_MAX. */ +#define xtimes(N, ELSIZE) \ + ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX) + +/* Check for overflow. */ +#define size_overflow_p(SIZE) \ + ((SIZE) == SIZE_MAX) +/* Check against overflow. */ +#define size_in_bounds_p(SIZE) \ + ((SIZE) != SIZE_MAX) + +_GL_INLINE_HEADER_END + +#endif /* _XSIZE_H */ diff --git a/grub-core/lib/hexdump.c b/grub-core/lib/hexdump.c new file mode 100644 index 0000000..317635a --- /dev/null +++ b/grub-core/lib/hexdump.c @@ -0,0 +1,85 @@ +/* hexdump.c - hexdump function */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/types.h> +#include <grub/misc.h> +#include <grub/lib/hexdump.h> + +void +hexdump (unsigned long bse, char *buf, int len) +{ + int pos; + char line[80]; + + while (len > 0) + { + int cnt, i; + + pos = grub_snprintf (line, sizeof (line), "%08lx ", bse); + cnt = 16; + if (cnt > len) + cnt = len; + + for (i = 0; i < cnt; i++) + { + pos += grub_snprintf (&line[pos], sizeof (line) - pos, + "%02x ", (unsigned char) buf[i]); + if ((i & 7) == 7) + line[pos++] = ' '; + } + + for (; i < 16; i++) + { + pos += grub_snprintf (&line[pos], sizeof (line) - pos, " "); + if ((i & 7) == 7) + line[pos++] = ' '; + } + + line[pos++] = '|'; + + for (i = 0; i < cnt; i++) + line[pos++] = ((buf[i] >= 32) && (buf[i] < 127)) ? buf[i] : '.'; + + line[pos++] = '|'; + + line[pos] = 0; + + grub_printf ("%s\n", line); + + /* Print only first and last line if more than 3 lines are identical. */ + if (len >= 4 * 16 + && ! grub_memcmp (buf, buf + 1 * 16, 16) + && ! grub_memcmp (buf, buf + 2 * 16, 16) + && ! grub_memcmp (buf, buf + 3 * 16, 16)) + { + grub_printf ("*\n"); + do + { + bse += 16; + buf += 16; + len -= 16; + } + while (len >= 3 * 16 && ! grub_memcmp (buf, buf + 2 * 16, 16)); + } + + bse += 16; + buf += 16; + len -= cnt; + } +} diff --git a/grub-core/lib/i386/backtrace.c b/grub-core/lib/i386/backtrace.c new file mode 100644 index 0000000..c3e03c7 --- /dev/null +++ b/grub-core/lib/i386/backtrace.c @@ -0,0 +1,66 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/misc.h> +#include <grub/command.h> +#include <grub/err.h> +#include <grub/dl.h> +#include <grub/mm.h> +#include <grub/term.h> +#include <grub/backtrace.h> + +#define MAX_STACK_FRAME 102400 + +void +grub_backtrace_pointer (void *ebp) +{ + void *ptr, *nptr; + unsigned i; + + ptr = ebp; + while (1) + { + grub_printf ("%p: ", ptr); + grub_backtrace_print_address (((void **) ptr)[1]); + grub_printf (" ("); + for (i = 0; i < 2; i++) + grub_printf ("%p,", ((void **)ptr) [i + 2]); + grub_printf ("%p)\n", ((void **)ptr) [i + 2]); + nptr = *(void **)ptr; + if (nptr < ptr || (void **) nptr - (void **) ptr > MAX_STACK_FRAME + || nptr == ptr) + { + grub_printf ("Invalid stack frame at %p (%p)\n", ptr, nptr); + break; + } + ptr = nptr; + } +} + +void +grub_backtrace (void) +{ +#ifdef __x86_64__ + asm volatile ("movq %%rbp, %%rdi\n" + "callq *%%rax": :"a"(grub_backtrace_pointer)); +#else + asm volatile ("movl %%ebp, %%eax\n" + "calll *%%ecx": :"c"(grub_backtrace_pointer)); +#endif +} + diff --git a/grub-core/lib/i386/halt.c b/grub-core/lib/i386/halt.c new file mode 100644 index 0000000..2364fe4 --- /dev/null +++ b/grub-core/lib/i386/halt.c @@ -0,0 +1,82 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/cpu/io.h> +#include <grub/misc.h> +#include <grub/acpi.h> +#include <grub/i18n.h> +#include <grub/pci.h> +#include <grub/mm.h> + +const char bochs_shutdown[] = "Shutdown"; + +/* + * This call is special... it never returns... in fact it should simply + * hang at this point! + */ +static inline void __attribute__ ((noreturn)) +stop (void) +{ + asm volatile ("cli"); + while (1) + { + asm volatile ("hlt"); + } +} + +static int +grub_shutdown_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + /* QEMU. */ + if (pciid == 0x71138086) + { + grub_pci_address_t addr; + addr = grub_pci_make_address (dev, 0x40); + grub_pci_write (addr, 0x7001); + addr = grub_pci_make_address (dev, 0x80); + grub_pci_write (addr, grub_pci_read (addr) | 1); + grub_outw (0x2000, 0x7004); + } + return 0; +} + +void +grub_halt (void) +{ + unsigned int i; + +#if defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) + grub_acpi_halt (); +#endif + + /* Disable interrupts. */ + asm volatile ("cli"); + + /* Bochs, QEMU, etc. Removed in newer QEMU releases. */ + for (i = 0; i < sizeof (bochs_shutdown) - 1; i++) + grub_outb (bochs_shutdown[i], 0x8900); + + grub_pci_iterate (grub_shutdown_pci_iter, NULL); + + grub_puts_ (N_("GRUB doesn't know how to halt this machine yet!")); + + /* In order to return we'd have to check what the previous status of IF + flag was. But user most likely doesn't want to return anyway ... */ + stop (); +} diff --git a/grub-core/lib/i386/pc/biosnum.c b/grub-core/lib/i386/pc/biosnum.c new file mode 100644 index 0000000..0f0e743 --- /dev/null +++ b/grub-core/lib/i386/pc/biosnum.c @@ -0,0 +1,47 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/env.h> +#include <grub/misc.h> +#include <grub/disk.h> +#include <grub/machine/biosnum.h> + +static int +grub_get_root_biosnumber_default (void) +{ + const char *biosnum; + int ret = -1; + grub_device_t dev; + + biosnum = grub_env_get ("biosnum"); + + if (biosnum) + return grub_strtoul (biosnum, 0, 0); + + dev = grub_device_open (0); + if (dev && dev->disk && dev->disk->dev + && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID) + ret = (int) dev->disk->id; + + if (dev) + grub_device_close (dev); + + return ret; +} + +int (*grub_get_root_biosnumber) (void) = grub_get_root_biosnumber_default; diff --git a/grub-core/lib/i386/pc/vesa_modes_table.c b/grub-core/lib/i386/pc/vesa_modes_table.c new file mode 100644 index 0000000..6dc4b7d --- /dev/null +++ b/grub-core/lib/i386/pc/vesa_modes_table.c @@ -0,0 +1,127 @@ + +#include <grub/i386/pc/vesa_modes_table.h> + +/* This is the reverse of the table in [linux]/Documentation/fb/vesafb.txt + plus a few more modes based on the table in + http://en.wikipedia.org/wiki/VESA_BIOS_Extensions */ +struct grub_vesa_mode_table_entry +grub_vesa_mode_table[GRUB_VESA_MODE_TABLE_END + - GRUB_VESA_MODE_TABLE_START + 1] = + { + { 640, 400, 8 }, /* 0x300 */ + { 640, 480, 8 }, /* 0x301 */ + { 800, 600, 4 }, /* 0x302 */ + { 800, 600, 8 }, /* 0x303 */ + { 1024, 768, 4 }, /* 0x304 */ + { 1024, 768, 8 }, /* 0x305 */ + { 1280, 1024, 4 }, /* 0x306 */ + { 1280, 1024, 8 }, /* 0x307 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 320, 200, 15 }, /* 0x30d */ + { 320, 200, 16 }, /* 0x30e */ + { 320, 200, 24 }, /* 0x30f */ + { 640, 480, 15 }, /* 0x310 */ + { 640, 480, 16 }, /* 0x311 */ + { 640, 480, 24 }, /* 0x312 */ + { 800, 600, 15 }, /* 0x313 */ + { 800, 600, 16 }, /* 0x314 */ + { 800, 600, 24 }, /* 0x315 */ + { 1024, 768, 15 }, /* 0x316 */ + { 1024, 768, 16 }, /* 0x317 */ + { 1024, 768, 24 }, /* 0x318 */ + { 1280, 1024, 15 }, /* 0x319 */ + { 1280, 1024, 16 }, /* 0x31a */ + { 1280, 1024, 24 }, /* 0x31b */ + { 1600, 1200, 8 }, /* 0x31c */ + { 1600, 1200, 15 }, /* 0x31d */ + { 1600, 1200, 16 }, /* 0x31e */ + { 1600, 1200, 24 }, /* 0x31f */ + { 0, 0, 0 }, + { 640, 400, 15 }, /* 0x321 */ + { 640, 400, 16 }, /* 0x322 */ + { 640, 400, 24 }, /* 0x323 */ + { 640, 400, 32 }, /* 0x324 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 640, 480, 32 }, /* 0x329 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 896, 672, 8 }, /* 0x32f */ + { 896, 672, 15 }, /* 0x330 */ + { 896, 672, 16 }, /* 0x331 */ + { 896, 672, 24 }, /* 0x332 */ + { 896, 672, 32 }, /* 0x333 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 1600, 1200, 32 }, /* 0x342 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 1440, 900, 8 }, /* 0x360 */ + { 1440, 900, 15 }, /* 0x361 */ + { 1440, 900, 16 }, /* 0x362 */ + { 1440, 900, 24 }, /* 0x363 */ + { 1440, 900, 32 }, /* 0x364 */ + { 1152, 720, 8 }, /* 0x365 */ + { 1152, 720, 15 }, /* 0x366 */ + { 1152, 720, 16 }, /* 0x367 */ + { 1152, 720, 24 }, /* 0x368 */ + { 1152, 720, 32 }, /* 0x369 */ + { 1024, 640, 8 }, /* 0x36a */ + { 1024, 640, 15 }, /* 0x36b */ + { 1024, 640, 16 }, /* 0x36c */ + { 1024, 640, 24 }, /* 0x36d */ + { 1024, 640, 32 }, /* 0x36e */ + { 800, 500, 8 }, /* 0x36f */ + { 800, 500, 15 }, /* 0x370 */ + { 800, 500, 16 }, /* 0x371 */ + { 800, 500, 24 }, /* 0x372 */ + { 800, 500, 32 }, /* 0x373 */ + }; diff --git a/grub-core/lib/i386/random.c b/grub-core/lib/i386/random.c new file mode 100644 index 0000000..cd83d2f --- /dev/null +++ b/grub-core/lib/i386/random.c @@ -0,0 +1,103 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2016 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/random.h> +#include <grub/i386/io.h> +#include <grub/i386/tsc.h> +#include <grub/i386/pmtimer.h> +#include <grub/acpi.h> + +static int have_tsc = -1, have_pmtimer = -1; +static grub_port_t pmtimer_port; + +static int +detect_pmtimer (void) +{ + struct grub_acpi_fadt *fadt; + fadt = grub_acpi_find_fadt (); + if (!fadt) + return 0; + pmtimer_port = fadt->pmtimer; + if (!pmtimer_port) + return 0; + return 1; +} + +static int +pmtimer_tsc_get_random_bit (void) +{ + /* It's hard to come up with figures about pmtimer and tsc jitter but + 50 ppm seems to be typical. So we need 10^6/50 tsc cycles to get drift + of one tsc cycle. With TSC at least of 800 MHz it means 1/(50*800) + = 1/40000 s or about 3579545 / 40000 = 90 pmtimer ticks. + This gives us rate of 40000 bit/s or 5 kB/s. + */ + grub_uint64_t tsc_diff; + tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer_port, 90); + if (tsc_diff == 0) + { + have_pmtimer = 0; + return -1; + } + return tsc_diff & 1; +} + +static int +pmtimer_tsc_get_random_byte (void) +{ + grub_uint8_t ret = 0; + int i, c; + for (i = 0; i < 8; i++) + { + c = pmtimer_tsc_get_random_bit (); + if (c < 0) + return -1; + ret |= c << i; + } + return ret; +} + +static int +pmtimer_fill_buffer (void *buffer, grub_size_t sz) +{ + grub_uint8_t *p = buffer; + int c; + while (sz) + { + c = pmtimer_tsc_get_random_byte (); + if (c < 0) + return 0; + *p++ = c; + sz--; + } + return 1; +} + +int +grub_crypto_arch_get_random (void *buffer, grub_size_t sz) +{ + if (have_tsc == -1) + have_tsc = grub_cpu_is_tsc_supported (); + if (!have_tsc) + return 0; + if (have_pmtimer == -1) + have_pmtimer = detect_pmtimer (); + if (!have_pmtimer) + return 0; + return pmtimer_fill_buffer (buffer, sz); +} diff --git a/grub-core/lib/i386/reboot.c b/grub-core/lib/i386/reboot.c new file mode 100644 index 0000000..dce0b56 --- /dev/null +++ b/grub-core/lib/i386/reboot.c @@ -0,0 +1,64 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_MACHINE_EFI + +#include <grub/relocator.h> +#include <grub/cpu/relocator.h> +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/cpu/reboot.h> +#include <grub/i386/floppy.h> + +void +grub_reboot (void) +{ + struct grub_relocator *relocator = NULL; + grub_relocator_chunk_t ch; + grub_err_t err; + void *buf; + struct grub_relocator16_state state; + grub_uint16_t segment; + + relocator = grub_relocator_new (); + if (!relocator) + while (1); + err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000, 0x1000, + grub_reboot_end - grub_reboot_start, + 16, GRUB_RELOCATOR_PREFERENCE_NONE, + 0); + if (err) + while (1); + buf = get_virtual_current_address (ch); + grub_memcpy (buf, grub_reboot_start, grub_reboot_end - grub_reboot_start); + + segment = ((grub_addr_t) get_physical_target_address (ch)) >> 4; + state.gs = state.fs = state.es = state.ds = state.ss = segment; + state.sp = 0; + state.cs = segment; + state.ip = 0; + state.a20 = 0; + + grub_stop_floppy (); + + err = grub_relocator16_boot (relocator, state); + + while (1); +} + +#endif /* GRUB_MACHINE_EFI */ diff --git a/grub-core/lib/i386/reboot_trampoline.S b/grub-core/lib/i386/reboot_trampoline.S new file mode 100644 index 0000000..c088cd0 --- /dev/null +++ b/grub-core/lib/i386/reboot_trampoline.S @@ -0,0 +1,34 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> +#include <grub/i386/reboot.h> + + .p2align 4 + +VARIABLE(grub_reboot_start) + .code16 + + /* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */ + movw $0x0472, %di + xorw %ax, %ax + movw %ax, (%di) + ljmp $0xf000, $0xfff0 + + .code32 +VARIABLE(grub_reboot_end) diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c new file mode 100644 index 0000000..34cbe83 --- /dev/null +++ b/grub-core/lib/i386/relocator.c @@ -0,0 +1,210 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/mm.h> +#include <grub/misc.h> + +#include <grub/types.h> +#include <grub/err.h> +#include <grub/term.h> + +#include <grub/i386/relocator.h> +#include <grub/relocator_private.h> +#include <grub/i386/relocator_private.h> +#include <grub/i386/pc/int.h> + +extern grub_uint8_t grub_relocator16_start; +extern grub_uint8_t grub_relocator16_end; +extern grub_uint16_t grub_relocator16_cs; +extern grub_uint16_t grub_relocator16_ip; +extern grub_uint16_t grub_relocator16_ds; +extern grub_uint16_t grub_relocator16_es; +extern grub_uint16_t grub_relocator16_fs; +extern grub_uint16_t grub_relocator16_gs; +extern grub_uint16_t grub_relocator16_ss; +extern grub_uint16_t grub_relocator16_sp; +extern grub_uint32_t grub_relocator16_edx; +extern grub_uint32_t grub_relocator16_ebx; +extern grub_uint32_t grub_relocator16_esi; +extern grub_uint32_t grub_relocator16_ebp; + +extern grub_uint16_t grub_relocator16_keep_a20_enabled; + +extern grub_uint8_t grub_relocator32_start; +extern grub_uint8_t grub_relocator32_end; +extern grub_uint32_t grub_relocator32_eax; +extern grub_uint32_t grub_relocator32_ebx; +extern grub_uint32_t grub_relocator32_ecx; +extern grub_uint32_t grub_relocator32_edx; +extern grub_uint32_t grub_relocator32_eip; +extern grub_uint32_t grub_relocator32_esp; +extern grub_uint32_t grub_relocator32_ebp; +extern grub_uint32_t grub_relocator32_esi; +extern grub_uint32_t grub_relocator32_edi; + +extern grub_uint8_t grub_relocator64_start; +extern grub_uint8_t grub_relocator64_end; +extern grub_uint64_t grub_relocator64_rax; +extern grub_uint64_t grub_relocator64_rbx; +extern grub_uint64_t grub_relocator64_rcx; +extern grub_uint64_t grub_relocator64_rdx; +extern grub_uint64_t grub_relocator64_rip; +extern grub_uint64_t grub_relocator64_rsp; +extern grub_uint64_t grub_relocator64_rsi; +extern grub_addr_t grub_relocator64_cr3; +extern struct grub_i386_idt grub_relocator16_idt; + +#define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start) + +grub_err_t +grub_relocator32_boot (struct grub_relocator *rel, + struct grub_relocator32_state state, + int avoid_efi_bootservices) +{ + grub_err_t err; + void *relst; + grub_relocator_chunk_t ch; + + /* Specific memory range due to Global Descriptor Table for use by payload + that we will store in returned chunk. The address range and preference + are based on "THE LINUX/x86 BOOT PROTOCOL" specification. */ + err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x1000, 0x9a000, + RELOCATOR_SIZEOF (32), 16, + GRUB_RELOCATOR_PREFERENCE_LOW, + avoid_efi_bootservices); + if (err) + return err; + + grub_relocator32_eax = state.eax; + grub_relocator32_ebx = state.ebx; + grub_relocator32_ecx = state.ecx; + grub_relocator32_edx = state.edx; + grub_relocator32_eip = state.eip; + grub_relocator32_esp = state.esp; + grub_relocator32_ebp = state.ebp; + grub_relocator32_esi = state.esi; + grub_relocator32_edi = state.edi; + + grub_memmove (get_virtual_current_address (ch), &grub_relocator32_start, + RELOCATOR_SIZEOF (32)); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); + if (err) + return err; + + asm volatile ("cli"); + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} + +grub_err_t +grub_relocator16_boot (struct grub_relocator *rel, + struct grub_relocator16_state state) +{ + grub_err_t err; + void *relst; + grub_relocator_chunk_t ch; + + /* Put it higher than the byte it checks for A20 check. */ + err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x8010, 0xa0000, + RELOCATOR_SIZEOF (16) + + GRUB_RELOCATOR16_STACK_SIZE, 16, + GRUB_RELOCATOR_PREFERENCE_NONE, 0); + if (err) + return err; + + grub_relocator16_cs = state.cs; + grub_relocator16_ip = state.ip; + + grub_relocator16_ds = state.ds; + grub_relocator16_es = state.es; + grub_relocator16_fs = state.fs; + grub_relocator16_gs = state.gs; + + grub_relocator16_ss = state.ss; + grub_relocator16_sp = state.sp; + + grub_relocator16_ebp = state.ebp; + grub_relocator16_ebx = state.ebx; + grub_relocator16_edx = state.edx; + grub_relocator16_esi = state.esi; +#ifdef GRUB_MACHINE_PCBIOS + grub_relocator16_idt = *grub_realidt; +#else + grub_relocator16_idt.base = 0; + grub_relocator16_idt.limit = 0; +#endif + + grub_relocator16_keep_a20_enabled = state.a20; + + grub_memmove (get_virtual_current_address (ch), &grub_relocator16_start, + RELOCATOR_SIZEOF (16)); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); + if (err) + return err; + + asm volatile ("cli"); + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} + +grub_err_t +grub_relocator64_boot (struct grub_relocator *rel, + struct grub_relocator64_state state, + grub_addr_t min_addr, grub_addr_t max_addr) +{ + grub_err_t err; + void *relst; + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_align_safe (rel, &ch, min_addr, max_addr, + RELOCATOR_SIZEOF (64), 16, + GRUB_RELOCATOR_PREFERENCE_NONE, 0); + if (err) + return err; + + grub_relocator64_rax = state.rax; + grub_relocator64_rbx = state.rbx; + grub_relocator64_rcx = state.rcx; + grub_relocator64_rdx = state.rdx; + grub_relocator64_rip = state.rip; + grub_relocator64_rsp = state.rsp; + grub_relocator64_rsi = state.rsi; + grub_relocator64_cr3 = state.cr3; + + grub_memmove (get_virtual_current_address (ch), &grub_relocator64_start, + RELOCATOR_SIZEOF (64)); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); + if (err) + return err; + + asm volatile ("cli"); + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S new file mode 100644 index 0000000..e923811 --- /dev/null +++ b/grub-core/lib/i386/relocator16.S @@ -0,0 +1,341 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +/* The code segment of the protected mode. */ +#define CODE_SEGMENT 0x08 + +/* The data segment of the protected mode. */ +#define DATA_SEGMENT 0x10 + +#define PSEUDO_REAL_CSEG 0x18 + +#define PSEUDO_REAL_DSEG 0x20 + +#include <grub/i386/relocator_private.h> + +#include "relocator_common.S" + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE(grub_relocator16_start) + PREAMBLE + +#ifdef __APPLE__ + LOCAL(cs_base_bytes12_offset) = LOCAL (cs_base_bytes12) - LOCAL (base) + LOCAL(cs_base_byte3_offset) = LOCAL (cs_base_byte3) - LOCAL (base) + LOCAL(ds_base_bytes12_offset) = LOCAL (ds_base_bytes12) - LOCAL (base) + LOCAL(ds_base_byte3_offset) = LOCAL (ds_base_byte3) - LOCAL (base) + movl %esi, %eax + movw %ax, (LOCAL(cs_base_bytes12_offset)) (RSI, 1) + movw %ax, (LOCAL(ds_base_bytes12_offset)) (RSI, 1) + shrl $16, %eax + movb %al, (LOCAL (cs_base_byte3_offset)) (RSI, 1) + movb %al, (LOCAL (ds_base_byte3_offset)) (RSI, 1) +#else + movl %esi, %eax + movw %ax, (LOCAL (cs_base_bytes12) - LOCAL (base)) (RSI, 1) + movw %ax, (LOCAL (ds_base_bytes12) - LOCAL (base)) (RSI, 1) + shrl $16, %eax + movb %al, (LOCAL (cs_base_byte3) - LOCAL (base)) (RSI, 1) + movb %al, (LOCAL (ds_base_byte3) - LOCAL (base)) (RSI, 1) +#endif + + RELOAD_GDT + .code32 + /* Update other registers. */ + movl $DATA_SEGMENT, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + DISABLE_PAGING + +#ifdef __x86_64__ + /* Disable amd64. */ + movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx + rdmsr + andl $(~GRUB_MEMORY_CPU_AMD64_MSR_ON), %eax + wrmsr +#endif + + /* Turn off PAE. */ + movl %cr4, %eax + andl $(~GRUB_MEMORY_CPU_CR4_PAE_ON), %eax + movl %eax, %cr4 + + /* Update other registers. */ + movl $PSEUDO_REAL_DSEG, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + movl %esi, %eax + shrl $4, %eax +#ifdef __APPLE__ + LOCAL(segment_offset) = LOCAL (segment) - LOCAL (base) + LOCAL(idt_offset) = LOCAL(relocator16_idt) - LOCAL (base) + LOCAL(cont2_offset) = LOCAL (cont2) - LOCAL(base) + movw %ax, (LOCAL(segment_offset)) + lidt (LOCAL(idt_offset)) + + /* jump to a 16 bit segment */ + ljmp $PSEUDO_REAL_CSEG, $(LOCAL(cont2_offset)) +#else + movw %ax, (LOCAL (segment) - LOCAL (base)) + + lidt (EXT_C(grub_relocator16_idt) - LOCAL (base)) + + /* jump to a 16 bit segment */ + ljmp $PSEUDO_REAL_CSEG, $(LOCAL (cont2) - LOCAL(base)) +#endif +LOCAL(cont2): + .code16 + + /* clear the PE bit of CR0 */ + movl %cr0, %eax + andl $(~GRUB_MEMORY_CPU_CR0_PE_ON), %eax + movl %eax, %cr0 + + /* flush prefetch queue, reload %cs */ + /* ljmp */ + .byte 0xea +#ifdef __APPLE__ + LOCAL(cont3_offset) = LOCAL(cont3) - LOCAL(base) + .word LOCAL(cont3_offset) +#else + .word LOCAL(cont3)-LOCAL(base) +#endif +LOCAL(segment): + .word 0 + +LOCAL(cont3): + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_keep_a20_enabled) + .word 0 + + test %ax, %ax + jnz LOCAL(gate_a20_done) + + movw %cs, %ax + movw %ax, %ss +#ifdef __APPLE__ + LOCAL(relocator16_end_offset) = LOCAL(relocator16_end) - LOCAL(base) + leaw LOCAL(relocator16_end_offset), %sp +#else + leaw LOCAL(relocator16_end) - LOCAL(base), %sp +#endif + addw $GRUB_RELOCATOR16_STACK_SIZE, %sp + + /* second, try a BIOS call */ + movw $0x2400, %ax + int $0x15 + + call LOCAL(gate_a20_check_state) + testb %al, %al + jz LOCAL(gate_a20_done) + + /* + * In macbook, the keyboard test would hang the machine, so we move + * this forward. + */ + /* fourth, try the system control port A */ + inb $0x92 + andb $(~0x03), %al + outb $0x92 + + /* When turning off Gate A20, do not check the state strictly, + because a failure is not fatal usually, and Gate A20 is always + on some modern machines. */ + jmp LOCAL(gate_a20_done) + +LOCAL(gate_a20_check_state): + /* iterate the checking for a while */ + movw $100, %cx +1: + xorw %ax, %ax + movw %ax, %ds + decw %ax + movw %ax, %es + xorw %ax, %ax + + movw $0x8000, %ax + /* compare the byte at ADDR with that at 0x100000 + ADDR */ + movw %ax, %si + addw $0x10, %ax + movw %ax, %di + + /* save the original byte in DL */ + movb %ds:(%si), %dl + movb %es:(%di), %al + /* try to set one less value at ADDR */ + movb %al, %dh + decb %dh + movb %dh, %ds:(%si) + /* serialize */ + outb %al, $0x80 + outb %al, $0x80 + /* obtain the value at 0x100000 + ADDR in CH */ + movb %es:(%di), %dh + /* this result is 1 if A20 is on or 0 if it is off */ + subb %dh, %al + xorb $1, %al + /* restore the original */ + movb %dl, %ds:(%si) + + testb %al, %al + jz LOCAL(gate_a20_done) + loop 1b +2: + ret + +LOCAL(gate_a20_done): + /* + * We are in real mode now. Set up the real mode segment registers and + * all the other general purpose registers. cs is updated with ljmp. + */ + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_ds) + .word 0 + movw %ax, %ds + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_es) + .word 0 + movw %ax, %es + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_fs) + .word 0 + movw %ax, %fs + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_gs) + .word 0 + movw %ax, %gs + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_ss) + .word 0 + movw %ax, %ss + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_sp) + .word 0 + movzwl %ax, %esp + + /* movw imm32, %eax. */ + .byte 0x66, 0xb8 +VARIABLE(grub_relocator16_esi) + .long 0 + movl %eax, %esi + + /* movw imm32, %edx. */ + .byte 0x66, 0xba +VARIABLE(grub_relocator16_edx) + .long 0 + + /* movw imm32, %ebx. */ + .byte 0x66, 0xbb +VARIABLE(grub_relocator16_ebx) + .long 0 + + /* movl imm32, %ebp. */ + .byte 0x66, 0xbd +VARIABLE(grub_relocator16_ebp) + .long 0 + + /* Cleared direction flag is of no problem with any current + payload and makes this implementation easier. */ + cld + + /* ljmp */ + .byte 0xea +VARIABLE(grub_relocator16_ip) + .word 0 +VARIABLE(grub_relocator16_cs) + .word 0 + + .code32 + + /* GDT. Copied from loader/i386/linux.c. */ + .p2align 4 +LOCAL(gdt): + .word 0, 0 + .byte 0, 0, 0, 0 + + /* -- code segment -- + * base = 0x00000000, limit = 0xFFFFF (4 KiB Granularity), present + * type = 32bit code execute/read, DPL = 0 + */ + .word 0xFFFF, 0 + .byte 0, 0x9A, 0xCF, 0 + + /* -- data segment -- + * base = 0x00000000, limit 0xFFFFF (4 KiB Granularity), present + * type = 32 bit data read/write, DPL = 0 + */ + .word 0xFFFF, 0 + .byte 0, 0x92, 0xCF, 0 + + /* -- 16 bit real mode CS -- + * base = filled by code, limit 0x0FFFF (1 B Granularity), present + * type = 16 bit code execute/read only/conforming, DPL = 0 + */ + .word 0xFFFF +LOCAL(cs_base_bytes12): + .word 0 +LOCAL(cs_base_byte3): + .byte 0 + + .byte 0x9E, 0, 0 + + /* -- 16 bit real mode DS -- + * base = filled by code, limit 0x0FFFF (1 B Granularity), present + * type = 16 bit data read/write, DPL = 0 + */ + .word 0xFFFF +LOCAL(ds_base_bytes12): + .word 0 +LOCAL(ds_base_byte3): + .byte 0 + + .byte 0x92, 0, 0 + +LOCAL(gdt_end): + +#ifdef __APPLE__ +LOCAL(relocator16_idt): +#endif +VARIABLE(grub_relocator16_idt) + .word 0 + .long 0 +LOCAL(relocator16_end): +VARIABLE(grub_relocator16_end) + .byte 0 diff --git a/grub-core/lib/i386/relocator32.S b/grub-core/lib/i386/relocator32.S new file mode 100644 index 0000000..09ce56a --- /dev/null +++ b/grub-core/lib/i386/relocator32.S @@ -0,0 +1,134 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +/* The code segment of the protected mode. */ +#define CODE_SEGMENT 0x10 + +/* The data segment of the protected mode. */ +#define DATA_SEGMENT 0x18 + +#include "relocator_common.S" + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE(grub_relocator32_start) + PREAMBLE + + RELOAD_GDT + .code32 + /* Update other registers. */ + movl $DATA_SEGMENT, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + DISABLE_PAGING + +#ifdef __x86_64__ + /* Disable amd64. */ + movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx + rdmsr + andl $(~GRUB_MEMORY_CPU_AMD64_MSR_ON), %eax + wrmsr +#endif + + /* Turn off PAE. */ + movl %cr4, %eax + andl $(~GRUB_MEMORY_CPU_CR4_PAE_ON), %eax + movl %eax, %cr4 + + jmp LOCAL(cont2) +LOCAL(cont2): + .code32 + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator32_esp) + .long 0 + + movl %eax, %esp + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator32_ebp) + .long 0 + + movl %eax, %ebp + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator32_esi) + .long 0 + + movl %eax, %esi + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator32_edi) + .long 0 + + movl %eax, %edi + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator32_eax) + .long 0 + + /* mov imm32, %ebx */ + .byte 0xbb +VARIABLE(grub_relocator32_ebx) + .long 0 + + /* mov imm32, %ecx */ + .byte 0xb9 +VARIABLE(grub_relocator32_ecx) + .long 0 + + /* mov imm32, %edx */ + .byte 0xba +VARIABLE(grub_relocator32_edx) + .long 0 + + /* Cleared direction flag is of no problem with any current + payload and makes this implementation easier. */ + cld + + .byte 0xea +VARIABLE(grub_relocator32_eip) + .long 0 + .word CODE_SEGMENT + + /* GDT. Copied from loader/i386/linux.c. */ + .p2align 4 +LOCAL(gdt): + /* NULL. */ + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + + /* Reserved. */ + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + + /* Code segment. */ + .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00 + + /* Data segment. */ + .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00 +LOCAL(gdt_end): + +VARIABLE(grub_relocator32_end) diff --git a/grub-core/lib/i386/relocator64.S b/grub-core/lib/i386/relocator64.S new file mode 100644 index 0000000..00bf315 --- /dev/null +++ b/grub-core/lib/i386/relocator64.S @@ -0,0 +1,210 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#define CODE32_SEGMENT 0x18 +#define CODE_SEGMENT 0x08 + +/* The data segment of the protected mode. */ +#define DATA_SEGMENT 0x10 + +#include "relocator_common.S" + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE(grub_relocator64_start) + PREAMBLE +#ifndef __x86_64__ + DISABLE_PAGING + + /* Turn on PAE. */ + movl %cr4, %eax + orl $(GRUB_MEMORY_CPU_CR4_PAE_ON | GRUB_MEMORY_CPU_CR4_PSE_ON), %eax + movl %eax, %cr4 + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator64_cr3) + .long 0 + movl %eax, %cr3 + + /* Turn on amd64. */ + movl $GRUB_MEMORY_CPU_AMD64_MSR, %ecx + rdmsr + orl $GRUB_MEMORY_CPU_AMD64_MSR_ON, %eax + wrmsr + + /* Enable paging. */ + movl %cr0, %eax + orl $GRUB_MEMORY_CPU_CR0_PAGING_ON, %eax + movl %eax, %cr0 + + RELOAD_GDT +#else + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator64_cr3) + .quad 0 + movq %rax, %cr3 +#endif + +#ifdef __x86_64__ + .code64 +#endif + + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator64_rsp) + .quad 0 + +#ifdef __x86_64__ + movq %rax, %rsp +#else + /* movq %rax, %rsp */ + .byte 0x48 + .byte 0x89 + .byte 0xc4 +#endif + +#ifdef GRUB_MACHINE_EFI + jmp LOCAL(skip_efi_stack_align) + + /* + * Here is grub_relocator64_efi_start() entry point. Most of the + * code below is shared between grub_relocator64_efi_start() + * and grub_relocator64_start(). + * + * Think twice before changing anything there!!! + */ +VARIABLE(grub_relocator64_efi_start) + /* Align the stack as UEFI spec requires. */ +#ifdef __x86_64__ + andq $~15, %rsp +#else + /* andq $~15, %rsp */ + .byte 0x48 + .byte 0x83 + .byte 0xe4 + .byte 0xf0 +#endif + +LOCAL(skip_efi_stack_align): +#endif + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator64_rsi) + .quad 0 + +#ifdef __x86_64__ + movq %rax, %rsi +#else + /* movq %rax, %rsi */ + .byte 0x48 + .byte 0x89 + .byte 0xc6 +#endif + + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator64_rax) + .quad 0 + + /* mov imm64, %rbx */ + .byte 0x48 + .byte 0xbb +VARIABLE(grub_relocator64_rbx) + .quad 0 + + /* mov imm64, %rcx */ + .byte 0x48 + .byte 0xb9 +VARIABLE(grub_relocator64_rcx) + .quad 0 + + /* mov imm64, %rdx */ + .byte 0x48 + .byte 0xba +VARIABLE(grub_relocator64_rdx) + .quad 0 + + /* Cleared direction flag is of no problem with any current + payload and makes this implementation easier. */ + cld + +#if defined (__APPLE__) || !defined (__x86_64__) + .byte 0xff, 0x25 + .quad 0 +#else + jmp *LOCAL(jump_addr) (%rip) +#endif + +LOCAL(jump_addr): +VARIABLE(grub_relocator64_rip) + .quad 0 + +#ifdef GRUB_MACHINE_EFI + /* Here grub_relocator64_efi_start() ends. Ufff... */ +VARIABLE(grub_relocator64_efi_end) +#endif + +#ifndef __x86_64__ + .p2align 4 +LOCAL(gdt): + /* NULL. */ + .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + + /* 64-bit segment. */ + .word 0xffff /* Limit xffff. */ + .word 0x0000 /* Base xxxx0000. */ + .byte 0x00 /* Base xx00xxxx. */ + .byte (0x8 /* Type 8. */ | (1 << 4) /* Code. */ \ + | (0 << 5) /* Ring 0. */ | (1 << 7) /* Present. */) + .byte (0xf /* Limit fxxxx. */ | (0 << 4) /* AVL flag. */ \ + | (1 << 5) /* 64-bit. */ | (0 << 6) \ + | (1 << 7) /* 4K granular. */) + .byte 0x00 /* Base 00xxxxxx. */ + + /* Data segment*/ + .word 0xffff /* Limit xffff. */ + .word 0x0000 /* Base xxxx0000. */ + .byte 0x00 /* Base xx00xxxx. */ + .byte (0x0 /* Type 0. */ | (0 << 4) /* Data. */ \ + | (0 << 5) /* Ring 0. */ | (1 << 7) /* Present. */) + .byte (0xf /* Limit fxxxx. */ | (0 << 4) /* AVL flag. */ \ + | (0 << 5) /* Data. */ | (0 << 6) \ + | (1 << 7) /* 4K granular. */) + .byte 0x00 /* Base 00xxxxxx. */ + + /* Compatibility segment. */ + .word 0xffff /* Limit xffff. */ + .word 0x0000 /* Base xxxx0000. */ + .byte 0x00 /* Base xx00xxxx. */ + .byte (0x8 /* Type 8. */ | (1 << 4) /* Code. */ \ + | (0 << 5) /* Ring 0. */ | (1 << 7) /* Present. */) + .byte (0xf /* Limit fxxxx. */ | (0 << 4) /* AVL flag. */ \ + | (0 << 5) /* 32-bit. */ | (1 << 6) /* 32-bit. */ \ + | (1 << 7) /* 4K granular. */) + .byte 0x00 /* Base 00xxxxxx. */ + +LOCAL(gdt_end): +#endif + +VARIABLE(grub_relocator64_end) diff --git a/grub-core/lib/i386/relocator_asm.S b/grub-core/lib/i386/relocator_asm.S new file mode 100644 index 0000000..f273586 --- /dev/null +++ b/grub-core/lib/i386/relocator_asm.S @@ -0,0 +1,80 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> +#include <grub/i386/memory.h> + + .p2align 2 + +VARIABLE(grub_relocator_backward_start) + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_backward_dest) + .long 0 + movl %eax, %edi + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_backward_src) + .long 0 + movl %eax, %esi + + /* mov imm32, %ecx */ + .byte 0xb9 +VARIABLE(grub_relocator_backward_chunk_size) + .long 0 + + add %ecx, %esi + add %ecx, %edi + + + /* Backward movsb is implicitly off-by-one. compensate that. */ + sub $1, %esi + sub $1, %edi + + /* Backward copy. */ + std + + rep + movsb +VARIABLE(grub_relocator_backward_end) + + +VARIABLE(grub_relocator_forward_start) + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_forward_dest) + .long 0 + movl %eax, %edi + + /* mov imm32, %rax */ + .byte 0xb8 +VARIABLE(grub_relocator_forward_src) + .long 0 + movl %eax, %esi + + /* mov imm32, %ecx */ + .byte 0xb9 +VARIABLE(grub_relocator_forward_chunk_size) + .long 0 + + /* Forward copy. */ + cld + rep + movsb +VARIABLE(grub_relocator_forward_end) diff --git a/grub-core/lib/i386/relocator_common.S b/grub-core/lib/i386/relocator_common.S new file mode 100644 index 0000000..1b5210d --- /dev/null +++ b/grub-core/lib/i386/relocator_common.S @@ -0,0 +1,111 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include <grub/symbol.h> +#include <grub/i386/memory.h> + +#ifdef __x86_64__ +#define RAX %rax +#define RSI %rsi +#else +#define RAX %eax +#define RSI %esi +#endif + + .macro DISABLE_PAGING + + movl %cr0, %eax + andl $(~GRUB_MEMORY_CPU_CR0_PAGING_ON), %eax + movl %eax, %cr0 + .endm + + .macro PREAMBLE +LOCAL(base): + /* %rax contains now our new 'base'. */ + mov RAX, RSI + +#if defined (__APPLE__) && defined (__x86_64__) + leaq LOCAL(cont0) (%rip), RAX +#elif defined (__APPLE__) + LOCAL(cont0_offset) = LOCAL(cont0) - LOCAL(base) + add $LOCAL(cont0_offset), RAX +#else + add $(LOCAL(cont0) - LOCAL(base)), RAX +#endif + jmp *RAX +LOCAL(cont0): + .endm + + .macro RELOAD_GDT +#ifdef __APPLE__ + LOCAL(cont1_offset) = LOCAL(cont1) - LOCAL(base) + LOCAL(jump_vector_offset) = LOCAL(jump_vector) - LOCAL(base) + LOCAL(gdt_offset) = LOCAL(gdt) - LOCAL(base) + LOCAL(gdt_addr_offset) = LOCAL(gdt_addr) - LOCAL(base) + LOCAL(gdtdesc_offset) = LOCAL(gdtdesc) - LOCAL(base) + + lea LOCAL(cont1_offset) (RSI, 1), RAX + movl %eax, LOCAL(jump_vector_offset) (RSI, 1) + + lea LOCAL(gdt_offset) (RSI, 1), RAX + mov RAX, (LOCAL(gdt_addr_offset)) (RSI, 1) + + /* Switch to compatibility mode. */ + lgdt (LOCAL(gdtdesc_offset)) (RSI, 1) + + /* Update %cs. */ + ljmp *(LOCAL(jump_vector_offset)) (RSI, 1) + .p2align 4 +LOCAL(gdtdesc): + LOCAL(gdtsize) = LOCAL(gdt_end) - LOCAL(gdt) + .word LOCAL(gdtsize) +#else + lea (LOCAL(cont1) - LOCAL(base)) (RSI, 1), RAX + movl %eax, (LOCAL(jump_vector) - LOCAL(base)) (RSI, 1) + + lea (LOCAL(gdt) - LOCAL(base)) (RSI, 1), RAX + mov RAX, (LOCAL(gdt_addr) - LOCAL(base)) (RSI, 1) + + /* Switch to compatibility mode. */ + lgdt (LOCAL(gdtdesc) - LOCAL(base)) (RSI, 1) + + /* Update %cs. */ + ljmp *(LOCAL(jump_vector) - LOCAL(base)) (RSI, 1) + + .p2align 4 +LOCAL(gdtdesc): + .word LOCAL(gdt_end) - LOCAL(gdt) +#endif +LOCAL(gdt_addr): +#ifdef __x86_64__ + /* Filled by the code. */ + .quad 0 +#else + /* Filled by the code. */ + .long 0 +#endif + + .p2align 4 +LOCAL(jump_vector): + /* Jump location. Is filled by the code */ + .long 0 + .long CODE_SEGMENT + +LOCAL(cont1): + .endm diff --git a/grub-core/lib/i386/relocator_common_c.c b/grub-core/lib/i386/relocator_common_c.c new file mode 100644 index 0000000..7be609b --- /dev/null +++ b/grub-core/lib/i386/relocator_common_c.c @@ -0,0 +1,109 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009-2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/mm.h> +#include <grub/misc.h> + +#include <grub/types.h> +#include <grub/err.h> +#include <grub/term.h> + +#include <grub/relocator.h> +#include <grub/relocator_private.h> + +extern grub_uint8_t grub_relocator_forward_start; +extern grub_uint8_t grub_relocator_forward_end; +extern grub_uint8_t grub_relocator_backward_start; +extern grub_uint8_t grub_relocator_backward_end; + +extern void *grub_relocator_backward_dest; +extern void *grub_relocator_backward_src; +extern grub_size_t grub_relocator_backward_chunk_size; + +extern void *grub_relocator_forward_dest; +extern void *grub_relocator_forward_src; +extern grub_size_t grub_relocator_forward_chunk_size; + +#define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start) + +grub_size_t grub_relocator_align = 1; +grub_size_t grub_relocator_forward_size; +grub_size_t grub_relocator_backward_size; +#ifdef __x86_64__ +grub_size_t grub_relocator_jumper_size = 12; +#else +grub_size_t grub_relocator_jumper_size = 7; +#endif + +void +grub_cpu_relocator_init (void) +{ + grub_relocator_forward_size = RELOCATOR_SIZEOF (_forward); + grub_relocator_backward_size = RELOCATOR_SIZEOF (_backward); +} + +void +grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) +{ + grub_uint8_t *ptr; + ptr = rels; +#ifdef __x86_64__ + /* movq imm64, %rax (for relocator) */ + *(grub_uint8_t *) ptr = 0x48; + ptr++; + *(grub_uint8_t *) ptr = 0xb8; + ptr++; + *(grub_uint64_t *) ptr = addr; + ptr += sizeof (grub_uint64_t); +#else + /* movl imm32, %eax (for relocator) */ + *(grub_uint8_t *) ptr = 0xb8; + ptr++; + *(grub_uint32_t *) ptr = addr; + ptr += sizeof (grub_uint32_t); +#endif + /* jmp $eax/$rax */ + *(grub_uint8_t *) ptr = 0xff; + ptr++; + *(grub_uint8_t *) ptr = 0xe0; + ptr++; +} + +void +grub_cpu_relocator_backward (void *ptr, void *src, void *dest, + grub_size_t size) +{ + grub_relocator_backward_dest = dest; + grub_relocator_backward_src = src; + grub_relocator_backward_chunk_size = size; + + grub_memmove (ptr, + &grub_relocator_backward_start, RELOCATOR_SIZEOF (_backward)); +} + +void +grub_cpu_relocator_forward (void *ptr, void *src, void *dest, + grub_size_t size) +{ + grub_relocator_forward_dest = dest; + grub_relocator_forward_src = src; + grub_relocator_forward_chunk_size = size; + + grub_memmove (ptr, + &grub_relocator_forward_start, RELOCATOR_SIZEOF (_forward)); +} diff --git a/grub-core/lib/i386/setjmp.S b/grub-core/lib/i386/setjmp.S new file mode 100644 index 0000000..0b0740f --- /dev/null +++ b/grub-core/lib/i386/setjmp.S @@ -0,0 +1,59 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2007 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> +#include <grub/dl.h> + + .file "setjmp.S" + +GRUB_MOD_LICENSE "GPLv3+" + + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + movl %ebx, 0(%eax) /* EBX */ + movl %esi, 4(%eax) /* ESI */ + movl %edi, 8(%eax) /* EDI */ + movl %ebp, 12(%eax) /* EBP */ + popl %ecx + movl %esp, 16(%eax) /* ESP */ + movl %ecx, 20(%eax) /* EIP */ + xorl %eax, %eax + jmp *%ecx + + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + movl 0(%eax), %ebx + movl 4(%eax), %esi + movl 8(%eax), %edi + movl 12(%eax), %ebp + movl 16(%eax), %esp + movl 20(%eax), %ecx + + movl %edx, %eax + testl %eax, %eax + jnz 1f + incl %eax +1: jmp *%ecx + diff --git a/grub-core/lib/i386/xen/relocator.S b/grub-core/lib/i386/xen/relocator.S new file mode 100644 index 0000000..96e51b5 --- /dev/null +++ b/grub-core/lib/i386/xen/relocator.S @@ -0,0 +1,165 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/i386/memory.h> +#include <grub/i386/types.h> +#include <grub/symbol.h> +#include <grub/xen.h> + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE(grub_relocator_xen_remap_start) +LOCAL(base): + /* Remap the remapper to it's new address. */ + /* mov imm32, %ebx - %ebx: new virtual address of remapper */ + .byte 0xbb +VARIABLE(grub_relocator_xen_remapper_virt) + .long 0 + + /* mov imm32, %ecx - %ecx: low part of page table entry */ + .byte 0xb9 +VARIABLE(grub_relocator_xen_remapper_map) + .long 0 + + /* mov imm32, %edx - %edx: high part of page table entry */ + .byte 0xba +VARIABLE(grub_relocator_xen_remapper_map_high) + .long 0 + + movl %ebx, %ebp /* %ebx is clobbered by hypercall */ + + movl $UVMF_INVLPG, %esi /* esi: flags (inv. single entry) */ + movl $__HYPERVISOR_update_va_mapping, %eax + int $0x82 + + movl %ebp, %ebx + addl $(LOCAL(cont) - LOCAL(base)), %ebx + + jmp *%ebx /* Continue with new virtual address */ + +LOCAL(cont): + /* Modify mappings of new page tables to be read-only. */ + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_paging_areas_addr) + .long 0 + movl %eax, %ebx +1: + movl 0(%ebx), %ebp /* Get start pfn of the current area */ + movl GRUB_TARGET_SIZEOF_LONG(%ebx), %ecx /* Get # of pg tables */ + testl %ecx, %ecx /* 0 -> last area reached */ + jz 3f + addl $(2 * GRUB_TARGET_SIZEOF_LONG), %ebx + movl %ebx, %esp /* Save current area pointer */ + +2: + movl %ecx, %edi + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_mfn_list) + .long 0 + movl 0(%eax, %ebp, 4), %ecx /* mfn */ + movl %ebp, %ebx + shll $PAGE_SHIFT, %ebx /* virtual address (1:1 mapping) */ + movl %ecx, %edx + shll $PAGE_SHIFT, %ecx /* prepare pte low part */ + shrl $(32 - PAGE_SHIFT), %edx /* pte high part */ + orl $(GRUB_PAGE_PRESENT | GRUB_PAGE_USER), %ecx /* pte low */ + movl $UVMF_INVLPG, %esi + movl $__HYPERVISOR_update_va_mapping, %eax + int $0x82 /* parameters: eax, ebx, ecx, edx, esi */ + + incl %ebp /* next pfn */ + movl %edi, %ecx + + loop 2b + + mov %esp, %ebx /* restore area poniter */ + jmp 1b + +3: + /* Switch page tables: pin new L3 pt, load cr3, unpin old L3. */ + /* mov imm32, %ebx */ + .byte 0xbb +VARIABLE(grub_relocator_xen_mmu_op_addr) + .long 0 + movl $3, %ecx /* 3 mmu ops */ + movl $0, %edx /* pdone (not used) */ + movl $DOMID_SELF, %esi + movl $__HYPERVISOR_mmuext_op, %eax + int $0x82 + + /* Continue in virtual kernel mapping. */ + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_remap_continue) + .long 0 + + jmp *%eax + +VARIABLE(grub_relocator_xen_paging_areas) + .long 0, 0, 0, 0, 0, 0, 0, 0 + +VARIABLE(grub_relocator_xen_mmu_op) + .space 256 + +VARIABLE(grub_relocator_xen_remap_end) + + +VARIABLE(grub_relocator_xen_start) + /* Unmap old remapper area. */ + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_remapper_virt2) + .long 0 + + movl %eax, %ebx + + xorl %ecx, %ecx /* Invalid pte */ + xorl %edx, %edx + + movl $UVMF_INVLPG, %esi + movl $__HYPERVISOR_update_va_mapping, %eax + int $0x82 + + /* Prepare registers for starting kernel. */ + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_stack) + .long 0 + + movl %eax, %esp + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_start_info) + .long 0 + + movl %eax, %esi + + cld + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_entry_point) + .long 0 + + /* Now start the new kernel. */ + jmp *%eax + +VARIABLE(grub_relocator_xen_end) diff --git a/grub-core/lib/ia64/longjmp.S b/grub-core/lib/ia64/longjmp.S new file mode 100644 index 0000000..38afb22 --- /dev/null +++ b/grub-core/lib/ia64/longjmp.S @@ -0,0 +1,162 @@ +/* Copyright (C) 1999, 2000, 2001, 2002, 2008 Free Software Foundation, Inc. + Contributed by David Mosberger-Tang <davidm@hpl.hp.com>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Note that __sigsetjmp() did NOT flush the register stack. Instead, + we do it here since __longjmp() is usually much less frequently + invoked than __sigsetjmp(). The only difficulty is that __sigsetjmp() + didn't (and wouldn't be able to) save ar.rnat either. This is a problem + because if we're not careful, we could end up loading random NaT bits. + There are two cases: + + (i) ar.bsp < ia64_rse_rnat_addr(jmpbuf.ar_bsp) + ar.rnat contains the desired bits---preserve ar.rnat + across loadrs and write to ar.bspstore + + (ii) ar.bsp >= ia64_rse_rnat_addr(jmpbuf.ar_bsp) + The desired ar.rnat is stored in + ia64_rse_rnat_addr(jmpbuf.ar_bsp). Load those + bits into ar.rnat after setting ar.bspstore. */ + + + +# define pPos p6 /* is rotate count positive? */ +# define pNeg p7 /* is rotate count negative? */ + + + /* __longjmp(__jmp_buf buf, int val) */ + + .text + + .proc EXT_C(grub_longjmp) +FUNCTION(grub_longjmp) + alloc r8=ar.pfs,2,1,0,0 + mov r27=ar.rsc + add r2=0x98,in0 // r2 <- &jmpbuf.orig_jmp_buf_addr + ;; + ld8 r8=[r2],-16 // r8 <- orig_jmp_buf_addr + mov r10=ar.bsp + and r11=~0x3,r27 // clear ar.rsc.mode + ;; + flushrs // flush dirty regs to backing store (must be first in insn grp) + ld8 r23=[r2],8 // r23 <- jmpbuf.ar_bsp + sub r8=r8,in0 // r8 <- &orig_jmpbuf - &jmpbuf + ;; + ld8 r25=[r2] // r25 <- jmpbuf.ar_unat + extr.u r8=r8,3,6 // r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f + ;; + cmp.lt pNeg,pPos=r8,r0 + mov r2=in0 + ;; +(pPos) mov r16=r8 +(pNeg) add r16=64,r8 +(pPos) sub r17=64,r8 +(pNeg) sub r17=r0,r8 + ;; + mov ar.rsc=r11 // put RSE in enforced lazy mode + shr.u r8=r25,r16 + add r3=8,in0 // r3 <- &jmpbuf.r1 + shl r9=r25,r17 + ;; + or r25=r8,r9 + ;; + mov r26=ar.rnat + mov ar.unat=r25 // setup ar.unat (NaT bits for r1, r4-r7, and r12) + ;; + ld8.fill.nta sp=[r2],16 // r12 (sp) + ld8.fill.nta gp=[r3],16 // r1 (gp) + dep r11=-1,r23,3,6 // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp) + ;; + ld8.nta r16=[r2],16 // caller's unat + ld8.nta r17=[r3],16 // fpsr + ;; + ld8.fill.nta r4=[r2],16 // r4 + ld8.fill.nta r5=[r3],16 // r5 (gp) + cmp.geu p8,p0=r10,r11 // p8 <- (ar.bsp >= jmpbuf.ar_bsp) + ;; + ld8.fill.nta r6=[r2],16 // r6 + ld8.fill.nta r7=[r3],16 // r7 + ;; + mov ar.unat=r16 // restore caller's unat + mov ar.fpsr=r17 // restore fpsr + ;; + ld8.nta r16=[r2],16 // b0 + ld8.nta r17=[r3],16 // b1 + ;; +(p8) ld8 r26=[r11] // r26 <- *ia64_rse_rnat_addr(jmpbuf.ar_bsp) + mov ar.bspstore=r23 // restore ar.bspstore + ;; + ld8.nta r18=[r2],16 // b2 + ld8.nta r19=[r3],16 // b3 + ;; + ld8.nta r20=[r2],16 // b4 + ld8.nta r21=[r3],16 // b5 + ;; + ld8.nta r11=[r2],16 // ar.pfs + ld8.nta r22=[r3],56 // ar.lc + ;; + ld8.nta r24=[r2],32 // pr + mov b0=r16 + ;; + ldf.fill.nta f2=[r2],32 + ldf.fill.nta f3=[r3],32 + mov b1=r17 + ;; + ldf.fill.nta f4=[r2],32 + ldf.fill.nta f5=[r3],32 + mov b2=r18 + ;; + ldf.fill.nta f16=[r2],32 + ldf.fill.nta f17=[r3],32 + mov b3=r19 + ;; + ldf.fill.nta f18=[r2],32 + ldf.fill.nta f19=[r3],32 + mov b4=r20 + ;; + ldf.fill.nta f20=[r2],32 + ldf.fill.nta f21=[r3],32 + mov b5=r21 + ;; + ldf.fill.nta f22=[r2],32 + ldf.fill.nta f23=[r3],32 + mov ar.lc=r22 + ;; + ldf.fill.nta f24=[r2],32 + ldf.fill.nta f25=[r3],32 + cmp.eq p8,p9=0,in1 + ;; + ldf.fill.nta f26=[r2],32 + ldf.fill.nta f27=[r3],32 + mov ar.pfs=r11 + ;; + ldf.fill.nta f28=[r2],32 + ldf.fill.nta f29=[r3],32 + ;; + ldf.fill.nta f30=[r2] + ldf.fill.nta f31=[r3] +(p8) mov r8=1 + + mov ar.rnat=r26 // restore ar.rnat + ;; + mov ar.rsc=r27 // restore ar.rsc +(p9) mov r8=in1 + + invala // virt. -> phys. regnum mapping may change + mov pr=r24,-1 + br.ret.dptk.few rp + .endp EXT_C(grub_longjmp) diff --git a/grub-core/lib/ia64/setjmp.S b/grub-core/lib/ia64/setjmp.S new file mode 100644 index 0000000..a0382d8 --- /dev/null +++ b/grub-core/lib/ia64/setjmp.S @@ -0,0 +1,177 @@ +/* Copyright (C) 1999, 2000, 2001, 2002, 2008 Free Software Foundation, Inc. + Contributed by David Mosberger-Tang <davidm@hpl.hp.com>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + The layout of the jmp_buf is as follows. This is subject to change + and user-code should never depend on the particular layout of + jmp_buf! + + + offset: description: + ------- ------------ + 0x000 stack pointer (r12) ; unchangeable (see _JMPBUF_UNWINDS) + 0x008 r1 (gp) + 0x010 caller's unat + 0x018 fpsr + 0x020 r4 + 0x028 r5 + 0x030 r6 + 0x038 r7 + 0x040 rp (b0) + 0x048 b1 + 0x050 b2 + 0x058 b3 + 0x060 b4 + 0x068 b5 + 0x070 ar.pfs + 0x078 ar.lc + 0x080 pr + 0x088 ar.bsp ; unchangeable (see __longjmp.S) + 0x090 ar.unat + 0x098 &__jmp_buf ; address of the jmpbuf (needed to locate NaT bits in unat) + 0x0a0 f2 + 0x0b0 f3 + 0x0c0 f4 + 0x0d0 f5 + 0x0e0 f16 + 0x0f0 f17 + 0x100 f18 + 0x110 f19 + 0x120 f20 + 0x130 f21 + 0x130 f22 + 0x140 f23 + 0x150 f24 + 0x160 f25 + 0x170 f26 + 0x180 f27 + 0x190 f28 + 0x1a0 f29 + 0x1b0 f30 + 0x1c0 f31 */ + +#include <grub/symbol.h> +#include <grub/dl.h> + + .file "setjmp.S" + +GRUB_MOD_LICENSE "GPLv2+" + + /* The following two entry points are the traditional entry points: */ + + .text + + .proc EXT_C(grub_setjmp) +FUNCTION(grub_setjmp) + alloc r8=ar.pfs,2,0,0,0 + mov in1=1 + br.cond.sptk.many __sigsetjmp + .endp EXT_C(grub_setjmp) + + /* __sigsetjmp(__jmp_buf buf, int savemask) */ + + .proc __sigsetjmp +__sigsetjmp: + //.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) + alloc loc1=ar.pfs,2,2,2,0 + mov r16=ar.unat + ;; + mov r17=ar.fpsr + mov r2=in0 + add r3=8,in0 + ;; + st8.spill.nta [r2]=sp,16 // r12 (sp) + st8.spill.nta [r3]=gp,16 // r1 (gp) + ;; + st8.nta [r2]=r16,16 // save caller's unat + st8.nta [r3]=r17,16 // save fpsr + add r8=0xa0,in0 + ;; + st8.spill.nta [r2]=r4,16 // r4 + st8.spill.nta [r3]=r5,16 // r5 + add r9=0xb0,in0 + ;; + stf.spill.nta [r8]=f2,32 + stf.spill.nta [r9]=f3,32 + mov loc0=rp + .body + ;; + stf.spill.nta [r8]=f4,32 + stf.spill.nta [r9]=f5,32 + mov r17=b1 + ;; + stf.spill.nta [r8]=f16,32 + stf.spill.nta [r9]=f17,32 + mov r18=b2 + ;; + stf.spill.nta [r8]=f18,32 + stf.spill.nta [r9]=f19,32 + mov r19=b3 + ;; + stf.spill.nta [r8]=f20,32 + stf.spill.nta [r9]=f21,32 + mov r20=b4 + ;; + stf.spill.nta [r8]=f22,32 + stf.spill.nta [r9]=f23,32 + mov r21=b5 + ;; + stf.spill.nta [r8]=f24,32 + stf.spill.nta [r9]=f25,32 + mov r22=ar.lc + ;; + stf.spill.nta [r8]=f26,32 + stf.spill.nta [r9]=f27,32 + mov r24=pr + ;; + stf.spill.nta [r8]=f28,32 + stf.spill.nta [r9]=f29,32 + ;; + stf.spill.nta [r8]=f30 + stf.spill.nta [r9]=f31 + + st8.spill.nta [r2]=r6,16 // r6 + st8.spill.nta [r3]=r7,16 // r7 + ;; + mov r23=ar.bsp + mov r25=ar.unat + mov out0=in0 + + st8.nta [r2]=loc0,16 // b0 + st8.nta [r3]=r17,16 // b1 + mov out1=in1 + ;; + st8.nta [r2]=r18,16 // b2 + st8.nta [r3]=r19,16 // b3 + ;; + st8.nta [r2]=r20,16 // b4 + st8.nta [r3]=r21,16 // b5 + ;; + st8.nta [r2]=loc1,16 // ar.pfs + st8.nta [r3]=r22,16 // ar.lc + ;; + st8.nta [r2]=r24,16 // pr + st8.nta [r3]=r23,16 // ar.bsp + ;; + st8.nta [r2]=r25 // ar.unat + st8.nta [r3]=in0 // &__jmp_buf + mov r8=0 + mov rp=loc0 + mov ar.pfs=loc1 + br.ret.sptk.many rp + + .endp __sigsetjmp diff --git a/grub-core/lib/ieee1275/cmos.c b/grub-core/lib/ieee1275/cmos.c new file mode 100644 index 0000000..328d70a --- /dev/null +++ b/grub-core/lib/ieee1275/cmos.c @@ -0,0 +1,77 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/datetime.h> +#include <grub/cmos.h> +#include <grub/dl.h> +#include <grub/ieee1275/ieee1275.h> +#include <grub/misc.h> + +volatile grub_uint8_t *grub_cmos_port = 0; + +/* Helper for grub_cmos_find_port. */ +static int +grub_cmos_find_port_iter (struct grub_ieee1275_devalias *alias) +{ + grub_ieee1275_phandle_t dev; + grub_uint32_t addr[2]; + grub_ssize_t actual; + /* Enough to check if it's "m5819" */ + char compat[100]; + if (grub_ieee1275_finddevice (alias->path, &dev)) + return 0; + if (grub_ieee1275_get_property (dev, "compatible", compat, sizeof (compat), + 0)) + return 0; + if (grub_strcmp (compat, "m5819") != 0) + return 0; + if (grub_ieee1275_get_integer_property (dev, "address", + addr, sizeof (addr), &actual)) + return 0; + if (actual == 4) + { + grub_cmos_port = (volatile grub_uint8_t *) (grub_addr_t) addr[0]; + return 1; + } + +#if GRUB_CPU_SIZEOF_VOID_P == 8 + if (actual == 8) + { + grub_cmos_port = (volatile grub_uint8_t *) + ((((grub_addr_t) addr[0]) << 32) | addr[1]); + return 1; + } +#else + if (actual == 8 && addr[0] == 0) + { + grub_cmos_port = (volatile grub_uint8_t *) addr[1]; + return 1; + } +#endif + return 0; +} + +grub_err_t +grub_cmos_find_port (void) +{ + grub_ieee1275_devices_iterate (grub_cmos_find_port_iter); + if (!grub_cmos_port) + return grub_error (GRUB_ERR_IO, "no cmos found"); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/ieee1275/datetime.c b/grub-core/lib/ieee1275/datetime.c new file mode 100644 index 0000000..b81fba2 --- /dev/null +++ b/grub-core/lib/ieee1275/datetime.c @@ -0,0 +1,156 @@ +/* kern/cmos_datetime.c - CMOS datetime function. + * + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/datetime.h> +#include <grub/ieee1275/ieee1275.h> +#include <grub/misc.h> +#include <grub/dl.h> +#if defined (__powerpc__) || defined (__sparc__) +#include <grub/cmos.h> +#endif + +GRUB_MOD_LICENSE ("GPLv3+"); + +static char *rtc = 0; +static int no_ieee1275_rtc = 0; + +/* Helper for find_rtc. */ +static int +find_rtc_iter (struct grub_ieee1275_devalias *alias) +{ + if (grub_strcmp (alias->type, "rtc") == 0) + { + grub_dprintf ("datetime", "Found RTC %s\n", alias->path); + rtc = grub_strdup (alias->path); + return 1; + } + return 0; +} + +static void +find_rtc (void) +{ + grub_ieee1275_devices_iterate (find_rtc_iter); + if (!rtc) + no_ieee1275_rtc = 1; +} + +grub_err_t +grub_get_datetime (struct grub_datetime *datetime) +{ + struct get_time_args + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t device; + grub_ieee1275_cell_t catch_result; + grub_ieee1275_cell_t year; + grub_ieee1275_cell_t month; + grub_ieee1275_cell_t day; + grub_ieee1275_cell_t hour; + grub_ieee1275_cell_t minute; + grub_ieee1275_cell_t second; + } + args; + int status; + grub_ieee1275_ihandle_t ihandle; + + if (no_ieee1275_rtc) + return grub_get_datetime_cmos (datetime); + if (!rtc) + find_rtc (); + if (!rtc) + return grub_get_datetime_cmos (datetime); + + status = grub_ieee1275_open (rtc, &ihandle); + if (status == -1) + return grub_error (GRUB_ERR_IO, "couldn't open RTC"); + + INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 7); + args.device = (grub_ieee1275_cell_t) ihandle; + args.method = (grub_ieee1275_cell_t) "get-time"; + + status = IEEE1275_CALL_ENTRY_FN (&args); + + grub_ieee1275_close (ihandle); + + if (status == -1 || args.catch_result) + return grub_error (GRUB_ERR_IO, "get-time failed"); + + datetime->year = args.year; + datetime->month = args.month; + datetime->day = args.day + 1; + datetime->hour = args.hour; + datetime->minute = args.minute; + datetime->second = args.second; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_set_datetime (struct grub_datetime *datetime) +{ + struct set_time_args + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t device; + grub_ieee1275_cell_t year; + grub_ieee1275_cell_t month; + grub_ieee1275_cell_t day; + grub_ieee1275_cell_t hour; + grub_ieee1275_cell_t minute; + grub_ieee1275_cell_t second; + grub_ieee1275_cell_t catch_result; + } + args; + int status; + grub_ieee1275_ihandle_t ihandle; + + if (no_ieee1275_rtc) + return grub_set_datetime_cmos (datetime); + if (!rtc) + find_rtc (); + if (!rtc) + return grub_set_datetime_cmos (datetime); + + status = grub_ieee1275_open (rtc, &ihandle); + if (status == -1) + return grub_error (GRUB_ERR_IO, "couldn't open RTC"); + + INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 1); + args.device = (grub_ieee1275_cell_t) ihandle; + args.method = (grub_ieee1275_cell_t) "set-time"; + + args.year = datetime->year; + args.month = datetime->month; + args.day = datetime->day - 1; + args.hour = datetime->hour; + args.minute = datetime->minute; + args.second = datetime->second; + + status = IEEE1275_CALL_ENTRY_FN (&args); + + grub_ieee1275_close (ihandle); + + if (status == -1 || args.catch_result) + return grub_error (GRUB_ERR_IO, "set-time failed"); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/ieee1275/halt.c b/grub-core/lib/ieee1275/halt.c new file mode 100644 index 0000000..8fc16d2 --- /dev/null +++ b/grub-core/lib/ieee1275/halt.c @@ -0,0 +1,33 @@ +/* openfw.c -- Open firmware support functions. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/ieee1275/ieee1275.h> +#include <grub/misc.h> + +void +grub_halt (void) +{ + /* Not standardized. We try three known commands. */ + + grub_ieee1275_interpret ("power-off", 0); + grub_ieee1275_interpret ("shut-down", 0); + grub_ieee1275_interpret ("poweroff", 0); + + while (1); +} diff --git a/grub-core/lib/ieee1275/reboot.c b/grub-core/lib/ieee1275/reboot.c new file mode 100644 index 0000000..91c8779 --- /dev/null +++ b/grub-core/lib/ieee1275/reboot.c @@ -0,0 +1,27 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/ieee1275/ieee1275.h> +#include <grub/misc.h> + +void +grub_reboot (void) +{ + grub_ieee1275_interpret ("reset-all", 0); + for (;;) ; +} diff --git a/grub-core/lib/ieee1275/relocator.c b/grub-core/lib/ieee1275/relocator.c new file mode 100644 index 0000000..c6dd8fa --- /dev/null +++ b/grub-core/lib/ieee1275/relocator.c @@ -0,0 +1,114 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/relocator.h> +#include <grub/relocator_private.h> +#include <grub/memory.h> +#include <grub/ieee1275/ieee1275.h> + +/* Helper for grub_relocator_firmware_get_max_events. */ +static int +count (grub_uint64_t addr __attribute__ ((unused)), + grub_uint64_t len __attribute__ ((unused)), + grub_memory_type_t type __attribute__ ((unused)), void *data) +{ + int *counter = data; + + (*counter)++; + return 0; +} + +unsigned +grub_relocator_firmware_get_max_events (void) +{ + int counter = 0; + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) + return 0; + grub_machine_mmap_iterate (count, &counter); + return 2 * counter; +} + +/* Context for grub_relocator_firmware_fill_events. */ +struct grub_relocator_firmware_fill_events_ctx +{ + struct grub_relocator_mmap_event *events; + int counter; +}; + +/* Helper for grub_relocator_firmware_fill_events. */ +static int +grub_relocator_firmware_fill_events_iter (grub_uint64_t addr, + grub_uint64_t len, + grub_memory_type_t type, void *data) +{ + struct grub_relocator_firmware_fill_events_ctx *ctx = data; + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) + { + if (addr + len <= 0x180000) + return 0; + + if (addr < 0x180000) + { + len = addr + len - 0x180000; + addr = 0x180000; + } + } + + ctx->events[ctx->counter].type = REG_FIRMWARE_START; + ctx->events[ctx->counter].pos = addr; + ctx->counter++; + ctx->events[ctx->counter].type = REG_FIRMWARE_END; + ctx->events[ctx->counter].pos = addr + len; + ctx->counter++; + + return 0; +} + +unsigned +grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) +{ + struct grub_relocator_firmware_fill_events_ctx ctx = { + .events = events, + .counter = 0 + }; + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM)) + return 0; + grub_machine_mmap_iterate (grub_relocator_firmware_fill_events_iter, &ctx); + return ctx.counter; +} + +int +grub_relocator_firmware_alloc_region (grub_addr_t start, grub_size_t size) +{ + grub_err_t err; + err = grub_claimmap (start, size); + grub_errno = 0; + return (err == 0); +} + +void +grub_relocator_firmware_free_region (grub_addr_t start, grub_size_t size) +{ + grub_ieee1275_release (start, size); +} diff --git a/grub-core/lib/json/jsmn.h b/grub-core/lib/json/jsmn.h new file mode 100644 index 0000000..3178dcc --- /dev/null +++ b/grub-core/lib/json/jsmn.h @@ -0,0 +1,471 @@ +/* + * MIT License + * + * Copyright (c) 2010 Serge Zaitsev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef JSMN_H +#define JSMN_H + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef JSMN_STATIC +#define JSMN_API static +#else +#define JSMN_API extern +#endif + +/** + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ +typedef enum { + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1, + JSMN_ARRAY = 2, + JSMN_STRING = 3, + JSMN_PRIMITIVE = 4 +} jsmntype_t; + +enum jsmnerr { + /* Not enough tokens were provided */ + JSMN_ERROR_NOMEM = -1, + /* Invalid character inside JSON string */ + JSMN_ERROR_INVAL = -2, + /* The string is not a full JSON packet, more bytes expected */ + JSMN_ERROR_PART = -3 +}; + +/** + * JSON token description. + * type type (object, array, string etc.) + * start start position in JSON data string + * end end position in JSON data string + */ +typedef struct jsmntok { + jsmntype_t type; + int start; + int end; + int size; +#ifdef JSMN_PARENT_LINKS + int parent; +#endif +} jsmntok_t; + +/** + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string. + */ +typedef struct jsmn_parser { + unsigned int pos; /* offset in the JSON string */ + unsigned int toknext; /* next token to allocate */ + int toksuper; /* superior token node, e.g. parent object or array */ +} jsmn_parser; + +/** + * Create JSON parser over an array of tokens + */ +JSMN_API void jsmn_init(jsmn_parser *parser); + +/** + * Run JSON parser. It parses a JSON data string into and array of tokens, each + * describing + * a single JSON object. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens); + +#ifndef JSMN_HEADER +/** + * Allocates a fresh unused token from the token pool. + */ +static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *tok; + if (parser->toknext >= num_tokens) { + return NULL; + } + tok = &tokens[parser->toknext++]; + tok->start = tok->end = -1; + tok->size = 0; +#ifdef JSMN_PARENT_LINKS + tok->parent = -1; +#endif + return tok; +} + +/** + * Fills token type and boundaries. + */ +static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, + const int start, const int end) { + token->type = type; + token->start = start; + token->end = end; + token->size = 0; +} + +/** + * Fills next available token with JSON primitive. + */ +static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + int start; + + start = parser->pos; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + switch (js[parser->pos]) { +#ifndef JSMN_STRICT + /* In strict mode primitive must be followed by "," or "}" or "]" */ + case ':': +#endif + case '\t': + case '\r': + case '\n': + case ' ': + case ',': + case ']': + case '}': + goto found; + default: + /* to quiet a warning from gcc*/ + break; + } + if (js[parser->pos] < 32 || js[parser->pos] >= 127) { + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } +#ifdef JSMN_STRICT + /* In strict mode primitive must be followed by a comma/object/array */ + parser->pos = start; + return JSMN_ERROR_PART; +#endif + +found: + if (tokens == NULL) { + parser->pos--; + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + parser->pos--; + return 0; +} + +/** + * Fills next token with JSON string. + */ +static int jsmn_parse_string(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + + int start = parser->pos; + + parser->pos++; + + /* Skip starting quote */ + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c = js[parser->pos]; + + /* Quote: end of string */ + if (c == '\"') { + if (tokens == NULL) { + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + return 0; + } + + /* Backslash: Quoted symbol expected */ + if (c == '\\' && parser->pos + 1 < len) { + int i; + parser->pos++; + switch (js[parser->pos]) { + /* Allowed escaped symbols */ + case '\"': + case '/': + case '\\': + case 'b': + case 'f': + case 'r': + case 'n': + case 't': + break; + /* Allows escaped symbol \uXXXX */ + case 'u': + parser->pos++; + for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; + i++) { + /* If it isn't a hex character we have an error */ + if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ + (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ + (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ + parser->pos = start; + return JSMN_ERROR_INVAL; + } + parser->pos++; + } + parser->pos--; + break; + /* Unexpected symbol */ + default: + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } + } + parser->pos = start; + return JSMN_ERROR_PART; +} + +/** + * Parse JSON string and fill tokens. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens) { + int r; + int i; + jsmntok_t *token; + int count = parser->toknext; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c; + jsmntype_t type; + + c = js[parser->pos]; + switch (c) { + case '{': + case '[': + count++; + if (tokens == NULL) { + break; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + return JSMN_ERROR_NOMEM; + } + if (parser->toksuper != -1) { + jsmntok_t *t = &tokens[parser->toksuper]; +#ifdef JSMN_STRICT + /* In strict mode an object or array can't become a key */ + if (t->type == JSMN_OBJECT) { + return JSMN_ERROR_INVAL; + } +#endif + t->size++; +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + } + token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); + token->start = parser->pos; + parser->toksuper = parser->toknext - 1; + break; + case '}': + case ']': + if (tokens == NULL) { + break; + } + type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); +#ifdef JSMN_PARENT_LINKS + if (parser->toknext < 1) { + return JSMN_ERROR_INVAL; + } + token = &tokens[parser->toknext - 1]; + for (;;) { + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + token->end = parser->pos + 1; + parser->toksuper = token->parent; + break; + } + if (token->parent == -1) { + if (token->type != type || parser->toksuper == -1) { + return JSMN_ERROR_INVAL; + } + break; + } + token = &tokens[token->parent]; + } +#else + for (i = parser->toknext - 1; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + parser->toksuper = -1; + token->end = parser->pos + 1; + break; + } + } + /* Error if unmatched closing bracket */ + if (i == -1) { + return JSMN_ERROR_INVAL; + } + for (; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + parser->toksuper = i; + break; + } + } +#endif + break; + case '\"': + r = jsmn_parse_string(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + case '\t': + case '\r': + case '\n': + case ' ': + break; + case ':': + parser->toksuper = parser->toknext - 1; + break; + case ',': + if (tokens != NULL && parser->toksuper != -1 && + tokens[parser->toksuper].type != JSMN_ARRAY && + tokens[parser->toksuper].type != JSMN_OBJECT) { +#ifdef JSMN_PARENT_LINKS + parser->toksuper = tokens[parser->toksuper].parent; +#else + for (i = parser->toknext - 1; i >= 0; i--) { + if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { + if (tokens[i].start != -1 && tokens[i].end == -1) { + parser->toksuper = i; + break; + } + } + } +#endif + } + break; +#ifdef JSMN_STRICT + /* In strict mode primitives are: numbers and booleans */ + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 't': + case 'f': + case 'n': + /* And they must not be keys of the object */ + if (tokens != NULL && parser->toksuper != -1) { + const jsmntok_t *t = &tokens[parser->toksuper]; + if (t->type == JSMN_OBJECT || + (t->type == JSMN_STRING && t->size != 0)) { + return JSMN_ERROR_INVAL; + } + } +#else + /* In non-strict mode every unquoted value is a primitive */ + default: +#endif + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + +#ifdef JSMN_STRICT + /* Unexpected char in strict mode */ + default: + return JSMN_ERROR_INVAL; +#endif + } + } + + if (tokens != NULL) { + for (i = parser->toknext - 1; i >= 0; i--) { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) { + return JSMN_ERROR_PART; + } + } + } + + return count; +} + +/** + * Creates a new parser based over a given buffer with an array of tokens + * available. + */ +JSMN_API void jsmn_init(jsmn_parser *parser) { + parser->pos = 0; + parser->toknext = 0; + parser->toksuper = -1; +} + +#endif /* JSMN_HEADER */ + +#ifdef __cplusplus +} +#endif + +#endif /* JSMN_H */ diff --git a/grub-core/lib/json/json.c b/grub-core/lib/json/json.c new file mode 100644 index 0000000..1c20c75 --- /dev/null +++ b/grub-core/lib/json/json.c @@ -0,0 +1,264 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2019 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/dl.h> +#include <grub/mm.h> + +#define JSMN_STATIC +#include "jsmn.h" +#include "json.h" + +GRUB_MOD_LICENSE ("GPLv3"); + +grub_err_t +grub_json_parse (grub_json_t **out, char *string, grub_size_t string_len) +{ + grub_json_t *json = NULL; + jsmn_parser parser; + grub_err_t ret = GRUB_ERR_NONE; + int jsmn_ret; + + if (!string) + return GRUB_ERR_BAD_ARGUMENT; + + json = grub_zalloc (sizeof (*json)); + if (!json) + return GRUB_ERR_OUT_OF_MEMORY; + json->string = string; + + /* + * Parse the string twice: first to determine how many tokens + * we need to allocate, second to fill allocated tokens. + */ + jsmn_init (&parser); + jsmn_ret = jsmn_parse (&parser, string, string_len, NULL, 0); + if (jsmn_ret <= 0) + { + ret = GRUB_ERR_BAD_ARGUMENT; + goto err; + } + + json->tokens = grub_calloc (jsmn_ret, sizeof (jsmntok_t)); + if (!json->tokens) + { + ret = GRUB_ERR_OUT_OF_MEMORY; + goto err; + } + + jsmn_init (&parser); + jsmn_ret = jsmn_parse (&parser, string, string_len, json->tokens, jsmn_ret); + if (jsmn_ret <= 0) + { + ret = GRUB_ERR_BAD_ARGUMENT; + goto err; + } + + *out = json; + + err: + if (ret) + grub_json_free (json); + + return ret; +} + +void +grub_json_free (grub_json_t *json) +{ + if (json) + { + grub_free (json->tokens); + grub_free (json); + } +} + +grub_err_t +grub_json_getsize (grub_size_t *out, const grub_json_t *json) +{ + int size; + + size = json->tokens[json->idx].size; + if (size < 0) + return GRUB_ERR_OUT_OF_RANGE; + + *out = (grub_size_t) size; + return GRUB_ERR_NONE; +} + +grub_err_t +grub_json_gettype (grub_json_type_t *out, const grub_json_t *json) +{ + switch (json->tokens[json->idx].type) + { + case JSMN_OBJECT: + *out = GRUB_JSON_OBJECT; + break; + case JSMN_ARRAY: + *out = GRUB_JSON_ARRAY; + break; + case JSMN_STRING: + *out = GRUB_JSON_STRING; + break; + case JSMN_PRIMITIVE: + *out = GRUB_JSON_PRIMITIVE; + break; + default: + return GRUB_ERR_BAD_ARGUMENT; + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_json_getchild (grub_json_t *out, const grub_json_t *parent, grub_size_t n) +{ + grub_size_t offset = 1, size; + jsmntok_t *p; + + if (grub_json_getsize (&size, parent) || n >= size) + return GRUB_ERR_OUT_OF_RANGE; + + /* + * Skip the first n children. For each of the children, we need + * to skip their own potential children (e.g. if it's an + * array), as well. We thus add the children's size to n on + * each iteration. + */ + p = &parent->tokens[parent->idx]; + while (n--) + n += p[offset++].size; + + out->string = parent->string; + out->tokens = parent->tokens; + out->idx = parent->idx + offset; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_json_getvalue (grub_json_t *out, const grub_json_t *parent, const char *key) +{ + grub_json_type_t type; + grub_size_t i, size; + + if (grub_json_gettype (&type, parent) || type != GRUB_JSON_OBJECT) + return GRUB_ERR_BAD_ARGUMENT; + + if (grub_json_getsize (&size, parent)) + return GRUB_ERR_BAD_ARGUMENT; + + for (i = 0; i < size; i++) + { + grub_json_t child; + const char *s; + + if (grub_json_getchild (&child, parent, i) || + grub_json_getstring (&s, &child, NULL) || + grub_strcmp (s, key) != 0) + continue; + + return grub_json_getchild (out, &child, 0); + } + + return GRUB_ERR_FILE_NOT_FOUND; +} + +static grub_err_t +get_value (grub_json_type_t *out_type, const char **out_string, const grub_json_t *parent, const char *key) +{ + const grub_json_t *p = parent; + grub_json_t child; + grub_err_t ret; + jsmntok_t *tok; + + if (key) + { + ret = grub_json_getvalue (&child, parent, key); + if (ret) + return ret; + p = &child; + } + + tok = &p->tokens[p->idx]; + p->string[tok->end] = '\0'; + + *out_string = p->string + tok->start; + + return grub_json_gettype (out_type, p); +} + +grub_err_t +grub_json_getstring (const char **out, const grub_json_t *parent, const char *key) +{ + grub_json_type_t type; + const char *value; + grub_err_t ret; + + ret = get_value (&type, &value, parent, key); + if (ret) + return ret; + if (type != GRUB_JSON_STRING) + return GRUB_ERR_BAD_ARGUMENT; + + *out = value; + return GRUB_ERR_NONE; +} + +grub_err_t +grub_json_getuint64 (grub_uint64_t *out, const grub_json_t *parent, const char *key) +{ + grub_json_type_t type; + const char *value; + const char *end; + grub_err_t ret; + + ret = get_value (&type, &value, parent, key); + if (ret) + return ret; + if (type != GRUB_JSON_STRING && type != GRUB_JSON_PRIMITIVE) + return GRUB_ERR_BAD_ARGUMENT; + + grub_errno = GRUB_ERR_NONE; + *out = grub_strtoul (value, &end, 10); + if (grub_errno != GRUB_ERR_NONE || *end) + return GRUB_ERR_BAD_NUMBER; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_json_getint64 (grub_int64_t *out, const grub_json_t *parent, const char *key) +{ + grub_json_type_t type; + const char *value; + const char *end; + grub_err_t ret; + + ret = get_value (&type, &value, parent, key); + if (ret) + return ret; + if (type != GRUB_JSON_STRING && type != GRUB_JSON_PRIMITIVE) + return GRUB_ERR_BAD_ARGUMENT; + + grub_errno = GRUB_ERR_NONE; + *out = grub_strtol (value, &end, 10); + if (grub_errno != GRUB_ERR_NONE || *end) + return GRUB_ERR_BAD_NUMBER; + + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/json/json.h b/grub-core/lib/json/json.h new file mode 100644 index 0000000..4ea2a22 --- /dev/null +++ b/grub-core/lib/json/json.h @@ -0,0 +1,128 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2019 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_JSON_JSON_H +#define GRUB_JSON_JSON_H 1 + +#include <grub/types.h> + +enum grub_json_type +{ + /* Unordered collection of key-value pairs. */ + GRUB_JSON_OBJECT, + /* Ordered list of zero or more values. */ + GRUB_JSON_ARRAY, + /* Zero or more Unicode characters. */ + GRUB_JSON_STRING, + /* Number, boolean or empty value. */ + GRUB_JSON_PRIMITIVE, + /* Invalid token. */ + GRUB_JSON_UNDEFINED, +}; +typedef enum grub_json_type grub_json_type_t; + +/* Forward-declaration to avoid including jsmn.h. */ +struct jsmntok; + +struct grub_json +{ + struct jsmntok *tokens; + char *string; + grub_size_t idx; +}; +typedef struct grub_json grub_json_t; + +/* + * Parse a JSON-encoded string. Note that the string passed to + * this function will get modified on subsequent calls to + * grub_json_get*(). Returns the root object of the parsed JSON + * object, which needs to be free'd via grub_json_free(). Callers + * must ensure that the string outlives the returned root object, + * and that child objects must not be used after the root object + * has been free'd. + */ +extern grub_err_t EXPORT_FUNC(grub_json_parse) (grub_json_t **out, + char *string, + grub_size_t string_len); + +/* + * Free the structure and its contents. The string passed to + * grub_json_parse() will not be free'd. + */ +extern void EXPORT_FUNC(grub_json_free) (grub_json_t *json); + +/* + * Get the child count of a valid grub_json_t instance. Children + * are present for arrays, objects (dicts) and keys of a dict. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getsize) (grub_size_t *out, + const grub_json_t *json); + +/* Get the type of a valid grub_json_t instance. */ +extern grub_err_t EXPORT_FUNC(grub_json_gettype) (grub_json_type_t *out, + const grub_json_t *json); + +/* + * Get n'th child of a valid object, array or key. Will return an + * error if no such child exists. The result does not need to be + * free'd. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getchild) (grub_json_t *out, + const grub_json_t *parent, + grub_size_t n); + +/* + * Get value of key from a valid grub_json_t instance. The result + * does not need to be free'd. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getvalue) (grub_json_t *out, + const grub_json_t *parent, + const char *key); + +/* + * Get the string representation of a valid grub_json_t instance. + * If a key is given and parent is a JSON object, this function + * will return the string value of a child mapping to the key. + * If no key is given, it will return the string value of the + * parent itself. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getstring) (const char **out, + const grub_json_t *parent, + const char *key); + +/* + * Get the uint64 representation of a valid grub_json_t instance. + * Returns an error if the value pointed to by `parent` cannot be + * converted to an uint64. See grub_json_getstring() for details + * on the key parameter. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getuint64) (grub_uint64_t *out, + const grub_json_t *parent, + const char *key); + +/* + * Get the int64 representation of a valid grub_json_t instance. + * Returns an error if the value pointed to by `parent` cannot be + * converted to an int64. See grub_json_getstring() for + * details on the key parameter. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getint64) (grub_int64_t *out, + const grub_json_t *parent, + const char *key); + +#endif diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c new file mode 100644 index 0000000..05719ab --- /dev/null +++ b/grub-core/lib/legacy_parse.c @@ -0,0 +1,875 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2010,2012 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/types.h> +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/err.h> +#include <grub/legacy_parse.h> +#include <grub/i386/pc/vesa_modes_table.h> +#include <grub/i18n.h> + +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + +struct legacy_command +{ + const char *name; + const char *map; + const char *suffix; + unsigned suffixarg; + unsigned argc; + enum arg_type { + TYPE_VERBATIM, + TYPE_FORCE_OPTION, + TYPE_NOAPM_OPTION, + TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_OPTION, + TYPE_FILE, + TYPE_FILE_NO_CONSUME, + TYPE_PARTITION, + TYPE_BOOL, + TYPE_INT, + TYPE_REST_VERBATIM, + TYPE_VBE_MODE, + TYPE_WITH_CONFIGFILE_OPTION + } argt[4]; + enum { + FLAG_IGNORE_REST = 0x001, + FLAG_FALLBACK_AVAILABLE = 0x004, + FLAG_FALLBACK = 0x008, + FLAG_COLOR_INVERT = 0x010, + FLAG_NO_MENUENTRY = 0x020, + FLAG_MENUENTRY_ONLY = 0x040, + FLAG_TERMINAL = 0x080, + FLAG_TITLE = 0x100, + } flags; + const char *shortdesc; + const char *longdesc; +}; + +/* Help texts are kept here mostly for reference. They are never shown. So + no need to gettextize. + */ +static struct legacy_command legacy_commands[] = + { + /* FIXME: background unsupported. */ + {"blocklist", "blocklist '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", + "Print the blocklist notation of the file FILE."}, + {"boot", "boot\n", NULL, 0, 0, {}, 0, 0, + "Boot the OS/chain-loader which has been loaded."}, + {"bootp", "net_bootp; net_ls_addr; echo $\"" N_("Default server is ${net_default_server}") "\"; if [ x%s = x--with-configfile ]; then " + "if net_get_dhcp_option configfile_name pxe 150 string; then " + "configfile $configfile_name; fi; fi\n", NULL, 0, 1, + {TYPE_WITH_CONFIGFILE_OPTION}, FLAG_IGNORE_REST, "[--with-configfile]", + "Initialize a network device via BOOTP. If the option `--with-configfile'" + " is given, try to load a configuration file specified by the 150 vendor" + " tag."}, + /* FIXME: border unsupported. */ + {"cat", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", + "Print the contents of the file FILE."}, + {"chainloader", "chainloader %s '%s'\n", NULL, 0, + 2, {TYPE_FORCE_OPTION, TYPE_FILE}, 0, "[--force] FILE", + "Load the chain-loader FILE. If --force is specified, then load it" + " forcibly, whether the boot loader signature is present or not."}, + {"clear", "clear\n", NULL, 0, 0, {}, 0, 0, + "Clear the screen."}, + {"cmp", "cmp '%s' '%s'\n", NULL, 0, + 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST, "FILE1 FILE2", + "Compare the file FILE1 with the FILE2 and inform the different values" + " if any."}, + {"color", "set color_normal='%s'; set color_highlight='%s'\n", NULL, 0, + 2, {TYPE_VERBATIM, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE, "NORMAL [HIGHLIGHT]", + "Change the menu colors. The color NORMAL is used for most" + " lines in the menu, and the color HIGHLIGHT is used to highlight the" + " line where the cursor points. If you omit HIGHLIGHT, then the" + " inverted color of NORMAL is used for the highlighted line." + " The format of a color is \"FG/BG\". FG and BG are symbolic color names." + " A symbolic color name must be one of these: black, blue, green," + " cyan, red, magenta, brown, light-gray, dark-gray, light-blue," + " light-green, light-cyan, light-red, light-magenta, yellow and white." + " But only the first eight names can be used for BG. You can prefix" + " \"blink-\" to FG if you want a blinking foreground color."}, + {"color", "set color_normal='%s'; set color_highlight='%s'\n", NULL, 0, + 1, {TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_COLOR_INVERT, NULL, NULL}, + {"configfile", "legacy_configfile '%s'\n", NULL, 0, 1, {TYPE_FILE}, + 0, "FILE", "Load FILE as the configuration file."}, + {"debug", + "if [ -z \"$debug\" ]; then set debug=all; else set debug=; fi\n", NULL, 0, + 0, {}, 0, 0, "Turn on/off the debug mode."}, + {"default", + "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; " + "set default=\"$saved_entry\"; fi\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, + "[NUM | `saved']", + "Set the default entry to entry number NUM (if not specified, it is" + " 0, the first entry) or the entry number saved by savedefault."}, + {"dhcp", "net_bootp; net_ls_addr; if [ x%s = x--with-configfile ]; then " + "if net_get_dhcp_option configfile_name pxe 150 string; then " + "configfile $configfile_name; fi; fi\n", NULL, 0, 1, + {TYPE_WITH_CONFIGFILE_OPTION}, FLAG_IGNORE_REST, "[--with-configfile]", + "Initialize a network device via BOOTP. If the option `--with-configfile'" + " is given, try to load a configuration file specified by the 150 vendor" + " tag."}, + {"displayapm", "lsapm\n", NULL, 0, 0, {}, 0, 0, + "Display APM BIOS information."}, + {"displaymem", "lsmmap\n", NULL, 0, 0, {}, 0, 0, + "Display what GRUB thinks the system address space map of the" + " machine is, including all regions of physical RAM installed."}, + /* FIXME: device and efimap unsupported. */ + /* NOTE: embed unsupported. */ + {"fallback", "set fallback='%s'\n", NULL, 0, + 1, {TYPE_VERBATIM}, 0, "NUM...", + "Go into unattended boot mode: if the default boot entry has any" + " errors, instead of waiting for the user to do anything, it" + " immediately starts over using the NUM entry (same numbering as the" + " `default' command). This obviously won't help if the machine" + " was rebooted by a kernel that GRUB loaded."}, + {"find", "search -f '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILENAME", + "Search for the filename FILENAME in all of partitions and print the list of" + " the devices which contain the file."}, + /* FIXME: findiso unsupported. */ + /* FIXME: foreground unsupported. */ + /* FIXME: fstest unsupported. */ + /* NOTE: The obsolete C/H/S geometry isn't shown anymore. */ + {"geometry", "insmod regexp; ls -l (%s*)\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "DRIVE", + "Print the information for a drive DRIVE. "}, + {"halt", "halt %s\n", NULL, 0, 1, {TYPE_NOAPM_OPTION}, 0, "[--no-apm]", + "Halt your system. If APM is available on it, turn off the power using" + " the APM BIOS, unless you specify the option `--no-apm'."}, + /* FIXME: help unsupported. */ /* NUL_TERMINATE */ + {"hiddenmenu", NULL, + "if sleep -i $timeout; then timeout=0; else timeout=-1; fi\n", 0, + 0, {}, 0, "", "Hide the menu."}, + {"hide", "parttool '%s' hidden+\n", NULL, 0, 1, {TYPE_PARTITION}, + 0, "PARTITION", + "Hide PARTITION by setting the \"hidden\" bit in" + " its partition type code."}, + /* FIXME: ifconfig unsupported. */ + /* FIXME: impsprobe unsupported. */ + {"initrd", "legacy_initrd '%s' %s\n", NULL, 0, 2, {TYPE_FILE_NO_CONSUME, + TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "Load an initial ramdisk FILE for a Linux format boot image and set the" + " appropriate parameters in the Linux setup area in memory."}, + /* NOTE: install unsupported. */ + /* FIXME: ioprobe unsupported. */ + /* FIXME: really support --no-mem-option. */ + {"kernel", "legacy_kernel %s %s '%s' %s\n", NULL, 0, + 4, {TYPE_TYPE_OR_NOMEM_OPTION, TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, + "[--no-mem-option] [--type=TYPE] FILE [ARG ...]", + "Attempt to load the primary boot image from FILE. The rest of the" + " line is passed verbatim as the \"kernel command line\". Any modules" + " must be reloaded after using this command. The option --type is used" + " to suggest what type of kernel to be loaded. TYPE must be either of" + " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" + " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" + " Linux's mem option automatically."}, + {"lock", "if ! authenticate legacy; then return; fi", NULL, 0, 0, {}, 0, + 0, "Break a command execution unless the user is authenticated."}, + {"makeactive", "parttool \"$root\" boot+\n", NULL, 0, 0, {}, 0, 0, + "Set the active partition on the root disk to GRUB's root device." + " This command is limited to _primary_ PC partitions on a hard disk."}, + {"map", "drivemap '%s' '%s'\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_PARTITION}, + FLAG_IGNORE_REST, "TO_DRIVE FROM_DRIVE", + "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" + " when you chain-load some operating systems, such as DOS, if such an" + " OS resides at a non-first drive."}, + /* NOTE: md5crypt unsupported since GRUB has not enough entropy and this + hash shouldn't be used anymore. */ + {"module", "legacy_initrd '%s' %s\n", NULL, 0, 2, {TYPE_FILE_NO_CONSUME, + TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "Load a boot module FILE for a Multiboot format boot image (no" + " interpretation of the file contents is made, so users of this" + " command must know what the kernel in question expects). The" + " rest of the line is passed as the \"module command line\", like" + " the `kernel' command."}, + {"modulenounzip", "legacy_initrd_nounzip '%s' %s\n", NULL, 0, 2, + {TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "The same as `module', except that automatic decompression is" + " disabled."}, + {"pager", "set pager=%s; if [ \"$pager\" = 0 ]; then " + " echo Internal pager is now off; else " + "echo Internal pager is now on; fi\n", NULL, 0, + 1, {TYPE_BOOL}, FLAG_FALLBACK_AVAILABLE, "[FLAG]", + "Toggle pager mode with no argument. If FLAG is given and its value" + " is `on', turn on the mode. If FLAG is `off', turn off the mode."}, + {"pager", + "if [ \"$pager\" = 1 ]; then pager=0; echo Internal pager is now off;" + "else pager=1; echo Internal pager is now on; fi\n", NULL, 0, 0, {}, + FLAG_FALLBACK, NULL, NULL}, + /* FIXME: partnew unsupported. */ + {"parttype", "parttool '%s' type=%s\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_INT}, 0, + "PART TYPE", "Change the type of the partition PART to TYPE."}, + {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" + "legacy_password %s '%s'\n", + "menuentry \"Superuser menu\" --users \"legacy\" { configfile '%s'; }\n", + 2, 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE | FLAG_NO_MENUENTRY, + "[--md5] PASSWD [FILE]", + "If used in the first section of a menu file, disable all" + " interactive editing control (menu entry editor and" + " command line). If the password PASSWD is entered, it loads the" + " FILE as a new config file and restarts the GRUB Stage 2. If you" + " omit the argument FILE, then GRUB just unlocks privileged" + " instructions. You can also use it in the script section, in" + " which case it will ask for the password, before continuing." + " The option --md5 tells GRUB that PASSWD is encrypted with" + " md5crypt."}, + {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" + "legacy_password %s '%s'\n", NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_NO_MENUENTRY, NULL, NULL}, + {"password", "if legacy_check_password %s '%s'; then configfile '%s'; " + "else return; fi\n", NULL, 2, 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE | FLAG_MENUENTRY_ONLY, + NULL, NULL}, + {"password", "if ! legacy_check_password %s '%s'; then return fi;\n", + NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_MENUENTRY_ONLY, NULL, NULL}, + /* NOTE: GRUB2 has a design principle of not eternally waiting for user + input. 60 seconds should be enough. + */ + {"pause", "echo %s; if ! sleep -i 60; then return; fi\n", NULL, 0, 1, + {TYPE_REST_VERBATIM}, 0, + "[MESSAGE ...]", "Print MESSAGE, then wait until a key is pressed."}, + {"print", "echo %s\n", NULL, 0, 1, + {TYPE_REST_VERBATIM}, 0, + "[MESSAGE ...]", "Print MESSAGE."}, + /* FIXME: quit unsupported. */ + /* FIXME: rarp unsupported. */ + {"read", "read_dword %s\n", NULL, 0, 1, {TYPE_INT}, 0, "ADDR", + "Read a 32-bit value from memory at address ADDR and" + " display it in hex format."}, + {"reboot", "reboot\n", NULL, 0, 0, {}, 0, 0, "Reboot your system."}, + {"root", "set root='%s'; set legacy_hdbias='%s'\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_INT}, FLAG_FALLBACK_AVAILABLE, + "[DEVICE [HDBIAS]]", + "Set the current \"root device\" to the device DEVICE, then" + " attempt to mount it to get the partition size (for passing the" + " partition descriptor in `ES:ESI', used by some chain-loaded" + " bootloaders), the BSD drive-type (for booting BSD kernels using" + " their native boot format), and correctly determine " + " the PC partition where a BSD sub-partition is located. The" + " optional HDBIAS parameter is a number to tell a BSD kernel" + " how many BIOS drive numbers are on controllers before the current" + " one. For example, if there is an IDE disk and a SCSI disk, and your" + " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."}, + {"root", "echo \"$root\"\n", NULL, 0, 0, {}, FLAG_FALLBACK, NULL, NULL}, + {"rootnoverify", "set root='%s'; set legacy_hdbias='%s'\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_INT}, 0, + "[DEVICE [HDBIAS]]", + "Similar to `root', but don't attempt to mount the partition. This" + " is useful for when an OS is outside of the area of the disk that" + " GRUB can read, but setting the correct root device is still" + " desired. Note that the items mentioned in `root' which" + " derived from attempting the mount will NOT work correctly."}, + {"rootnoverify", "echo \"$root\"\n", NULL, 0, + 0, {}, FLAG_FALLBACK, NULL, NULL}, + /* FIXME: support saving NUM and fallback. */ + {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", NULL, 0, + 0, {}, 0, "[NUM | `fallback']", + "Save the current entry as the default boot entry if no argument is" + " specified. If a number is specified, this number is saved. If" + " `fallback' is used, next fallback entry is saved."}, + {"serial", "serial %s\n", NULL, 0, 1, {TYPE_REST_VERBATIM}, 0, + "[--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] " + "[--parity=PARITY] [--stop=STOP] [--device=DEV]", + "Initialize a serial device. UNIT is a digit that specifies which serial" + " device is used (e.g. 0 == COM1). If you need to specify the port number," + " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," + " PARITY is the type of parity, which is one of `no', `odd' and `even'." + " STOP is the length of stop bit(s). The option --device can be used only" + " in the grub shell, which specifies the file name of a tty device. The" + " default values are COM1, 9600, 8N1."}, + /* FIXME: shade unsupported. */ + /* FIXME: silent unsupported. */ + /* FIXME: splashimage unsupported. */ + /* FIXME: setkey unsupported. */ /* NUL_TERMINATE */ + /* NOTE: setup unsupported. */ + /* FIXME: --no-echo, --no-edit unsupported. */ + /* NOTE: both terminals are activated so --silent and --timeout + are useless. */ + /* FIXME: graphics unsupported. */ + {"terminal", NULL, NULL, 0, 0, {}, FLAG_TERMINAL | FLAG_IGNORE_REST, + "[--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] " + "[--silent] [console] [serial] [hercules] [graphics]", + "Select a terminal. When multiple terminals are specified, wait until" + " you push any key to continue. If both console and serial are specified," + " the terminal to which you input a key first will be selected. If no" + " argument is specified, print current setting. The option --dumb" + " specifies that your terminal is dumb, otherwise, vt100-compatibility" + " is assumed. If you specify --no-echo, input characters won't be echoed." + " If you specify --no-edit, the BASH-like editing feature will be disabled." + " If --timeout is present, this command will wait at most for SECS" + " seconds. The option --lines specifies the maximum number of lines." + " The option --silent is used to suppress messages."}, + /* FIXME: terminfo unsupported. */ /* NUL_TERMINATE */ + {"testload", "testload '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", + "Read the entire contents of FILE in several different ways and" + " compares them, to test the filesystem code. " + " If this test succeeds, then a good next" + " step is to try loading a kernel."}, + {"testvbe", "insmod vbe; videotest '%s'\n", NULL, 0, 1, {TYPE_VBE_MODE}, 0, + "MODE", "Test the VBE mode MODE. Hit any key to return."}, + /* FIXME: tftpserver unsupported. */ + {"timeout", "set timeout=%s\n", NULL, 0, 1, {TYPE_INT}, 0, "SEC", + "Set a timeout, in SEC seconds, before automatically booting the" + " default entry (normally the first entry defined)."}, + {"title", NULL, NULL, 0, 0, {}, FLAG_TITLE, "NAME ...", + "Start a new boot entry, and set its name to the contents of the" + " rest of the line, starting with the first non-space character."}, + {"unhide", "parttool '%s' hidden-\n", NULL, 0, + 1, {TYPE_PARTITION}, 0, "PARTITION", + "Unhide PARTITION by clearing the \"hidden\" bit in its" + " partition type code."}, + /* FIXME: uppermem unsupported. */ + {"uuid", "search --set=root --fs-uuid '%s'\n", NULL, 0, 1, {TYPE_VERBATIM}, + 0, "UUID", "Find root by UUID"}, + {"vbeprobe", "insmod vbe; videoinfo '%s'\n", NULL, 0, 1, {TYPE_VBE_MODE}, + FLAG_FALLBACK_AVAILABLE, "[MODE]", + "Probe VBE information. If the mode number MODE is specified, show only" + " the information about only the mode."}, + {"vbeprobe", "insmod vbe; videoinfo\n", NULL, 0, 0, {}, + FLAG_FALLBACK, NULL, NULL} + /* FIXME: verbose unsupported. */ + /* FIXME: version unsupported. */ + /* FIXME: viewport unsupported. */ + }; + +char * +grub_legacy_escape (const char *in, grub_size_t len) +{ + char *ptr; + char *ret; + char saved; + int overhead = 0; + + for (ptr = (char*)in; ptr < in + len && *ptr; ptr++) + if (*ptr == '\'') + overhead += 3; + ret = grub_malloc (ptr - in + overhead + 1); + if (!ret) + return NULL; + + ptr = (char*)in; + saved = ptr[len]; + ptr[len] = '\0'; + grub_strchrsub (ret, ptr, '\'', "'\\''"); + ptr[len] = saved; + return ret; +} + +static char * +adjust_file (const char *in, grub_size_t len) +{ + const char *comma, *ptr, *rest; + char *ret, *outptr; + int overhead = 0; + int part = -1, subpart = -1; + if (in[0] != '(') + return grub_legacy_escape (in, len); + for (ptr = in + 1; ptr < in + len && *ptr && *ptr != ')' + && *ptr != ','; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + comma = ptr; + if (*comma == ')' && comma - in == 3 + && in[1] == 'n' && in[2] == 'd') + { + rest = comma + 1; + for (ptr = rest; ptr < in + len && *ptr; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + + ret = grub_malloc (ptr - in + overhead + 15); + if (!ret) + return NULL; + + outptr = grub_stpcpy (ret, "(tftp)");; + for (ptr = rest; ptr < in + len; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + *outptr = 0; + return ret; + } + if (*comma != ',') + return grub_legacy_escape (in, len); + part = grub_strtoull (comma + 1, &rest, 0); + if (rest[0] == ',' && rest[1] >= 'a' && rest[1] <= 'z') + { + subpart = rest[1] - 'a'; + rest += 2; + } + for (ptr = rest; ptr < in + len && *ptr; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + + /* 35 is enough for any 2 numbers. */ + ret = grub_malloc (ptr - in + overhead + 35 + 5); + if (!ret) + return NULL; + + outptr = ret; + for (ptr = in; ptr < in + len && ptr <= comma; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + if (subpart != -1) + grub_snprintf (outptr, 35, "%d,%d", part + 1, subpart + 1); + else + grub_snprintf (outptr, 35, "%d", part + 1); + while (*outptr) + outptr++; + for (ptr = rest; ptr < in + len; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + *outptr = 0; + return ret; +} + +static int +check_option (const char *a, const char *b, grub_size_t len) +{ + if (grub_strlen (b) != len) + return 0; + return grub_strncmp (a, b, len) == 0; +} + +static int +is_option (enum arg_type opt, const char *curarg, grub_size_t len) +{ + switch (opt) + { + case TYPE_WITH_CONFIGFILE_OPTION: + return check_option (curarg, "--with-configfile", len); + case TYPE_NOAPM_OPTION: + return check_option (curarg, "--no-apm", len); + case TYPE_FORCE_OPTION: + return check_option (curarg, "--force", len); + case TYPE_TYPE_OR_NOMEM_OPTION: + return check_option (curarg, "--type=netbsd", len) + || check_option (curarg, "--type=freebsd", len) + || check_option (curarg, "--type=openbsd", len) + || check_option (curarg, "--type=linux", len) + || check_option (curarg, "--type=biglinux", len) + || check_option (curarg, "--type=multiboot", len) + || check_option (curarg, "--no-mem-option", len); + case TYPE_OPTION: + return (len >= 2 && curarg[0] == '-' && curarg[1] == '-'); + default: + return 0; + } +} + +char * +grub_legacy_parse (const char *buf, char **entryname, char **suffix) +{ + const char *ptr; + const char *cmdname; + unsigned i, cmdnum; + char *args[ARRAY_SIZE (legacy_commands[0].argt)]; + + *suffix = NULL; + + for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); + if (!*ptr || *ptr == '#') + { + char *ret; + int len = grub_strlen (buf); + ret = grub_malloc (len + 2); + grub_memcpy (ret, buf, len); + if (len && ret[len - 1] == '\n') + ret[len] = 0; + else + { + ret[len] = '\n'; + ret[len + 1] = 0; + } + return ret; + } + + cmdname = ptr; + for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++); + + for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++) + if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0 + && legacy_commands[cmdnum].name[ptr - cmdname] == 0 + && (!(*entryname != NULL && (legacy_commands[cmdnum].flags + & FLAG_NO_MENUENTRY))) + && (!(*entryname == NULL && (legacy_commands[cmdnum].flags + & FLAG_MENUENTRY_ONLY)))) + break; + if (cmdnum == ARRAY_SIZE (legacy_commands)) + return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); + + for (; grub_isspace (*ptr) || *ptr == '='; ptr++); + + if (legacy_commands[cmdnum].flags & FLAG_TITLE) + { + const char *ptr2; + ptr2 = ptr + grub_strlen (ptr); + while (ptr2 > ptr && grub_isspace (*(ptr2 - 1))) + ptr2--; + *entryname = grub_strndup (ptr, ptr2 - ptr); + return NULL; + } + + if (legacy_commands[cmdnum].flags & FLAG_TERMINAL) + { + int dumb = 0, lines = 24; +#ifdef TODO + int no_echo = 0, no_edit = 0; +#endif + int hercules = 0; + int console = 0, serial = 0, graphics = 0; + /* Big enough for any possible resulting command. */ + char outbuf[512] = ""; + char *outptr; + while (*ptr) + { + /* "[--timeout=SECS] [--silent]" + " [console] [serial] [hercules]"*/ + if (grub_memcmp (ptr, "--dumb", sizeof ("--dumb") - 1) == 0) + dumb = 1; +#ifdef TODO + if (grub_memcmp (ptr, "--no-echo", sizeof ("--no-echo") - 1) == 0) + no_echo = 1; + + if (grub_memcmp (ptr, "--no-edit", sizeof ("--no-edit") - 1) == 0) + no_edit = 1; +#endif + if (grub_memcmp (ptr, "--lines=", sizeof ("--lines=") - 1) == 0) + { + lines = grub_strtoul (ptr + sizeof ("--lines=") - 1, 0, 0); + if (grub_errno) + { + lines = 24; + grub_errno = GRUB_ERR_NONE; + } + } + + if (grub_memcmp (ptr, "console", sizeof ("console") - 1) == 0) + console = 1; + + if (grub_memcmp (ptr, "serial", sizeof ("serial") - 1) == 0) + serial = 1; + if (grub_memcmp (ptr, "hercules", sizeof ("hercules") - 1) == 0) + hercules = 1; + if (grub_memcmp (ptr, "graphics", sizeof ("graphics") - 1) == 0) + graphics = 1; + while (*ptr && !grub_isspace (*ptr)) + ptr++; + while (*ptr && grub_isspace (*ptr)) + ptr++; + } + + if (!console && !serial && !hercules && !graphics) + return grub_strdup ("terminal_input; terminal_output; terminfo\n"); + + outptr = outbuf; + + if (graphics) + outptr = grub_stpcpy (outptr, "insmod all_video; "); + + outptr = grub_stpcpy (outptr, "terminal_input "); + if (serial) + outptr = grub_stpcpy (outptr, "serial "); + if (console || hercules || graphics) + outptr = grub_stpcpy (outptr, "console "); + outptr = grub_stpcpy (outptr, "; terminal_output "); + if (serial) + outptr = grub_stpcpy (outptr, "serial "); + if (console) + outptr = grub_stpcpy (outptr, "console "); + if (hercules) + outptr = grub_stpcpy (outptr, "mda_text "); + if (graphics) + outptr = grub_stpcpy (outptr, "gfxterm "); + outptr = grub_stpcpy (outptr, "; "); + *outptr = '\0'; + if (serial) + { + grub_snprintf (outptr, outbuf + sizeof (outbuf) - outptr, + "terminfo serial -g 80x%d %s; ", + lines, dumb ? "dumb" : "vt100"); + outptr += grub_strlen (outptr); + } + + grub_strcpy (outptr, "\n"); + + return grub_strdup (outbuf); + } + + grub_memset (args, 0, sizeof (args)); + + { + int hold_arg = 0; + const char *curarg = NULL; + for (i = 0; i < legacy_commands[cmdnum].argc; i++) + { + grub_size_t curarglen; + if (hold_arg) + { + ptr = curarg; + hold_arg = 0; + } + for (; grub_isspace (*ptr); ptr++); + curarg = ptr; + if (!*curarg) + break; + for (; *ptr && !grub_isspace (*ptr); ptr++); + if (i != legacy_commands[cmdnum].argc - 1 + || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST)) + curarglen = ptr - curarg; + else + { + curarglen = grub_strlen (curarg); + while (curarglen > 0 && grub_isspace (curarg[curarglen - 1])) + curarglen--; + } + if (*ptr) + ptr++; + switch (legacy_commands[cmdnum].argt[i]) + { + case TYPE_FILE_NO_CONSUME: + hold_arg = 1; + /* Fallthrough. */ + case TYPE_PARTITION: + case TYPE_FILE: + args[i] = adjust_file (curarg, curarglen); + break; + + case TYPE_REST_VERBATIM: + { + char *outptr, *outptr0; + int overhead = 3; + ptr = curarg; + while (*ptr) + { + for (; *ptr && grub_isspace (*ptr); ptr++); + for (; *ptr && !grub_isspace (*ptr); ptr++) + if (*ptr == '\'') + overhead += 3; + if (*ptr) + ptr++; + overhead += 3; + } + + outptr0 = args[i] = grub_malloc (overhead + (ptr - curarg)); + if (!outptr0) + return NULL; + ptr = curarg; + outptr = outptr0; + while (*ptr) + { + for (; *ptr && grub_isspace (*ptr); ptr++); + if (outptr != outptr0) + *outptr++ = ' '; + *outptr++ = '\''; + for (; *ptr && !grub_isspace (*ptr); ptr++) + { + if (*ptr == '\'') + { + *outptr++ = '\''; + *outptr++ = '\\'; + *outptr++ = '\''; + *outptr++ = '\''; + } + else + *outptr++ = *ptr; + } + *outptr++ = '\''; + if (*ptr) + ptr++; + } + *outptr++ = 0; + } + break; + + case TYPE_VERBATIM: + args[i] = grub_legacy_escape (curarg, curarglen); + break; + case TYPE_WITH_CONFIGFILE_OPTION: + case TYPE_FORCE_OPTION: + case TYPE_NOAPM_OPTION: + case TYPE_TYPE_OR_NOMEM_OPTION: + case TYPE_OPTION: + if (is_option (legacy_commands[cmdnum].argt[i], curarg, curarglen)) + { + args[i] = grub_strndup (curarg, curarglen); + break; + } + args[i] = grub_strdup (""); + hold_arg = 1; + break; + case TYPE_INT: + { + const char *brk; + int base = 10; + brk = curarg; + if (brk[0] == '0' && brk[1] == 'x') + { + base = 16; + brk += 2; + } + else if (brk[0] == '0') + base = 8; + for (; *brk && brk < curarg + curarglen; brk++) + { + if (base == 8 && (*brk == '8' || *brk == '9')) + break; + if (grub_isdigit (*brk)) + continue; + if (base != 16) + break; + if (!(*brk >= 'a' && *brk <= 'f') + && !(*brk >= 'A' && *brk <= 'F')) + break; + } + if (brk == curarg) + args[i] = grub_strdup ("0"); + else + args[i] = grub_strndup (curarg, brk - curarg); + } + break; + case TYPE_VBE_MODE: + { + unsigned mod; + struct grub_vesa_mode_table_entry *modedesc; + + mod = grub_strtoul (curarg, 0, 0); + if (grub_errno) + { + mod = 0; + grub_errno = GRUB_ERR_NONE; + } + if (mod < GRUB_VESA_MODE_TABLE_START + || mod > GRUB_VESA_MODE_TABLE_END) + { + args[i] = grub_strdup ("auto"); + break; + } + modedesc = &grub_vesa_mode_table[mod - GRUB_VESA_MODE_TABLE_START]; + if (!modedesc->width) + { + args[i] = grub_strdup ("auto"); + break; + } + args[i] = grub_xasprintf ("%ux%ux%u", + modedesc->width, modedesc->height, + modedesc->depth); + break; + } + case TYPE_BOOL: + if (curarglen == 2 && curarg[0] == 'o' && curarg[1] == 'n') + args[i] = grub_strdup ("1"); + else + args[i] = grub_strdup ("0"); + break; + } + } + } + + while (legacy_commands[cmdnum].argc > 0 + && args[legacy_commands[cmdnum].argc - 1] == NULL + && (legacy_commands[cmdnum].flags & FLAG_FALLBACK_AVAILABLE) + && args[legacy_commands[cmdnum + 1].argc] == NULL) + cmdnum++; + + for (; i < legacy_commands[cmdnum].argc; i++) + switch (legacy_commands[cmdnum].argt[i]) + { + case TYPE_FILE_NO_CONSUME: + case TYPE_PARTITION: + case TYPE_FILE: + case TYPE_REST_VERBATIM: + case TYPE_VERBATIM: + case TYPE_WITH_CONFIGFILE_OPTION: + case TYPE_FORCE_OPTION: + case TYPE_NOAPM_OPTION: + case TYPE_TYPE_OR_NOMEM_OPTION: + case TYPE_OPTION: + args[i] = grub_strdup (""); + break; + case TYPE_BOOL: + case TYPE_INT: + args[i] = grub_strdup ("0"); + break; + case TYPE_VBE_MODE: + args[i] = grub_strdup ("auto"); + break; + } + + if (legacy_commands[cmdnum].flags & FLAG_COLOR_INVERT) + { + char *corig = args[legacy_commands[cmdnum].argc - 1]; + char *slash = grub_strchr (corig, '/'); + char *invert; + grub_size_t len; + + len = grub_strlen (corig); + if (!slash) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid color specification `%s'"), + args[0]); + return NULL; + } + invert = grub_malloc (len + 1); + if (!invert) + return NULL; + grub_memcpy (invert, slash + 1, len - (slash - corig) - 1); + invert[len - (slash - args[0]) - 1] = '/'; + grub_memcpy (invert + len - (slash - corig), corig, slash - corig); + invert[len] = 0; + args[legacy_commands[cmdnum].argc] = invert; + } + + if (legacy_commands[cmdnum].suffix) + { + *suffix = grub_xasprintf (legacy_commands[cmdnum].suffix, + args[legacy_commands[cmdnum].suffixarg]); + if (*suffix) + return NULL; + } + + { + char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], + args[2], args[3]); + grub_free (args[0]); + grub_free (args[1]); + grub_free (args[2]); + grub_free (args[3]); + return ret; + } +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/ChangeLog b/grub-core/lib/libgcrypt-grub/cipher/ChangeLog new file mode 100644 index 0000000..a00136b --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/ChangeLog @@ -0,0 +1,4357 @@ +2021-06-08 Automatic import tool + + Imported ciphers to GRUB + + * Makefile.am: Removed + * Manifest: Removed + * ac.c: Removed + * arcfour.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (elftest): Removed declaration. + (selftest): Removed. + (GRUB_MOD_INIT(gcry_arcfour)): New function + + Register cipher _gcry_cipher_spec_arcfour + (GRUB_MOD_FINI(gcry_arcfour)): New function + + Unregister cipher _gcry_cipher_spec_arcfour + * blowfish.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (selftest): Removed. + (GRUB_MOD_INIT(gcry_blowfish)): New function + + Register cipher _gcry_cipher_spec_blowfish + (GRUB_MOD_FINI(gcry_blowfish)): New function + + Unregister cipher _gcry_cipher_spec_blowfish + * camellia-glue.c: Removed including of config.h + Removed including of config.h + (elftest): Removed declaration. + (selftest): Removed. + (GRUB_MOD_INIT(gcry_camellia)): New function + + Register cipher _gcry_cipher_spec_camellia128 + Register cipher _gcry_cipher_spec_camellia192 + Register cipher _gcry_cipher_spec_camellia256 + (GRUB_MOD_FINI(gcry_camellia)): New function + + Unregister cipher _gcry_cipher_spec_camellia128 + Unregister cipher _gcry_cipher_spec_camellia192 + Unregister cipher _gcry_cipher_spec_camellia256 + * cast5.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (selftest): Removed. + (GRUB_MOD_INIT(gcry_cast5)): New function + + Register cipher _gcry_cipher_spec_cast5 + (GRUB_MOD_FINI(gcry_cast5)): New function + + Unregister cipher _gcry_cipher_spec_cast5 + * cipher.c: Removed + * crc.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (GRUB_MOD_INIT(gcry_crc)): New function + + Register digest _gcry_digest_spec_crc32 + Register digest _gcry_digest_spec_crc32_rfc1510 + Register digest _gcry_digest_spec_crc24_rfc2440 + (GRUB_MOD_FINI(gcry_crc)): New function + + Unregister MD _gcry_digest_spec_crc32 + Unregister MD _gcry_digest_spec_crc32_rfc1510 + Unregister MD _gcry_digest_spec_crc24_rfc2440 + * des.c: Removed including of config.h + Removed including of stdio.h + Removed including of string.h + (elftest): Removed declaration. + (weak_keys_chksum): Removed. + (tripledes_set2keys): Removed. + (selftest): Removed. + (do_tripledes_set_extra_info): Removed. + (selftest_fips): Removed. + (run_selftests): Removed. + (_gcry_cipher_extraspec_tripledes): Removed. + (GRUB_MOD_INIT(gcry_des)): New function + + Register cipher _gcry_cipher_spec_des + Register cipher _gcry_cipher_spec_tripledes + (GRUB_MOD_FINI(gcry_des)): New function + + Unregister cipher _gcry_cipher_spec_des + Unregister cipher _gcry_cipher_spec_tripledes + * dsa.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (gen_k): Removed declaration. + (test_keys): Removed declaration. + (progress_cb): Removed declaration. + (progress_cb): Removed declaration. + (_gcry_register_pk_dsa_progress): Removed. + (progress): Removed. + (gen_k): Removed. + (test_keys): Removed. + (generate): Removed. + (generate_fips186): Removed. + (sign): Removed. + (dsa_generate_ext): Removed. + (dsa_generate): Removed. + (dsa_sign): Removed. + (selftest_sign_1024): Removed. + (selftests_dsa): Removed. + (run_selftests): Removed. + (_gcry_pubkey_extraspec_dsa): Removed. + (GRUB_MOD_INIT(gcry_dsa)): New function + + Register pk _gcry_digest_spec_crc24_rfc2440 + (GRUB_MOD_FINI(gcry_dsa)): New function + + Unregister pk _gcry_digest_spec_crc24_rfc2440 + * ecc.c: Removed + * elgamal.c: Removed + * hash-common.c: Removed + * hmac-tests.c: Removed + * idea.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + Removed including of assert.h + (elftest): Removed declaration. + (selftest): Removed. + (GRUB_MOD_INIT(gcry_idea)): New function + + Register cipher _gcry_cipher_spec_idea + (GRUB_MOD_FINI(gcry_idea)): New function + + Unregister cipher _gcry_cipher_spec_idea + * kdf.c: Removed + * md.c: Removed + * md4.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (GRUB_MOD_INIT(gcry_md4)): New function + + Register digest _gcry_digest_spec_md4 + (GRUB_MOD_FINI(gcry_md4)): New function + + Unregister MD _gcry_digest_spec_md4 + * md5.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (GRUB_MOD_INIT(gcry_md5)): New function + + Register digest _gcry_digest_spec_md5 + (GRUB_MOD_FINI(gcry_md5)): New function + + Unregister MD _gcry_digest_spec_md5 + * primegen.c: Removed + * pubkey.c: Removed + * rfc2268.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (elftest): Removed declaration. + (selftest): Removed. + (GRUB_MOD_INIT(gcry_rfc2268)): New function + + Register cipher _gcry_cipher_spec_rfc2268_40 + (GRUB_MOD_FINI(gcry_rfc2268)): New function + + Unregister cipher _gcry_cipher_spec_rfc2268_40 + * rijndael.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (elftest): Removed declaration. + (_gcry_aes_cfb_enc): Removed. + (_gcry_aes_cbc_enc): Removed. + (_gcry_aes_ctr_enc): Removed. + (_gcry_aes_cfb_dec): Removed. + (_gcry_aes_cbc_dec): Removed. + (selftest_basic_128): Removed. + (selftest_basic_192): Removed. + (selftest_basic_256): Removed. + (selftest): Removed. + (selftest_fips_128_38a): Removed. + (selftest_fips_128): Removed. + (selftest_fips_192): Removed. + (selftest_fips_256): Removed. + (run_selftests): Removed. + (_gcry_cipher_extraspec_aes): Removed. + (_gcry_cipher_extraspec_aes192): Removed. + (_gcry_cipher_extraspec_aes256): Removed. + (GRUB_MOD_INIT(gcry_rijndael)): New function + + Register cipher _gcry_cipher_spec_aes + Register cipher _gcry_cipher_spec_aes192 + Register cipher _gcry_cipher_spec_aes256 + (GRUB_MOD_FINI(gcry_rijndael)): New function + + Unregister cipher _gcry_cipher_spec_aes + Unregister cipher _gcry_cipher_spec_aes192 + Unregister cipher _gcry_cipher_spec_aes256 + * rmd160.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (_gcry_rmd160_mixblock): Removed. + (_gcry_rmd160_hash_buffer): Removed. + (GRUB_MOD_INIT(gcry_rmd160)): New function + + Register digest _gcry_digest_spec_rmd160 + (GRUB_MOD_FINI(gcry_rmd160)): New function + + Unregister MD _gcry_digest_spec_rmd160 + * rsa.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + Removed including of errno.h + (test_keys): Removed declaration. + (secret): Removed declaration. + (test_keys): Removed. + (check_exponent): Removed. + (generate_std): Removed. + (gen_x931_parm_xp): Removed. + (gen_x931_parm_xi): Removed. + (generate_x931): Removed. + (secret): Removed. + (rsa_blind): Removed. + (rsa_unblind): Removed. + (rsa_generate_ext): Removed. + (rsa_generate): Removed. + (rsa_decrypt): Removed. + (rsa_sign): Removed. + (compute_keygrip): Removed. + (selftest_sign_1024): Removed. + (extract_a_from_sexp): Removed. + (selftest_encr_1024): Removed. + (selftests_rsa): Removed. + (run_selftests): Removed. + (_gcry_pubkey_extraspec_rsa): Removed. + (GRUB_MOD_INIT(gcry_rsa)): New function + + Register pk _gcry_digest_spec_rmd160 + (GRUB_MOD_FINI(gcry_rsa)): New function + + Unregister pk _gcry_digest_spec_rmd160 + * seed.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + (elftest): Removed declaration. + (selftest): Removed. + (GRUB_MOD_INIT(gcry_seed)): New function + + Register cipher _gcry_cipher_spec_seed + (GRUB_MOD_FINI(gcry_seed)): New function + + Unregister cipher _gcry_cipher_spec_seed + * serpent.c: Removed including of config.h + Removed including of string.h + Removed including of stdio.h + (serpent_test): Removed. + (GRUB_MOD_INIT(gcry_serpent)): New function + + Register cipher _gcry_cipher_spec_serpent128 + Register cipher _gcry_cipher_spec_serpent192 + Register cipher _gcry_cipher_spec_serpent256 + (GRUB_MOD_FINI(gcry_serpent)): New function + + Unregister cipher _gcry_cipher_spec_serpent128 + Unregister cipher _gcry_cipher_spec_serpent192 + Unregister cipher _gcry_cipher_spec_serpent256 + * sha1.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + Removed including of stdint.h + (_gcry_sha1_hash_buffer): Removed. + (selftests_sha1): Removed. + (run_selftests): Removed. + (_gcry_digest_extraspec_sha1): Removed. + (GRUB_MOD_INIT(gcry_sha1)): New function + + Register digest _gcry_digest_spec_sha1 + (GRUB_MOD_FINI(gcry_sha1)): New function + + Unregister MD _gcry_digest_spec_sha1 + * sha256.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (selftests_sha224): Removed. + (selftests_sha256): Removed. + (run_selftests): Removed. + (_gcry_digest_extraspec_sha224): Removed. + (_gcry_digest_extraspec_sha256): Removed. + (GRUB_MOD_INIT(gcry_sha256)): New function + + Register digest _gcry_digest_spec_sha224 + Register digest _gcry_digest_spec_sha256 + (GRUB_MOD_FINI(gcry_sha256)): New function + + Unregister MD _gcry_digest_spec_sha224 + Unregister MD _gcry_digest_spec_sha256 + * sha512.c: Removed including of config.h + Removed including of string.h + (selftests_sha384): Removed. + (selftests_sha512): Removed. + (run_selftests): Removed. + (_gcry_digest_extraspec_sha512): Removed. + (_gcry_digest_extraspec_sha384): Removed. + (GRUB_MOD_INIT(gcry_sha512)): New function + + Register digest _gcry_digest_spec_sha512 + Register digest _gcry_digest_spec_sha384 + (GRUB_MOD_FINI(gcry_sha512)): New function + + Unregister MD _gcry_digest_spec_sha512 + Unregister MD _gcry_digest_spec_sha384 + * test-getrusage.c: Removed + * tiger.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (GRUB_MOD_INIT(gcry_tiger)): New function + + Register digest _gcry_digest_spec_tiger + Register digest _gcry_digest_spec_tiger1 + Register digest _gcry_digest_spec_tiger2 + (GRUB_MOD_FINI(gcry_tiger)): New function + + Unregister MD _gcry_digest_spec_tiger + Unregister MD _gcry_digest_spec_tiger1 + Unregister MD _gcry_digest_spec_tiger2 + * twofish.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (elftest): Removed declaration. + (selftest): Removed. + Removed including of stdio.h + Removed including of string.h + Removed including of time.h + (GRUB_MOD_INIT(gcry_twofish)): New function + + Register cipher _gcry_cipher_spec_twofish + Register cipher _gcry_cipher_spec_twofish128 + (GRUB_MOD_FINI(gcry_twofish)): New function + + Unregister cipher _gcry_cipher_spec_twofish + Unregister cipher _gcry_cipher_spec_twofish128 + * whirlpool.c: Removed including of config.h + Removed including of stdio.h + Removed including of stdlib.h + Removed including of string.h + (GRUB_MOD_INIT(gcry_whirlpool)): New function + + Register digest _gcry_digest_spec_whirlpool + (GRUB_MOD_FINI(gcry_whirlpool)): New function + + Unregister MD _gcry_digest_spec_whirlpool + * crypto.lst: New file. + * types.h: New file. + * memory.h: New file. + * cipher.h: Likewise. + * g10lib.h: Likewise. + +2010-08-19 Werner Koch <wk@g10code.com> + + * cipher.c (gcry_cipher_open): Remove double release of the module. + Fixes bug#1263. + +2010-06-10 Jeff Johnson <n3npq@mac.com> (wk) + + * ecc.c (ecc_generate_ext): Parse transient-key flag. + (generate_key): Add arg TRANSIENT_KEY and use it to set the random + level. + +2010-04-12 Brad Hards <bradh@frogmouth.net> (wk) + + Spelling fixes. + +2010-03-26 Werner Koch <wk@g10code.com> + + * tiger.c (asn): Unfetter the old TIGER from an OID. + (TIGER_CONTEXT): Add field VARIANT. + (tiger_init): Factor code out to ... + (do_init): New. + (tiger1_init, tiger2_init): New. + (_gcry_digest_spec_tiger1, _gcry_digest_spec_tiger2): New. + * md.c (digest_table): Add TIGER1 and TIGER2 variants. + +2009-12-11 Werner Koch <wk@g10code.com> + + * sha256.c (Cho, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables + + * sha512.c (ROTR, Ch, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables. + Suggested by Christian Grothoff. + +2009-12-10 Werner Koch <wk@g10code.com> + + * Makefile.am (o_flag_munging): New. + (tiger.o, tiger.lo): Use it. + + * cipher.c (do_ctr_encrypt): Add arg OUTBUFLEN. Check for + suitable value. Add check for valid inputlen. Wipe temporary + memory. + (do_ctr_decrypt): Likewise. + (do_cbc_encrypt, do_cbc_decrypt): Add arg OUTBUFLEN. Check for + suitable value. Move check for valid inputlen to here; change + returned error from INV_ARG to INV_LENGTH. + (do_ecb_encrypt, do_ecb_decrypt): Ditto. + (do_cfb_encrypt, do_cfb_decrypt): Ditto. + (do_ofb_encrypt, do_ofb_decrypt): Ditto. + (cipher_encrypt, cipher_encrypt): Adjust for above changes. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Simplify. + +2009-12-09 Werner Koch <wk@g10code.com> + + * cipher.c (gcry_cipher_open): Allow for GCRY_CIPHER_MODE_AESWRAP. + (cipher_encrypt, cipher_decrypt): Ditto. + (do_aeswrap_encrypt, do_aeswrap_decrypt): New. + (struct gcry_cipher_handle): Add field marks. + (cipher_setkey, cipher_setiv): Update marks flags. + (cipher_reset): Reset marks. + (cipher_encrypt, cipher_decrypt): Add new arg OUTBUFLEN. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Pass outbuflen to + cipher_encrypt. Replace GPG_ERR_TOO_SHORT by + GPG_ERR_BUFFER_TOO_SHORT. + +2009-08-21 Werner Koch <wk@g10code.com> + + * dsa.c (dsa_generate_ext): Release retfactors array before + setting it to NULL. Reported by Daiko Ueno. + +2009-07-02 Werner Koch <wk@g10code.com> + + * md.c (md_read): Fix incomplete check for NULL. + Reported by Fabian Kail. + +2009-03-31 Werner Koch <wk@g10code.com> + + * rsa.c (rsa_check_secret_key): Return GPG_ERR_BAD_SECKEY and not + GPG_ERR_PUBKEY_ALGO. + +2009-02-16 Werner Koch <wk@g10code.com> + + * rsa.c (generate_x931): Do not initialize TBL with automatic + variables. + * whirlpool.c, tiger.c, sha256.c, sha1.c, rmd160.c, md5.c + * md4.c, crc.c: Remove memory.h. This is garbage from gnupg. + Reported by Dan Fandrich. + +2009-01-22 Werner Koch <wk@g10code.com> + + * ecc.c (compute_keygrip): Remove superfluous const. + +2009-01-06 Werner Koch <wk@g10code.com> + + * rmd160.c (oid_spec_rmd160): Add TeleTrust identifier. + +2008-12-10 Werner Koch <wk@g10code.com> + + * dsa.c (generate): Add arg DOMAIN and use it if specified. + (generate_fips186): Ditto. + (dsa_generate_ext): Parse and check the optional "domain" + parameter and pass them to the generate functions. + + * rijndael.c (rijndael_names): Add "AES128" and "AES-128". + (rijndael192_names): Add "AES-192". + (rijndael256_names): Add "AES-256". + +2008-12-05 Werner Koch <wk@g10code.com> + + * dsa.c (generate): Add arg TRANSIENT_KEY and use it to detrmine + the RNG quality needed. + (dsa_generate_ext): Parse the transient-key flag und pass it to + generate. + +2008-11-28 Werner Koch <wk@g10code.com> + + * dsa.c (generate_fips186): Add arg DERIVEPARMS and use the seed + value if available. + + * primegen.c (_gcry_generate_fips186_2_prime): Fix inner p loop. + +2008-11-26 Werner Koch <wk@g10code.com> + + * primegen.c (_gcry_generate_fips186_3_prime): New. + * dsa.c (generate_fips186): Add arg USE_FIPS186_2. + (dsa_generate_ext): Parse new flag use-fips183-2. + +2008-11-25 Werner Koch <wk@g10code.com> + + * dsa.c (generate_fips186): New. + (dsa_generate_ext): Use new function if derive-parms are given or + if in FIPS mode. + * primegen.c (_gcry_generate_fips186_2_prime): New. + +2008-11-24 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Insert code to output extrainfo. + (pubkey_generate): Add arg R_EXTRAINFO and pass it to the extended + key generation function. + * rsa.c (gen_x931_parm_xp, gen_x931_parm_xi): New. + (generate_x931): Generate params if not given. + (rsa_generate_ext): Parse use-x931 flag. Return p-q-swapped + indicator. + * dsa.c (dsa_generate_ext): Put RETFACTORS into R_EXTRAINFO if + possible. + + * pubkey.c (gcry_pk_genkey): Remove parsing of almost all + parameters and pass the parameter S-expression to pubkey_generate. + (pubkey_generate): Simplify by requitring modules to parse the + parameters. Remove the special cases for Elgamal and ECC. + (sexp_elements_extract_ecc): Add arg EXTRASPEC and use it. Fix + small memory leak. + (sexp_to_key): Pass EXTRASPEC to sexp_elements_extract_ecc. + (pubkey_table) [USE_ELGAMAL]: Add real extraspec. + * rsa.c (rsa_generate_ext): Adjust for new calling convention. + * dsa.c (dsa_generate_ext): Ditto. + * elgamal.c (_gcry_elg_generate): Ditto. Rename to elg_generate_ext. + (elg_generate): New. + (_gcry_elg_generate_using_x): Remove after merging code with + elg_generate_ext. + (_gcry_pubkey_extraspec_elg): New. + (_gcry_elg_check_secret_key, _gcry_elg_encrypt, _gcry_elg_sign) + (_gcry_elg_verify, _gcry_elg_get_nbits): Make static and remove + _gcry_ prefix. + * ecc.c (_gcry_ecc_generate): Rename to ecc_generate_ext and + adjust for new calling convention. + (_gcry_ecc_get_param): Rename to ecc_get_param and make static. + (_gcry_pubkey_extraspec_ecdsa): Add ecc_generate_ext and + ecc_get_param. + +2008-11-20 Werner Koch <wk@g10code.com> + + * pubkey.c (pubkey_generate): Add arg DERIVEPARMS. + (gcry_pk_genkey): Parse derive-parms and pass it to above. + * rsa.c (generate_x931): New. + (rsa_generate_ext): Add arg DERIVEPARMS and call new function in + fips mode or if DERIVEPARMS is given. + * primegen.c (_gcry_derive_x931_prime, find_x931_prime): New. + +2008-11-19 Werner Koch <wk@g10code.com> + + * rsa.c (rsa_decrypt): Use gcry_create_nonce for blinding. + (generate): Rename to generate_std. + +2008-11-05 Werner Koch <wk@g10code.com> + + * md.c (md_open): Use a switch to set the Bsize. + (prepare_macpads): Fix long key case for SHA384 and SHA512. + + * cipher.c (gcry_cipher_handle): Add field EXTRASPEC. + (gcry_cipher_open): Set it. + (gcry_cipher_ctl): Add private control code to disable weak key + detection and to return the current input block. + * des.c (_tripledes_ctx): Add field FLAGS. + (do_tripledes_set_extra_info): New. + (_gcry_cipher_extraspec_tripledes): Add new function. + (do_tripledes_setkey): Disable weak key detection. + +2008-10-24 Werner Koch <wk@g10code.com> + + * md.c (digest_table): Allow MD5 in fips mode. + (md_register_default): Take special action for MD5. + (md_enable, gcry_md_hash_buffer): Ditto. + +2008-09-30 Werner Koch <wk@g10code.com> + + * rijndael.c (do_setkey): Properly align "t" and "tk". + (prepare_decryption): Properly align "w". Fixes bug #936. + +2008-09-18 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Parse domain parameter. + (pubkey_generate): Add new arg DOMAIN and remove special case for + DSA with qbits. + * rsa.c (rsa_generate): Add dummy args QBITS, NAME and DOMAIN and + rename to rsa_generate_ext. Change caller. + (_gcry_rsa_generate, _gcry_rsa_check_secret_key) + (_gcry_rsa_encrypt, _gcry_rsa_decrypt, _gcry_rsa_sign) + (_gcry_rsa_verify, _gcry_rsa_get_nbits): Make static and remove + _gcry_ prefix. + (_gcry_pubkey_spec_rsa, _gcry_pubkey_extraspec_rsa): Adjust names. + * dsa.c (dsa_generate_ext): New. + (_gcry_dsa_generate): Replace code by a call to dsa_generate. + (_gcry_dsa_check_secret_key, _gcry_dsa_sign, _gcry_dsa_verify) + (_gcry_dsa_get_nbits): Make static and remove _gcry prefix. + (_gcry_dsa_generate2): Remove. + (_gcry_pubkey_spec_dsa): Adjust to name changes. + (_gcry_pubkey_extraspec_rsa): Add dsa_generate_ext. + +2008-09-16 Werner Koch <wk@g10code.com> + + * ecc.c (run_selftests): Add arg EXTENDED. + +2008-09-12 Werner Koch <wk@g10code.com> + + * rsa.c (test_keys): Do a bad case signature check. + * dsa.c (test_keys): Do a bad case check. + + * cipher.c (_gcry_cipher_selftest): Add arg EXTENDED and pass it + to the called tests. + * md.c (_gcry_md_selftest): Ditto. + * pubkey.c (_gcry_pk_selftest): Ditto. + * rijndael.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftest_fips_128): Add arg EXTENDED and run only one test + non-extended mode. + (selftest_fips_192): Add dummy arg EXTENDED. + (selftest_fips_256): Ditto. + * hmac-tests.c (_gcry_hmac_selftest): Ditto. + (run_selftests): Ditto. + (selftests_sha1): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha224, selftests_sha256): Ditto. + (selftests_sha384, selftests_sha512): Ditto. + * sha1.c (run_selftests): Add arg EXTENDED and pass it to the + called test. + (selftests_sha1): Add arg EXTENDED and run only one test + non-extended mode. + * sha256.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftests_sha224): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha256): Ditto. + * sha512.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftests_sha384): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha512): Ditto. + * des.c (run_selftests): Add arg EXTENDED and pass it to the + called test. + (selftest_fips): Add dummy arg EXTENDED. + * rsa.c (run_selftests): Add dummy arg EXTENDED. + + * dsa.c (run_selftests): Add dummy arg EXTENDED. + + * rsa.c (extract_a_from_sexp): New. + (selftest_encr_1024): Check that the ciphertext does not match the + plaintext. + (test_keys): Improve tests and return an error status. + (generate): Return an error if test_keys fails. + * dsa.c (test_keys): Add comments and return an error status. + (generate): Return an error if test_keys failed. + +2008-09-11 Werner Koch <wk@g10code.com> + + * rsa.c (_gcry_rsa_decrypt): Return an error instead of calling + BUG in case of a practically impossible condition. + (sample_secret_key, sample_public_key): New. + (selftest_sign_1024, selftest_encr_1024): New. + (selftests_rsa): Implement tests. + * dsa.c (sample_secret_key, sample_public_key): New. + (selftest_sign_1024): New. + (selftests_dsa): Implement tests. + +2008-09-09 Werner Koch <wk@g10code.com> + + * hmac-tests.c (selftests_sha1): Add tests. + (selftests_sha224, selftests_sha384, selftests_sha512): Make up tests. + + * hash-common.c, hash-common.h: New. + * sha1.c (selftests_sha1): Add 3 tests. + * sha256.c (selftests_sha256, selftests_sha224): Ditto. + * sha512.c (selftests_sha512, selftests_sha384): Ditto. + +2008-08-29 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_get_keygrip): Remove the special case for RSA + and check whether a custom computation function has been setup. + * rsa.c (compute_keygrip): New. + (_gcry_pubkey_extraspec_rsa): Setup this function. + * ecc.c (compute_keygrip): New. + (_gcry_pubkey_extraspec_ecdsa): Setup this function. + +2008-08-28 Werner Koch <wk@g10code.com> + + * cipher.c (cipher_decrypt, cipher_encrypt): Return an error if + mode NONE is used. + (gcry_cipher_open): Allow mode NONE only with a debug flag set and + if not in FIPS mode. + +2008-08-26 Werner Koch <wk@g10code.com> + + * pubkey.c (pubkey_generate): Add arg KEYGEN_FLAGS. + (gcry_pk_genkey): Implement new parameter "transient-key" and + pass it as flags to pubkey_generate. + (pubkey_generate): Make use of an ext_generate function. + * rsa.c (generate): Add new arg transient_key and pass appropriate + args to the prime generator. + (_gcry_rsa_generate): Factor all code out to ... + (rsa_generate): .. new func with extra arg KEYGEN_FLAGS. + (_gcry_pubkey_extraspec_ecdsa): Setup rsa_generate. + * primegen.c (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Add new arg RANDOM_LEVEL. + +2008-08-21 Werner Koch <wk@g10code.com> + + * primegen.c (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Use a constant macro for the random + level. + +2008-08-19 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_elements_extract_ecc) [!USE_ECC]: Do not allow + allow "curve" parameter. + +2008-08-15 Werner Koch <wk@g10code.com> + + * pubkey.c (_gcry_pk_selftest): New. + * dsa.c (selftests_dsa, run_selftests): New. + * rsa.c (selftests_rsa, run_selftests): New. + * ecc.c (selftests_ecdsa, run_selftests): New. + + * md.c (_gcry_md_selftest): New. + * sha1.c (run_selftests, selftests_sha1): New. + * sha256.c (selftests_sha224, selftests_sha256, run_selftests): New. + * sha512.c (selftests_sha384, selftests_sha512, run_selftests): New. + + * des.c (selftest): Remove static variable form selftest. + (des_setkey): No on-the-fly self test in fips mode. + (tripledes_set3keys): Ditto. + + * cipher.c (_gcry_cipher_setkey, _gcry_cipher_setiv): + + * dsa.c (generate): Bail out in fips mode if NBITS is less than 1024. + * rsa.c (generate): Return an error code if the the requested size + is less than 1024 and we are in fpis mode. + (_gcry_rsa_generate): Take care of that error code. + + * ecc.c (generate_curve): In fips mode enable only NIST curves. + + * cipher.c (_gcry_cipher_selftest): New. + + * sha512.c (_gcry_digest_extraspec_sha384) + (_gcry_digest_extraspec_sha512): New. + * sha256.c (_gcry_digest_extraspec_sha224) + (_gcry_digest_extraspec_sha256): New. + * sha1.c (_gcry_digest_extraspec_sha1): New. + * ecc.c (_gcry_pubkey_extraspec_ecdsa): New. + * dsa.c (_gcry_pubkey_extraspec_dsa): New. + * rsa.c (_gcry_pubkey_extraspec_rsa): New. + * rijndael.c (_gcry_cipher_extraspec_aes) + (_gcry_cipher_extraspec_aes192, _gcry_cipher_extraspec_aes256): New. + * des.c (_gcry_cipher_extraspec_tripledes): New. + + * cipher.c (gcry_cipher_register): Rename to _gcry_cipher_register. + Add arg EXTRASPEC. + (dummy_extra_spec): New. + (cipher_table_entry): Add extraspec field. + * md.c (_gcry_md_register): Rename to _gcry_md_register. Add + arg EXTRASPEC. + (dummy_extra_spec): New. + (digest_table_entry): Add extraspec field. + * pubkey.c (gcry_pk_register): Rename to _gcry_pk_register. Add + arg EXTRASPEC. + (dummy_extra_spec): New. + (pubkey_table_entry): Add extraspec field. + + * ac.c: Let most public functions return GPG_ERR_UNSUPPORTED in + fips mode. + + * pubkey.c (pubkey_table_entry): Add field FIPS_ALLOWED and mark + appropriate algorithms. + (dummy_generate, dummy_check_secret_key, dummy_encrypt) + (dummy_decrypt, dummy_sign, dummy_verify, dummy_get_nbits): Signal + a fips error when used. + (gcry_pk_register): In fips mode do not allow to register new + algorithms. + + * md.c (digest_table): Add field FIPS_ALLOWED and mark appropriate + algorithms. + (md_register_default): In fips mode register only fips algorithms. + (gcry_md_register): In fips mode do not allow to register new + algorithms. + (gcry_md_get): Signal a fips error if called. + (gcry_md_hash_buffer): Do not allow rmd160 when not in fips mode. + (md_start_debug): Disable in fips_mode. + + * md.c (gcry_md_register_default): Rename to .. + (md_register_default): .. this. + (md_digest): Remove this commented fucntion. + * pubkey.c (gcry_pk_register_default): Rename to .. + (pk_register_default): .. this. + + * cipher.c (cipher_table_entry): Add field FIPS_ALLOWED. + (gcry_cipher_register_default): Register only fips approved + algorithms. + (gcry_cipher_register): Do not allow to register new ciphers. + (cipher_setiv): Signal fips error. + + * cipher (gcry_cipher_register_default): Rename to .. + (cipher_register_default): .. this. + (REGISTER_DEFAULT_CIPHERS): Adjust for that change. + +2008-07-05 Werner Koch <wk@g10code.com> + + * random-daemon.c, random.h, rndhw.c, rndunix.c, rand-internal.h + * random.c, rndegd.c, rndlinux.c, rndw32.c: Move to ../cipher. + * Makefile.am: Remove random stuff. + +2008-06-24 Szakats Istvan <szaki.ms@gmail.com> (wk) + + * ac.c (_gcry_ac_key_destroy, _gcry_ac_key_pair_generate): Relase + some more memory. + +2008-04-22 Werner Koch <wk@g10code.com> + + * rijndael.c (_gcry_aes_cfb_enc, _gcry_aes_cbc_enc) + (_gcry_aes_cfb_dec, _gcry_aes_cbc_dec): Use Padlock if possible. + +2008-04-18 Werner Koch <wk@g10code.com> + + * sha1.c (transform_aligned): Remove. That is will obviosuly not + work because we need a scratch working area and our internal API + does not allow to modify the buffers. + + * rijndael.c: Factor tables out to .. + * rijndael-tables.h: .. new. + + * ac.c (ac_data_extract): Make static. + + * camellia.h [HAVE_CONFIG_H]: Include config.h. + + * rndw32.c (registry_poll): Only print the performance data + problem warning once. Suggested by Simon Josefsson. + +2008-03-19 Werner Koch <wk@g10code.com> + + * cipher.c (gcry_cipher_open) [USE_AES]: Init bulk encryption only + if requested. Suggested by Dirk Stoecker. + +2008-03-18 Werner Koch <wk@g10code.com> + + * sha1.c: Include stdint.h. + (transform): Add arg NBLOCKS so that we can work on more than one + block and avoid updates of the chaining variables. Changed all + callers to use 1. + (sha1_write): Replace loop around transform. + (transform_aligned) [WORDS_BIGENDIAN]: New. + (TRANSFORM): New macro to replace all direct calls of transform. + +2008-03-17 Werner Koch <wk@g10code.com> + + * rijndael.c (_gcry_aes_cfb_dec): New. + (do_encrypt): Factor code out to .. + (do_encrypt_aligned): .. New. + (_gcry_aes_cfb_enc, _gcry_aes_cfb_dec): Use new function. + (do_decrypt): Factor code out to .. + (do_decrypt_aligned): .. new. + (_gcry_aes_cbc_enc, _gcry_aes_cbc_dec): New. + * cipher.c (struct gcry_cipher_handle): Put field IV into new + union U_IV to enforce proper alignment. Change all users. + (do_cfb_decrypt): Optimize. + (do_cbc_encrypt, do_cbc_decrypt): Optimize. + +2008-03-15 Werner Koch <wk@g10code.com> + + * rijndael.c (_gcry_aes_cfb_enc): New. + * cipher.c (struct gcry_cipher_handle): Add field ALGO and BULK. + (gcry_cipher_open): Set ALGO and BULK. + (do_cfb_encrypt): Optimize. + +2008-02-18 Werner Koch <wk@g10code.com> + + * rsa.c (_gcry_rsa_verify) [IS_DEVELOPMENT_VERSION]: Print + intermediate results. + +2008-01-08 Werner Koch <wk@g10code.com> + + * random.c (add_randomness): Do not just increment + POOL_FILLED_COUNTER but update it by the actual amount of data. + +2007-12-13 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_data_to_mpi): Support SHA-224. + +2007-12-05 Werner Koch <wk@g10code.com> + + * rijndael.c (USE_PADLOCK): Depend on ENABLE_PADLOCK_SUPPORT. + * rndhw.c (USE_PADLOCK): Ditto + + * rsa.c (secret): Fixed condition test for using CRT. Reported by + Dean Scarff. Fixes bug#864. + (_gcry_rsa_check_secret_key): Return an erro if the optional + parameters are missing. + * pubkey.c (sexp_elements_extract): Add arg ALGO_NAME. Changed all + callers to pass NULL. Add hack to allow for optional RSA + parameters. + (sexp_to_key): Pass algo name to sexp_elements_extract. + +2007-12-03 Werner Koch <wk@g10code.com> + + * random.c (gcry_random_add_bytes): Implement it. + * rand-internal.h (RANDOM_ORIGIN_EXTERNAL): New. + +2007-11-30 Werner Koch <wk@g10code.com> + + * rndhw.c: New. + * rndlinux.c (_gcry_rndlinux_gather_random): Try to read 50% + directly from the hwrng. + * random.c (do_fast_random_poll): Also run the hw rng fast poll. + (_gcry_random_dump_stats): Tell whether the hw rng failed. + +2007-11-29 Werner Koch <wk@g10code.com> + + * rijndael.c (USE_PADLOCK): Define new macro used for ia32. + (RIJNDAEL_context) [USE_PADLOCK]: Add fields USE_PADLOCK and + PADLOCK_KEY. + (do_setkey) [USE_PADLOCK]: Enable padlock if available for 128 bit + AES. + (do_padlock) [USE_PADLOCK]: New. + (rijndael_encrypt, rijndael_decrypt) [USE_PADLOCK]: Divert to + do_padlock. + * cipher.c (cipher_context_alignment_t): New. Use it in this + module in place of PROPERLY_ALIGNED_TYPE. + (NEED_16BYTE_ALIGNED_CONTEXT): Define macro for ia32. + (struct gcry_cipher_handle): Add field HANDLE_OFFSET. + (gcry_cipher_open): Take care of increased alignment requirements. + (gcry_cipher_close): Ditto. + +2007-11-28 Werner Koch <wk@g10code.com> + + * sha256.c (asn224): Fixed wrong template. It happened due to a + bug in RFC4880. SHA-224 is not in the stable version of libgcrypt + so the consequences are limited to users of this devel version. + +2007-10-31 Werner Koch <wk@g10code.com> + + * ac.c (gcry_ac_data_new): Remove due to the visibility wrapper. + (gcry_ac_data_destroy, gcry_ac_data_copy, gcry_ac_data_length) + (gcry_ac_data_set, gcry_ac_data_get_name, gcry_ac_data_get_index) + (gcry_ac_data_to_sexp, gcry_ac_data_from_sexp) + (gcry_ac_data_clear, gcry_ac_io_init, gcry_ac_open) + (gcry_ac_close, gcry_ac_key_init, gcry_ac_key_pair_generate) + (gcry_ac_key_pair_extract, gcry_ac_key_destroy) + (gcry_ac_key_pair_destroy, gcry_ac_key_data_get) + (gcry_ac_key_test, gcry_ac_key_get_nbits, gcry_ac_key_get_grip) + (gcry_ac_data_encrypt, gcry_ac_data_decrypt, gcry_ac_data_sign) + (gcry_ac_data_verify, gcry_ac_data_encode, gcry_ac_data_decode) + (gcry_ac_mpi_to_os, gcry_ac_mpi_to_os_alloc, gcry_ac_os_to_mpi) + (gcry_ac_data_encrypt_scheme, gcry_ac_data_decrypt_scheme) + (gcry_ac_data_sign_scheme, gcry_ac_data_verify_scheme) + (gcry_ac_io_init_va): Ditto. + (gcry_ac_id_to_name, gcry_ac_name_to_id): Remove as these + deprecated functions are now implemented by visibility.c. + +2007-10-26 Werner Koch <wk@g10code.com> + + * rndw32.c: Disable debug flag. + +2007-10-25 Werner Koch <wk@g10code.com> + + * rndw32.c: Updated from current cryptlib snapshot and modified + for our use. Removed support from pre NT systems. + (slow_gatherer_windows95): Remove. + (_gcry_rndw32_gather_random): Require an NT platform. + (init_system_rng, read_system_rng, read_mbm_data): New. + (slow_gatherer_windowsNT): Rename to ... + (slow_gatherer): .. this. Read system RNG and MBM. + (registry_poll): New with code factored out from slow_gatherer. + +2007-08-23 Werner Koch <wk@g10code.com> + + * random.c (pool_filled_counter): New. + (add_randomness): Use it. + +2007-08-22 Werner Koch <wk@g10code.com> + + * rndw32.c, rndunix.c: Switched to LGPL. + +2007-05-30 Werner Koch <wk@g10code.com> + + * camellia.h, camellia.c: Replace by new LGPL version and adjusted + camellia.h. + +2007-05-09 Marcus Brinkmann <marcus@g10code.de> + + * ac.c (_gcry_ac_io_init_va, _gcry_ac_io_write, _gcry_ac_io_read): + Adjust users of gcry_ac_io_t because union is not anonymous + anymore. + +2007-05-02 Werner Koch <wk@g10code.com> + + * camellia-glue.c (camellia_setkey, camellia_encrypt) + (camellia_decrypt): Recalculated used stack size in called + functions. + * camellia.h: Redefine external symbols. + +2007-05-02 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am, cipher.c: Add Camellia. + + * camellia-glue.c: New. The necessary glue to interface libgcrypt + to the stock NTT Camellia distribution. + + * camellia.h, camellia.c: The stock NTT Camellia distribution + (GPL). + +2007-04-30 David Shaw <dshaw@jabberwocky.com> + + * cipher.c: Use #if instead of #ifdef as configure defines the + USE_cipher defines as 0 for disabled. + +2007-04-30 Werner Koch <wk@g10code.com> + + * rndegd.c (_gcry_rndegd_set_socket_name): New. + +2007-04-30 Marcus Brinkmann <marcus@g10code.de> + + * ecc.c (ec2os): Fix relocation of short numbers. + + * ecc.c (generate_key): Do not allocate D, which will be allocated + by GEN_K. Remove G. Fix test if g_x, g_y resp. q_x, q_y are + requested. + (_gcry_ecc_generate): Release unneeded members of SK. + * pubkey.c (sexp_to_key): Release NAME. + +2007-04-28 Marcus Brinkmann <marcus@g10code.de> + + * ac.c (gcry_ac_mpi): Remove member NAME_PROVIDED. + (ac_data_mpi_copy, _gcry_ac_data_set, _gcry_ac_data_get_name) + (_gcry_ac_data_get_index, ac_data_construct): Adjust handling of + NAME accordingly. + +2007-04-20 Werner Koch <wk@g10code.com> + + * ecc.c (domain_parms): Add standard brainpool curves. + +2007-04-18 Werner Koch <wk@g10code.com> + + * ecc.c (generate_curve): Implement alias mechanism. + + * pubkey.c (sexp_elements_extract_ecc): New. + (sexp_to_key): Add special case for ecc. + (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_genkey): Replace + name_terminated stuff by a call to _gcry_sexp_nth_string. + (gcry_pk_get_keygrip): Ditto. + +2007-04-16 Werner Koch <wk@g10code.com> + + * ecc.c (_gcry_ecc_generate): Renamed DUMMY to CURVE and use it. + +2007-04-13 Marcus Brinkmann <marcus@g10code.de> + + * ac.c (ac_data_construct): Cast const away to suppress compiler + warning. + + * ecc.c (ecc_generate): Avoid compiler warning for unused argument + DUMMY. + (ecc_verify): Avoid compiler warning for unused arguments CMP and + OPAQUEV. + +2007-04-06 Werner Koch <wk@g10code.com> + + * sha1.c (oid_spec_sha1): Add another oid from X9.62. + +2007-03-28 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Do not issue misc-key-info if it is + empty. + (gcry_pk_genkey): New parameter "curve". + + * ecc.c: Entirely rewritten with only a few traces of the old + code left. + (_gcry_ecc_generate): New. + (generate_key) New arg NAME. + (generate_curve): Ditto. Return actual number of NBITS. + +2007-03-26 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Increase size of SKEY array and add a + runtime bounds check. + +2007-03-23 Werner Koch <wk@g10code.com> + + * ecc.c (ecc_ctx_init, ecc_ctx_free, ecc_mod, ecc_mulm): New. + (duplicate_point, sum_points, escalar_mult): Don't use a + copy of base->p. Replaced all mpi_mulm by ecc_mulm so that we can + experiment with different algorithms. + (generate_key, check_secret_key, sign, verify): Initialize a + computation context for use by ecc_mulm. + +2007-03-22 Werner Koch <wk@g10code.com> + + * pubkey.c (pubkey_table): Initialize ECC. + * Makefile.am (EXTRA_libcipher_la_SOURCES): Add ecc.c. + * ecc.c: New. Heavily reformatted and changed for use in libgcrypt. + (point_init): New. + (escalar_mult): Make arg R the first arg to be similar to the mpi + functions. + (duplicate_point): Ditto + (sum_points): Ditto + (sign, verify): Remove unneeded copy operations. + (sum_points): Removed memory leaks and optimized some compares. + (verify): Simplified input check. + +2007-03-14 Werner Koch <wk@g10code.com> + + * random.c (MASK_LEVEL): Removed macro as it was used only at one + place. Open coded it there. + (gcry_randomize, _gcry_update_random_seed_file) + (_gcry_fast_random_poll): Factor lock code out to .. + (lock_pool, unlock_pool): .. new. + (initialize): Look the pool while allocating. + (read_random_source, do_fast_random_poll): Moved intialization to ... + (initialize): .. here. + (_gcry_enable_quick_random_gen): No more need for initialization. + (is_initialized): Moved this global flag to .. + (initialize): .. here and changed all users to unconditionally call + initialize. + (add_randomness): Remove initalization here. It simply can't + happen. + + * random.c (enum random_origins): Moved to .. + * rand-internal.h: .. here. + * rndunix.c (_gcry_rndunix_gather_random): Use enum in prototype + for ORIGIN and renamed REQUESTOR to ORIGIN. + * rndegd.c (_gcry_rndegd_gather_random): Ditto. + * rndlinux.c (_gcry_rndlinux_gather_random): Ditto. + * rndw32.c (_gcry_rndw32_gather_random): Ditto. + (_gcry_rndw32_gather_random_fast): Ditto. + +2007-03-13 Werner Koch <wk@g10code.com> + + * random.c (enum random_origins): New. + (add_randomness): Renamed arg SOURCE to ORIGIN. + (read_random_source): Renamed arg REQUESTOR to ORIGIN. + (getfnc_gather_random): Removed static variable because this + function is only called one and thus we don't need this + optimization. + (_gcry_quick_random_gen): Removed and replaced by.. + (_gcry_enable_quick_random_gen): .. this. It is onlyu used to + enable it and it does not make sense to disable it later. Changed + the only one caller too. + (get_random_bytes): Removed. + (gcry_random_bytes, gcry_random_bytes_secure): Implement in terms + of gcry_randomize. + * random-daemon.c (_gcry_daemon_get_random_bytes): Removed. + +2007-02-23 Werner Koch <wk@g10code.com> + + * elgamal.c (generate): Removed unused variable TEMP. + (test_keys): New arg NODIE. + (generate_using_x, _gcry_elg_generate_using_x): New. + * pubkey.c (pubkey_generate): New arg XVALUE and direct call to + the new elgamal generate fucntion. + (gcry_pk_genkey): Parse the new "xvalue" tag. + +2007-02-22 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_data_to_mpi): Handle dynamically allocated + algorithms. Suggested by Neil Dunbar. Fixes bug#596. + + * rndw32.c (_gcry_rndw32_gather_random_fast): Make it return void. + + * cipher.c (gcry_cipher_algo_name): Simplified. + + * random.c: Use the daemon only if compiled with USE_RANDOM_DAEMON. + + * Makefile.am (libcipher_la_SOURCES): Build random-daemon support + only if requested. + +2007-02-21 Werner Koch <wk@g10code.com> + + * random.c (rndpool, keypool): Make unsigned. + (mix_pool): Change char* variables to unsigned char*. + (gcry_randomize): Make arg BUFFER a void*. + (gcry_create_nonce): Ditto. + + * rmd160.c (gcry_rmd160_mixblock): Make BUFFER a void*. + (_gcry_rmd160_hash_buffer): Make OUTBUF and BUFFER void*. + * sha1.c (_gcry_sha1_hash_buffer): Ditto. + + * cipher.c (gcry_cipher_encrypt, cry_cipher_decrypt): Change + buffer args to void*. + (gcry_cipher_register): Make ALGORITHM_ID a int *. + + * md.c (md_start_debug): Make SUFFIX a const char*. Use snprintf. + (gcry_md_debug): New. + (gcry_md_ctl): Changed arg BUFFER from unsigned char*. + + * md.c (md_write): Make INBUF a const void*. + (gcry_md_write): Remove needless cast. + * crc.c (crc32_write): Make INBUF a const void* + (update_crc32, crc24rfc2440_write): Ditto. + * sha512.c (sha512_write, transform): Ditto. + * sha256.c (sha256_write, transform): Ditto. + * rmd160.c (rmd160_write, transform): Ditto. + * md5.c (md5_write, transform): Ditto. + * md4.c (md4_write, transform): Ditto. + * sha1.c (sha1_write, transform): Ditto. + + * tiger.c (tiger_write, transform): Ditto. + * whirlpool.c (whirlpool_write, whirlpool_add, transform): Ditto. + + * elgamal.c (elg_names): Change to a const*. + * dsa.c (dsa_names): Ditto. + * rsa.c (rsa_names): Ditto. + * pubkey.c (gcry_pk_lookup_func_name): Make ALIASES a const. + +2007-02-20 Werner Koch <wk@g10code.com> + + * rndlinux.c (open_device): Remove unsused arg MINOR. + +2007-01-30 Werner Koch <wk@g10code.com> + + * sha256.c (oid_spec_sha256): Add alias from pkcs#1. + * sha512.c (oid_spec_sha512): Ditto. + (oid_spec_sha384): Ditto. + +2006-12-18 Werner Koch <wk@g10code.com> + + * rndlinux.c (set_cloexec_flag): New. + (open_device): Set close-on-exit flags. Suggested by Max + Kellermann. Fixes Debian#403613. + + * Makefile.am (AM_CPPFLAGS, AM_CFLAGS): Splitted and merged + Moritz' changes. + (INCLUDES): Removed. + +2006-11-30 Werner Koch <wk@g10code.com> + + * serpent.c (byte_swap_32): Remove trailing semicolon. + +2006-11-15 Werner Koch <wk@g10code.com> + + * Makefile.am (INCLUDES): Include ../src/ + +2006-11-03 Werner Koch <wk@g10code.com> + + * random.c [HAVE_GETTIMEOFDAY]: Included sys/time.h and not + sys/times.h. Reported by Rafaël Carré. + +2006-11-05 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (AM_CFLAGS): Added -I$(top_builddir)/src so that the + new gcrypt.h is used, not the one installed in the system. + +2006-10-25 Werner Koch <wk@g10code.com> + + * primegen.c (prime_generate_internal): Tweaked use of secure + memory and entropy use. Safe unused primes from the pool. Allocate + at least a pool of 30. + (save_pool_prime, get_pool_prime): New. + +2006-10-23 Werner Koch <wk@g10code.com> + + * ac.c (_gcry_ac_data_from_sexp): Reset sexp_tmp for failsafe + means. Release sexp_cur if needed. Reported by Dirk Stoecker. + + * pubkey.c (pubkeys_registered_lock): Intialized it. It is not + realy needed because this is a mere initialization to 0 anyway. + Noted by Victor Stinner. + +2006-10-17 Werner Koch <wk@g10code.com> + + * dsa.c (_gcry_dsa_generate2): New. + (generate): New arg QBITS. Add sanity checks for reasonable qbits + and nbits. + * pubkey.c (gcry_pk_genkey): Parse an qbits element. + (pubkey_generate): New arg QBITS. Pass it to the DSA generation. + +2006-10-05 Werner Koch <wk@g10code.com> + + * md.c (gcry_md_algo_info) <get_asnoid>: Check that the algo is + available. + +2006-10-04 David Shaw <dshaw@jabberwocky.com> (wk) + + * tiger.c (round): Rename to tiger_round as gcc 4 has a built-in + round function that this conflicts with. + +2006-09-11 Werner Koch <wk@g10code.com> + + * rndw32.c (slow_gatherer_windowsNT): While adding data use the + size of the diskPerformance and not its address. Has been fixed in + GnuPG more than a year ago. Noted by Lee Fisher. + +2006-08-30 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_data_to_mpi): Need to allow "ripemd160" here as + this is the canonical name. + +2006-08-29 Hye-Shik Chang <perky@FreeBSD.org> (wk) + + * seed.c: New. + +2006-08-03 Werner Koch <wk@g10code.com> + + * random-daemon.c (_gcry_daemon_initialize_basics): Don't + initialize the socket. Remove arg SOCKETNAME. + (connect_to_socket): Make sure that daemon is set to -1 on error. + (call_daemon): Initialize the socket on the first call. + (_gcry_daemon_randomize, _gcry_daemon_get_random_bytes) + (_gcry_daemon_create_nonce): New arg SOCKETNAME. + * random.c (initialize): Call new daemon initializator. + (get_random_bytes, gcry_randomize, gcry_create_nonce): Pass socket + name to daemon call and reset allow_daemon on failure. + +2006-07-26 Werner Koch <wk@g10code.com> + + * rmd160.c (_gcry_rmd160_mixblock): Add cast to transform call. + + * blowfish.c (selftest): Cast string to usnigned char*. + + * primegen.c (prime_generate_internal): Cast unsigned/char* + mismatch in calling m_out_of_n. + (is_prime): Changed COUNT to unsigned int *. + + * ac.c (_gcry_ac_data_copy): Initialize DATA_MPIS. + + * random.c (gcry_create_nonce): Update the pid after a fork. + Reported by Uoti Urpala. + +2006-07-04 Marcus Brinkmann <marcus@g10code.de> + + * sha512.c: Fix typo in copyright notice. + +2006-06-21 Werner Koch <wk@g10code.com> + + * rsa.c (_gcry_rsa_generate): Replace xcalloc by calloc. + * pubkey.c (gcry_pk_encrypt, gcry_pk_sign): Ditto. + (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_encrypt) + (gcry_pk_sign, gcry_pk_genkey, gcry_pk_get_keygrip): Ditto. + * md.c (md_copy): Ditto. + +2006-04-22 Moritz Schulte <moritz@g10code.com> + + * random-daemon.c (_gcry_daemon_initialize_basics): New argument: + SOCKETNAME. Passing on to connect_to_socket() if non-NULL. + (connect_to_socket, writen, readn, call_daemon): New functions. + (_gcry_daemon_randomize, _gcry_daemon_get_random_bytes) + (_gcry_daemon_create_nonce): Call call_daemon(). + (RANDOM_DAEMON_SOCKET): New symbol. + (daemon_socket): New static variable. + + * random.h (_gcry_daemon_initialize_basics): New parameter: + SOCKETNAME. + (_gcry_set_random_daemon_socket): New declaration. + + * random.c (initialize_basics): Pass DAEMON_SOCKET_NAME to + _gcry_daemon_initialize_basics. + (_gcry_set_random_daemon_socket): New function, setting + DAEMON_SOCKET_NAME. + +2006-04-01 Moritz Schulte <moritz@g10code.com> + + * ac.c (eme_pkcs_v1_5_encode): Use KEY_SIZE directly, no need to + call gcry_ac_key_get_nbits. + (eme_pkcs_v1_5_decode): Likewise. + (ac_es_dencode_prepare_pkcs_v1_5): Fill options_em structure with + key_size. + (_gcry_ac_data_dump, gcry_ac_data_dump): New functions. + (_gcry_ac_data_to_sexp, _gcry_ac_data_from_sexp): More or less + rewritten; changed S-Expression format so that it matches the one + used in pubkey.c. + +2006-03-15 Werner Koch <wk@g10code.com> + + * random-daemon.c: New. + * random.c (_gcry_use_random_daemon): New. + (get_random_bytes, gcry_randomize, gcry_create_nonce): Try + diverting to the daemon functions. + +2006-03-14 Werner Koch <wk@g10code.com> + + * random.c (lock_seed_file): New. + (read_seed_file, _gcry_update_random_seed_file): Use it. + + * random.c (gcry_create_nonce): Detect a fork and re-seed. + (read_pool): Fixed the fork detection; it used to work only for + multi-threaded processes. + +2006-03-12 Brad Hards <bradh@frogmouth.net> (wk) + + * md.c (md_open): Use new variable macpads_Bsize instead of + hardwiring the block size. Changed at all places. + +2006-03-10 Brad Hards <bradh@frogmouth.net> (wk, patch 2005-04-22) + + * md.c, sha256.c: Add support for SHA-224. + (sha224_init): New. + +2006-01-18 Brad Hards <bradh@frogmouth.net> (wk 2006-03-07) + + * cipher.c (cipher_encrypt, cipher_decrypt, do_ofb_encrypt) + (do_ofb_decrypt, gcry_cipher_open): Implement Output Feedback Mode. + +2005-11-02 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_algo_name): Return "?" instead of NULL for + unknown algorithm IDs. + * cipher.c (cipher_algo_to_string): Likewise. + +2005-11-01 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_algo_info): Don't forget to break after switch + case. + +2005-09-19 Werner Koch <wk@g10code.com> + + * dsa.c (generate): Add preliminary support for 2 and 4 keys. + Return an error code if the key size is not supported. + (_gcry_dsa_generate): Return an error. + +2005-08-22 Werner Koch <wk@g10code.com> + + * primegen.c (check_prime): New arg RM_ROUNDS. + (prime_generate_internal): Call it here with 5 rounds as used + before. + (gcry_prime_check): But here with 64 rounds. + (is_prime): Make sure never to use less than 5 rounds. + +2005-04-16 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_init): New function. + +2005-04-12 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_io_write, _gcry_ac_io_read): Initialize err to + make the compiler happy. + Always use errno, now that gcry_malloc() is guaranteed to set + errno on failure. + (_gcry_ac_data_to_sexp): Don't forget to goto out after error in + loop. + (_gcry_ac_data_to_sexp): Remove unused variable: mpi_list; + (_gcry_ac_data_to_sexp): Always deallocate sexp_buffer. + (_gcry_ac_data_from_sexp): Don't forget to initialize data_set_new. + (_gcry_ac_data_from_sexp): Handle special case, which is + necessary, since gcry_sexp_nth() does not distinguish between + "element does not exist" and "element is the empty list". + (_gcry_ac_io_init_va): Use assert to make sure that mode and type + are correct. + Use gcry_error_t types where gcry_err_code_t types have been used + before. + +2005-04-11 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_data_sign_scheme): Don't forget to initialize + buffer. + + * whirlpool.c: New file. + * md.c (digest_table): Add whirlpool. + * Makefile.am (EXTRA_libcipher_la_SOURCES): Added: whirlpool.c. + +2005-03-30 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_data_from_sexp): Use length of SEXP_CUR, not + length of SEXP; do not forget to set SEXP_TMP to NULL after it has + been released. + + (struct gcry_ac_mpi): New member: name_provided. + (_gcry_ac_data_set): Rename variable `name_final' to `name_cp'; + remove const qualifier; change code to not cast away const + qualifiers; use name_provided member as well. + (_gcry_ac_data_set, _gcry_ac_data_get_name): Use name_provided + member of named mpi structure. + + (gcry_ac_name_to_id): Do not forget to initialize err. + (_gcry_ac_data_get_index): Do not forget to initialize mpi_return; + use gcry_free() instead of free(); remove unnecessary cast; rename + mpi_return and name_return to mpi_cp and name_cp; adjust code. + (ac_data_mpi_copy): Do not cast away const qualifier. + (ac_data_values_destroy): Likewise. + (ac_data_construct): Likewise. + + (ac_data_mpi_copy): Initialize flags to GCRY_AC_FLAG_DEALLOC. + (ac_data_extract): Use GCRY_AC_FLAG_DEALLOC instead of + GCRY_AC_FLAG_COPY. + + (_gcry_ac_io_init_va, _gcry_ac_io_init, gcry_ac_io_init) + (gcry_ac_io_init_va, _gcry_ac_io_write, _gcry_ac_io_read) + (_gcry_ac_io_read_all, _gcry_ac_io_process): New functions. + (gry_ac_em_dencode_t): Use gcry_ac_io_t in prototype instead of + memroy strings directly; adjust encode/decode functions to use io + objects. + (emsa_pkcs_v1_5_encode_data_cb): New function ... + (emsa_pkcs_v1_5_encode): ... use it here. + (ac_data_dencode): Use io objects. + (_gcry_ac_data_encode, _gcry_ac_data_decode, gcry_ac_data_encode) + (gcry_ac_data_decode): Likewise. + (_gcry_ac_data_encrypt_scheme, gcry_ac_data_encrypt_scheme) + (_gcry_ac_data_decrypt_scheme, gcry_ac_data_decrypt_scheme) + (_gcry_ac_data_sign_scheme, gcry_ac_data_sign_scheme) + (_gcry_ac_data_verify_scheme, gcry_ac_data_verify_scheme): + Likewise. + +2005-03-23 Werner Koch <wk@g10code.com> + + * rndw32.c (_gcry_rndw32_gather_random_fast): While adding data + use the size of the object and not the one of its address. Bug + reported by Sascha Kiefer. + +2005-03-19 Moritz Schulte <moritz@g10code.com> + + * cipher.c (do_cbc_encrypt): Be careful to not overwrite data, + which is to be used later on. This happend, in case CTS is + enabled and OUTBUF is equal to INBUF. + +2005-02-25 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_get_keygrip): Allow for shadowed-private-key. + +2005-02-13 Moritz Schulte <moritz@g10code.com> + + * serpent.c: Updated from 1.2 branch: + + s/u32_t/u32/ and s/byte_t/byte/. Too match what we have always + used and are using in all other files too + (serpent_test): Moved prototype out of a fucntion. + +2005-02-07 Moritz Schulte <moritz@g10code.com> + + * ac.c: Major parts rewritten. + * pubkey.c (_gcry_pk_get_elements): New function. + +2004-12-09 Werner Koch <wk@g10code.com> + + * serpent.c (serpent_setkey): Moved prototype of serpent_test to + outer scope. + +2004-09-11 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (pubkey_table): Added an alias entry for GCRY_PK_ELG_E. + +2004-08-23 Moritz Schulte <moritz@g10code.com> + + * ac.c: Do not include <assert.h>. + * rndegd.c: Likewise. + * sha1.c: Likewise. + * rndunix.c: Likewise. + * rndlinux.c: Likewise. + * rmd160.c: Likewise. + * md5.c: Likewise. + * md4.c: Likewise. + * cipher.c: Likewise. + * crc.c: Likewise. + * blowfish.c: Likewise. + + * pubkey.c (dummy_generate, dummy_check_secret_key) + (dummy_encrypt, dummy_decrypt, dummy_sign, dummy_verify): Return + err code GPG_ERR_NOT_IMPLEMENTED instead of aborting through + log_bug(). + (dummy_get_nbits): Return 0 instead of aborting though log_bug(). + +2004-08-19 Werner Koch <wk@g10code.de> + + * pubkey.c (sexp_data_to_mpi): Changed the zero random byte + substituting code to actually do clever things. Thanks to + Matthias Urlichs for noting the implementation problem. + +2004-08-09 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_sign): Fixed memory leak; fix provided by + Modestas Vainius. + +2004-07-16 Werner Koch <wk@gnupg.org> + + * rijndael.c (do_encrypt): Fix alignment problem. Bugs found by + Matthias Urlichs. + (do_decrypt): Ditto. + (keySched, keySched2): Use 2 macros along with unions in the key + schedule context. + +2004-07-14 Moritz Schulte <moritz@g10code.com> + + * rsa.c (_gcry_rsa_decrypt): Don't forget to free "a". Thanks to + Nikos Mavroyanopoulos. + +2004-05-09 Werner Koch <wk@gnupg.org> + + * random.c (read_pool): Mix the PID in to better protect after a + fork. + +2004-07-04 Moritz Schulte <moritz@g10code.com> + + * serpent.c: Use "u32_t" instead of "unsigned long", do not + declare S-Box variables as "register". Fixes failure on + OpenBSD/sparc64, reported by Nikolay Sturm. + +2004-05-07 Werner Koch <wk@gnupg.org> + + * random.c (initialize): Factored out some code to .. + (initialize_basics): .. new function. + (_gcry_random_initialize): Just call initialize_basics unless the + new arg FULL is set to TRUE. + (_gcry_fast_random_poll): Don't do anything unless the random + system has been really initialized. + +2004-05-07 Moritz Schulte <moritz@g10code.de> + + * ac.c (gcry_ac_open): Do not dereference NULL pointer. Reported + by Umberto Salsi. + +2004-02-20 Werner Koch <wk@gnupg.org> + + * primegen.c (check_prime): New args CB_FUNC and CB_ARG; call them + at different stages. Pass these arguments through all callers. + +2004-02-06 Werner Koch <wk@gnupg.org> + + * des.c: Add a new OID as used by pkcs#12. + + * rfc2268.c: New. Taken from libgcrypt. + * cipher.c: Setup the rfc2268 algorithm. + +2004-01-25 Moritz Schulte <mo@g10code.com> + + * primegen.c (prime_generate_internal): Do not forget to free + `q_factor'; fixed by Brieuc Jeunhomme. + (prime_generate_internal): Do not forget to free `prime'. + +2004-01-14 Moritz Schulte <mo@g10code.com> + + * ac.c (gcry_ac_data_set): New argument: flags; slightly + rewritten. + (gcry_ac_data_get_name, gcry_ac_data_get_index): Likewise. + (gcry_ac_key_pair_generate): New argument: misc_data; modified + order of arguments. + (gcry_ac_key_test): New argument: handle. + (gcry_ac_key_get_nbits, gcry_ac_key_get_grip): Likewise. + Use GCRY_AC_FLAG_NO_BLINDING instead of + GCRY_AC_DATA_FLAG_NO_BLINDING. + (gcry_ac_mpi): New member: flags. + (gcry_ac_data_search, gcry_ac_data_add): Removed functions. + +2003-12-22 Werner Koch <wk@gnupg.org> + + * primegen.c (is_prime): Release A2. + +2003-12-19 Werner Koch <wk@gnupg.org> + + * md.c: Moved a couple of functions down below the data structure + definitions. + (struct gcry_md_context): New field ACTUAL_HANDLE_SIZE. + (md_open): Set it here. + (strcut gcry_md_list): New field ACTUAL_STRUCT_SIZE. + (md_enable): Set it here. + (md_close): Wipe the context memory. + secure memory. + * cipher.c (struct gcry_cipher_handle): New field ACTUAL_HANDLE_SIZE. + (gcry_cipher_open): Set it here. + (gcry_cipher_close): Use it to always wipe out the handle data. + + * ac.c (gcry_ac_open): Make sure HANDLE gets initialized even when + the function is not successful. + (gcry_ac_close): Allow a NULL handle. + (gcry_ac_key_destroy, gcry_ac_key_pair_destroy): Ditto. + (gcry_ac_key_get_grip): Return INV_OBJ on error. + + * primegen.c (prime_generate_internal): Fixed error code for + failed malloc. Replaced the !err if chain by gotos. + (gcry_prime_group_generator): Remove the extra sanity check. + + * md.c: Minor code and comment cleanups. + +2003-12-16 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): Doc fix. Thanks to Newton Hammet. + +2003-12-11 Werner Koch <wk@gnupg.org> + + * rndunix.c (slow_poll): Don't use #warning but #error. + + * rndegd.c: Changed indentation. + (my_make_filename): Removd the var_arg cruft becuase we + don't need it here. Changed caller. + + * rndlinux.c: Changed indentation. + (open_device): Remove the superfluous stat call and clarify + comment. + + * rsa.c: Changed indentation. + (secret): Use the standard algorithm if p, q and u are not + available. + (rsa_blind, rsa_unblind): Renamed from _gcry_rsa_blind, + _gcry_rsa_unblind and moved more to the top. + + * md4.c: Changed indentation. Removed unnecessary casts. + * md5.c, rmd160.c, sha1.c, tiger.c: Ditto. + * rijndael.c, twofish.c: Ditto. + * serpent.c: Removed unnecessary casts. + * sha256.c, sha512.c: Ditto. + +2003-12-09 Werner Koch <wk@gnupg.org> + + * dsa.c: Unified indentation style. + * elgamal.c: Ditto. + * des.c (des_key_schedule): Code beautifications. + * blowfish.c: Changed indentation style. + * cast5.c (do_cast_setkey): Ditto. + + * pubkey.c (gcry_pk_encrypt): Replaced the chain of if(!err) tests + by straightforward gotos. Other cleanups. + (gcry_pk_decrypt): Ditto. + (gcry_pk_sign): Ditto. + (gcry_pk_verify): Ditto. + (gcry_pk_genkey): Ditto. Use strtoul instead of strtol. + (gcry_pk_ctl): Use GPG_ERR_INV_ARG to indicate bad arguments. + +2003-12-07 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_register_default): Undef the helper macro. + (gcry_pk_map_name): Allow NULL for string. + (sexp_to_key): Use memcpy and not strncpy. Use gcry_free and not + free. + (sexp_to_sig): Ditto. + (sexp_to_enc): Ditto. Replaced the chain of if(!err) tests by + straightforward gotos. + +2003-12-05 Werner Koch <wk@gnupg.org> + + * cipher.c: Documentation cleanups. + (gcry_cipher_mode_from_oid): Allow NULL for STRING. + +2003-12-03 Werner Koch <wk@gnupg.org> + + * elgamal.c (sign, do_encrypt, gen_k): Make sure that a small K is + only used for encryption. + +2003-11-18 Werner Koch <wk@gnupg.org> + + * random.h (rndw32_set_dll_name): Removed unused prototype. + + * Makefile.am (EXTRA_DIST): Added Manifest. + +2003-11-11 Werner Koch <wk@gnupg.org> + + * Manifest: New. + +2003-11-04 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Use shortcut for SHA1 + * sha1.c (_gcry_sha1_hash_buffer): New. + + * random.c: Reformatted most functions. + (mix_pool): Moved the failsafe_digest from global + scope to here. + (do_fast_random_poll): Use the generic fucntions even if a fast + gathering function has been used. + (read_pool): Detect a fork and retry. + (gcry_randomize, get_random_bytes): Don't distinguish anymore + between weak and strong random. + (gcry_create_nonce): New. + +2003-10-31 Werner Koch <wk@gnupg.org> + + * rndw32.c (slow_gatherer_windowsNT): Use a plain buffer for the + disk performance values and not the W32 API structure. + + * dsa.c (verify): s/exp/ex/ due to shadowing of a builtin. + * elgamal.c (verify): Ditto. + + * ac.c (gcry_ac_data_get_index): s/index/idx/ + (gcry_ac_data_copy_internal): Remove the cast in _gcry_malloc. + (gcry_ac_data_add): Must use gcry_realloc instead of realloc. + * pubkey.c (sexp_elements_extract): s/index/idx/ as tribute to the + forehackers. + (gcry_pk_encrypt): Removed shadowed definition of I. Reordered + arguments to malloc for clarity. + (gcry_pk_sign, gcry_pk_genkey): Ditto. + * primegen.c (prime_generate_internal): s/random/randomlevel/. + +2003-10-27 Moritz Schulte <mo@g10code.com> + + * pubkey.c (gcry_pk_encrypt): Don't forget to deallocate pkey. + +2003-10-27 Werner Koch <wk@gnupg.org> + + * random.c (gcry_random_add_bytes): Return if buflen is zero to + avoid gcc warning about unsed parameter. + (MASK_LEVEL): Simplified; does now work for signed and unsigned + w/o warnings. + + * md.c (md_start_debug): Removed the const from SUFFIX, because + this function is called from the control fucntion which does not + require const. + + Prefixed all (pubkey,digest,cipher}_spec_* globale variables with + _gcry_. + + * ac.c (ac_key_identifiers): Made static. + + * random.c (getfnc_gather_random,getfnc_fast_random_poll): Move + prototypes to .. + * rand-internal.h: .. here + * random.c (getfnc_gather_random): Include rndw32 gatherer. + * rndunix.c, rndw32.c, rndegd.c: Include them here. + * rndlinux.c (_gcry_rndlinux_gather_random): Prepend the _gcry_ + prefix. Changed all callers. + * rndegd.c (_gcry_rndegd_gather_random): Likewise. + (_gcry_rndegd_connect_socket): Likewise. + * rndunix.c (_gcry_rndunix_gather_random): Likewise. + (waitpid): Made static. + * rndw32.c: Removed the old and unused winseed.dll cruft. + (_gcry_rndw32_gather_random_fast): Renamed from + gather_random_fast. + (_gcry_rndw32_gather_random): Renamed from gather_random. Note, + that the changes 2003-04-08 somehow got lost. + + * sha512.c (sha512_init, sha384_init): Made static. + + * cipher.c (do_ctr_decrypt): Removed "return" from this void + function. + +2003-10-24 Moritz Schulte <mo@g10code.com> + + * serpent.c: Fix an issue on big-endian systems. + + * rndw32.c: Removed IS_MODULE -cruft. + * rndlinux.c (rndlinux_gather_random): Likewise. + +2003-10-10 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): Bail out if NBITS is less than 16. + (prime_generate_internal): Initialize prime variable to suppress + compiler warning. Check pbits, initialize qbits when passed as + zero. + + * primegen.c (prime_generate_internal): New arg + ALL_FACTORS. Changed all callers. + (gcry_prime_generate): Make the factors arg optional. Request + all_factors. Make sure PRIME is set to NULL even on error. + (gcry_prime_group_generator): New. + (gcry_prime_release_factors): New. + +2003-10-06 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): Assert that NBITS is never zero, it + would cause a segv. + +2003-09-28 Moritz Schulte <mo@g10code.com> + + * ac.c: Include "cipher.h". + +2003-09-27 Moritz Schulte <mo@g10code.com> + + * rndegd.c (do_read): Return nread instead of nbytes; thanks to + Michael Caerwyn. + +2003-09-04 Werner Koch <wk@gnupg.org> + + * pubkey.c (_gcry_pk_aliased_algo_name): New. + * ac.c (gcry_ac_open): Use it here. + + * Makefile.am (EXTRA_libcipher_la_SOURCES): Add serpent.c + +2003-09-02 Moritz Schulte <mo@g10code.com> + + * primegen.c (gcry_prime_check, gcry_prime_generate): New + functions. + (prime_generate_internal): New function, based on + _gcry_generate_elg_prime. + (_gcry_generate_elg_prime): Rewritten as a wrapper for + prime_generate_internal. + +2003-08-28 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_encrypt): Don't include the flags list in the + return value. This does not make sense and breaks any programs + parsing the output strictly (e.g. current gpgsm). + (gcry_pk_encrypt): If aliases for the algorithm name exists, take + the first one instead of the regular name to adhere to SPKI + conventions. + (gcry_pk_genkey): Ditto. + (gcry_pk_sign): Ditto. Removed unused KEY_ALGO_NAME. + +2003-08-19 Moritz Schulte <mo@g10code.com> + + * cipher.c: Add support for Serpent + * serpent.c: New file. + +2003-08-10 Moritz Schulte <moritz@g10code.com> + + * rsa.c (_gcry_rsa_blind, _gcry_rsa_unblind): Declare static. + +2003-08-09 Timo Schulz <twoaday@freakmail.de> + + * random.c (getfnc_gather_random): Don't check NAME_OF_DEV_RANDOM + two times, but also the NAME_OF_DEV_URANDOM device. + +2003-08-08 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_to_enc): Fixed extraction of S-Expression: do not + fail if no `flags' sub S-Expression is found. + +2003-07-27 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_lookup_func_oid): Allow for empty OID lists. + +2003-07-23 Moritz Schulte <moritz@g10code.com> + + * ac.c (gcry_ac_data_construct): New argument: include_flags, only + include `flags' S-expression, if include_flags is true. Adjust + callers. Thanks for triggering a bug caused by `flags' + sub-S-expression where they are not expected to Ralf Schneider. + +2003-07-21 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_lookup_func_name): Use new member name + `aliases' instead of `sexp_names'. + + * ac.c (gcry_ac_key_data_get): New function. + + * cipher.c (gcry_cipher_lookup_func_name): Fix return value. + +2003-07-20 Moritz Schulte <moritz@g10code.com> + + * blowfish.c: Adjusted for new gcry_cipher_spec_t structure. + * cast5.c: Likewise. + * twofish.c: Likewise. + * arcfour.c: Likewise. + * rijndael.c (rijndael_oids, rijndael192_oids, rijndael256_oids): + New variables, adjust for new gcry_cipher_spec_t structure. + * des.c (oids_tripledes): New variable, adjust for new + gcry_cipher_spec_t structure. + + * md.c (oid_table): Removed. + + * tiger.c (oid_spec_tiger): New variable. + (digest_spec_tiger): Adjusted for new gry_md_spec_t structure. + + * sha512.c (oid_spec_sha512): New variable. + (digest_spec_sha512): Adjusted for new gry_md_spec_t structure. + + * sha512.c (oid_spec_sha384): New variable. + (digest_spec_sha384): Adjusted for new gry_md_spec_t structure. + + * sha256.c (oid_spec_sha256): New variable. + (digest_spec_sha256): Adjusted for new gry_md_spec_t structure. + + * sha1.c (oid_spec_sha1): New variable. + (digest_spec_sha1): Adjusted for new gry_md_spec_t structure. + + * rmd160.c (oid_spec_rmd160): New variable. + (digest_spec_rnd160): Adjusted for new gry_md_spec_t structure. + + * md5.c (oid_spec_md5): New variable. + (digest_spec_md5): Adjusted for new gry_md_spec_t structure. + + * md4.c (oid_spec_md4): New variable. + (digest_spec_md4): Adjusted for new gry_md_spec_t structure. + + * crc.c (digest_spec_crc32, digest_spec_crc32_rfc1510, + digest_spec_crc32_rfc2440): Adjusted for new gry_md_spec_t + structure. + +2003-07-19 Moritz Schulte <moritz@g10code.com> + + * md.c (gcry_md_lookup_func_oid): New function. + (search_oid): New function, copied from cipher.c. + (gcry_md_map_name): Adjust for new search_oid_interface. + + * cipher.c (oid_table): Removed table. + (gcry_cipher_lookup_func_oid): New function. + (search_oid): Rewritten to use the module functions. + (gcry_cipher_map_name): Adjust for new search_oid interface. + (gcry_cipher_mode_from_oid): Likewise. + +2003-07-18 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Convert ERR to gpg_error_t in + gpg_strerror. + +2003-07-14 Moritz Schulte <moritz@g10code.com> + + * cipher.c (gcry_cipher_lookup_func_name): Also check the cipher + name aliases, not just the primary name. + (gcry_cipher_map_name): Remove kludge for aliasing Rijndael to + AES. + + * arcfour.c, blowfish.c, cast5.c, des.c, twofish.c: Adjust cipher + specification structures. + + * rijndael.c (rijndael_names, rijndael192_names, + rijndael256_names): New variables, use them in the cipher + specifications. + + * rmd160test.c: Removed file. + + * ac.c, arcfour.c, blowfish.c, cast5.c, cipher.c, des.c, dsa.c, + elgamal.c, md.c, pubkey.c, random.c, rijndael.c, rsa.c, twofish.c: + Used gcry_err* wrappers for libgpg symbols. + + * primegen.c (gen_prime): Correct the order arguments to + extra_check. + +2003-07-12 Moritz Schulte <moritz@g10code.com> + + * ac.c: Replaced all public occurences of gpg_error_t with + gcry_error_t. + * cipher.c: Likewise. + * md.c: Likewise. + * pubkey.c: Likewise. + * random.c: Likewise. + + * cipher.c: Added support for TWOFISH128. + +2003-07-08 Moritz Schulte <moritz@g10code.com> + + * ac.c (gcry_ac_data_copy_internal): New function, based on + gcry_ac_data_copy. + (gcry_ac_data_copy): Made public, use gcry_ac_data_copy_internal. + (gcry_ac_key_init): Use gcry_ac_data_copy_internal. + +2003-07-07 Moritz Schulte <moritz@g10code.com> + + * ac.c (gcry_ac_data_set): Only release old MPI value if it is + different from the new value. Bug reported by Simon Josefsson + <jas@extundo.com>. + + * pubkey.c (gcry_pk_list): New function. + * md.c (gcry_md_list): New function. + + * ac.c (gcry_ac_key_pair_generate): Fix calculation of format + string size. + +2003-07-05 Moritz Schulte <moritz@g10code.com> + + * md.c: Named struct of digest_table `digest_table_entry'. + (digest_table_entry): New member: algorithm; filled in. + (digest_table_entry): Removed unused member: flags. + (gcry_md_register): New argument: algorithm_id, filled in. + (gcry_md_register_default): Used algorithm ID from module + structure. + (gcry_md_map_name): Likewise. + (md_enable): Likewise. + (md_read): Likewise. + (gcry_md_info): Likewise. + + * pubkey.c: Named truct for pubkey_table `pubkey_table_entry'. + (pubkey_table_entry): New member: algorithm; filled in. + (gcry_pk_register_default): Used algorithm ID from pubkey_table. + (gcry_pk_register): New argument: algorithm_id, filled in. + (gcry_pk_map_name): Used algorithm ID from module structure. + (gcry_pk_decrypt): Likewise. + (gcry_pk_encrypt): Likewise. + (gcry_pk_verify): Likewise. + (gcry_pk_sign): Likewise. + (gcry_pk_testkey): Likewise. + (gcry_pk_genkey): Likewise. + (gcry_pk_get_nbits): Likewise. + (sexp_to_key): Removed unused variable: algo. + (sexp_to_sig): Likewise. + + * cipher.c: Named struct for cipher_table `cipher_table_entry'. + (cipher_table_entry): New member: algorithm; filled in. + (gcry_cipher_register_default): Used algorithm ID from + cipher_table. + (gcry_cipher_register): New argument: algorithm_id, filled in. + (gcry_cipher_map_name): Used algorithm ID from module structure. + + * arcfour.c (cipher_spec_arcfour): Removed algorithm ID. + * blowfish.c (cipher_spec_blowfish): Likewise. + * cast5.c (cipher_spec_cast5): Likewise. + * crc.c (digest_spec_crc32): Likewise. + * crc.c (digest_spec_crc32_rfc1510): Likewise. + * crc.c (digest_spec_crc32_rfc2440): Likewise. + * des.c (cipher_spec_des): Likewise. + * des.c (cipher_spec_tripledes): Likewise. + * dsa.c (pubkey_spec_dsa): Likewise. + * elgamal.c (pubkey_spec_elg): Likewise. + * md4.c (digest_spec_md4): Likewise. + * md5.c (digest_spec_md5): Likewise. + * aes.c (cipher_spec_aes): Likewise. + * aes.c (cipher_spec_aes192): Likewise. + * aes.c (cipher_spec_aes256): Likewise. + * rsa.c (pubkey_spec_rsa): Likewise. + * sha1.c (digest_spec_sha1): Likewise. + * sha256.c (digest_spec_sha256): Likewise. + * sha512.c (digest_spec_sha512): Likewise. + * tiger.c (digest_spec_tiger): Likewise. + * twofish.c (cipher_spec_twofish): Likewise. + * twofish.c (cipher_spec_twofish128): Likewise. + + * Makefile.am (EXTRA_libcipher_la_SOURCES): Fix list of source + files; reported by Simon Josefsson <jas@extundo.com>. + + * pubkey.c: Replaced all occurences of `id' with `algorithm', + since `id' is a keyword in obj-c. + * md.c: Likewise. + * cipher.c: Likewise. + + * crc.c, md4.c, md5.c, rmd160.c, sha1.c, sha256.c, tiger.c: + Replaced all occurences of gcry_digest_spec_t with gcry_md_spec_t. + + * dsa.c, rsa.c, elgamal.c: Replaced all occurencens of + gcry_pubkey_spec_t with gcry_pk_spec_t. + + * md.c: Replaced all occurences of gcry_digest_spec_t with + gcry_md_spec_t. + (gcry_digest_register_default): Renamed to ... + (gcry_md_register_default): ... this; adjusted callers. + (gcry_digest_lookup_func_name): Renamed to ... + (gcry_md_lookup_func_name): ... this; adjusted callers. + (gcry_digest_lookup_name): Renamed to ... + (gcry_md_lookup_name): ... this; adjusted callers. + (gcry_digest_register): Renamed to ... + (gcry_md_register): ... this. + (gcry_digest_unregister): Renamed to ... + (gcry_md_unregister): ... this. + + * pubkey.c (gcry_pubkey_register): Renamed to ... + (gcry_pk_register): ... this. + (gcry_pubkey_unregister): Renamed to ... + (gcry_pk_unregister): ... this. + Replaced all occurences of gcry_pubkey_spec_t with gcry_pk_spec_t. + (gcry_pubkey_register_default): Renamed to ... + (gcry_pk_register_default): ... this; adjusted callers. + (gcry_pubkey_lookup_func_name): Renamed to ... + (gcry_pk_lookup_func_name): ... this; adjusted callers. + (gcry_pubkey_lookup_name): Renamed to ... + (gcry_pk_lookup_name): ... this; adjusted callers. + + * md.c (gcry_md_hash_buffer): Fix error checking. Thanks to Simon + Josefsson <jas@extunde.com>. + +2003-07-04 Moritz Schulte <moritz@g10code.com> + + * cipher.c (gcry_cipher_list): New function. + +2003-07-01 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_to_sig): Accept a `flags' S-expression to be more + consistent with sexp_to_enc. + +2003-06-30 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (libcipher_la_SOURCES): Added: ac.c. + + * pubkey.c (_gcry_pk_module_lookup): New function. + (_gcry_pk_module_release): New function. + +2003-06-29 Moritz Schulte <moritz@g10code.com> + + * ac.c: New file. + +2003-06-26 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Trigger BUG correcly with new API. + +2003-06-19 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_is_enabled): Fixed. + +2003-06-18 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_get_algo_keylen): New. + (gcry_cipher_get_algo_blklen): New. + +2003-06-18 Moritz Schulte <moritz@g10code.com> + + * arcfour.c, cipher.c, blowfish.c, md.c, cast5.c, pubkey.c, crc.c, + des.c, dsa.c, elgamal.c, md4.c, md5.c, random.c, rijndael.c, + rmd160.c, rsa.c, sha1.c, sha256.c, sha512.c, tiger.c, twofish.c: + Replaced older types GcryDigestSpec, GcryCipherSpec and + GcryPubkeySpec with newer types: gcry_digest_spec_t, + gcry_cipher_spec_t and gcry_pubkey_spec_t. + + * md.c (gcry_digest_id_new): Removed function. + (gcry_digest_register): Removed code for generating a new module + ID. + + * pubkey.c (gcry_pubkey_id_new): Removed function. + (gcry_pubkey_register): Removed code for generating a new module + ID. + + * cipher.c, md.c, pubkey.c: Replace old type GcryModule with newer + one: gcry_module_t. + (gcry_cipher_id_new): Removed function. + (gcry_cipher_register): Removed code for generating a new module + ID. + + * cipher.c (gcry_cipher_register): Adjust call to + _gcry_module_add. + (gcry_cipher_register_default): Likewise. + * pubkey.c (gcry_pubkey_register_default): Likewise. + (gcry_pubkey_register): Likewise. + * md.c (gcry_digest_register_default): Likewise. + (gcry_digest_register): Likewise. + + * md.c (gcry_digest_lookup_func_id): Removed function. + (gcry_digest_lookup_id): Likewise. + (gcry_digest_id_new): Use _gcry_module_lookup_id instead of + gcry_digest_lookup_id. + (digest_algo_to_string): Likewise. + (check_digest_algo): Likewise. + (md_enable): Likewise. + (md_digest_length): Likewise. + (md_asn_oid): Likewise. + + * pubkey.c (gcry_pubkey_lookup_id): Removed function. + (gcry_pubkey_lookup_func_id): Likewise. + (gcry_pubkey_id_new): Use _gcry_module_lookup_id instead of + gcry_pubkey_id_new. + (gcry_pk_algo_name): Likewise. + (disable_pubkey_algo): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_get_npkey): Likewise. + (pubkey_get_nskey): Likewise. + (pubkey_get_nsig): Likewise. + (pubkey_get_nenc): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (gcry_pk_algo_info): Likewise. + + * cipher.c (gcry_cipher_lookup_func_id): Removed function. + (gcry_cipher_lookup_id): Likewise. + (cipher_algo_to_string): use _gcry_module_lookup_id instead of + gcry_cipher_lookup_id. + (disable_cipher_algo): Likewise. + (check_cipher_algo): Likewise. + (cipher_get_blocksize): Likewise. + (gcry_cipher_open): Likewise. + (gcry_cipher_id_new): Likewise. + +2003-06-17 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (GCRYPT_MODULES): Set to @GCRYPT_CIPHERS@, + @GCRYPT_PUBKEY_CIPHERS@, @GCRYPT_DIGESTS@ and @GCRYPT_RANDOM@. + (libcipher_la_DEPENDENCIES): Set to $(GCRYPT_MODULES). + (libcipher_la_LIBADD): Likewise. + (AM_CFLAGS): Added: @GPG_ERROR_CFLAGS@. + (EXTRA_libcipher_la_SOURCES): Added all conditional sources. + + * md.c (md_open): Use _gcry_fast_random_poll instead of + fast_random_poll. + * cipher.c (gcry_cipher_open): Likewise. + + * random.h (fast_random_poll): Removed macro. + + * blowfish.c, md4.c, md5.c, rmd160.c, sha1.c, sha256.c, sha512.c, + tiger.c: Use Autoconf's WORDS_BIGENDIAN instead of our own + BIG_ENDIAN_HOST. + +2003-06-16 Moritz Schulte <moritz@g10code.com> + + * random.c (getfnc_gather_random): Do not special-case + USE_ALL_RANDOM_MODULES, make it the default. + + * dsa.c: Replace last occurences of old type names with newer + names (i.e. replace MPI with gcry_mpi_t). + * elgamal.c: Likewise. + * primegen.c: Likewise. + * pubkey.c: Likewise. + * rsa.c: Likewise. + +2003-06-14 Moritz Schulte <moritz@g10code.com> + + * des.c (des_setkey): Add selftest check. + (tripledes_set3keys): Likewise. + (do_tripledes_setkey): Remove selftest check. + (do_des_setkey): Likewise. + +2003-06-11 Moritz Schulte <moritz@g10code.com> + + * md.c (_gcry_md_init): New function. + * cipher.c (_gcry_cipher_init): New function. + * pubkey.c (_gcry_pk_init): New function. + +2003-06-13 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_get_algo): Reverted to old API. This is a + convenience function anyway and error checking is not approriate. + (gcry_md_is_secure): New. + (gcry_md_is_enabled): New. + +2003-06-12 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_open): Make sure HANDLE is set to NULL on + error. + +2003-06-11 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_open): Make sure H receives either NULL or an + valid handle. + (gcry_md_copy): Swapped arguments so that it is more in lione with + md_open and most other API fucntions like memcpy (destination + comes first). Make sure HANDLE is set to NULL on error. + + * rijndael.c (do_encrypt): Hack to force correct alignment. It + seems not to be not sufficient, though. We should rework this + fucntions and remove all these ugly casts. Let the compiler + optimize or have an assembler implementation. + +2003-06-09 Moritz Schulte <moritz@g10code.com> + + * Makefile.am: Removed rules serpent, since that is not commited + yet. + +2003-06-08 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_encrypt): Improve calculation for size of the + format string. + +2003-06-07 Moritz Schulte <moritz@g10code.com> + + * arcfour.c, bithelp.h, blowfish.c, cast5.c, cipher.c, crc.c, + des.c, dsa.c, elgamal.c, md4.c, md5.c, md.c, primegen.c, pubkey.c, + rand-internal.h, random.c, random.h, rijndael.c, rmd160.c, + rmd160test.c, rmd.h, rndeged.c, rndlinux.c, rndunix.c, rndw32.c, + rsa.c, sha1.c, sha256.c, sha512.c, tiger.c, twofish.c: Edited all + preprocessor instructions to remove whitespace before the '#'. + This is not required by C89, but there are some compilers out + there that don't like it. Replaced any occurence of the now + deprecated type names with the new ones. + +2003-06-04 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_encrypt): Construct an arg_list and use + gcry_sexp_build_array instead of gcry_sexp_build. + (gcry_pk_sign): Likewise. + (gcry_pk_genkey): Likewise. + +2003-06-01 Moritz Schulte <moritz@g10code.com> + + * dsa.c (_gcry_dsa_generate): Do not check wether the algorithm ID + does indeed belong to DSA. + (_gcry_dsa_sign): Likewise. + (_gcry_dsa_verify): Likewise. + (_gcry_dsa_get_nbits): Likewise. + + * elgamal.c (_gcry_elg_check_secret_key): Do not check wether the + algorithm ID does indeed belong to ElGamal. + (_gcry_elg_encrypt): Likewise. + (_gcry_elg_decrypt): Likewise. + (_gcry_elg_sign): Likewise. + (_gcry_elg_verify): Likewise. + (_gcry_elg_get_nbits): Likewise. + (_gcry_elg_generate): Likewise. + + * rsa.c (_gcry_rsa_generate): Do not check wether the algorithm ID + does indeed belong to RSA. + (_gcry_rsa_encrypt): Likewise. + (_gcry_rsa_decrypt): Likewise. + (_gcry_rsa_sign): Likewise. + (_gcry_rsa_verify): Likewise. + (_gcry_rsa_get_nbits): Likewise. + +2003-05-30 Moritz Schulte <moritz@g10code.com> + + * md.c (md_get_algo): Return zero in case to algorithm is enabled. + + * md.c (gcry_md_info): Adjusted for new no-errno-API. + (md_final): Likewise. + (gcry_md_get_algo): Likewise. + * pubkey.c (gcry_pk_get_keygrip): Likewise. + (gcry_pk_ctl): Likewise. + (gcry_pk_algo_info): Likewise. + * des.c (selftest): Likewise. + +2003-05-29 Moritz Schulte <moritz@g10code.com> + + * md.c (md_enable): Do not forget to release module on error. + (gcry_md_open): Adjusted for new no-errno-API. + (md_open): Likewise. + (md_copy): Likewise. + (gcry_md_copy): Likewise. + (gcry_md_setkey): Likewise. + (gcry_md_algo_info): Likewise. + + * cipher.c (gcry_cipher_open): Adjusted for new no-errno-API and + also fixed a locking bug. + (gcry_cipher_encrypt): Adjusted for new no-errno-API. + (gcry_cipher_decrypt): Likewise. + (gcry_cipher_ctl): Likewise. + (gcry_cipher_info): Likewise. + (gcry_cipher_algo_info): Likewise. + +2003-05-28 Moritz Schulte <moritz@g10code.com> + + * md.c (md_enable): Adjusted for libgpg-error. + (gcry_md_enable): Likewise. + (gcry_digest_register_default): Likewise. + (gcry_digest_register): Likewise. + (check_digest_algo): Likewise. + (prepare_macpads): Likewise. + (gcry_md_setkey): Likewise. + (gcry_md_ctl): Likewise. + (gcry_md_get): Likewise. + (gcry_md_algo_info): Likewise. + (gcry_md_info): Likewise. + * dsa.c (_gcry_dsa_generate): Likewise. + (_gcry_dsa_check_secret_key): Likewise. + (_gcry_dsa_sign): Likewie. + (_gcry_dsa_verify): Likewise. + * twofish.c (do_twofish_setkey): Likewise. + (twofish_setkey): Likewise. + * cipher.c (gcry_cipher_register): Likewise. + +2003-05-25 Moritz Schulte <moritz@g10code.com> + + * rijndael.c (do_setkey): Adjusted for libgpg-error. + (rijndael_setkey): Likewise. + * random.c (gcry_random_add_bytes): Likewise. + * elgamal.c (_gcry_elg_generate): Likewise. + (_gcry_elg_check_secret_key): Likewise. + (_gcry_elg_encrypt): Likewise. + (_gcry_elg_decrypt): Likewise. + (_gcry_elg_sign): Likewise. + (_gcry_elg_verify): Likewise. + * rsa.c (_gcry_rsa_generate): Likewise. + (_gcry_rsa_check_secret_key): Likewise. + (_gcry_rsa_encrypt): Likewise. + (_gcry_rsa_decrypt): Likewise. + (_gcry_rsa_sign): Likewise. + (_gcry_rsa_verify): Likewise. + * pubkey.c (dummy_generate, dummy_check_secret_key, dummy_encrypt, + dummy_decrypt, dummy_sign, dummy_verify): Likewise. + (gcry_pubkey_register): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (sexp_elements_extract): Likewise. + (sexp_to_key): Likewise. + (sexp_to_sig): Likewise. + (sexp_to_enc): Likewise. + (sexp_data_to_mpi): Likewise. + (gcry_pk_encrypt): Likewise. + (gcry_pk_decrypt): Likewise. + (gcry_pk_sign): Likewise. + (gcry_pk_verify): Likewise. + (gcry_pk_testkey): Likewise. + (gcry_pk_genkey): Likewise. + (gcry_pk_ctl): Likewise. + * cipher.c (dummy_setkey): Likewise. + (check_cipher_algo): Likewise. + (gcry_cipher_open): Likewise. + (cipher_setkey): Likewise. + (gcry_cipher_ctl): Likewise. + (cipher_encrypt): Likewise. + (gcry_cipher_encrypt): Likewise. + (cipher_decrypt): Likewise. + (gcry_cipher_decrypt): Likewise. + (gcry_cipher_info): Likewise. + (gcry_cipher_algo_info): Likewise. + * cast5.c (cast_setkey): Likewise. + (do_cast_setkey): Likewise. + * arcfour.c (arcfour_setkey): Likewise. + (do_arcfour_setkey): Likewise. + * blowfish.c (do_bf_setkey): Likewise. + (bf_setkey): Likewise. + * des.c (do_des_setkey): Likewise. + (do_tripledes_setkey): Likewise. + +2003-05-22 Moritz Schulte <moritz@g10code.com> + + * tiger.c: Merged code ussing the U64_C macro from GnuPG. + + * sha512.c: Likewise. + +2003-05-17 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_genkey): Fix type: acquire a lock, instead of + releasing it. + +2003-05-11 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_testkey): Call REGISTER_DEFAULT_CIPHERS. + (gcry_pk_ctl): Likewise. + +2003-04-27 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_genkey): Release sexp after extracted data has + been used. + + * md.c (gcry_md_get_algo_dlen): Simplified, simply call + md_digest_length to do the job. + + * des.c (do_des_setkey): Check for selftest failure not only + during initialization. + (do_tripledes_setkey): Include check for selftest failure. + + * pubkey.c (gcry_pubkey_register_default): New macro + `pubkey_use_dummy', use it. + + * elgamal.c (elg_names): New variable. + (pubkey_spec_elg): Include elg_names. + + * dsa.c (dsa_names): New variable. + (pubkey_spec_dsa): Include dsa_names. + + * rsa.c (rsa_names): New variable. + (pubkey_spec_rsa): Include rsa_names. + + * pubkey.c (gcry_pubkey_lookup_func_name): Compare name also with + the names listed in `sexp_names'. + +2003-04-24 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_to_key): New variables: module, pubkey. Adjusted + to new module interface. + (sexp_to_key): Changend type of argument `retalgo' from `int *' to + `GcryModule **'. Adjusted all callers. Removed argument: + r_algotblidx. + (sexp_to_sig): Changend type of argument `retalgo' from `int *' to + `GcryModule **'. Adjusted all callers. + (sexp_to_enc): Likewise. + + (pubkey_get_npkey, pubkey_get_nskey, pubkey_get_nsig, + pubkey_get_nenc): Use strlen to find out the number. + + * rsa.c: Adjust pubkey_spec_rsa to new internal interface. + * dsa.c: Likewise. + * elgamal.c: Likewise. + +2003-04-17 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_elements_extract): New function. + * pubkey.c (sexp_to_key): Removed variable `idx', added `err', use + sexp_elements_extract. + (sexp_to_sig): Likewise. + (sexp_to_enc): Likewise. + + * pubkey.c: Terminate list correctly. + * md.c: Include sha512/sha384 in digest_table. + +2003-04-16 Moritz Schulte <moritz@g10code.com> + + * Makefile.am: Include support for sha512.c. + + * sha512.c: New file, merged from GnuPG, with few modifications + for libgcrypt. + + * rand-internal.h: Removed declarations for constructor functions. + + * md.c (md_copy): Call _gcry_module_use for incrementing the usage + counter of the digest modules. + + * rsa.c: Do not include "rsa.h". + * dsa.c: Do not include "dsa.h". + * elgamal.c: Do not include "elgamal.h". + * des.c: Do not include "des.h". + * cast5.c: Do not include "cast5.h". + * blowfish.c: Do not include "blowfish.h". + * arcfour.c: Do not include "arcfour.h". + + * Makefile.am (libcipher_la_DEPENDENCIES): Removed. + (libcipher_la_LIBADD): Removed. + Use Automake conditionals for conditional compilation. + +2003-04-13 Moritz Schulte <moritz@g10code.com> + + * cipher.c (gcry_cipher_open): Call REGISTER_DEFAULT_CIPHERS. + + * md.c (gcry_md_list): New member: module. + (md_enable): New variable: module, changed use of module and + digest. + (md_enable): Initialize member: module. + (md_close): Call _gcry_module_release. + + * cipher.c (gcry_cipher_open): New variable: module, changed use of + module and cipher. + (struct gcry_cipher_handle): New member: module. + (gcry_cipher_open): Initialize member: module. + (gcry_cipher_close): Call _gcry_module_release. + +2003-04-09 Moritz Schulte <moritz@g10code.com> + + * cipher.c: Include "ath.h". + * md.c: Likewise. + * pubkey.c: Likewise. + + * cipher.c (ciphers_registered_lock): New variable. + * md.c (digests_registered_lock): New variable. + * pubkey.c (pubkeys_registered_lock): New variable. + + * rndlinux.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndlinux_constructor): Removed function. + + * rndegd.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndegd_constructor): Removed function. + + * rndunix.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndunix_constructor): Removed function. + + * rndw32.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndw32_constructor): Removed function. + + * rndegd.c (rndegd_connect_socket): Simplify code for creating the + egd socket address. + (rndegd_connect_socket): Call log_fatal use instead of + g10_log_fatal. + (egd_gather_random): Renamed to ... + (rndegd_gather_random): ... here. + +2003-04-08 Moritz Schulte <moritz@g10code.com> + + * rndlinux.c: Do not include "dynload.h". + * rndunix.c: Likewise. + * rndw32.c: Likewise. + + * rndegd.c (rndegd_connect_socket): Factored out from ... + (egd_gather_random): here; call it. + (egd_socket): New variable. + (egd_gather_random): Initialize fd with egd_socket, do not declare + fd static. + (do_read): Merged few changes from GnuPG. FIXME - not finished? + Do not include "dynload.h". + + * rndw32.c (gather_random): Renamed to rndw32_gather_random, do + not declare static. + (gather_random_fast): Renamed to rndw32_gather_random_fast, do not + declare static. + + * rndunix.c (gather_random): Renamed to rndunix_gather_random, do + not declare static. + * rndegd.c (gather_random): Renamed to rndegd_gather_random, do + not declare static. + * rndlinux.c (gather_random): Renamed to rndlinux_gather_random, + do not declare static. + +2003-04-07 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (libcipher_la_SOURCES): Removed construct.c. + (libcipher_la_SOURCES): Added sha1.c, sha256.c, rmd160.c, md4.c, + md5.c, tiger.c and crc.c + (EXTRA_PROGRAMS): Removed sha1, sha256, rmd160, md4, md5, tiger + and crc. Removed definitions: EXTRA_md4_SOURCES, + EXTRA_md5_SOURCES, EXTRA_rmd160_SOURCES, EXTRA_sha1_SOURCES, + EXTRA_sha256_SOURCES, EXTRA_tiger_SOURCES and EXTRA_crc_SOURCES, + BUILT_SOURCES, DISTCLEANFILES. + + * pubkey.c: Do not include "elgamal.h", "dsa.h" and "rsa.h". + + * Makefile.am (libcipher_la_SOURCES): Removed rsa.h, elgamal.h, + dsa.h, des.h, cast5.h, arcfour.h and blowfish.h. + + * rsa.h: Removed file. + * elgamal.h: Removed file. + * dsa.h: Removed file. + * des.h: Removed file. + * cast5.h: Removed file. + * arcfour.h: Removed file. + * blowfish.h: Removed file. + + * Makefile.am (libcipher_la_SOURCES): Removed dynload.c and + dynload.h. + + * rsa.c (pubkey_spec_rsa): New variable. + * dsa.c (pubkey_spec_rsa): New variable. + * elgamal.c (pubkey_spec_elg): New variable. + + * rsa.c (_gcry_rsa_get_info): Removed function. + * elgamal.c (_gcry_elg_get_info): Removed function. + * dsa.c (_gcry_dsa_get_info): Removed function. + + * tiger.c (tiger_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_tiger_constructor): Removed function. + + * sha1.c (sha1_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_sha1_constructor): Removed function. + + * sha256.c (sha256_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_sha256_constructor): Removed function. + + * rmd160.c (rmd160_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rmd160_constructor): Removed function. + + * md5.c (md5_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_md5_constructor): Removed function. + + * md4.c (md4_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_md4_constructor): Removed function. + + * crc.c (crc_get_info): Removed function. + + * arcfour.c (do_arcfour_setkey): Changed type of context argument + to `void *', added local variable for cast, adjusted callers. + (arcfour_setkey): Likewise. + (encrypt_stream): Likewise. + * cast5.c (cast_setkey): Likewise. + (encrypt_block): Likewise. + * rijndael.c (rijndael_setkey): Likewise. + (rijndael_encrypt): Likewise. + (rijndael_decrypt): Likewise. + * twofish.c (twofish_setkey): Likewise. + (twofish_encrypt): Likewise. + (twofish_decrypt): Likewise. + * des.c (do_des_setkey): Likewise. + (do_des_encrypt): Likewise. + (do_des_encrypt): Likewise. + (do_tripledes_encrypt): Likewise. + (do_tripledes_encrypt): Likewise. + * blowfish.c (bf_setkey: Likewise. + (encrypt_block): Likewise. + (decrypt_block): Likewise. + + * arcfour.c (encrypt_stream): Likewise. + + * rijndael.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func) Removed function. + + * twofish.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func) Removed function. + + * cast5.c (CIPHER_ALGO_CAST5): Removed. + + * blowfish.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Removed macros. + (CIPHER_ALGO_BLOWFISH): Removed symbol. + * cast5.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Likewise. + * des.c (selftest_failed): Removed. + (initialized): New variable. + (do_des_setkey): Run selftest, if not yet done. + (FNCCAST_SETKEY, FNCCAST_CRYPT): Removed macros. + + * arcfour.c (_gcry_arcfour_get_info): Removed function. + * blowfish.c (_gcry_blowfish_get_info): Removed function. + * cast5.c (_gcry_cast5_get_info): Removed function. + * des.c (_gcry_des_get_info): Removed function. + * rijndael.c (_gcry_rijndael_get_info): Removed function. + * twofish.c (_gcry_twofish_get_info): Removed function. + + * arcfour.c (cipher_spec_arcfour): New variable. + * twofish.c (cipher_spec_twofish, cipher_spec_twofish128): New + variables. + * rijndael.c (cipher_spec_aes, cipher_spec_aes192, + cipher_spec256): New variables. + * des.c (cipher_spec_des, cipher_spec_tripledes): New variables. + * cast5.c (cipher_spec_cast5): New variable. + * blowfish.c (cipher_spec_blowfish): Likewise. + + * twofish.c: Do not include "dynload.h". + * rijndael.c: Likewise. + * des.c: Likewise. + * cast5.c: Likewise. + * blowfish.c: Likewise. + * cipher.c: Likewise. + * crc.c: Likewise. + * md4.c: Likewise. + * md5.c: Likewise. + * md.c: Likewise. + * pubkey.c: Likewise. + * rijndael.c: Likewise. + * sha1.c: Likewise. + * sha256.c: Likewise. + + * arcfour.c: Include "cipher.h". + * twofish.c: Likewise. + * rijndael.c: Likewise. + * des.c: Likewise. + * cast5.c: Likewise. + * blowfish.c: Likewise. + + * twofish.c (twofish_setkey): Declared argument `key' const. + (twofish_encrypt): Declared argument `inbuf' const. + (twofish_decrypt): Likewise. + + * rijndael.c (rijndael_setkey): Declared argument `key' const. + (rijndael_encrypt): Declared argument `inbuf' const. + (rijndael_decrypt): Likewise. + + * des.c (do_des_setkey): Declared argument `key' const. + (do_tripledes_setkey): Likewise. + (do_des_encrypt): Declared argument `inbuf' const. + (do_des_decrypt): Likewise. + (do_tripledes_encrypt): Likewise. + (do_tripledes_decrypt): Likewise. + + * cast5.c (encrypt_block): Declared argument `inbuf' const. + (decrypt_block): Likewise. + (cast_setkey): Declared argument `key' const. + + * blowfish.c (do_bf_setkey): Declared argument `key' const. + (encrypt_block): Declared argument `inbuf' const. + (encrypt_block): Likewise. + + + + * cipher.c: Remove CIPHER_ALGO_DUMMY related code. + Removed struct cipher_table_s. + Changed definition of cipher_table. + Removed definition of disabled_algos. + (ciphers_registered, default_ciphers_registered): New variables. + (REGISTER_DEFAULT_CIPHERS): New macro. + (dummy_setkey): Declared argument `key' const. + (dummy_encrypt_block): Declared argument `inbuf' const. + (dummy_encrypt_block): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_setkey): Use `unsigned char' instead of `byte'. + (dummy_encrypt_block): Likewise. + (dummy_decrypt_block): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_decrypt_stream): Likewise. + (gcry_cipher_register_default): New function. + (gcry_cipher_lookup_func_id): New function. + (gcry_cipher_lookup_func_name): New function. + (gcry_cipher_lookup_id): New function. + (gcry_cipher_lookup_name): New function. + (gcry_cipher_id_new): New function. + (gcry_cipher_register): New function. + (gcry_cipher_unregister): New function. + (setup_cipher_table): Removed function. + (load_cipher_modules): Removed function. + (gcry_cipher_map_name): Adjusted to use new module management. + (cipher_algo_to_string): Likewise. + (disable_cipher_algo): Likewise. + (check_cipher_algo): Likewise. + (cipher_get_keylen): Likewise. + (cipher_get_blocksize): Likewise. + (gcry_cipher_open): Likewise. + (struct gcry_cipher_handle): Replaced members algo, algo_index, + blocksize, setkey, encrypt, decrypt, stencrypt, stdecrypt with one + member: cipher. + (gcry_cipher_open): Adjusted code for new handle structure. + (cipher_setkey): Likewise. + (cipher_setiv): Likewise. + (cipher_reset): Likewise. + (do_ecb_encrypt): Likewise. + (do_ecb_decrypt): Likewise. + (do_cbc_encrypt): Likewise. + (do_cbc_decrypt): Likewise. + (do_cfb_encrypt): Likewise. + (do_cfb_decrypt): Likewise. + (do_ctr_encrypt): Likewise. + (cipher_encrypt): Likewise. + (gcry_cipher_encrypt): Likewise. + (cipher_decrypt): Likewise. + (gcry_cipher_decrypt): Likewise. + (cipher_sync): Likewise. + (gcry_cipher_ctl): Likewise. + + * pubkey.c: Removed struct pubkey_table_s. + Changed definition of pubkey_table. + Removed definition of disabled_algos. + (pubkeys_registered, default_pubkeys_registered): New variables. + (REGISTER_DEFAULT_PUBKEYS): New macro. + (setup_pubkey_table): Removed function. + (load_pubkey_modules): Removed function. + (gcry_pubkey_register_default): New function. + (gcry_pubkey_lookup_func_id): New function. + (gcry_pubkey_lookup_func_name): New function. + (gcry_pubkey_lookup_id): New function. + (gcry_pubkey_lookup_name): New function. + (gcry_pubkey_id_new): New function. + (gcry_pubkey_register): New function. + (gcry_pubkey_unregister): New function. + (gcry_pk_map_name): Adjusted to use new module management. + (gcry_pk_algo_name): Likewise. + (disable_pubkey_algo): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_get_npkey): Likewise. + (pubkey_get_nskey): Likewise. + (pubkey_get_nsig): Likewise. + (pubkey_get_nenc): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (gcry_pk_get_nbits): Likewise. + (gcry_pk_algo_info): Likewise. + + * md.c: Removed struct md_digest_list_s. + (digest_list): Changed definition. + (digests_registered, default_digests_registered): New variables. + (REGISTER_DEFAULT_DIGESTS): New macro. + (new_list_item): Removed function. + (setup_md_table): Removed function. + (load_digest_module): Removed function. + (gcry_digest_register_default): New function. + (gcry_digest_lookup_func_id): New function. + (gcry_digest_lookup_func_name): New function. + (gcry_digest_lookup_id): New function. + (gcry_digest_lookup_name): New function. + (gcry_digest_id_new): New function. + (gcry_digest_register): New function. + (gcry_digest_unregister): New function. + (GcryDigestEntry): New type. + (struct gcry_md_context): Adjusted type of `list'. + (gcry_md_map_name): Adjusted to use new module management. + (digest_algo_to_string): Likewise. + (check_digest_algo): Likewise. + (md_enable): Likewise. + (md_digest_length): Likewise. + (md_asn_oid): Likewise. + +2003-04-07 Moritz Schulte <moritz@g10code.com> + + * pubkey.c: Replaced PUBKEY_ALGO_DSA with GCRY_PK_DSA, + PUBKEY_ALGO_RSA with GCRY_PK_RSA and PUBKEY_ALGO_ELGAMAL with + GCRY_PK_ELG. + + * dsa.c: Replaced PUBKEY_ALGO_DSA with GCRY_PK_DSA. + +2003-04-01 Moritz Schulte <moritz@g10code.com> + + * des.c: Removed checks for GCRY_CIPHER_3DES and GCRY_CIPHER_DES. + +2003-03-31 Moritz Schulte <moritz@g10code.com> + + * tiger.c (tiger_get_info): Do not declare static. + * sha256.c (sha256_get_info): Likewise. + * sha1.c (sha1_get_info): Likewise. + * rmd160.c (rmd160_get_info): Likewise. + * md5.c (md5_get_info): Likewise. + * md4.c (md4_get_info): Likewise. + * crc.c (crc_get_info): Likewise. + + * md.c (load_digest_module): Call setup_md_table during + initialization. + (new_list_item): Link new element into digest_list. + + * cipher.c (do_ctr_decrypt): Made do_ctr_encrypt act as a wrapper + for do_ctr_encrypt, since these functions are identical. + +2003-03-30 Simon Josefsson <jas@extundo.com> + + * cipher.c (struct gcry_cipher_handle): Add counter field. + (gcry_cipher_open): Add CTR. + (cipher_reset): Clear counter field. + (do_ctr_encrypt, do_ctr_decrypt): New functions. + (cipher_encrypt, cipher_decrypt): Call CTR functions. + (gcry_cipher_ctl): Add SET_CTR to set counter. + +2003-03-30 Moritz Schulte <moritz@g10code.com> + + * rsa.c (_gcry_rsa_blind): New function. + (_gcry_rsa_unblind): New function. + (_gcry_rsa_decrypt): Use _gcry_rsa_blind and _gcry_rsa_decrypt. + +2003-03-26 Moritz Schulte <moritz@g10code.com> + + * dynload.c (_gcry_enum_gnupgext_pubkeys): Adjust `encrypt' and + `decrypt' function arguments. + (_gcry_enum_gnupgext_pubkeys): Likewise. + * dynload.h: Likewise. + + * pubkey.c (dummy_decrypt): Add argument: int flags. + (dummy_encrypt): Likewise. + + * elgamal.c (_gcry_elg_encrypt): Add argument: int flags. + (_gcry_elg_decrypt): Likewise. + + * rsa.c (_gcry_rsa_encrypt): Add argument: int flags. + (_gcry_rsa_decrypt): Likewise. + + * pubkey.c: Add `flags' argument to members `encrypt' and + `decrypt' of struct `pubkey_table_s'. + + * rsa.h: Add `flags' argument to function declarations. + * elgamal.h: Likewise. + + * pubkey.c (sexp_data_to_mpi): New variable: int parsed_flags. + (sexp_data_to_mpi): Set `parsed_flags'. + (sexp_data_to_mpi): New argument: int *flags. + (gcry_pk_encrypt): New variable: int flags. + (gcry_pk_encrypt): Pass `flags' to pubkey_encrypt. + (pubkey_encrypt): New variable: int flags. + (pubkey_encrypt): Pass `flags' to pubkey encrypt function. + (pubkey_decrypt): Likewise. + (pubkey_decrypt): Pass `flags' to pubkey encrypt function. + (gcry_pk_encrypt): Include `flags' s-exp in return list. + (sexp_to_enc): New argument: int *flags. + (gcry_pk_decrypt): New variable: int flags. + (gcry_pk_decrypt): Pass `flags' to pubkey_decrypt. + (sexp_to_enc): New variable: int parsed_flags. + (sexp_to_enc): Set `parsed_flags'. + +2003-03-22 Simon Josefsson <jas@extundo.com> + + * cipher.c (gcry_cipher_open, do_cbc_encrypt) + (gcry_cipher_encrypt): Support GCRY_CIPHER_CBC_MAC. + (gcry_cipher_ctl): Support GCRYCTL_SET_CBC_MAC. + +2003-03-19 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): New args EXTRA_CHECK and EXTRA_CHECK_ARG + to allow for a user callback. Changed all callers. + (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Ditto, pass them to gen_prime. + * rsa.c (check_exponent): New. + (generate): Use a callback to ensure that a given exponent is + actually generated. + +2003-03-12 Moritz Schulte <moritz@g10code.com> + + * primegen.c: Initialize `no_of_small_prime_numbers' statically. + (gen_prime): Remove calculation of `no_of_small_prime_numbers'. + +2003-03-03 Moritz Schulte <moritz@g10code.com> + + * md.c (gcry_md_ctl): Rewritten to use same style like the other + functions dispatchers. + +2003-03-02 Moritz Schulte <moritz@g10code.com> + + * cipher.c (struct gcry_cipher_handle): New member: algo_index. + (gcry_cipher_open): Allocate memory for two cipher contexts. + Initialize algo_index. + (cipher_setkey): Duplicate context into reserved memory. + (cipher_reset): New function, which resets the context and clear + the IV. + (gcry_cipher_ctl): Call cipher_reset. + +2003-02-23 Moritz Schulte <moritz@g10code.com> + + * cipher.c: Remove (bogus) `digitp' macro definition. + * md.c: Likewise. + + * blowfish.c (burn_stack): Removed. + * arcfour.c (burn_stack): Likewise. + * cast5.c (burn_stack): Likewise. + * des.c (burn_stack): Likewise. + * md4.c (burn_stack): Likewise. + * md5.c (burn_stack): Likewise. + * random.c (burn_stack): Likewise. + * rijndael.c (burn_stack): Likewise. + * rmd160.c (burn_stack): Likewise. + * sha1.c (burn_stack): Likewise. + * sha256.c (burn_stack): Likewise. + * tiger.c (burn_stack): Likewise. + * twofish.c (burn_stack): Likewise. + + * blowfish.c: Changed all occurences of burn_stack to + _gcry_burn_stack. + * arcfour.c: Likewise. + * cast5.c: Likewise. + * des.c: Likewise. + * md4.c: Likewise. + * md5.c: Likewise. + * random.c: Likewise. + * rijndael.c: Likewise. + * rmd160.c: Likewise. + * sha1.c: Likewise. + * sha256.c: Likewise. + * tiger.c: Likewise. + * twofish.c: Likewise. + + * arcfour.c (_gcry_arcfour_get_info): Use GCRY_CIPHER_ARCFOUR + instead of hard-coded value `301'. + +2003-01-24 Werner Koch <wk@gnupg.org> + + * random.c (_gcry_register_random_progress): New. + (_gcry_random_progress): New. + + * rndlinux.c (gather_random): Call the random progress function. + +2003-01-23 Werner Koch <wk@gnupg.org> + + * rsa.c (generate): New arg USE_E to request a specific public + exponent. + (_gcry_rsa_generate): Ditto. + * elgamal.c (_gcry_elg_generate): Must add an dummy argument + instead of USE_E. + * dsa.c (_gcry_dsa_generate): Ditto. + * pubkey.c (dummy_generate): Ditto. + (pubkey_generate): Add USE_E arg and pass it down. + (gcry_pk_genkey): Detect "rsa-use-e" parameter and pass it to generate. + + * pubkey.c (sexp_to_enc): New arg RET_MODERN. + (gcry_pk_decrypt): Make use of it to return a real S-expression. + Return better error codes. + (gcry_pk_verify): Return better error codes. + +2003-01-21 Werner Koch <wk@gnupg.org> + + * random.c (gcry_random_add_bytes): Add QUALITY argument, let + function return an error code and disable its core for now. + +2003-01-21 Timo Schulz <twoaday@freakmail.de> + + * random.c (gcry_random_add_bytes): New. Function to add external + random to the pool. + +2003-01-20 Simon Josefsson <jas@extundo.com> + + * crc.c: New. + * Makefile.am (EXTRA_PROGRAMS, EXTRA_crc_SOURCES): Add crc.c. + * md.c (gcry_md_get_algo_dlen): Add values for CRC. + +2003-01-20 Werner Koch <wk@gnupg.org> + + * sha256.c: New. + * bithelp.h (ror): New. + * Makfile.am: Add sha256.c. + * md.c (oid_table): Add values for SHA256 et al. + (gcry_md_get_algo_dlen): Likewise + +2003-01-20 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_get_keygrip): Implemented keygrips for DSA + and ElGamal. + +2003-01-17 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_encrypt): Reworked so that the output will + never contain the plaintext even if the caller did not checked the + return value. + + * md.c (gcry_md_get_algo): Changed error code to GCRYERR_GENERAL + because we don't have an invalid md algo but no algorithm enabled. + + * pubkey.c (gcry_pk_genkey): Changed error code for bounds check + of table parameters to GCRYERR_INTERNAL. + + * md.c (gcry_md_open): Partly reverted Timo's change from + 2002-10-10 by removing the check for the algorithm. An algorithm + of 0 is allowed and anyway we should not double check it or check + it using a different function. Also fixed the flags check. + + * pubkey.c (gcry_pk_encrypt): Make sure that R_CIPH points to NULL + on error. + (gcry_pk_decrypt): Ditto for R_PLAIN. + (gcry_pk_sign): Ditto for R_SIG. + (gcry_pk_genkey): Ditto for R_KEY. + +2003-01-16 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_write): Changed 2nd argument type to void*. + (gcry_md_hash_buffer): Changed type of boths buffers to void*. + (gcry_md_setkey): Changed 2nd argument type to void*. + +2003-01-15 Werner Koch <wk@gnupg.org> + + * pubkey.c (sexp_data_to_mpi): New. This handles pkcs1 padding. + (gcry_pk_sign, gcry_pk_verify): Use it here. + (gcry_pk_encrypt): And here. + (pubkey_verify): Add debug code. + (sexp_to_enc): Handle flags in the input and return the pkcs1 flag + in a new parameter. + (gcry_pk_decrypt): Prepare for future pkcs1 handling. + +2002-12-19 Werner Koch <wk@gnupg.org> + + * random.c (_gcry_random_initialize): New. + +2002-12-16 Werner Koch <wk@gnupg.org> + + * cipher.c: Added a Teletrust specific OID for 3DES. + +2002-12-12 Werner Koch <wk@gnupg.org> + + * md.c: Added another oddball OIW OID (sha-1WithRSAEncryption). + +2002-11-23 Werner Koch <wk@gnupg.org> + + * md.c (load_digest_module): Enlarged checked_algos bitmap. + * md4.c (func_table): Fixed entry for md4. + Both by Simon Josephson. + (transform): Copy data to get the alignment straight. Tested only + on i386. + +2002-11-10 Simon Josefsson <jas@extundo.com> + + * cipher.c (gcry_cipher_open): Don't reject CTS flag. + (do_cbc_encrypt, do_cbc_decrypt, cipher_encrypt) + (gcry_cipher_encrypt, cipher_decrypt) + (gcry_cipher_decrypt): Support CTS flag. + (gcry_cipher_ctl): Toggle CTS flag. + +2002-11-10 Werner Koch <wk@gnupg.org> + + * md4.c: New. By Simon Josefsson. + * Makefile.am (EXTRA_PROGRAMS): Add md4.c. + * md.c (oid_table,gcry_md_get_algo_dlen): MD4 support. + +2002-10-14 Werner Koch <wk@gnupg.org> + + * arcfour.c (do_encrypt_stream): Don't use increment op when + assigning to the same variable. + +2002-10-10 Timo Schulz <ts@winpt.org> + + * pubkey.c (gcry_pk_genkey): Check boundaries. + + * md.c (gcry_md_open): Check that algo is available and only + valid flag values are used. + (gcry_md_get_algo): Add error handling. + +2002-09-26 Werner Koch <wk@gnupg.org> + + * md.c: Include an OID for TIGER. + * tiger.c (tiger_get_info): Use a regular OID. + +2002-09-17 Werner Koch <wk@gnupg.org> + + * random.c: Replaced mutex.h by the new ath.h. Changed all calls. + +2002-09-16 Werner Koch <wk@gnupg.org> + + * arcfour.c (do_encrypt_stream): Use register modifier and modulo. + According to Nikos Mavroyanopoulos this increases perfromace on + i386 system noticable. And I always tought gcc is clever enough. + * md5.c (transform): Use register modifier. + * rmd160.c (transform): Ditto. + * sha1.c (transform): Ditto. We hope that there are 6 free registers. + * random.c (gcry_randomize): Rewrote to avoid malloc calls. + + * rndlinux.c (gather_random): Replaced remaining fprintfs by log_*. + * arcfour.c (do_arcfour_setkey): Ditto. + * twofish.c (do_twofish_setkey): Ditto. + * rndegd.c (gather_random): Ditto. + * rijndael.c (do_setkey): Ditto. + * random.c (_gcry_random_dump_stats): Ditto. + * primegen.c (_gcry_generate_elg_prime): Ditto. + * des.c (_gcry_des_get_info): Ditto. + * cast5.c (do_cast_setkey): Ditto. + * blowfish.c (do_bf_setkey): Ditto. + +2002-08-26 Werner Koch <wk@gnupg.org> + + * des.c (weak_keys): Fixed one entry in the table and compared + all entries against the literature. + (selftest): Checksum the weak key table. + +2002-08-21 Werner Koch <wk@gnupg.org> + + * pubkey.c: Enable keygrip calculation for "openpgp-rsa". + +2002-08-17 Werner Koch <wk@gnupg.org> + + * cipher.c (setup_cipher_table): Don't overwrite the DES entry + with the entry for DUMMY. + +2002-08-14 Werner Koch <wk@gnupg.org> + + * des.c (do_des_setkey,do_des_encrypt, do_des_decrypt): New. + (_gcry_des_get_info): Support plain old DES. + * cipher.c (setup_cipher_table): Put DES into the table. + +2002-07-25 Werner Koch <wk@gnupg.org> + + * rndunix.c (_gcry_rndunix_constructor): Prefixed with _gcry_. + Noted by Stephan Austermuehle. + +2002-07-08 Timo Schulz <ts@winpt.org> + + * rndw32.c: Replaced the m_ memory functions with the real + gcry_ functions. Renamed all g10_ prefixed functions to log_. + +2002-06-12 Werner Koch <wk@gnupg.org> + + * rsa.c (generate): Use e = 65537 for now. + +2002-06-11 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_get_keygrip): Allow a "protected-private-key". + +2002-06-05 Timo Schulz <ts@winpt.org> + + * cipher.c (gcry_cipher_encrypt, gcry_cipher_decrypt): + Check that the input size is a multiple of the blocksize. + +2002-05-23 Werner Koch <wk@gnupg.org> + + * md.c (oid_table): Add an rsadsi OID for MD5. + +2002-05-21 Werner Koch <wk@gnupg.org> + + * primegen.c, elgamal.c, dsa.c (progress): Do not print anything + by default. Pass an extra identifying string to the callback and + reserved 2 argumenst for current and total counters. Changed the + register function prototype. + +2002-05-17 Werner Koch <wk@gnupg.org> + + * rndegd.c (rndegd_constructor): Fixed name of register function + and prefixed the function name with _gcry_. + * rndw32.c (rndw32_constructor): Ditto. + * tiger.c (tiger_constructor): Ditto. + + * Makefile.am: Removed all dynamic loading stuff. + * dynload.c: Ditto. Now only used for the constructor system. + +2002-05-15 Werner Koch <wk@gnupg.org> + + * random.c (gcry_random_bytes,gcry_random_bytes_secure) + (gcry_randomize): Make sure we are initialized. + +2002-05-14 Werner Koch <wk@gnupg.org> + + Changed license of most files to the LGPL. + +2002-05-02 Werner Koch <wk@gnupg.org> + + * random.c (_gcry_fast_random_poll): Initialize the module so the + mutex can be used. + + * primegen.c (small_prime_numbers): Moved table from smallprime.c + * smallprime.c: File removed. + + * des.c (leftkey_swap, rightkey_swap, working_memcmp): Made static. + + * cipher.c (gcry_cipher_map_name): Map "RIJNDAEL" to "AES". + * rijndael.c (rijndael_get_info): We do only support a 128 bit + blocksize so it makes sense to change the algorithm strings to + AES. + + * tiger.c (tiger_final): Removed superfluous token pasting operators. + * md5.c (md5_final): Ditto. + +2002-04-30 Werner Koch <wk@gnupg.org> + + * cipher.c: Fixed list of copyright years. + +2002-03-18 Werner Koch <wk@gnupg.org> + + * random.c (initialize): Initialize the new pool lock mutex. + (_gcry_fast_random_poll): Add locking and moved main + code out to... + (do_fast_random_poll): new function. + (read_pool): Use the new function here. + (get_random_bytes): Add locking. + (_gcry_update_random_seed_file): Ditto. + +2002-03-11 Werner Koch <wk@gnupg.org> + + * md.c: Add rsaSignatureWithripemd160 to OID table. + +2002-02-20 Werner Koch <wk@gnupg.org> + + * sha1.c: Removed a left over comment note. The code has been + rewritten from scratch in 1998. Thanks to Niels Möller for + reporting this misleading comment. + +2002-02-18 Werner Koch <wk@gnupg.org> + + * rndunix.c (rndunix_constructor): Use the the new prefixed + function name. Reported by Jordi Mallach. + +2002-02-10 Werner Koch <wk@gnupg.org> + + * random.c (mix_pool): Carry an extra failsafe_digest buffer + around to make the function more robust. + +2002-02-08 Werner Koch <wk@gnupg.org> + + * random.c (add_randomness): Xor new data into the pool and not + just copy it. This avoids any choosen input attacks which are not + serious in our setting because an outsider won't be able to mix + data in and even then we keep going with a PRNG. Thanks to Stefan + Keller for pointing this out. + +2002-01-04 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_genkey): Do not release skey - it is static. + + * primegen.c (gen_prime): Of course we should use set_bit + and not set_highbit to set the second high bit. + +2001-12-18 Werner Koch <wk@gnupg.org> + + * rsa.c (generate): Loop until we find the exact modulus size. + Changed the exponent to 41. + (rsa_get_info): s/usage/r_usage/ to avoid shadow warnings. + * primegen.c (gen_prime): Set 2 high order bits for secret primes. + + * Makefile.am (DISTCLEANFILES): Include construct.c. + +2001-12-17 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_get_keygrip): New - experimental. + +2001-12-11 Werner Koch <wk@gnupg.org> + + * cipher.c: Added OIDs for AES. + (gcry_cipher_mode_from_oid): New. + (gcry_cipher_map_name): Moved OID search code to .. + (search_oid): .. new function. + +2001-12-10 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_encrypt): Find the signature algorithm by name + and not by number. + + * pubkey.c (gcry_pk_encrypt,gcry_pk_decrypt,gcry_pk_sign) + (gcry_pk_verify,gcry_pk_testkey, gcry_pk_genkey) + (gcry_pk_get_nbits): Release the arrays. Noted by Nikos + Mavroyanopoulos. + +2001-12-06 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_map_name): Look also for OIDs prefixed + with "oid." or "OID.". + +2001-12-05 Werner Koch <wk@gnupg.org> + + * pubkey.c (algo_info_table): Fixed entry for openpgp-rsa. + +2001-11-24 Werner Koch <wk@gnupg.org> + + * pubkey.c: Added the rsaEncryption OID to the tables. + (sexp_to_key): Add an arg to return the index of the algorithm, + changed all callers. + (gcry_pk_sign): Find the signature algorithm by name and not by + number. + (gcry_pk_get_nbits): Fixed so that we can now really pass a secret + key to get the result. + + * md.c (gcry_md_map_name): Look also for OIDs prefixed with "oid." + or "OID." so that an OID string can be used as an S-Exp token. + +2001-11-20 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_map_name): Lookup by OID if the the name begins + with a digit. + (oid_table): New. + +2001-11-16 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_info): New operator GCRYCTL_IS_ALGO_ENABLED. + +2001-11-07 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Close the handle which was left open + for algorithms other than rmd160. + +2001-08-08 Werner Koch <wk@gnupg.org> + + * rndw32.c (gather_random): Use toolhelp in addition to the NT + gatherer for Windows2000. Suggested by Sami Tolvanen. + + * random.c (read_pool): Fixed length check, this used to be one + byte to strict. Made an assert out of it because the caller has + already made sure that only poolsize bytes are requested. + Reported by Marcus Brinkmann. + +2001-08-03 Werner Koch <wk@gnupg.org> + + * cipher.c (cipher_encrypt, cipher_decrypt): Prepare to return + errors. We have to change the interface to all ciphers to make + this really work but we should do so to prepare for hardware + encryption modules. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Return the error and + set lasterr. + (gcry_cipher_ctl): Make sure that errors from setkey are returned. + +2001-08-02 Werner Koch <wk@gnupg.org> + + * rndlinux.c (gather_random): casted a size_t arg to int so that + the format string is correct. Casting is okay here and avoids + translation changes. + + * random.c (fast_random_poll): Do not check the return code of + getrusage. + + * rndunix.c: Add a signal.h header to avoid warnings on Solaris 7 + and 8. + + * tiger.c (print_abc,print_data): Removed. + + * rijndael.c, des.c, blowfish.c, twofish.c, cast5.c, arcfour.c + (burn_stack): New. Add wrappers for most functions to be able to + call burn_stack after the function invocation. This methods seems + to be the most portable way to zeroise the stack used. It does + only work on stack frame based machines but it is highly portable + and has no side effects. Just setting the automatic variables at + the end of a function to zero does not work well because the + compiler will optimize them away - marking them as volatile would + be bad for performance. + * md5.c, sha1.c, rmd160.c, tiger.c (burn_stack): Likewise. + * random.c (burn_stack): New. + (mix_pool): Use it here to burn the stack of the mixblock function. + + * primegen.c (_gcry_generate_elg_prime): Freed q at 3 places. + Thanks to Tommi Komulainen. + + * arcfour.c (arcfour_setkey): Check the minimim keylength against + bytes and not bits. + (selftest): Must reset the key before decryption. + +2001-05-31 Werner Koch <wk@gnupg.org> + + * sha1.c (sha1_init): Made static. + + Changed all g10_ prefixed function names as well as some mpi_ + function names to cope with the introduced naming changes. + + * md.c (prepare_macpads): Made key const. + +2001-05-28 Werner Koch <wk@gnupg.org> + + * rndegd.c (gather_random): Removed the use of tty_printf. + +2001-03-29 Werner Koch <wk@gnupg.org> + + * md5.c (md5_final): Fixed calculation of hashed length. Thanks + to disastry@saiknes.lv for pointing out that it was horrible wrong + for more than 512MB of input. + * sha1.c (sha1_final): Ditto. + * rmd160.c (rmd160_final): Ditto. + * tiger.c (tiger_final): Ditto. + + * blowfish.c (encrypt,do_encrypt): Changed name to do_encrypt to + avoid name clashes with an encrypt function in stdlib.h of + Dynix/PIX. Thanks to Gene Carter. + * elgamal.c (encrypt,do_encrypt): Ditto. + + * twofish.c (gnupgext_enum_func): Use only when when compiled as a + module. + * rijndael.c (gnupgext_enum_func): Ditto. + + * tiger.c (tiger_get_info): Return "TIGER192" and not just + "TIGER". By Edwin Woudt. + + * random.c: Always include time.h - standard requirement. Thanks + to James Troup. + + * rndw32.c: Fixes to the macros. + +2001-01-11 Werner Koch <wk@gnupg.org> + + * cipher.c (cipher_encrypt,gcry_cipher_encrypt): Use blocksize and + not 8. + +2000-12-19 Werner Koch <wk@gnupg.org> + + Major change: + Removed all GnuPG stuff and renamed this piece of software + to gcrypt. + +2000-11-14 Werner Koch <wk@gnupg.org> + + * dsa.c (test_keys): Replaced mpi_alloc by gcry_mpi_new and + mpi_free by gcry_mpi_release. + * elgamal.c (test_keys,generate): Ditto, also for mpi_alloc_secure. + * rsa.c (test_keys,generate,rsa_verify): Ditto. + * primegen.c (generate_elg_prime): Ditto. + (gen_prime): Ditto and removed nlimbs. + + * rsa.c (generate): Allocate 2 more vars in secure memory. + + * Makefile.am (OMIT_DEPENDENCIES): Hack to work around dependency + problems. + +2000-10-09 Werner Koch <wk@gnupg.org> + + * arcfour.c, arcfour.h: New. + * cipher.c (cipher_encrypt, cipher_decrypt): Add stream mode. + (setup_cipher_table): Add Arcfour. + (gcry_cipher_open): Kludge to allow stream mode. + +Wed Oct 4 13:16:18 CEST 2000 Werner Koch <wk@openit.de> + + * sha1.c (transform): Use rol() macro. Actually this is not needed + for a newer gcc but there are still aoter compilers. + + * rsa.c (test_keys): Use new random function. + + * md.c (gcry_md_setkey): New function to overcome problems with + const conflics. + (gcry_md_ctl): Pass set key to the new functions. + + * rijndael.c: New. + * cipher.c: Add Rijndael support. + +Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de> + + * rndlinux.c (open_device): Loose random device checking. + By Nils Ellmenreich. + + * random.c (fast_random_poll): Check ENOSYS for getrusage. + * rndunix.c: Add 2 sources for QNX. By Sam Roberts. + + * pubkey.c (gcry_pk_algo_info): Add GCRYCTL_GET_ALGO_USAGE. + + * rsa.c: Changed the comment about the patent. + (secret): Speed up by using the CRT. For a 2k keys this + is about 3 times faster. + (stronger_key_check): New but unused code to check the secret key. + * Makefile.am: Included rsa.[ch]. + * pubkey.c: Enabled RSA support. + (pubkey_get_npkey): Removed RSA workaround. + +Mon Jul 31 10:04:47 CEST 2000 Werner Koch <wk@openit.de> + + * pubkey.c: Replaced all gcry_sexp_{car,cdr}_{data,mpi} by the new + gcry_sexp_nth_{data,mpi} functions. + +Tue Jul 25 17:44:15 CEST 2000 Werner Koch <wk@openit.de> + + * pubkey.c (exp_to_key,sexp_to_sig,sexp_to_enc,gcry_pk_encrypt, + gcry_pk_decrypt,gcry_pk_sign,gcry_pk_genkey): Changed to work with + the new S-Exp interface. + +Mon Jul 17 16:35:47 CEST 2000 Werner Koch <wk@> + + * random.c (gather_faked): Replaced make_timestamp by time(2) again. + +Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@> + + * md.c (gcry_md_ctl): Support GCRYCTL_{START,STOP}_DUMP. + + * Makefile.am: Never compile mingw32 as module. + + * Makefile.am: Tweaked module build and removed libtool + + * Makefile.am: Replaced -O1 by -O. Suggested by Alec Habig. + + * elgamal.c (sign): Removed inactive code. + + * rsa.c, rsa.h: New based on the old module version (only in CVS for now). + * pubkey.c (setup_pubkey_table): Added commented support for RSA. + + * rndunix.c (waitpid): New. For UTS 2.1. All by Dave Dykstra. + (my_popen): Do the FD_CLOEXEC only if it is available + (start_gatherer): Cope with missing _SC_OPEN_MAX + + * rndunix.c: Add some more headers for QNX. By Sam Roberts. + + * rndegd.c (gather_random): Shortcut level 0. + * rndunix.c (gather_random): Ditto. + * rndw32.c (gather_random): Ditto. + + * rndw32.c: Replaced with code from Cryptlib and commented the old stuff. + * rndw32.c: Add some debuging code enabled by an environment variable. + + * random.c (read_seed_file): Binary open for DOSish system + (update_random_seed_file): Ditto. + * random.c [MINGW32]: Include process.h for getpid. + * random.c (fast_random_poll): Add clock_gettime() as fallback for + system which support this POSIX.4 fucntion. By Sam Roberts. + + * random.c (read_seed_file): Removed the S_ISLNK test becuase it + is already covered by !S_ISREG and is not defined in Unixware. + Reported by Dave Dykstra. + (update_random_seed_file): Silently ignore update request when pool + is not filled. + + * random.c (read_seed_file): New. + (set_random_seed_file): New. + (read_pool): Try to read the seeding file. + (update_random_seed_file): New. + + (read_pool): Do an initial extra seeding when level 2 quality random + is requested the first time. This requestes at least POOLSIZE/2 bytes + of entropy. Compined with the seeding file this should make normal + random bytes cheaper and increase the quality of the random bytes + used for key generation. + + * random.c (read_pool): Print a more friendly error message in + cases when too much random is requested in one call. + + * random.c (fast_random_poll): Check whether RUSAGE_SELF is defined; + this is not the case for some ESIX and Unixware, although they have + getrusage(). + + * primegen.c (generate_elg_prime): All primes are now generated with + the lowest random quality level. Because they are public anyway we + don't need stronger random and by this we do not drain the systems + entropy so much. + + * primegen.c (register_primegen_progress): New. + * dsa.c (register_pk_dsa_progress): New. + * elgamal.c (register_pk_elg_progress): New. + + * elgamal.c (wiener_map): New. + (gen_k): Use a much smaller k. + (generate): Calculate the qbits using the wiener map and + choose an x at a size comparable to the one choosen in gen_k + + * rmd160.c (rmd160_get_info): Moved casting to the left side due to a + problem with UTS4.3. Suggested by Dave Dykstra. + * sha1.c (sha1_get_info): Ditto. + * tiger.c (tiger_get_info): Ditto. + * md5.c (md5_get_info): Ditto + * des.c (des_get_info): Ditto. + * blowfish.c (blowfish_get_info): Ditto. + * cast5.c (cast5_get_info): Ditto. + * twofish.c (twofish_get_info): Ditto. + +Fri Mar 24 11:25:45 CET 2000 Werner Koch <wk@openit.de> + + * md.c (md_open): Add hmac arg and allocate space for the pads. + (md_finalize): Add HMAC support. + (md_copy): Ditto. + (md_close): Ditto. + (gcry_md_reset): Ditto. + (gcry_md_ctl): Ditto. + (prepare_macpdas): New. + +Mon Mar 13 19:22:46 CET 2000 Werner Koch <wk@openit.de> + + * md.c (gcry_md_hash_buffer): Add support for the other algorithms. + +Mon Jan 31 16:37:34 CET 2000 Werner Koch <wk@gnupg.de> + + * genprime.c (generate_elg_prime): Fixed returned factors which never + worked for non-DSA keys. + +Thu Jan 27 18:00:44 CET 2000 Werner Koch <wk@gnupg.de> + + * pubkey.c (sexp_to_key): Fixed mem leaks in case of errors. + +Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de> + + * pubkey.c (gcry_pk_decrypt): Implemented. + (gcry_pk_encrypt): Implemented. + (gcry_pk_testkey): New. + (gcry_pk_genkey): New. + (pubkey_decrypt): Made static. + (pubkey_encrypt): Ditto. + (pubkey_check_secret_key): Ditto. + (pubkey_generate): Ditto. + +Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de> + + * pubkey.c (pubkey_nbits): Removed and replaced by ... + (gcry_pk_get_nbits): this new one. + +Wed Dec 8 21:58:32 CET 1999 Werner Koch <wk@gnupg.de> + + * dsa.c: s/mpi_powm/gcry_mpi_powm/g + * elgamal.c: Ditto. + * primegen.c: Ditto. + + * : Replaced g10_opt_verbose by g10_log_verbosity(). + + * Makefile.am (INCLUDES): removed intl, add ../gcrypt + +Fri Nov 19 17:15:20 CET 1999 Werner Koch <wk@gnupg.de> + + * dynload.c (cmp_filenames): New to replaced compare_filename() in + module. + (register_cipher_extension): Removed the tilde expansion stuff. + * rndeg.c (my_make_filename): New. + + * : Replaced header util.h by g10lib.h + + * random.c (gather_faked): Replaced make_timestamp by time(2). + Disabled wrning printed with tty_printf. + * rndlinux.c (gather_random): Always use fprintf instead of tty_xxx; + this should be replaced by a callback function. + + * primegen.c (gen_prime): Use gcry_mpi_randomize. + (is_prime): Ditto. + * elgamal.c (test_keys): Ditto. + * dsa.c (test_keys): Ditto. + + * cipher.c (gcry_cipher_close): Die on invalid handle. + +Mon Nov 15 21:36:02 CET 1999 Werner Koch <wk@gnupg.de> + + * elgamal.c (gen_k): Use the new random API. + (generate): Ditto. + * dsa.c (gen_k): Ditto. + (generate): Ditto. + +Sat Nov 13 17:44:23 CET 1999 Werner Koch <wk@gnupg.de> + + * pubkey.c (disable_pubkey_algo): Made static. + (gcry_pk_ctl): New. + + * random.c (get_random_bits): Renamed to ... + (get_random_bytes): ... this and made static. + (gcry_random_bytes): New. + (gcry_random_bytes_secure): New. + (randomize_buffer): Renamed to ... + (gcry_randomize): ...this. + + * md.c (gcry_md_hash_buffer): New. + + * pubkey.c (gcry_pk_algo_info): 4 new commands. + (pubkey_get_npkey): Made static. + (pubkey_get_nskey): Made static. + (pubkey_get_nsig): Made static. + (pubkey_get_nenc): Made static. + + * pubkey.c: Removed all G10ERR_xxx. + * cipher.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_CIPHER_ALGO. + * md.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_MD_ALGO. + * cast5.c (cast_setkey): Changed errocodes to GCRYERR_xxx. + * blowfish.c: Ditto. + * des.c: Ditto. + * twofish.c: Ditto. + * dsa.c: Ditto. + * elgamal.c: Ditto. + + * g10c.c: Removed + + * cipher.c (gcry_cipher_open): Replaced alloc functions and return NULL + if we are out of core. + * dynload.c: Replaced all memory allocation functions. + * md.c: Ditto. + * primegen.c: Ditto. + * pubkey.c: Ditto. + * random.c: Ditto. + * rndw32.c: Ditto. + * elgamal.c: Ditto. + * dsa.c: Ditto. + +Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de> + + * elgamal.c (sign): Hugh found strange code here. Replaced by BUG(). + + * cipher.c: Merged with gcrypt/symapi.c. + + * pubkey.c (string_to_pubkey_algo): Renamed function to ... + (gcry_pk_map_name): ... this. + (pubkey_algo_to_string): Renamed function to ... + (gcry_pk_algo_name): ... this. + (gcry_pk_algo_info): New. + * pubkey.c: Merged with gcrypt/pkapi.c. + + * md.c (md_reset): Clear finalized; thanks to Ulf Moeller for + fixing this bug. + + * md.c: Merged with gcrypt/mdapi.c + +Wed Sep 15 14:39:59 CEST 1999 Michael Roth <mroth@nessie.de> + + * des.c: Various speed improvements: One bit pre rotation + trick after initial permutation (Richard Outerbridge). + Finished test of SSLeay Tripple-DES patterns. + +Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndw32.c: New. + +Mon Sep 13 10:51:29 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * bithelp.h: New. + * rmd160.h, sha1.h, md5.h: Use the rol macro from bithelp.h + +Tue Sep 7 16:23:36 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Fixed seds for latest egcc. By Ollivier Robert. + +Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * des.c (selftest): Add some testpattern + +Mon Aug 30 20:38:33 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (do_cbc_encrypt): Fixed serious bug occuring when not using + in place encryption. Pointed out by Frank Stajano. + +Mon Jul 26 09:34:46 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * md5.c (md5_final): Fix for a SCO cpp bug. + +Thu Jul 15 10:15:35 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * elgamal.c (elg_check_secret_key,elg_encrypt + elg_decrypt,elg_sign,elg_verify): Sanity check on the args. + * dsa.c (dsa_check_secret_key,dsa_sign,dsa_verify): Ditto. + + * pubkey.c (disable_pubkey_algo): New. + (check_pubkey_algo2): Look at disabled algo table. + * cipher.c (disable_cipher_algo): New. + (check_cipher_algo): Look at disabled algo table. + +Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Support for libtool. + +Fri Jul 2 11:45:54 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * dsa.c (gen_k): Changed algorithm to consume less random bytes + * elgamal.c (gen_k): Ditto. + + * random.c (random_dump_stats): New. + +Thu Jul 1 12:47:31 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * primegen.c, elgamal.c, dsa.c (progess): New and replaced all + fputc with a call to this function. + +Sat Jun 26 12:15:59 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndegd.c (do_write): s/ssize_t/int/ due to SunOS 4.1 probs. + + * cipher.c (do_cbc_encrypt, do_cbc_decrypt): New. + + * dynload.c (HAVE_DL_SHL_LOAD): Map hpux API to dlopen (Dave Dykstra). + * Makefile.am (install-exec-hook): Removed. + +Sun May 23 14:20:22 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (setup_cipher_table): Enable Twofish + + * random.c (fast_random_poll): Disable use of times() for mingw32. + +Mon May 17 21:54:43 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (register_internal_cipher_extension): Minor init fix. + +Tue May 4 15:47:53 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * primegen.c (gen_prime): Readded the Fermat test. Fixed the bug + that we didn't correct for step when passing the prime to the + Rabin-Miller test which led to bad performance (Stefan Keller). + (check_prime): Add a first Fermat test. + +Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (cipher_setiv): Add ivlen arg, changed all callers. + + * random.c (randomize_buffer): alway use secure memory because + we can't use m_is_secure() on a statically allocated buffer. + + * twofish.c: Replaced some macros by a loop to reduce text size. + * Makefile.am (twofish): No more need for sed editing. + +Fri Apr 9 12:26:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (cipher_open): Reversed the changes for AUTO_CFB. + + * blowfish.c: Dropped the Blowfish 160 mode. + * cipher.c (cipher_open): Ditto. + (setup_cipher_table): Ditto. And removed support of twofish128 + +Wed Apr 7 20:51:39 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (get_random_bits): Can now handle requests > POOLSIZE + + * cipher.c (cipher_open): Now uses standard CFB for automode if + the blocksize is gt 8 (according to rfc2440). + + * twofish.c: Applied Matthew Skala's patches for 256 bit key. + +Tue Apr 6 19:58:12 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (get_random_bits): Can now handle requests > POOLSIZE + + * cipher.c (cipher_open): Now uses standard CFB for automode if + the blocksize is gt 8 (according to rfc2440). + +Sat Mar 20 11:44:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndlinux.c (tty_printf) [IS_MODULE]: Removed. + + * rndegd.c (gather_random): Some fixes. + +Wed Mar 17 13:09:03 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndegd.c (do_read): New. + (gather_random): Changed the implementation. + +Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed. + +Fri Feb 26 17:55:41 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * md.c: Nearly a total rewrote. + +Wed Feb 24 11:07:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (context): Fixed alignment + * md.c: Ditto. + + * rndegd.c: New + +Mon Feb 22 20:04:00 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndegd.c: New. + +Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Modules are now figured out by configure + * construct.c: New. Generated by configure. Changed all modules + to work with that. + * sha1.h: Removed. + * md5.h: Removed. + + * twofish.c: Changed interface to allow Twofish/256 + + * rndunix.c (start_gatherer): Die on SIGPIPE. + +Wed Jan 20 18:59:49 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndunix.c (gather_random): Fix to avoid infinite loop. + +Sun Jan 17 11:04:33 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * des.c (is_weak_key): Replace system memcmp due to bugs + in SunOS's memcmp. + (des_get_info): Return error on failed selftest. + * twofish.c (twofish_setkey): Return error on failed selftest or + invalid keylength. + * cast5.c (cast_setkey): Ditto. + * blowfish.c (bf_setkey): Return error on failed selftest. + +Tue Jan 12 11:17:18 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (random_is_faked): New. + + * tiger.c: Only compile if we have the u64 type + +Sat Jan 9 16:02:23 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndunix.c (gather_random): check for setuid. + + * Makefile.am: Add a way to staically link random modules + +Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * md.c (md_stop_debug): Do a flush first. + (md_open): size of buffer now depends on the secure parameter + +Sun Jan 3 15:28:44 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndunix.c (start_gatherer): Fixed stupid ==/= bug + +1998-12-31 Geoff Keating <geoffk@ozemail.com.au> + + * des.c (is_weak_key): Rewrite loop end condition. + +Tue Dec 29 14:41:47 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * random.c: add unistd.h for getpid(). + (RAND_MAX): Fallback value for Sun. + +Wed Dec 23 17:12:24 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * md.c (md_copy): Reset debug. + +Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (read_random_source): Changed the interface to the + random gathering function. + (gather_faked): Use new interface. + * dynload.c (dynload_getfnc_fast_random_poll): Ditto. + (dynload_getfnc_gather_random): Ditto. + * rndlinux.c (gather_random): Ditto. + * rndunix.c (gather_random): Ditto. + +Sat Dec 12 18:40:32 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (SYMBOL_VERSION): New to cope with system which needs + underscores. + + * rndunix.c: Rewrote large parts + +Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (load_extension): increased needed verbosity level. + + * random.c (fast_random_poll): Fallback to a default fast random + poll function. + (read_random_source): Always use the faked entroy gatherer if no + gather module is available. + * rndlinux.c (fast_poll): Removed. + * rndunix.c (fast_poll): Removed. + + +Wed Nov 25 12:33:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-*.c: Removed. + * rndlinux.c : New. + * rndunix.c : New. + * random.c : Restructured the interface to the gather modules. + (intialize): Call constructor functions + (read_radnom_source): Moved to here. + * dynload.c (dynload_getfnc_gather_random): New. + (dynload_getfnc_fast_random_poll): New. + (register_internal_cipher_extension): New. + (register_cipher_extension): Support of internal modules. + +Sun Nov 8 17:44:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c (read_random_source): Removed the assert. + +Mon Oct 19 18:34:30 1998 me,,, (wk@tobold) + + * pubkey.c: Hack to allow us to give some info about RSA keys back. + +Thu Oct 15 11:47:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dynload.c: Support for DLD + +Wed Oct 14 12:13:07 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c: Now uses names from configure for /dev/random. + +1998-10-10 SL Baur <steve@altair.xemacs.org> + + * Makefile.am: fix sed -O substitutions to catch -O6, etc. + +Tue Oct 6 10:06:32 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c (HAVE_GETTIMEOFDAY): Fixed (was ..GETTIMEOFTIME :-) + * rand-dummy.c (HAVE_GETTIMEOFDAY): Ditto. + +Mon Sep 28 13:23:09 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_digest): New. + (md_reset): New. + +Wed Sep 23 12:27:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c (TIGER_CONTEXT): moved "buf", so that it is 64 bit aligned. + +Mon Sep 21 06:22:53 1998 Werner Koch (wk@(none)) + + * des.c: Some patches from Michael. + +Thu Sep 17 19:00:06 1998 Werner Koch (wk@(none)) + + * des.c : New file from Michael Roth <mroth@nessie.de> + +Mon Sep 14 11:10:55 1998 Werner Koch (wk@(none)) + + * blowfish.c (bf_setkey): Niklas Hernaeus patch to detect weak keys. + +Mon Sep 14 09:19:25 1998 Werner Koch (wk@(none)) + + * dynload.c (RTLD_NOW): Now defined to 1 if it is undefined. + +Mon Sep 7 17:04:33 1998 Werner Koch (wk@(none)) + + * Makefile.am: Fixes to allow a different build directory + +Thu Aug 6 17:25:38 1998 Werner Koch,mobil,,, (wk@tobold) + + * random.c (get_random_byte): Removed and changed all callers + to use get_random_bits() + +Mon Jul 27 10:30:22 1998 Werner Koch (wk@(none)) + + * cipher.c : Support for other blocksizes + (cipher_get_blocksize): New. + * twofish.c: New. + * Makefile.am: Add twofish module. + +Mon Jul 13 21:30:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (read_pool): Simple alloc if secure_alloc is not set. + (get_random_bits): Ditto. + +Thu Jul 9 13:01:14 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dynload.c (load_extension): Function now nbails out if + the program is run setuid. + +Wed Jul 8 18:58:23 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (rmd160_hash_buffer): New. + +Thu Jul 2 10:50:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c (cipher_open): algos >=100 use standard CFB + +Thu Jun 25 11:18:25 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am: Support for extensions + +Thu Jun 18 12:09:38 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (mix_pool): simpler handling for level 0 + +Mon Jun 15 14:40:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c: Removed from dist, will reappear as dynload module + +Sat Jun 13 14:16:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * pubkey.c: Major changes to allow extensions. Changed the inteface + of all public key ciphers and added the ability to load extensions + on demand. + + * misc.c: Removed. + +Wed Jun 10 07:52:08 1998 Werner Koch,mobil,,, (wk@tobold) + + * dynload.c: New. + * cipher.c: Major changes to allow extensions. + +Mon Jun 8 22:43:00 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: Major internal chnages to support extensions. + * blowfish.c (blowfish_get_info): New and made all internal + functions static, changed heder. + * cast5.c (cast5_get_info): Likewise. + +Mon Jun 8 12:27:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c (transform): Fix for big endian + + * cipher.c (do_cfb_decrypt): Big endian fix. + +Fri May 22 07:30:39 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_get_oid): Add a new one for TIGER. + +Thu May 21 13:24:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: Add support for a dummy cipher + +Thu May 14 15:40:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (transform): fixed sigbus - I should better + add Christian von Roques's new implemenation of rmd160_write. + +Fri May 8 18:07:44 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-internal.h, rand-unix.c, rand-w32.c, rand_dummy.c: New + * random.c: Moved system specific functions to rand-****.c + +Fri May 8 14:01:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (fast_random_poll): add call to gethrtime. + +Tue May 5 21:28:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * elgamal.c (elg_generate): choosing x was not correct, could + yield 6 bytes which are not from the random pool, tsss, tsss.. + +Tue May 5 14:09:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * primegen.c (generate_elg_prime): Add arg mode, changed all + callers and implemented mode 1. + +Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c (cipher_get_keylen): New. + +Sun Apr 26 14:44:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c, tiger.h: New. + +Wed Apr 8 14:57:11 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (check_pubkey_algo2): New. + +Tue Apr 7 18:46:49 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: New + * misc.c (check_cipher_algo): Moved to cipher.c + * cast5.c: Moved many functions to cipher.c + * blowfish.c: Likewise. + +Sat Apr 4 19:52:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cast5.c: Implemented and tested. + +Wed Apr 1 16:38:27 1998 Werner Koch (wk@isil.d.shuttle.de) + + * elgamal.c (elg_generate): Faster generation of x in some cases. + +Thu Mar 19 13:54:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * blowfish.c (blowfish_decode_cfb): changed XOR operation + (blowfish_encode_cfb): Ditto. + +Thu Mar 12 14:04:05 1998 Werner Koch (wk@isil.d.shuttle.de) + + * sha1.c (transform): Rewrote + + * blowfish.c (encrypt): Unrolled for rounds == 16 + (decrypt): Ditto. + +Tue Mar 10 16:32:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (transform): Unrolled the loop. + +Tue Mar 10 13:05:14 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (read_pool): Add pool_balance stuff. + (get_random_bits): New. + + * elgamal.c (elg_generate): Now uses get_random_bits to generate x. + + +Tue Mar 10 11:33:51 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_digest_length): New. + +Tue Mar 10 11:27:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dsa.c (dsa_verify): Works. + +Mon Mar 9 12:59:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dsa.c, dsa.h: Removed some unused code. + +Wed Mar 4 10:39:22 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_open): Add call to fast_random_poll. + blowfish.c (blowfish_setkey): Ditto. + +Tue Mar 3 13:32:54 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (rmd160_mixblock): New. + * random.c: Restructured to start with a new RNG implementation. + * random.h: New. + +Mon Mar 2 19:21:46 1998 Werner Koch (wk@isil.d.shuttle.de) + + * gost.c, gost.h: Removed because they did only contain trash. + +Sun Mar 1 16:42:29 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (fill_buffer): removed error message if n == -1. + +Fri Feb 27 16:39:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_enable): No init if called twice. + +Thu Feb 26 07:57:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * primegen.c (generate_elg_prime): Changed the progress printing. + (gen_prime): Ditto. + +Tue Feb 24 12:28:42 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md5.c, md.5 : Replaced by a modified version of md5.c from + GNU textutils 1.22. + +Wed Feb 18 14:08:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c, md.h : New debugging support + +Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (cipher_algo_to_string): New + (pubkey_algo_to_string): New. + (digest_algo_to_string): New. + + + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/grub-core/lib/libgcrypt-grub/cipher/arcfour.c b/grub-core/lib/libgcrypt-grub/cipher/arcfour.c new file mode 100644 index 0000000..9d82360 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/arcfour.c @@ -0,0 +1,143 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* arcfour.c - The arcfour stream cipher + * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * For a description of the algorithm, see: + * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. + * ISBN 0-471-11709-9. Pages 397 ff. + */ + + +#include "types.h" +#include "g10lib.h" +#include "cipher.h" + + +typedef struct { + int idx_i, idx_j; + byte sbox[256]; +} ARCFOUR_context; + +static void +do_encrypt_stream( ARCFOUR_context *ctx, + byte *outbuf, const byte *inbuf, unsigned int length ) +{ + register int i = ctx->idx_i; + register int j = ctx->idx_j; + register byte *sbox = ctx->sbox; + register int t; + + while ( length-- ) + { + i++; + i = i & 255; /* The and-op seems to be faster than the mod-op. */ + j += sbox[i]; + j &= 255; + t = sbox[i]; sbox[i] = sbox[j]; sbox[j] = t; + *outbuf++ = *inbuf++ ^ sbox[(sbox[i] + sbox[j]) & 255]; + } + + ctx->idx_i = i; + ctx->idx_j = j; +} + +static void +encrypt_stream (void *context, + byte *outbuf, const byte *inbuf, unsigned int length) +{ + ARCFOUR_context *ctx = (ARCFOUR_context *) context; + do_encrypt_stream (ctx, outbuf, inbuf, length ); + _gcry_burn_stack (64); +} + + +static gcry_err_code_t +do_arcfour_setkey (void *context, const byte *key, unsigned int keylen) +{ + static int initialized; + static const char* selftest_failed; + int i, j; + byte karr[256]; + ARCFOUR_context *ctx = (ARCFOUR_context *) context; + + if (!initialized ) + { + initialized = 1; + selftest_failed = selftest(); + if( selftest_failed ) + log_error ("ARCFOUR selftest failed (%s)\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + if( keylen < 40/8 ) /* we want at least 40 bits */ + return GPG_ERR_INV_KEYLEN; + + ctx->idx_i = ctx->idx_j = 0; + for (i=0; i < 256; i++ ) + ctx->sbox[i] = i; + for (i=0; i < 256; i++ ) + karr[i] = key[i%keylen]; + for (i=j=0; i < 256; i++ ) + { + int t; + j = (j + ctx->sbox[i] + karr[i]) % 256; + t = ctx->sbox[i]; + ctx->sbox[i] = ctx->sbox[j]; + ctx->sbox[j] = t; + } + memset( karr, 0, 256 ); + + return GPG_ERR_NO_ERROR; +} + +static gcry_err_code_t +arcfour_setkey ( void *context, const byte *key, unsigned int keylen ) +{ + ARCFOUR_context *ctx = (ARCFOUR_context *) context; + gcry_err_code_t rc = do_arcfour_setkey (ctx, key, keylen ); + _gcry_burn_stack (300); + return rc; +} + + + + +gcry_cipher_spec_t _gcry_cipher_spec_arcfour = + { + "ARCFOUR", NULL, NULL, 1, 128, sizeof (ARCFOUR_context), + arcfour_setkey, NULL, NULL, encrypt_stream, encrypt_stream, +#ifdef GRUB_UTIL + .modname = "gcry_arcfour", +#endif + }; + + +GRUB_MOD_INIT(gcry_arcfour) +{ + grub_cipher_register (&_gcry_cipher_spec_arcfour); +} + +GRUB_MOD_FINI(gcry_arcfour) +{ + grub_cipher_unregister (&_gcry_cipher_spec_arcfour); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/bithelp.h b/grub-core/lib/libgcrypt-grub/cipher/bithelp.h new file mode 100644 index 0000000..e957b4e --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/bithelp.h @@ -0,0 +1,57 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +/* bithelp.h - Some bit manipulation helpers + * Copyright (C) 1999, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef G10_BITHELP_H +#define G10_BITHELP_H + + +/**************** + * Rotate the 32 bit unsigned integer X by N bits left/right + */ +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +rol( u32 x, int n) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else +#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +ror(u32 x, int n) +{ + __asm__("rorl %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else +#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) +#endif + + +#endif /*G10_BITHELP_H*/ diff --git a/grub-core/lib/libgcrypt-grub/cipher/blowfish.c b/grub-core/lib/libgcrypt-grub/cipher/blowfish.c new file mode 100644 index 0000000..612bfce --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/blowfish.c @@ -0,0 +1,592 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* blowfish.c - Blowfish encryption + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * For a description of the algorithm, see: + * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. + * ISBN 0-471-11709-9. Pages 336 ff. + */ + +/* Test values: + * key "abcdefghijklmnopqrstuvwxyz"; + * plain "BLOWFISH" + * cipher 32 4E D0 FE F4 13 A2 03 + * + */ + +#include "types.h" +#include "g10lib.h" +#include "cipher.h" + +#define BLOWFISH_BLOCKSIZE 8 +#define BLOWFISH_ROUNDS 16 + +typedef struct { + u32 s0[256]; + u32 s1[256]; + u32 s2[256]; + u32 s3[256]; + u32 p[BLOWFISH_ROUNDS+2]; +} BLOWFISH_context; + +static gcry_err_code_t bf_setkey (void *c, const byte *key, unsigned keylen); +static void encrypt_block (void *bc, byte *outbuf, const byte *inbuf); +static void decrypt_block (void *bc, byte *outbuf, const byte *inbuf); + + +/* precomputed S boxes */ +static const u32 ks0[256] = { + 0xD1310BA6,0x98DFB5AC,0x2FFD72DB,0xD01ADFB7,0xB8E1AFED,0x6A267E96, + 0xBA7C9045,0xF12C7F99,0x24A19947,0xB3916CF7,0x0801F2E2,0x858EFC16, + 0x636920D8,0x71574E69,0xA458FEA3,0xF4933D7E,0x0D95748F,0x728EB658, + 0x718BCD58,0x82154AEE,0x7B54A41D,0xC25A59B5,0x9C30D539,0x2AF26013, + 0xC5D1B023,0x286085F0,0xCA417918,0xB8DB38EF,0x8E79DCB0,0x603A180E, + 0x6C9E0E8B,0xB01E8A3E,0xD71577C1,0xBD314B27,0x78AF2FDA,0x55605C60, + 0xE65525F3,0xAA55AB94,0x57489862,0x63E81440,0x55CA396A,0x2AAB10B6, + 0xB4CC5C34,0x1141E8CE,0xA15486AF,0x7C72E993,0xB3EE1411,0x636FBC2A, + 0x2BA9C55D,0x741831F6,0xCE5C3E16,0x9B87931E,0xAFD6BA33,0x6C24CF5C, + 0x7A325381,0x28958677,0x3B8F4898,0x6B4BB9AF,0xC4BFE81B,0x66282193, + 0x61D809CC,0xFB21A991,0x487CAC60,0x5DEC8032,0xEF845D5D,0xE98575B1, + 0xDC262302,0xEB651B88,0x23893E81,0xD396ACC5,0x0F6D6FF3,0x83F44239, + 0x2E0B4482,0xA4842004,0x69C8F04A,0x9E1F9B5E,0x21C66842,0xF6E96C9A, + 0x670C9C61,0xABD388F0,0x6A51A0D2,0xD8542F68,0x960FA728,0xAB5133A3, + 0x6EEF0B6C,0x137A3BE4,0xBA3BF050,0x7EFB2A98,0xA1F1651D,0x39AF0176, + 0x66CA593E,0x82430E88,0x8CEE8619,0x456F9FB4,0x7D84A5C3,0x3B8B5EBE, + 0xE06F75D8,0x85C12073,0x401A449F,0x56C16AA6,0x4ED3AA62,0x363F7706, + 0x1BFEDF72,0x429B023D,0x37D0D724,0xD00A1248,0xDB0FEAD3,0x49F1C09B, + 0x075372C9,0x80991B7B,0x25D479D8,0xF6E8DEF7,0xE3FE501A,0xB6794C3B, + 0x976CE0BD,0x04C006BA,0xC1A94FB6,0x409F60C4,0x5E5C9EC2,0x196A2463, + 0x68FB6FAF,0x3E6C53B5,0x1339B2EB,0x3B52EC6F,0x6DFC511F,0x9B30952C, + 0xCC814544,0xAF5EBD09,0xBEE3D004,0xDE334AFD,0x660F2807,0x192E4BB3, + 0xC0CBA857,0x45C8740F,0xD20B5F39,0xB9D3FBDB,0x5579C0BD,0x1A60320A, + 0xD6A100C6,0x402C7279,0x679F25FE,0xFB1FA3CC,0x8EA5E9F8,0xDB3222F8, + 0x3C7516DF,0xFD616B15,0x2F501EC8,0xAD0552AB,0x323DB5FA,0xFD238760, + 0x53317B48,0x3E00DF82,0x9E5C57BB,0xCA6F8CA0,0x1A87562E,0xDF1769DB, + 0xD542A8F6,0x287EFFC3,0xAC6732C6,0x8C4F5573,0x695B27B0,0xBBCA58C8, + 0xE1FFA35D,0xB8F011A0,0x10FA3D98,0xFD2183B8,0x4AFCB56C,0x2DD1D35B, + 0x9A53E479,0xB6F84565,0xD28E49BC,0x4BFB9790,0xE1DDF2DA,0xA4CB7E33, + 0x62FB1341,0xCEE4C6E8,0xEF20CADA,0x36774C01,0xD07E9EFE,0x2BF11FB4, + 0x95DBDA4D,0xAE909198,0xEAAD8E71,0x6B93D5A0,0xD08ED1D0,0xAFC725E0, + 0x8E3C5B2F,0x8E7594B7,0x8FF6E2FB,0xF2122B64,0x8888B812,0x900DF01C, + 0x4FAD5EA0,0x688FC31C,0xD1CFF191,0xB3A8C1AD,0x2F2F2218,0xBE0E1777, + 0xEA752DFE,0x8B021FA1,0xE5A0CC0F,0xB56F74E8,0x18ACF3D6,0xCE89E299, + 0xB4A84FE0,0xFD13E0B7,0x7CC43B81,0xD2ADA8D9,0x165FA266,0x80957705, + 0x93CC7314,0x211A1477,0xE6AD2065,0x77B5FA86,0xC75442F5,0xFB9D35CF, + 0xEBCDAF0C,0x7B3E89A0,0xD6411BD3,0xAE1E7E49,0x00250E2D,0x2071B35E, + 0x226800BB,0x57B8E0AF,0x2464369B,0xF009B91E,0x5563911D,0x59DFA6AA, + 0x78C14389,0xD95A537F,0x207D5BA2,0x02E5B9C5,0x83260376,0x6295CFA9, + 0x11C81968,0x4E734A41,0xB3472DCA,0x7B14A94A,0x1B510052,0x9A532915, + 0xD60F573F,0xBC9BC6E4,0x2B60A476,0x81E67400,0x08BA6FB5,0x571BE91F, + 0xF296EC6B,0x2A0DD915,0xB6636521,0xE7B9F9B6,0xFF34052E,0xC5855664, + 0x53B02D5D,0xA99F8FA1,0x08BA4799,0x6E85076A }; + +static const u32 ks1[256] = { + 0x4B7A70E9,0xB5B32944,0xDB75092E,0xC4192623,0xAD6EA6B0,0x49A7DF7D, + 0x9CEE60B8,0x8FEDB266,0xECAA8C71,0x699A17FF,0x5664526C,0xC2B19EE1, + 0x193602A5,0x75094C29,0xA0591340,0xE4183A3E,0x3F54989A,0x5B429D65, + 0x6B8FE4D6,0x99F73FD6,0xA1D29C07,0xEFE830F5,0x4D2D38E6,0xF0255DC1, + 0x4CDD2086,0x8470EB26,0x6382E9C6,0x021ECC5E,0x09686B3F,0x3EBAEFC9, + 0x3C971814,0x6B6A70A1,0x687F3584,0x52A0E286,0xB79C5305,0xAA500737, + 0x3E07841C,0x7FDEAE5C,0x8E7D44EC,0x5716F2B8,0xB03ADA37,0xF0500C0D, + 0xF01C1F04,0x0200B3FF,0xAE0CF51A,0x3CB574B2,0x25837A58,0xDC0921BD, + 0xD19113F9,0x7CA92FF6,0x94324773,0x22F54701,0x3AE5E581,0x37C2DADC, + 0xC8B57634,0x9AF3DDA7,0xA9446146,0x0FD0030E,0xECC8C73E,0xA4751E41, + 0xE238CD99,0x3BEA0E2F,0x3280BBA1,0x183EB331,0x4E548B38,0x4F6DB908, + 0x6F420D03,0xF60A04BF,0x2CB81290,0x24977C79,0x5679B072,0xBCAF89AF, + 0xDE9A771F,0xD9930810,0xB38BAE12,0xDCCF3F2E,0x5512721F,0x2E6B7124, + 0x501ADDE6,0x9F84CD87,0x7A584718,0x7408DA17,0xBC9F9ABC,0xE94B7D8C, + 0xEC7AEC3A,0xDB851DFA,0x63094366,0xC464C3D2,0xEF1C1847,0x3215D908, + 0xDD433B37,0x24C2BA16,0x12A14D43,0x2A65C451,0x50940002,0x133AE4DD, + 0x71DFF89E,0x10314E55,0x81AC77D6,0x5F11199B,0x043556F1,0xD7A3C76B, + 0x3C11183B,0x5924A509,0xF28FE6ED,0x97F1FBFA,0x9EBABF2C,0x1E153C6E, + 0x86E34570,0xEAE96FB1,0x860E5E0A,0x5A3E2AB3,0x771FE71C,0x4E3D06FA, + 0x2965DCB9,0x99E71D0F,0x803E89D6,0x5266C825,0x2E4CC978,0x9C10B36A, + 0xC6150EBA,0x94E2EA78,0xA5FC3C53,0x1E0A2DF4,0xF2F74EA7,0x361D2B3D, + 0x1939260F,0x19C27960,0x5223A708,0xF71312B6,0xEBADFE6E,0xEAC31F66, + 0xE3BC4595,0xA67BC883,0xB17F37D1,0x018CFF28,0xC332DDEF,0xBE6C5AA5, + 0x65582185,0x68AB9802,0xEECEA50F,0xDB2F953B,0x2AEF7DAD,0x5B6E2F84, + 0x1521B628,0x29076170,0xECDD4775,0x619F1510,0x13CCA830,0xEB61BD96, + 0x0334FE1E,0xAA0363CF,0xB5735C90,0x4C70A239,0xD59E9E0B,0xCBAADE14, + 0xEECC86BC,0x60622CA7,0x9CAB5CAB,0xB2F3846E,0x648B1EAF,0x19BDF0CA, + 0xA02369B9,0x655ABB50,0x40685A32,0x3C2AB4B3,0x319EE9D5,0xC021B8F7, + 0x9B540B19,0x875FA099,0x95F7997E,0x623D7DA8,0xF837889A,0x97E32D77, + 0x11ED935F,0x16681281,0x0E358829,0xC7E61FD6,0x96DEDFA1,0x7858BA99, + 0x57F584A5,0x1B227263,0x9B83C3FF,0x1AC24696,0xCDB30AEB,0x532E3054, + 0x8FD948E4,0x6DBC3128,0x58EBF2EF,0x34C6FFEA,0xFE28ED61,0xEE7C3C73, + 0x5D4A14D9,0xE864B7E3,0x42105D14,0x203E13E0,0x45EEE2B6,0xA3AAABEA, + 0xDB6C4F15,0xFACB4FD0,0xC742F442,0xEF6ABBB5,0x654F3B1D,0x41CD2105, + 0xD81E799E,0x86854DC7,0xE44B476A,0x3D816250,0xCF62A1F2,0x5B8D2646, + 0xFC8883A0,0xC1C7B6A3,0x7F1524C3,0x69CB7492,0x47848A0B,0x5692B285, + 0x095BBF00,0xAD19489D,0x1462B174,0x23820E00,0x58428D2A,0x0C55F5EA, + 0x1DADF43E,0x233F7061,0x3372F092,0x8D937E41,0xD65FECF1,0x6C223BDB, + 0x7CDE3759,0xCBEE7460,0x4085F2A7,0xCE77326E,0xA6078084,0x19F8509E, + 0xE8EFD855,0x61D99735,0xA969A7AA,0xC50C06C2,0x5A04ABFC,0x800BCADC, + 0x9E447A2E,0xC3453484,0xFDD56705,0x0E1E9EC9,0xDB73DBD3,0x105588CD, + 0x675FDA79,0xE3674340,0xC5C43465,0x713E38D8,0x3D28F89E,0xF16DFF20, + 0x153E21E7,0x8FB03D4A,0xE6E39F2B,0xDB83ADF7 }; + +static const u32 ks2[256] = { + 0xE93D5A68,0x948140F7,0xF64C261C,0x94692934,0x411520F7,0x7602D4F7, + 0xBCF46B2E,0xD4A20068,0xD4082471,0x3320F46A,0x43B7D4B7,0x500061AF, + 0x1E39F62E,0x97244546,0x14214F74,0xBF8B8840,0x4D95FC1D,0x96B591AF, + 0x70F4DDD3,0x66A02F45,0xBFBC09EC,0x03BD9785,0x7FAC6DD0,0x31CB8504, + 0x96EB27B3,0x55FD3941,0xDA2547E6,0xABCA0A9A,0x28507825,0x530429F4, + 0x0A2C86DA,0xE9B66DFB,0x68DC1462,0xD7486900,0x680EC0A4,0x27A18DEE, + 0x4F3FFEA2,0xE887AD8C,0xB58CE006,0x7AF4D6B6,0xAACE1E7C,0xD3375FEC, + 0xCE78A399,0x406B2A42,0x20FE9E35,0xD9F385B9,0xEE39D7AB,0x3B124E8B, + 0x1DC9FAF7,0x4B6D1856,0x26A36631,0xEAE397B2,0x3A6EFA74,0xDD5B4332, + 0x6841E7F7,0xCA7820FB,0xFB0AF54E,0xD8FEB397,0x454056AC,0xBA489527, + 0x55533A3A,0x20838D87,0xFE6BA9B7,0xD096954B,0x55A867BC,0xA1159A58, + 0xCCA92963,0x99E1DB33,0xA62A4A56,0x3F3125F9,0x5EF47E1C,0x9029317C, + 0xFDF8E802,0x04272F70,0x80BB155C,0x05282CE3,0x95C11548,0xE4C66D22, + 0x48C1133F,0xC70F86DC,0x07F9C9EE,0x41041F0F,0x404779A4,0x5D886E17, + 0x325F51EB,0xD59BC0D1,0xF2BCC18F,0x41113564,0x257B7834,0x602A9C60, + 0xDFF8E8A3,0x1F636C1B,0x0E12B4C2,0x02E1329E,0xAF664FD1,0xCAD18115, + 0x6B2395E0,0x333E92E1,0x3B240B62,0xEEBEB922,0x85B2A20E,0xE6BA0D99, + 0xDE720C8C,0x2DA2F728,0xD0127845,0x95B794FD,0x647D0862,0xE7CCF5F0, + 0x5449A36F,0x877D48FA,0xC39DFD27,0xF33E8D1E,0x0A476341,0x992EFF74, + 0x3A6F6EAB,0xF4F8FD37,0xA812DC60,0xA1EBDDF8,0x991BE14C,0xDB6E6B0D, + 0xC67B5510,0x6D672C37,0x2765D43B,0xDCD0E804,0xF1290DC7,0xCC00FFA3, + 0xB5390F92,0x690FED0B,0x667B9FFB,0xCEDB7D9C,0xA091CF0B,0xD9155EA3, + 0xBB132F88,0x515BAD24,0x7B9479BF,0x763BD6EB,0x37392EB3,0xCC115979, + 0x8026E297,0xF42E312D,0x6842ADA7,0xC66A2B3B,0x12754CCC,0x782EF11C, + 0x6A124237,0xB79251E7,0x06A1BBE6,0x4BFB6350,0x1A6B1018,0x11CAEDFA, + 0x3D25BDD8,0xE2E1C3C9,0x44421659,0x0A121386,0xD90CEC6E,0xD5ABEA2A, + 0x64AF674E,0xDA86A85F,0xBEBFE988,0x64E4C3FE,0x9DBC8057,0xF0F7C086, + 0x60787BF8,0x6003604D,0xD1FD8346,0xF6381FB0,0x7745AE04,0xD736FCCC, + 0x83426B33,0xF01EAB71,0xB0804187,0x3C005E5F,0x77A057BE,0xBDE8AE24, + 0x55464299,0xBF582E61,0x4E58F48F,0xF2DDFDA2,0xF474EF38,0x8789BDC2, + 0x5366F9C3,0xC8B38E74,0xB475F255,0x46FCD9B9,0x7AEB2661,0x8B1DDF84, + 0x846A0E79,0x915F95E2,0x466E598E,0x20B45770,0x8CD55591,0xC902DE4C, + 0xB90BACE1,0xBB8205D0,0x11A86248,0x7574A99E,0xB77F19B6,0xE0A9DC09, + 0x662D09A1,0xC4324633,0xE85A1F02,0x09F0BE8C,0x4A99A025,0x1D6EFE10, + 0x1AB93D1D,0x0BA5A4DF,0xA186F20F,0x2868F169,0xDCB7DA83,0x573906FE, + 0xA1E2CE9B,0x4FCD7F52,0x50115E01,0xA70683FA,0xA002B5C4,0x0DE6D027, + 0x9AF88C27,0x773F8641,0xC3604C06,0x61A806B5,0xF0177A28,0xC0F586E0, + 0x006058AA,0x30DC7D62,0x11E69ED7,0x2338EA63,0x53C2DD94,0xC2C21634, + 0xBBCBEE56,0x90BCB6DE,0xEBFC7DA1,0xCE591D76,0x6F05E409,0x4B7C0188, + 0x39720A3D,0x7C927C24,0x86E3725F,0x724D9DB9,0x1AC15BB4,0xD39EB8FC, + 0xED545578,0x08FCA5B5,0xD83D7CD3,0x4DAD0FC4,0x1E50EF5E,0xB161E6F8, + 0xA28514D9,0x6C51133C,0x6FD5C7E7,0x56E14EC4,0x362ABFCE,0xDDC6C837, + 0xD79A3234,0x92638212,0x670EFA8E,0x406000E0 }; + +static const u32 ks3[256] = { + 0x3A39CE37,0xD3FAF5CF,0xABC27737,0x5AC52D1B,0x5CB0679E,0x4FA33742, + 0xD3822740,0x99BC9BBE,0xD5118E9D,0xBF0F7315,0xD62D1C7E,0xC700C47B, + 0xB78C1B6B,0x21A19045,0xB26EB1BE,0x6A366EB4,0x5748AB2F,0xBC946E79, + 0xC6A376D2,0x6549C2C8,0x530FF8EE,0x468DDE7D,0xD5730A1D,0x4CD04DC6, + 0x2939BBDB,0xA9BA4650,0xAC9526E8,0xBE5EE304,0xA1FAD5F0,0x6A2D519A, + 0x63EF8CE2,0x9A86EE22,0xC089C2B8,0x43242EF6,0xA51E03AA,0x9CF2D0A4, + 0x83C061BA,0x9BE96A4D,0x8FE51550,0xBA645BD6,0x2826A2F9,0xA73A3AE1, + 0x4BA99586,0xEF5562E9,0xC72FEFD3,0xF752F7DA,0x3F046F69,0x77FA0A59, + 0x80E4A915,0x87B08601,0x9B09E6AD,0x3B3EE593,0xE990FD5A,0x9E34D797, + 0x2CF0B7D9,0x022B8B51,0x96D5AC3A,0x017DA67D,0xD1CF3ED6,0x7C7D2D28, + 0x1F9F25CF,0xADF2B89B,0x5AD6B472,0x5A88F54C,0xE029AC71,0xE019A5E6, + 0x47B0ACFD,0xED93FA9B,0xE8D3C48D,0x283B57CC,0xF8D56629,0x79132E28, + 0x785F0191,0xED756055,0xF7960E44,0xE3D35E8C,0x15056DD4,0x88F46DBA, + 0x03A16125,0x0564F0BD,0xC3EB9E15,0x3C9057A2,0x97271AEC,0xA93A072A, + 0x1B3F6D9B,0x1E6321F5,0xF59C66FB,0x26DCF319,0x7533D928,0xB155FDF5, + 0x03563482,0x8ABA3CBB,0x28517711,0xC20AD9F8,0xABCC5167,0xCCAD925F, + 0x4DE81751,0x3830DC8E,0x379D5862,0x9320F991,0xEA7A90C2,0xFB3E7BCE, + 0x5121CE64,0x774FBE32,0xA8B6E37E,0xC3293D46,0x48DE5369,0x6413E680, + 0xA2AE0810,0xDD6DB224,0x69852DFD,0x09072166,0xB39A460A,0x6445C0DD, + 0x586CDECF,0x1C20C8AE,0x5BBEF7DD,0x1B588D40,0xCCD2017F,0x6BB4E3BB, + 0xDDA26A7E,0x3A59FF45,0x3E350A44,0xBCB4CDD5,0x72EACEA8,0xFA6484BB, + 0x8D6612AE,0xBF3C6F47,0xD29BE463,0x542F5D9E,0xAEC2771B,0xF64E6370, + 0x740E0D8D,0xE75B1357,0xF8721671,0xAF537D5D,0x4040CB08,0x4EB4E2CC, + 0x34D2466A,0x0115AF84,0xE1B00428,0x95983A1D,0x06B89FB4,0xCE6EA048, + 0x6F3F3B82,0x3520AB82,0x011A1D4B,0x277227F8,0x611560B1,0xE7933FDC, + 0xBB3A792B,0x344525BD,0xA08839E1,0x51CE794B,0x2F32C9B7,0xA01FBAC9, + 0xE01CC87E,0xBCC7D1F6,0xCF0111C3,0xA1E8AAC7,0x1A908749,0xD44FBD9A, + 0xD0DADECB,0xD50ADA38,0x0339C32A,0xC6913667,0x8DF9317C,0xE0B12B4F, + 0xF79E59B7,0x43F5BB3A,0xF2D519FF,0x27D9459C,0xBF97222C,0x15E6FC2A, + 0x0F91FC71,0x9B941525,0xFAE59361,0xCEB69CEB,0xC2A86459,0x12BAA8D1, + 0xB6C1075E,0xE3056A0C,0x10D25065,0xCB03A442,0xE0EC6E0E,0x1698DB3B, + 0x4C98A0BE,0x3278E964,0x9F1F9532,0xE0D392DF,0xD3A0342B,0x8971F21E, + 0x1B0A7441,0x4BA3348C,0xC5BE7120,0xC37632D8,0xDF359F8D,0x9B992F2E, + 0xE60B6F47,0x0FE3F11D,0xE54CDA54,0x1EDAD891,0xCE6279CF,0xCD3E7E6F, + 0x1618B166,0xFD2C1D05,0x848FD2C5,0xF6FB2299,0xF523F357,0xA6327623, + 0x93A83531,0x56CCCD02,0xACF08162,0x5A75EBB5,0x6E163697,0x88D273CC, + 0xDE966292,0x81B949D0,0x4C50901B,0x71C65614,0xE6C6C7BD,0x327A140A, + 0x45E1D006,0xC3F27B9A,0xC9AA53FD,0x62A80F00,0xBB25BFE2,0x35BDD2F6, + 0x71126905,0xB2040222,0xB6CBCF7C,0xCD769C2B,0x53113EC0,0x1640E3D3, + 0x38ABBD60,0x2547ADF0,0xBA38209C,0xF746CE76,0x77AFA1C5,0x20756060, + 0x85CBFE4E,0x8AE88DD8,0x7AAAF9B0,0x4CF9AA7E,0x1948C25C,0x02FB8A8C, + 0x01C36AE4,0xD6EBE1F9,0x90D4F869,0xA65CDEA0,0x3F09252D,0xC208E69F, + 0xB74E6132,0xCE77E25B,0x578FDFE3,0x3AC372E6 }; + +static const u32 ps[BLOWFISH_ROUNDS+2] = { + 0x243F6A88,0x85A308D3,0x13198A2E,0x03707344,0xA4093822,0x299F31D0, + 0x082EFA98,0xEC4E6C89,0x452821E6,0x38D01377,0xBE5466CF,0x34E90C6C, + 0xC0AC29B7,0xC97C50DD,0x3F84D5B5,0xB5470917,0x9216D5D9,0x8979FB1B }; + + + +#if BLOWFISH_ROUNDS != 16 +static inline u32 +function_F( BLOWFISH_context *bc, u32 x ) +{ + u16 a, b, c, d; + +#ifdef WORDS_BIGENDIAN + a = ((byte*)&x)[0]; + b = ((byte*)&x)[1]; + c = ((byte*)&x)[2]; + d = ((byte*)&x)[3]; +#else + a = ((byte*)&x)[3]; + b = ((byte*)&x)[2]; + c = ((byte*)&x)[1]; + d = ((byte*)&x)[0]; +#endif + + return ((bc->s0[a] + bc->s1[b]) ^ bc->s2[c] ) + bc->s3[d]; +} +#endif + +#ifdef WORDS_BIGENDIAN +#define F(x) ((( s0[((byte*)&x)[0]] + s1[((byte*)&x)[1]]) \ + ^ s2[((byte*)&x)[2]]) + s3[((byte*)&x)[3]] ) +#else +#define F(x) ((( s0[((byte*)&x)[3]] + s1[((byte*)&x)[2]]) \ + ^ s2[((byte*)&x)[1]]) + s3[((byte*)&x)[0]] ) +#endif +#define R(l,r,i) do { l ^= p[i]; r ^= F(l); } while(0) + + +static void +do_encrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) +{ +#if BLOWFISH_ROUNDS == 16 + u32 xl, xr, *s0, *s1, *s2, *s3, *p; + + xl = *ret_xl; + xr = *ret_xr; + p = bc->p; + s0 = bc->s0; + s1 = bc->s1; + s2 = bc->s2; + s3 = bc->s3; + + R( xl, xr, 0); + R( xr, xl, 1); + R( xl, xr, 2); + R( xr, xl, 3); + R( xl, xr, 4); + R( xr, xl, 5); + R( xl, xr, 6); + R( xr, xl, 7); + R( xl, xr, 8); + R( xr, xl, 9); + R( xl, xr, 10); + R( xr, xl, 11); + R( xl, xr, 12); + R( xr, xl, 13); + R( xl, xr, 14); + R( xr, xl, 15); + + xl ^= p[BLOWFISH_ROUNDS]; + xr ^= p[BLOWFISH_ROUNDS+1]; + + *ret_xl = xr; + *ret_xr = xl; + +#else + u32 xl, xr, temp, *p; + int i; + + xl = *ret_xl; + xr = *ret_xr; + p = bc->p; + + for(i=0; i < BLOWFISH_ROUNDS; i++ ) + { + xl ^= p[i]; + xr ^= function_F(bc, xl); + temp = xl; + xl = xr; + xr = temp; + } + temp = xl; + xl = xr; + xr = temp; + + xr ^= p[BLOWFISH_ROUNDS]; + xl ^= p[BLOWFISH_ROUNDS+1]; + + *ret_xl = xl; + *ret_xr = xr; +#endif +} + + +static void +decrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) +{ +#if BLOWFISH_ROUNDS == 16 + u32 xl, xr, *s0, *s1, *s2, *s3, *p; + + xl = *ret_xl; + xr = *ret_xr; + p = bc->p; + s0 = bc->s0; + s1 = bc->s1; + s2 = bc->s2; + s3 = bc->s3; + + R( xl, xr, 17); + R( xr, xl, 16); + R( xl, xr, 15); + R( xr, xl, 14); + R( xl, xr, 13); + R( xr, xl, 12); + R( xl, xr, 11); + R( xr, xl, 10); + R( xl, xr, 9); + R( xr, xl, 8); + R( xl, xr, 7); + R( xr, xl, 6); + R( xl, xr, 5); + R( xr, xl, 4); + R( xl, xr, 3); + R( xr, xl, 2); + + xl ^= p[1]; + xr ^= p[0]; + + *ret_xl = xr; + *ret_xr = xl; + +#else + u32 xl, xr, temp, *p; + int i; + + xl = *ret_xl; + xr = *ret_xr; + p = bc->p; + + for (i=BLOWFISH_ROUNDS+1; i > 1; i-- ) + { + xl ^= p[i]; + xr ^= function_F(bc, xl); + temp = xl; + xl = xr; + xr = temp; + } + + temp = xl; + xl = xr; + xr = temp; + + xr ^= p[1]; + xl ^= p[0]; + + *ret_xl = xl; + *ret_xr = xr; +#endif +} + +#undef F +#undef R + +static void +do_encrypt_block ( BLOWFISH_context *bc, byte *outbuf, const byte *inbuf ) +{ + u32 d1, d2; + + d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + do_encrypt( bc, &d1, &d2 ); + outbuf[0] = (d1 >> 24) & 0xff; + outbuf[1] = (d1 >> 16) & 0xff; + outbuf[2] = (d1 >> 8) & 0xff; + outbuf[3] = d1 & 0xff; + outbuf[4] = (d2 >> 24) & 0xff; + outbuf[5] = (d2 >> 16) & 0xff; + outbuf[6] = (d2 >> 8) & 0xff; + outbuf[7] = d2 & 0xff; +} + +static void +encrypt_block (void *context, byte *outbuf, const byte *inbuf) +{ + BLOWFISH_context *bc = (BLOWFISH_context *) context; + do_encrypt_block (bc, outbuf, inbuf); + _gcry_burn_stack (64); +} + + +static void +do_decrypt_block (BLOWFISH_context *bc, byte *outbuf, const byte *inbuf) +{ + u32 d1, d2; + + d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + decrypt( bc, &d1, &d2 ); + outbuf[0] = (d1 >> 24) & 0xff; + outbuf[1] = (d1 >> 16) & 0xff; + outbuf[2] = (d1 >> 8) & 0xff; + outbuf[3] = d1 & 0xff; + outbuf[4] = (d2 >> 24) & 0xff; + outbuf[5] = (d2 >> 16) & 0xff; + outbuf[6] = (d2 >> 8) & 0xff; + outbuf[7] = d2 & 0xff; +} + +static void +decrypt_block (void *context, byte *outbuf, const byte *inbuf) +{ + BLOWFISH_context *bc = (BLOWFISH_context *) context; + do_decrypt_block (bc, outbuf, inbuf); + _gcry_burn_stack (64); +} + + + + + +static gcry_err_code_t +do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) +{ + int i, j; + u32 data, datal, datar; + static int initialized; + static const char *selftest_failed; + + if( !initialized ) + { + initialized = 1; + selftest_failed = selftest(); + if( selftest_failed ) + log_error ("%s\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + for(i=0; i < BLOWFISH_ROUNDS+2; i++ ) + c->p[i] = ps[i]; + for(i=0; i < 256; i++ ) + { + c->s0[i] = ks0[i]; + c->s1[i] = ks1[i]; + c->s2[i] = ks2[i]; + c->s3[i] = ks3[i]; + } + + for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) + { +#ifdef WORDS_BIGENDIAN + ((byte*)&data)[0] = key[j]; + ((byte*)&data)[1] = key[(j+1)%keylen]; + ((byte*)&data)[2] = key[(j+2)%keylen]; + ((byte*)&data)[3] = key[(j+3)%keylen]; +#else + ((byte*)&data)[3] = key[j]; + ((byte*)&data)[2] = key[(j+1)%keylen]; + ((byte*)&data)[1] = key[(j+2)%keylen]; + ((byte*)&data)[0] = key[(j+3)%keylen]; +#endif + c->p[i] ^= data; + j = (j+4) % keylen; + } + + datal = datar = 0; + for(i=0; i < BLOWFISH_ROUNDS+2; i += 2 ) + { + do_encrypt( c, &datal, &datar ); + c->p[i] = datal; + c->p[i+1] = datar; + } + for(i=0; i < 256; i += 2 ) + { + do_encrypt( c, &datal, &datar ); + c->s0[i] = datal; + c->s0[i+1] = datar; + } + for(i=0; i < 256; i += 2 ) + { + do_encrypt( c, &datal, &datar ); + c->s1[i] = datal; + c->s1[i+1] = datar; + } + for(i=0; i < 256; i += 2 ) + { + do_encrypt( c, &datal, &datar ); + c->s2[i] = datal; + c->s2[i+1] = datar; + } + for(i=0; i < 256; i += 2 ) + { + do_encrypt( c, &datal, &datar ); + c->s3[i] = datal; + c->s3[i+1] = datar; + } + + + /* Check for weak key. A weak key is a key in which a value in + the P-array (here c) occurs more than once per table. */ + for(i=0; i < 255; i++ ) + { + for( j=i+1; j < 256; j++) + { + if( (c->s0[i] == c->s0[j]) || (c->s1[i] == c->s1[j]) || + (c->s2[i] == c->s2[j]) || (c->s3[i] == c->s3[j]) ) + return GPG_ERR_WEAK_KEY; + } + } + + return GPG_ERR_NO_ERROR; +} + + +static gcry_err_code_t +bf_setkey (void *context, const byte *key, unsigned keylen) +{ + BLOWFISH_context *c = (BLOWFISH_context *) context; + gcry_err_code_t rc = do_bf_setkey (c, key, keylen); + _gcry_burn_stack (64); + return rc; +} + + +gcry_cipher_spec_t _gcry_cipher_spec_blowfish = + { + "BLOWFISH", NULL, NULL, BLOWFISH_BLOCKSIZE, 128, + sizeof (BLOWFISH_context), + bf_setkey, encrypt_block, decrypt_block + , +#ifdef GRUB_UTIL + .modname = "gcry_blowfish", +#endif + }; + + +GRUB_MOD_INIT(gcry_blowfish) +{ + grub_cipher_register (&_gcry_cipher_spec_blowfish); +} + +GRUB_MOD_FINI(gcry_blowfish) +{ + grub_cipher_unregister (&_gcry_cipher_spec_blowfish); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/bufhelp.h b/grub-core/lib/libgcrypt-grub/cipher/bufhelp.h new file mode 100644 index 0000000..89471e6 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/bufhelp.h @@ -0,0 +1,435 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +/* bufhelp.h - Some buffer manipulation helpers + * Copyright (C) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef GCRYPT_BUFHELP_H +#define GCRYPT_BUFHELP_H + + +#include "bithelp.h" + + +#undef BUFHELP_FAST_UNALIGNED_ACCESS +#if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \ + defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \ + (defined(__i386__) || defined(__x86_64__) || \ + (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \ + defined(__aarch64__)) +/* These architectures are able of unaligned memory accesses and can + handle those fast. + */ +# define BUFHELP_FAST_UNALIGNED_ACCESS 1 +#endif + + +#ifdef BUFHELP_FAST_UNALIGNED_ACCESS +/* Define type with one-byte alignment on architectures with fast unaligned + memory accesses. + */ +typedef struct bufhelp_int_s +{ + uintptr_t a; +} __attribute__((packed, aligned(1))) bufhelp_int_t; +#else +/* Define type with default alignment for other architectures (unaligned + accessed handled in per byte loops). + */ +typedef struct bufhelp_int_s +{ + uintptr_t a; +} bufhelp_int_t; +#endif + + +/* Optimized function for small buffer copying */ +static inline void +buf_cpy(void *_dst, const void *_src, size_t len) +{ +#if __GNUC__ >= 4 && (defined(__x86_64__) || defined(__i386__)) + /* For AMD64 and i386, memcpy is faster. */ + memcpy(_dst, _src, len); +#else + byte *dst = _dst; + const byte *src = _src; + bufhelp_int_t *ldst; + const bufhelp_int_t *lsrc; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)dst | (uintptr_t)src) & longmask) + goto do_bytes; +#endif + + ldst = (bufhelp_int_t *)(void *)dst; + lsrc = (const bufhelp_int_t *)(const void *)src; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst++)->a = (lsrc++)->a; + + dst = (byte *)ldst; + src = (const byte *)lsrc; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst++ = *src++; +#endif /*__GNUC__ >= 4 && (__x86_64__ || __i386__)*/ +} + + +/* Optimized function for buffer xoring */ +static inline void +buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len) +{ + byte *dst = _dst; + const byte *src1 = _src1; + const byte *src2 = _src2; + bufhelp_int_t *ldst; + const bufhelp_int_t *lsrc1, *lsrc2; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)dst | (uintptr_t)src1 | (uintptr_t)src2) & longmask) + goto do_bytes; +#endif + + ldst = (bufhelp_int_t *)(void *)dst; + lsrc1 = (const bufhelp_int_t *)(const void *)src1; + lsrc2 = (const bufhelp_int_t *)(const void *)src2; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst++)->a = (lsrc1++)->a ^ (lsrc2++)->a; + + dst = (byte *)ldst; + src1 = (const byte *)lsrc1; + src2 = (const byte *)lsrc2; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst++ = *src1++ ^ *src2++; +} + + +/* Optimized function for in-place buffer xoring. */ +static inline void +buf_xor_1(void *_dst, const void *_src, size_t len) +{ + byte *dst = _dst; + const byte *src = _src; + bufhelp_int_t *ldst; + const bufhelp_int_t *lsrc; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)dst | (uintptr_t)src) & longmask) + goto do_bytes; +#endif + + ldst = (bufhelp_int_t *)(void *)dst; + lsrc = (const bufhelp_int_t *)(const void *)src; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst++)->a ^= (lsrc++)->a; + + dst = (byte *)ldst; + src = (const byte *)lsrc; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst++ ^= *src++; +} + + +/* Optimized function for buffer xoring with two destination buffers. Used + mainly by CFB mode encryption. */ +static inline void +buf_xor_2dst(void *_dst1, void *_dst2, const void *_src, size_t len) +{ + byte *dst1 = _dst1; + byte *dst2 = _dst2; + const byte *src = _src; + bufhelp_int_t *ldst1, *ldst2; + const bufhelp_int_t *lsrc; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)src | (uintptr_t)dst1 | (uintptr_t)dst2) & longmask) + goto do_bytes; +#endif + + ldst1 = (bufhelp_int_t *)(void *)dst1; + ldst2 = (bufhelp_int_t *)(void *)dst2; + lsrc = (const bufhelp_int_t *)(const void *)src; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst1++)->a = ((ldst2++)->a ^= (lsrc++)->a); + + dst1 = (byte *)ldst1; + dst2 = (byte *)ldst2; + src = (const byte *)lsrc; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst1++ = (*dst2++ ^= *src++); +} + + +/* Optimized function for combined buffer xoring and copying. Used by mainly + CBC mode decryption. */ +static inline void +buf_xor_n_copy_2(void *_dst_xor, const void *_src_xor, void *_srcdst_cpy, + const void *_src_cpy, size_t len) +{ + byte *dst_xor = _dst_xor; + byte *srcdst_cpy = _srcdst_cpy; + const byte *src_xor = _src_xor; + const byte *src_cpy = _src_cpy; + byte temp; + bufhelp_int_t *ldst_xor, *lsrcdst_cpy; + const bufhelp_int_t *lsrc_cpy, *lsrc_xor; + uintptr_t ltemp; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)src_cpy | (uintptr_t)src_xor | (uintptr_t)dst_xor | + (uintptr_t)srcdst_cpy) & longmask) + goto do_bytes; +#endif + + ldst_xor = (bufhelp_int_t *)(void *)dst_xor; + lsrc_xor = (const bufhelp_int_t *)(void *)src_xor; + lsrcdst_cpy = (bufhelp_int_t *)(void *)srcdst_cpy; + lsrc_cpy = (const bufhelp_int_t *)(const void *)src_cpy; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + { + ltemp = (lsrc_cpy++)->a; + (ldst_xor++)->a = (lsrcdst_cpy)->a ^ (lsrc_xor++)->a; + (lsrcdst_cpy++)->a = ltemp; + } + + dst_xor = (byte *)ldst_xor; + src_xor = (const byte *)lsrc_xor; + srcdst_cpy = (byte *)lsrcdst_cpy; + src_cpy = (const byte *)lsrc_cpy; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + { + temp = *src_cpy++; + *dst_xor++ = *srcdst_cpy ^ *src_xor++; + *srcdst_cpy++ = temp; + } +} + + +/* Optimized function for combined buffer xoring and copying. Used by mainly + CFB mode decryption. */ +static inline void +buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len) +{ + buf_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, len); +} + + +/* Constant-time compare of two buffers. Returns 1 if buffers are equal, + and 0 if buffers differ. */ +static inline int +buf_eq_const(const void *_a, const void *_b, size_t len) +{ + const byte *a = _a; + const byte *b = _b; + size_t diff, i; + + /* Constant-time compare. */ + for (i = 0, diff = 0; i < len; i++) + diff -= !!(a[i] - b[i]); + + return !diff; +} + + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + +/* Functions for loading and storing unaligned u32 values of different + endianness. */ +static inline u32 buf_get_be32(const void *_buf) +{ + const byte *in = _buf; + return ((u32)in[0] << 24) | ((u32)in[1] << 16) | \ + ((u32)in[2] << 8) | (u32)in[3]; +} + +static inline u32 buf_get_le32(const void *_buf) +{ + const byte *in = _buf; + return ((u32)in[3] << 24) | ((u32)in[2] << 16) | \ + ((u32)in[1] << 8) | (u32)in[0]; +} + +static inline void buf_put_be32(void *_buf, u32 val) +{ + byte *out = _buf; + out[0] = val >> 24; + out[1] = val >> 16; + out[2] = val >> 8; + out[3] = val; +} + +static inline void buf_put_le32(void *_buf, u32 val) +{ + byte *out = _buf; + out[3] = val >> 24; + out[2] = val >> 16; + out[1] = val >> 8; + out[0] = val; +} + + +/* Functions for loading and storing unaligned u64 values of different + endianness. */ +static inline u64 buf_get_be64(const void *_buf) +{ + const byte *in = _buf; + return ((u64)in[0] << 56) | ((u64)in[1] << 48) | \ + ((u64)in[2] << 40) | ((u64)in[3] << 32) | \ + ((u64)in[4] << 24) | ((u64)in[5] << 16) | \ + ((u64)in[6] << 8) | (u64)in[7]; +} + +static inline u64 buf_get_le64(const void *_buf) +{ + const byte *in = _buf; + return ((u64)in[7] << 56) | ((u64)in[6] << 48) | \ + ((u64)in[5] << 40) | ((u64)in[4] << 32) | \ + ((u64)in[3] << 24) | ((u64)in[2] << 16) | \ + ((u64)in[1] << 8) | (u64)in[0]; +} + +static inline void buf_put_be64(void *_buf, u64 val) +{ + byte *out = _buf; + out[0] = val >> 56; + out[1] = val >> 48; + out[2] = val >> 40; + out[3] = val >> 32; + out[4] = val >> 24; + out[5] = val >> 16; + out[6] = val >> 8; + out[7] = val; +} + +static inline void buf_put_le64(void *_buf, u64 val) +{ + byte *out = _buf; + out[7] = val >> 56; + out[6] = val >> 48; + out[5] = val >> 40; + out[4] = val >> 32; + out[3] = val >> 24; + out[2] = val >> 16; + out[1] = val >> 8; + out[0] = val; +} + +#else /*BUFHELP_FAST_UNALIGNED_ACCESS*/ + +typedef struct bufhelp_u32_s +{ + u32 a; +} __attribute__((packed, aligned(1))) bufhelp_u32_t; + +/* Functions for loading and storing unaligned u32 values of different + endianness. */ +static inline u32 buf_get_be32(const void *_buf) +{ + return be_bswap32(((const bufhelp_u32_t *)_buf)->a); +} + +static inline u32 buf_get_le32(const void *_buf) +{ + return le_bswap32(((const bufhelp_u32_t *)_buf)->a); +} + +static inline void buf_put_be32(void *_buf, u32 val) +{ + bufhelp_u32_t *out = _buf; + out->a = be_bswap32(val); +} + +static inline void buf_put_le32(void *_buf, u32 val) +{ + bufhelp_u32_t *out = _buf; + out->a = le_bswap32(val); +} + + +typedef struct bufhelp_u64_s +{ + u64 a; +} __attribute__((packed, aligned(1))) bufhelp_u64_t; + +/* Functions for loading and storing unaligned u64 values of different + endianness. */ +static inline u64 buf_get_be64(const void *_buf) +{ + return be_bswap64(((const bufhelp_u64_t *)_buf)->a); +} + +static inline u64 buf_get_le64(const void *_buf) +{ + return le_bswap64(((const bufhelp_u64_t *)_buf)->a); +} + +static inline void buf_put_be64(void *_buf, u64 val) +{ + bufhelp_u64_t *out = _buf; + out->a = be_bswap64(val); +} + +static inline void buf_put_le64(void *_buf, u64 val) +{ + bufhelp_u64_t *out = _buf; + out->a = le_bswap64(val); +} + + +#endif /*BUFHELP_FAST_UNALIGNED_ACCESS*/ + +#endif /*GCRYPT_BUFHELP_H*/ diff --git a/grub-core/lib/libgcrypt-grub/cipher/camellia-glue.c b/grub-core/lib/libgcrypt-grub/cipher/camellia-glue.c new file mode 100644 index 0000000..f1a9143 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/camellia-glue.c @@ -0,0 +1,211 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* camellia-glue.c - Glue for the Camellia cipher + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* I put all the libgcrypt-specific stuff in this file to keep the + camellia.c/camellia.h files exactly as provided by NTT. If they + update their code, this should make it easier to bring the changes + in. - dshaw + + There is one small change which needs to be done: Include the + following code at the top of camellia.h: */ +#if 0 + +/* To use Camellia with libraries it is often useful to keep the name + * space of the library clean. The following macro is thus useful: + * + * #define CAMELLIA_EXT_SYM_PREFIX foo_ + * + * This prefixes all external symbols with "foo_". + */ +#ifdef HAVE_CONFIG_H +#endif +#ifdef CAMELLIA_EXT_SYM_PREFIX +#define CAMELLIA_PREFIX1(x,y) x ## y +#define CAMELLIA_PREFIX2(x,y) CAMELLIA_PREFIX1(x,y) +#define CAMELLIA_PREFIX(x) CAMELLIA_PREFIX2(CAMELLIA_EXT_SYM_PREFIX,x) +#define Camellia_Ekeygen CAMELLIA_PREFIX(Camellia_Ekeygen) +#define Camellia_EncryptBlock CAMELLIA_PREFIX(Camellia_EncryptBlock) +#define Camellia_DecryptBlock CAMELLIA_PREFIX(Camellia_DecryptBlock) +#define camellia_decrypt128 CAMELLIA_PREFIX(camellia_decrypt128) +#define camellia_decrypt256 CAMELLIA_PREFIX(camellia_decrypt256) +#define camellia_encrypt128 CAMELLIA_PREFIX(camellia_encrypt128) +#define camellia_encrypt256 CAMELLIA_PREFIX(camellia_encrypt256) +#define camellia_setup128 CAMELLIA_PREFIX(camellia_setup128) +#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) +#define camellia_setup256 CAMELLIA_PREFIX(camellia_setup256) +#endif /*CAMELLIA_EXT_SYM_PREFIX*/ + +#endif /* Code sample. */ + + +#include "types.h" +#include "g10lib.h" +#include "cipher.h" +#include "camellia.h" + +typedef struct +{ + int keybitlength; + KEY_TABLE_TYPE keytable; +} CAMELLIA_context; + + +static gcry_err_code_t +camellia_setkey(void *c, const byte *key, unsigned keylen) +{ + CAMELLIA_context *ctx=c; + static int initialized=0; + static const char *selftest_failed=NULL; + + if(keylen!=16 && keylen!=24 && keylen!=32) + return GPG_ERR_INV_KEYLEN; + + if(!initialized) + { + initialized=1; + selftest_failed=selftest(); + if(selftest_failed) + log_error("%s\n",selftest_failed); + } + + if(selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + ctx->keybitlength=keylen*8; + Camellia_Ekeygen(ctx->keybitlength,key,ctx->keytable); + _gcry_burn_stack + ((19+34+34)*sizeof(u32)+2*sizeof(void*) /* camellia_setup256 */ + +(4+32)*sizeof(u32)+2*sizeof(void*) /* camellia_setup192 */ + +0+sizeof(int)+2*sizeof(void*) /* Camellia_Ekeygen */ + +3*2*sizeof(void*) /* Function calls. */ + ); + + return 0; +} + +static void +camellia_encrypt(void *c, byte *outbuf, const byte *inbuf) +{ + CAMELLIA_context *ctx=c; + + Camellia_EncryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); + _gcry_burn_stack + (sizeof(int)+2*sizeof(unsigned char *)+sizeof(KEY_TABLE_TYPE) + +4*sizeof(u32) + +2*sizeof(u32*)+4*sizeof(u32) + +2*2*sizeof(void*) /* Function calls. */ + ); +} + +static void +camellia_decrypt(void *c, byte *outbuf, const byte *inbuf) +{ + CAMELLIA_context *ctx=c; + + Camellia_DecryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); + _gcry_burn_stack + (sizeof(int)+2*sizeof(unsigned char *)+sizeof(KEY_TABLE_TYPE) + +4*sizeof(u32) + +2*sizeof(u32*)+4*sizeof(u32) + +2*2*sizeof(void*) /* Function calls. */ + ); +} + + +/* These oids are from + <http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications_oid.html>, + retrieved May 1, 2007. */ + +static gcry_cipher_oid_spec_t camellia128_oids[] = + { + {"1.2.392.200011.61.1.1.1.2", GCRY_CIPHER_MODE_CBC}, + {"0.3.4401.5.3.1.9.1", GCRY_CIPHER_MODE_ECB}, + {"0.3.4401.5.3.1.9.3", GCRY_CIPHER_MODE_OFB}, + {"0.3.4401.5.3.1.9.4", GCRY_CIPHER_MODE_CFB}, + { NULL } + }; + +static gcry_cipher_oid_spec_t camellia192_oids[] = + { + {"1.2.392.200011.61.1.1.1.3", GCRY_CIPHER_MODE_CBC}, + {"0.3.4401.5.3.1.9.21", GCRY_CIPHER_MODE_ECB}, + {"0.3.4401.5.3.1.9.23", GCRY_CIPHER_MODE_OFB}, + {"0.3.4401.5.3.1.9.24", GCRY_CIPHER_MODE_CFB}, + { NULL } + }; + +static gcry_cipher_oid_spec_t camellia256_oids[] = + { + {"1.2.392.200011.61.1.1.1.4", GCRY_CIPHER_MODE_CBC}, + {"0.3.4401.5.3.1.9.41", GCRY_CIPHER_MODE_ECB}, + {"0.3.4401.5.3.1.9.43", GCRY_CIPHER_MODE_OFB}, + {"0.3.4401.5.3.1.9.44", GCRY_CIPHER_MODE_CFB}, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_camellia128 = + { + "CAMELLIA128",NULL,camellia128_oids,CAMELLIA_BLOCK_SIZE,128, + sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_camellia", +#endif + }; + +gcry_cipher_spec_t _gcry_cipher_spec_camellia192 = + { + "CAMELLIA192",NULL,camellia192_oids,CAMELLIA_BLOCK_SIZE,192, + sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_camellia", +#endif + }; + +gcry_cipher_spec_t _gcry_cipher_spec_camellia256 = + { + "CAMELLIA256",NULL,camellia256_oids,CAMELLIA_BLOCK_SIZE,256, + sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_camellia", +#endif + }; + + +GRUB_MOD_INIT(gcry_camellia) +{ + grub_cipher_register (&_gcry_cipher_spec_camellia128); + grub_cipher_register (&_gcry_cipher_spec_camellia192); + grub_cipher_register (&_gcry_cipher_spec_camellia256); +} + +GRUB_MOD_FINI(gcry_camellia) +{ + grub_cipher_unregister (&_gcry_cipher_spec_camellia128); + grub_cipher_unregister (&_gcry_cipher_spec_camellia192); + grub_cipher_unregister (&_gcry_cipher_spec_camellia256); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/camellia.c b/grub-core/lib/libgcrypt-grub/cipher/camellia.c new file mode 100644 index 0000000..5c85ea8 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/camellia.c @@ -0,0 +1,1463 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* camellia.h ver 1.2.0 + * + * Copyright (C) 2006,2007 + * NTT (Nippon Telegraph and Telephone Corporation). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Algorithm Specification + * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html + */ + + +#include "camellia.h" + +/* u32 must be 32bit word */ +typedef unsigned int u32; +typedef unsigned char u8; + +/* key constants */ + +#define CAMELLIA_SIGMA1L (0xA09E667FL) +#define CAMELLIA_SIGMA1R (0x3BCC908BL) +#define CAMELLIA_SIGMA2L (0xB67AE858L) +#define CAMELLIA_SIGMA2R (0x4CAA73B2L) +#define CAMELLIA_SIGMA3L (0xC6EF372FL) +#define CAMELLIA_SIGMA3R (0xE94F82BEL) +#define CAMELLIA_SIGMA4L (0x54FF53A5L) +#define CAMELLIA_SIGMA4R (0xF1D36F1CL) +#define CAMELLIA_SIGMA5L (0x10E527FAL) +#define CAMELLIA_SIGMA5R (0xDE682D1DL) +#define CAMELLIA_SIGMA6L (0xB05688C2L) +#define CAMELLIA_SIGMA6R (0xB3E6C1FDL) + +/* + * macros + */ + + +#if defined(_MSC_VER) + +# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +# define GETU32(p) SWAP(*((u32 *)(p))) +# define PUTU32(ct, st) {*((u32 *)(ct)) = SWAP((st));} + +#else /* not MS-VC */ + +# define GETU32(pt) \ + (((u32)(pt)[0] << 24) \ + ^ ((u32)(pt)[1] << 16) \ + ^ ((u32)(pt)[2] << 8) \ + ^ ((u32)(pt)[3])) + +# define PUTU32(ct, st) { \ + (ct)[0] = (u8)((st) >> 24); \ + (ct)[1] = (u8)((st) >> 16); \ + (ct)[2] = (u8)((st) >> 8); \ + (ct)[3] = (u8)(st); } + +#endif + +#define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2]) +#define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1]) + +/* rotation right shift 1byte */ +#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24)) +/* rotation left shift 1bit */ +#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31)) +/* rotation left shift 1byte */ +#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24)) + +#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + ll = (ll << bits) + (lr >> (32 - bits)); \ + lr = (lr << bits) + (rl >> (32 - bits)); \ + rl = (rl << bits) + (rr >> (32 - bits)); \ + rr = (rr << bits) + (w0 >> (32 - bits)); \ + } while(0) + +#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + w1 = lr; \ + ll = (lr << (bits - 32)) + (rl >> (64 - bits)); \ + lr = (rl << (bits - 32)) + (rr >> (64 - bits)); \ + rl = (rr << (bits - 32)) + (w0 >> (64 - bits)); \ + rr = (w0 << (bits - 32)) + (w1 >> (64 - bits)); \ + } while(0) + +#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)]) +#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)]) +#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)]) +#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)]) + +#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + il = xl ^ kl; \ + ir = xr ^ kr; \ + t0 = il >> 16; \ + t1 = ir >> 16; \ + yl = CAMELLIA_SP1110(ir & 0xff) \ + ^ CAMELLIA_SP0222((t1 >> 8) & 0xff) \ + ^ CAMELLIA_SP3033(t1 & 0xff) \ + ^ CAMELLIA_SP4404((ir >> 8) & 0xff); \ + yr = CAMELLIA_SP1110((t0 >> 8) & 0xff) \ + ^ CAMELLIA_SP0222(t0 & 0xff) \ + ^ CAMELLIA_SP3033((il >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(il & 0xff); \ + yl ^= yr; \ + yr = CAMELLIA_RR8(yr); \ + yr ^= yl; \ + } while(0) + + +/* + * for speed up + * + */ +#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \ + do { \ + t0 = kll; \ + t0 &= ll; \ + lr ^= CAMELLIA_RL1(t0); \ + t1 = klr; \ + t1 |= lr; \ + ll ^= t1; \ + \ + t2 = krr; \ + t2 |= rr; \ + rl ^= t2; \ + t3 = krl; \ + t3 &= rl; \ + rr ^= CAMELLIA_RL1(t3); \ + } while(0) + +#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + ir = CAMELLIA_SP1110(xr & 0xff) \ + ^ CAMELLIA_SP0222((xr >> 24) & 0xff) \ + ^ CAMELLIA_SP3033((xr >> 16) & 0xff) \ + ^ CAMELLIA_SP4404((xr >> 8) & 0xff); \ + il = CAMELLIA_SP1110((xl >> 24) & 0xff) \ + ^ CAMELLIA_SP0222((xl >> 16) & 0xff) \ + ^ CAMELLIA_SP3033((xl >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(xl & 0xff); \ + il ^= kl; \ + ir ^= kr; \ + ir ^= il; \ + il = CAMELLIA_RR8(il); \ + il ^= ir; \ + yl ^= ir; \ + yr ^= il; \ + } while(0) + + +static const u32 camellia_sp1110[256] = { + 0x70707000,0x82828200,0x2c2c2c00,0xececec00, + 0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500, + 0xe4e4e400,0x85858500,0x57575700,0x35353500, + 0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100, + 0x23232300,0xefefef00,0x6b6b6b00,0x93939300, + 0x45454500,0x19191900,0xa5a5a500,0x21212100, + 0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00, + 0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00, + 0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00, + 0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00, + 0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00, + 0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00, + 0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00, + 0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00, + 0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600, + 0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00, + 0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600, + 0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00, + 0x74747400,0x12121200,0x2b2b2b00,0x20202000, + 0xf0f0f000,0xb1b1b100,0x84848400,0x99999900, + 0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200, + 0x34343400,0x7e7e7e00,0x76767600,0x05050500, + 0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100, + 0xd1d1d100,0x17171700,0x04040400,0xd7d7d700, + 0x14141400,0x58585800,0x3a3a3a00,0x61616100, + 0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00, + 0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600, + 0x53535300,0x18181800,0xf2f2f200,0x22222200, + 0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200, + 0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100, + 0x24242400,0x08080800,0xe8e8e800,0xa8a8a800, + 0x60606000,0xfcfcfc00,0x69696900,0x50505000, + 0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00, + 0xa1a1a100,0x89898900,0x62626200,0x97979700, + 0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500, + 0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200, + 0x10101000,0xc4c4c400,0x00000000,0x48484800, + 0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00, + 0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00, + 0x09090900,0x3f3f3f00,0xdddddd00,0x94949400, + 0x87878700,0x5c5c5c00,0x83838300,0x02020200, + 0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300, + 0x73737300,0x67676700,0xf6f6f600,0xf3f3f300, + 0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200, + 0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600, + 0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00, + 0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00, + 0x13131300,0xbebebe00,0x63636300,0x2e2e2e00, + 0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00, + 0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00, + 0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600, + 0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900, + 0x78787800,0x98989800,0x06060600,0x6a6a6a00, + 0xe7e7e700,0x46464600,0x71717100,0xbababa00, + 0xd4d4d400,0x25252500,0xababab00,0x42424200, + 0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00, + 0x72727200,0x07070700,0xb9b9b900,0x55555500, + 0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00, + 0x36363600,0x49494900,0x2a2a2a00,0x68686800, + 0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400, + 0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00, + 0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100, + 0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400, + 0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00, +}; + +static const u32 camellia_sp0222[256] = { + 0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9, + 0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb, + 0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a, + 0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282, + 0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727, + 0x008a8a8a,0x00323232,0x004b4b4b,0x00424242, + 0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c, + 0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b, + 0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f, + 0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d, + 0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe, + 0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434, + 0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595, + 0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a, + 0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad, + 0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a, + 0x00171717,0x001a1a1a,0x00353535,0x00cccccc, + 0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a, + 0x00e8e8e8,0x00242424,0x00565656,0x00404040, + 0x00e1e1e1,0x00636363,0x00090909,0x00333333, + 0x00bfbfbf,0x00989898,0x00979797,0x00858585, + 0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a, + 0x00dadada,0x006f6f6f,0x00535353,0x00626262, + 0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf, + 0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2, + 0x00bdbdbd,0x00363636,0x00222222,0x00383838, + 0x00646464,0x001e1e1e,0x00393939,0x002c2c2c, + 0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444, + 0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565, + 0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323, + 0x00484848,0x00101010,0x00d1d1d1,0x00515151, + 0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0, + 0x00555555,0x00a1a1a1,0x00414141,0x00fafafa, + 0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f, + 0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b, + 0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5, + 0x00202020,0x00898989,0x00000000,0x00909090, + 0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7, + 0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5, + 0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929, + 0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404, + 0x009b9b9b,0x00949494,0x00212121,0x00666666, + 0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7, + 0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5, + 0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c, + 0x00919191,0x006e6e6e,0x008d8d8d,0x00767676, + 0x00030303,0x002d2d2d,0x00dedede,0x00969696, + 0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c, + 0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919, + 0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d, + 0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d, + 0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2, + 0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4, + 0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575, + 0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484, + 0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5, + 0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa, + 0x00f1f1f1,0x00dddddd,0x00595959,0x00141414, + 0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0, + 0x00787878,0x00707070,0x00e3e3e3,0x00494949, + 0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6, + 0x00777777,0x00939393,0x00868686,0x00838383, + 0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9, + 0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d, +}; + +static const u32 camellia_sp3033[256] = { + 0x38003838,0x41004141,0x16001616,0x76007676, + 0xd900d9d9,0x93009393,0x60006060,0xf200f2f2, + 0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a, + 0x75007575,0x06000606,0x57005757,0xa000a0a0, + 0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9, + 0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090, + 0xf600f6f6,0x07000707,0xa700a7a7,0x27002727, + 0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede, + 0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7, + 0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767, + 0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf, + 0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d, + 0x53005353,0xf000f0f0,0x9c009c9c,0x65006565, + 0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e, + 0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b, + 0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6, + 0xc500c5c5,0x86008686,0x4d004d4d,0x33003333, + 0xfd00fdfd,0x66006666,0x58005858,0x96009696, + 0x3a003a3a,0x09000909,0x95009595,0x10001010, + 0x78007878,0xd800d8d8,0x42004242,0xcc00cccc, + 0xef00efef,0x26002626,0xe500e5e5,0x61006161, + 0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282, + 0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898, + 0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb, + 0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0, + 0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e, + 0x19001919,0x87008787,0x4e004e4e,0x0b000b0b, + 0xa900a9a9,0x0c000c0c,0x79007979,0x11001111, + 0x7f007f7f,0x22002222,0xe700e7e7,0x59005959, + 0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8, + 0x12001212,0x04000404,0x74007474,0x54005454, + 0x30003030,0x7e007e7e,0xb400b4b4,0x28002828, + 0x55005555,0x68006868,0x50005050,0xbe00bebe, + 0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb, + 0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca, + 0x70007070,0xff00ffff,0x32003232,0x69006969, + 0x08000808,0x62006262,0x00000000,0x24002424, + 0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded, + 0x45004545,0x81008181,0x73007373,0x6d006d6d, + 0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a, + 0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101, + 0xe600e6e6,0x25002525,0x48004848,0x99009999, + 0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9, + 0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171, + 0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313, + 0x64006464,0x9b009b9b,0x63006363,0x9d009d9d, + 0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5, + 0x89008989,0x5f005f5f,0xb100b1b1,0x17001717, + 0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646, + 0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747, + 0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b, + 0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac, + 0x3c003c3c,0x4c004c4c,0x03000303,0x35003535, + 0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d, + 0x6a006a6a,0x92009292,0xd500d5d5,0x21002121, + 0x44004444,0x51005151,0xc600c6c6,0x7d007d7d, + 0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa, + 0x7c007c7c,0x77007777,0x56005656,0x05000505, + 0x1b001b1b,0xa400a4a4,0x15001515,0x34003434, + 0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252, + 0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd, + 0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0, + 0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a, + 0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f, +}; + +static const u32 camellia_sp4404[256] = { + 0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0, + 0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae, + 0x23230023,0x6b6b006b,0x45450045,0xa5a500a5, + 0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092, + 0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f, + 0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b, + 0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d, + 0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c, + 0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0, + 0x74740074,0x2b2b002b,0xf0f000f0,0x84840084, + 0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076, + 0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004, + 0x14140014,0x3a3a003a,0xdede00de,0x11110011, + 0x32320032,0x9c9c009c,0x53530053,0xf2f200f2, + 0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a, + 0x24240024,0xe8e800e8,0x60600060,0x69690069, + 0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062, + 0x54540054,0x1e1e001e,0xe0e000e0,0x64640064, + 0x10100010,0x00000000,0xa3a300a3,0x75750075, + 0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd, + 0x87870087,0x83830083,0xcdcd00cd,0x90900090, + 0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf, + 0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6, + 0x81810081,0x6f6f006f,0x13130013,0x63630063, + 0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc, + 0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4, + 0x78780078,0x06060006,0xe7e700e7,0x71710071, + 0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d, + 0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac, + 0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1, + 0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043, + 0x15150015,0xadad00ad,0x77770077,0x80800080, + 0x82820082,0xecec00ec,0x27270027,0xe5e500e5, + 0x85850085,0x35350035,0x0c0c000c,0x41410041, + 0xefef00ef,0x93930093,0x19190019,0x21210021, + 0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd, + 0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce, + 0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a, + 0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d, + 0x01010001,0xd6d600d6,0x56560056,0x4d4d004d, + 0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d, + 0x12120012,0x20200020,0xb1b100b1,0x99990099, + 0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005, + 0xb7b700b7,0x31310031,0x17170017,0xd7d700d7, + 0x58580058,0x61610061,0x1b1b001b,0x1c1c001c, + 0x0f0f000f,0x16160016,0x18180018,0x22220022, + 0x44440044,0xb2b200b2,0xb5b500b5,0x91910091, + 0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050, + 0xd0d000d0,0x7d7d007d,0x89890089,0x97970097, + 0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2, + 0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db, + 0x03030003,0xdada00da,0x3f3f003f,0x94940094, + 0x5c5c005c,0x02020002,0x4a4a004a,0x33330033, + 0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2, + 0x9b9b009b,0x26260026,0x37370037,0x3b3b003b, + 0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e, + 0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e, + 0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059, + 0x98980098,0x6a6a006a,0x46460046,0xbaba00ba, + 0x25250025,0x42420042,0xa2a200a2,0xfafa00fa, + 0x07070007,0x55550055,0xeeee00ee,0x0a0a000a, + 0x49490049,0x68680068,0x38380038,0xa4a400a4, + 0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1, + 0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e, +}; + + +/** + * Stuff related to the Camellia key schedule + */ +#define subl(x) subL[(x)] +#define subr(x) subR[(x)] + +void camellia_setup128(const unsigned char *key, u32 *subkey) +{ + u32 kll, klr, krl, krr; + u32 il, ir, t0, t1, w0, w1; + u32 kw4l, kw4r, dw, tl, tr; + u32 subL[26]; + u32 subR[26]; + + /** + * k == kll || klr || krl || krr (|| is concatination) + */ + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + /** + * generate KL dependent subkeys + */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(4) = kll; subr(4) = klr; + subl(5) = krl; subr(5) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(10) = kll; subr(10) = klr; + subl(11) = krl; subr(11) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(18) = kll; subr(18) = klr; + subl(19) = krl; subr(19) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + + /* generate KA */ + kll = subl(0); klr = subr(0); + krl = subl(1); krr = subr(1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KA dependent subkeys */ + subl(2) = kll; subr(2) = klr; + subl(3) = krl; subr(3) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(8) = kll; subr(8) = klr; + subl(9) = krl; subr(9) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(12) = kll; subr(12) = klr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(20) = kll; subr(20) = klr; + subl(21) = krl; subr(21) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(24) = kll; subr(24) = klr; + subl(25) = krl; subr(25) = krr; + + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(24) ^= subl(1); subr(24) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(25); kw4r = subr(25); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + CamelliaSubkeyL(23) = subl(22); + CamelliaSubkeyR(23) = subr(22); + CamelliaSubkeyL(24) = subl(24) ^ subl(23); + CamelliaSubkeyR(24) = subr(24) ^ subr(23); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + + return; +} + +void camellia_setup256(const unsigned char *key, u32 *subkey) +{ + u32 kll,klr,krl,krr; /* left half of key */ + u32 krll,krlr,krrl,krrr; /* right half of key */ + u32 il, ir, t0, t1, w0, w1; /* temporary variables */ + u32 kw4l, kw4r, dw, tl, tr; + u32 subL[34]; + u32 subR[34]; + + /** + * key = (kll || klr || krl || krr || krll || krlr || krrl || krrr) + * (|| is concatination) + */ + + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + krll = GETU32(key + 16); + krlr = GETU32(key + 20); + krrl = GETU32(key + 24); + krrr = GETU32(key + 28); + + /* generate KL dependent subkeys */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45); + subl(12) = kll; subr(12) = klr; + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(30) = kll; subr(30) = klr; + subl(31) = krl; subr(31) = krr; + + /* generate KR dependent subkeys */ + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(4) = krll; subr(4) = krlr; + subl(5) = krrl; subr(5) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(8) = krll; subr(8) = krlr; + subl(9) = krrl; subr(9) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(18) = krll; subr(18) = krlr; + subl(19) = krrl; subr(19) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + subl(26) = krll; subr(26) = krlr; + subl(27) = krrl; subr(27) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + + /* generate KA */ + kll = subl(0) ^ krll; klr = subr(0) ^ krlr; + krl = subl(1) ^ krrl; krr = subr(1) ^ krrr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + kll ^= krll; klr ^= krlr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0 ^ krrl; krr ^= w1 ^ krrr; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KB */ + krll ^= kll; krlr ^= klr; + krrl ^= krl; krrr ^= krr; + CAMELLIA_F(krll, krlr, + CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R, + w0, w1, il, ir, t0, t1); + krrl ^= w0; krrr ^= w1; + CAMELLIA_F(krrl, krrr, + CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R, + w0, w1, il, ir, t0, t1); + krll ^= w0; krlr ^= w1; + + /* generate KA dependent subkeys */ + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + subl(24) = klr; subr(24) = krl; + subl(25) = krr; subr(25) = kll; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49); + subl(28) = kll; subr(28) = klr; + subl(29) = krl; subr(29) = krr; + + /* generate KB dependent subkeys */ + subl(2) = krll; subr(2) = krlr; + subl(3) = krrl; subr(3) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(10) = krll; subr(10) = krlr; + subl(11) = krrl; subr(11) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(20) = krll; subr(20) = krlr; + subl(21) = krrl; subr(21) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51); + subl(32) = krll; subr(32) = krlr; + subl(33) = krrl; subr(33) = krrr; + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(1) ^= subr(1) & ~subr(25); + dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw); + subl(27) ^= subl(1); subr(27) ^= subr(1); + subl(29) ^= subl(1); subr(29) ^= subr(1); + subl(31) ^= subl(1); subr(31) ^= subr(1); + subl(32) ^= subl(1); subr(32) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(33); kw4r = subr(33); + subl(30) ^= kw4l; subr(30) ^= kw4r; + subl(28) ^= kw4l; subr(28) ^= kw4r; + subl(26) ^= kw4l; subr(26) ^= kw4r; + kw4l ^= kw4r & ~subr(24); + dw = kw4l & subl(24), kw4r ^= CAMELLIA_RL1(dw); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + tl = subl(26) ^ (subr(26) & ~subr(24)); + dw = tl & subl(24), tr = subr(26) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(23) = subl(22) ^ tl; + CamelliaSubkeyR(23) = subr(22) ^ tr; + CamelliaSubkeyL(24) = subl(24); + CamelliaSubkeyR(24) = subr(24); + CamelliaSubkeyL(25) = subl(25); + CamelliaSubkeyR(25) = subr(25); + tl = subl(23) ^ (subr(23) & ~subr(25)); + dw = tl & subl(25), tr = subr(23) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(26) = tl ^ subl(27); + CamelliaSubkeyR(26) = tr ^ subr(27); + CamelliaSubkeyL(27) = subl(26) ^ subl(28); + CamelliaSubkeyR(27) = subr(26) ^ subr(28); + CamelliaSubkeyL(28) = subl(27) ^ subl(29); + CamelliaSubkeyR(28) = subr(27) ^ subr(29); + CamelliaSubkeyL(29) = subl(28) ^ subl(30); + CamelliaSubkeyR(29) = subr(28) ^ subr(30); + CamelliaSubkeyL(30) = subl(29) ^ subl(31); + CamelliaSubkeyR(30) = subr(29) ^ subr(31); + CamelliaSubkeyL(31) = subl(30); + CamelliaSubkeyR(31) = subr(30); + CamelliaSubkeyL(32) = subl(32) ^ subl(31); + CamelliaSubkeyR(32) = subr(32) ^ subr(31); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + dw = CamelliaSubkeyL(26) ^ CamelliaSubkeyR(26), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(26) = CamelliaSubkeyL(26) ^ dw, CamelliaSubkeyL(26) = dw; + dw = CamelliaSubkeyL(27) ^ CamelliaSubkeyR(27), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(27) = CamelliaSubkeyL(27) ^ dw, CamelliaSubkeyL(27) = dw; + dw = CamelliaSubkeyL(28) ^ CamelliaSubkeyR(28), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(28) = CamelliaSubkeyL(28) ^ dw, CamelliaSubkeyL(28) = dw; + dw = CamelliaSubkeyL(29) ^ CamelliaSubkeyR(29), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(29) = CamelliaSubkeyL(29) ^ dw, CamelliaSubkeyL(29) = dw; + dw = CamelliaSubkeyL(30) ^ CamelliaSubkeyR(30), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw; + dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw; + + return; +} + +void camellia_setup192(const unsigned char *key, u32 *subkey) +{ + unsigned char kk[32]; + u32 krll, krlr, krrl,krrr; + + memcpy(kk, key, 24); + memcpy((unsigned char *)&krll, key+16,4); + memcpy((unsigned char *)&krlr, key+20,4); + krrl = ~krll; + krrr = ~krlr; + memcpy(kk+24, (unsigned char *)&krrl, 4); + memcpy(kk+28, (unsigned char *)&krrr, 4); + camellia_setup256(kk, subkey); + return; +} + + +/** + * Stuff related to camellia encryption/decryption + * + * "io" must be 4byte aligned and big-endian data. + */ +void camellia_encrypt128(const u32 *subkey, u32 *io) +{ + u32 il, ir, t0, t1; + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + /* main iteration */ + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(24); + io[3] ^= CamelliaSubkeyR(24); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +void camellia_decrypt128(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(24); + io[1] ^= CamelliaSubkeyR(24); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/** + * stuff for 192 and 256bit encryption/decryption + */ +void camellia_encrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(32); + io[3] ^= CamelliaSubkeyR(32); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +void camellia_decrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(32); + io[1] ^= CamelliaSubkeyR(32); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/*** + * + * API for compatibility + */ + +void Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, + KEY_TABLE_TYPE keyTable) +{ + switch(keyBitLength) { + case 128: + camellia_setup128(rawKey, keyTable); + break; + case 192: + camellia_setup192(rawKey, keyTable); + break; + case 256: + camellia_setup256(rawKey, keyTable); + break; + default: + break; + } +} + + +void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, + unsigned char *ciphertext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(plaintext); + tmp[1] = GETU32(plaintext + 4); + tmp[2] = GETU32(plaintext + 8); + tmp[3] = GETU32(plaintext + 12); + + switch (keyBitLength) { + case 128: + camellia_encrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_encrypt256(keyTable, tmp); + break; + default: + break; + } + + PUTU32(ciphertext, tmp[0]); + PUTU32(ciphertext + 4, tmp[1]); + PUTU32(ciphertext + 8, tmp[2]); + PUTU32(ciphertext + 12, tmp[3]); +} + +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *ciphertext, + const KEY_TABLE_TYPE keyTable, + unsigned char *plaintext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(ciphertext); + tmp[1] = GETU32(ciphertext + 4); + tmp[2] = GETU32(ciphertext + 8); + tmp[3] = GETU32(ciphertext + 12); + + switch (keyBitLength) { + case 128: + camellia_decrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_decrypt256(keyTable, tmp); + break; + default: + break; + } + PUTU32(plaintext, tmp[0]); + PUTU32(plaintext + 4, tmp[1]); + PUTU32(plaintext + 8, tmp[2]); + PUTU32(plaintext + 12, tmp[3]); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/camellia.h b/grub-core/lib/libgcrypt-grub/cipher/camellia.h new file mode 100644 index 0000000..2ab2ddd --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/camellia.h @@ -0,0 +1,94 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +#include <grub/misc.h> +void camellia_setup128(const unsigned char *key, grub_uint32_t *subkey); +void camellia_setup192(const unsigned char *key, grub_uint32_t *subkey); +void camellia_setup256(const unsigned char *key, grub_uint32_t *subkey); +void camellia_encrypt128(const grub_uint32_t *subkey, grub_uint32_t *io); +void camellia_encrypt192(const grub_uint32_t *subkey, grub_uint32_t *io); +void camellia_encrypt256(const grub_uint32_t *subkey, grub_uint32_t *io); +void camellia_decrypt128(const grub_uint32_t *subkey, grub_uint32_t *io); +void camellia_decrypt192(const grub_uint32_t *subkey, grub_uint32_t *io); +void camellia_decrypt256(const grub_uint32_t *subkey, grub_uint32_t *io); +#define memcpy grub_memcpy +/* camellia.h ver 1.2.0 + * + * Copyright (C) 2006,2007 + * NTT (Nippon Telegraph and Telephone Corporation). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef HEADER_CAMELLIA_H +#define HEADER_CAMELLIA_H + +/* To use Camellia with libraries it is often useful to keep the name + * space of the library clean. The following macro is thus useful: + * + * #define CAMELLIA_EXT_SYM_PREFIX foo_ + * + * This prefixes all external symbols with "foo_". + */ +#ifdef HAVE_CONFIG_H +#endif +#ifdef CAMELLIA_EXT_SYM_PREFIX +#define CAMELLIA_PREFIX1(x,y) x ## y +#define CAMELLIA_PREFIX2(x,y) CAMELLIA_PREFIX1(x,y) +#define CAMELLIA_PREFIX(x) CAMELLIA_PREFIX2(CAMELLIA_EXT_SYM_PREFIX,x) +#define Camellia_Ekeygen CAMELLIA_PREFIX(Camellia_Ekeygen) +#define Camellia_EncryptBlock CAMELLIA_PREFIX(Camellia_EncryptBlock) +#define Camellia_DecryptBlock CAMELLIA_PREFIX(Camellia_DecryptBlock) +#define camellia_decrypt128 CAMELLIA_PREFIX(camellia_decrypt128) +#define camellia_decrypt256 CAMELLIA_PREFIX(camellia_decrypt256) +#define camellia_encrypt128 CAMELLIA_PREFIX(camellia_encrypt128) +#define camellia_encrypt256 CAMELLIA_PREFIX(camellia_encrypt256) +#define camellia_setup128 CAMELLIA_PREFIX(camellia_setup128) +#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) +#define camellia_setup256 CAMELLIA_PREFIX(camellia_setup256) +#endif /*CAMELLIA_EXT_SYM_PREFIX*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +#define CAMELLIA_BLOCK_SIZE 16 +#define CAMELLIA_TABLE_BYTE_LEN 272 +#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4) + +typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; + + +void Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, + KEY_TABLE_TYPE keyTable); + +void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, + unsigned char *cipherText); + +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *cipherText, + const KEY_TABLE_TYPE keyTable, + unsigned char *plaintext); + + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_CAMELLIA_H */ diff --git a/grub-core/lib/libgcrypt-grub/cipher/cast5.c b/grub-core/lib/libgcrypt-grub/cipher/cast5.c new file mode 100644 index 0000000..8598fa3 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/cast5.c @@ -0,0 +1,590 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* cast5.c - CAST5 cipher (RFC2144) + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* Test vectors: + * + * 128-bit key = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A + * plaintext = 01 23 45 67 89 AB CD EF + * ciphertext = 23 8B 4F E5 84 7E 44 B2 + * + * 80-bit key = 01 23 45 67 12 34 56 78 23 45 + * = 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00 + * plaintext = 01 23 45 67 89 AB CD EF + * ciphertext = EB 6A 71 1A 2C 02 27 1B + * + * 40-bit key = 01 23 45 67 12 + * = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00 + * plaintext = 01 23 45 67 89 AB CD EF + * ciphertext = 7A C8 16 D1 6E 9B 30 2E + */ + +#include "g10lib.h" +#include "types.h" +#include "cipher.h" + +#define CAST5_BLOCKSIZE 8 + +typedef struct { + u32 Km[16]; + byte Kr[16]; +} CAST5_context; + +static gcry_err_code_t cast_setkey (void *c, const byte *key, unsigned keylen); +static void encrypt_block (void *c, byte *outbuf, const byte *inbuf); +static void decrypt_block (void *c, byte *outbuf, const byte *inbuf); + + + + +static const u32 s1[256] = { +0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, +0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, +0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, +0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, +0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, +0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, +0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, +0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, +0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, +0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, +0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, +0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, +0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, +0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, +0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, +0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, +0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, +0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, +0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, +0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, +0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, +0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, +0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, +0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, +0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, +0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, +0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, +0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, +0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, +0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, +0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, +0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf +}; +static const u32 s2[256] = { +0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, +0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, +0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, +0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, +0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, +0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, +0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, +0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, +0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, +0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, +0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, +0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, +0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, +0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, +0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, +0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, +0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, +0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, +0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, +0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, +0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, +0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, +0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, +0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, +0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, +0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, +0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, +0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, +0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, +0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, +0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, +0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 +}; +static const u32 s3[256] = { +0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, +0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, +0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, +0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, +0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, +0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, +0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, +0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, +0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, +0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, +0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, +0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, +0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, +0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, +0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, +0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, +0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, +0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, +0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, +0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, +0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, +0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, +0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, +0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, +0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, +0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, +0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, +0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, +0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, +0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, +0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, +0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 +}; +static const u32 s4[256] = { +0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, +0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, +0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, +0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, +0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, +0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, +0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, +0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, +0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, +0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, +0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, +0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, +0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, +0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, +0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, +0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, +0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, +0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, +0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, +0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, +0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, +0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, +0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, +0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, +0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, +0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, +0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, +0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, +0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, +0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, +0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, +0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 +}; +static const u32 s5[256] = { +0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, +0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, +0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, +0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, +0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, +0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, +0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, +0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, +0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, +0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, +0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, +0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, +0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, +0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, +0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, +0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, +0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, +0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, +0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, +0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, +0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, +0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, +0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, +0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, +0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, +0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, +0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, +0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, +0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, +0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, +0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, +0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 +}; +static const u32 s6[256] = { +0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, +0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, +0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, +0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, +0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, +0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, +0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, +0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, +0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, +0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, +0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, +0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, +0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, +0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, +0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, +0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, +0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, +0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, +0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, +0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, +0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, +0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, +0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, +0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, +0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, +0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, +0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, +0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, +0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, +0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, +0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, +0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f +}; +static const u32 s7[256] = { +0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, +0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, +0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, +0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, +0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, +0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, +0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, +0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, +0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, +0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, +0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, +0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, +0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, +0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, +0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, +0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, +0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, +0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, +0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, +0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, +0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, +0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, +0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, +0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, +0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, +0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, +0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, +0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, +0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, +0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, +0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, +0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 +}; +static const u32 s8[256] = { +0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, +0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, +0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, +0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, +0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, +0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, +0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, +0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, +0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, +0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, +0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, +0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, +0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, +0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, +0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, +0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, +0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, +0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, +0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, +0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, +0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, +0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, +0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, +0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, +0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, +0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, +0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, +0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, +0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, +0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, +0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, +0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e +}; + + +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +rol(int n, u32 x) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else +#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + +#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol((r),I)), \ + (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) ) +#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol((r),I)), \ + (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) ) +#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol((r),I)), \ + (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) ) + +static void +do_encrypt_block( CAST5_context *c, byte *outbuf, const byte *inbuf ) +{ + u32 l, r, t; + u32 I; /* used by the Fx macros */ + u32 *Km; + byte *Kr; + + Km = c->Km; + Kr = c->Kr; + + /* (L0,R0) <-- (m1...m64). (Split the plaintext into left and + * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.) + */ + l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + + /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows: + * Li = Ri-1; + * Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2 + * Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1. + * Rounds 2, 5, 8, 11, and 14 use f function Type 2. + * Rounds 3, 6, 9, 12, and 15 use f function Type 3. + */ + + t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); + t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); + t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); + t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); + t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); + t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); + t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); + t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); + t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); + t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); + t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); + t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); + t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); + t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); + t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); + t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); + + /* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and + * concatenate to form the ciphertext.) */ + outbuf[0] = (r >> 24) & 0xff; + outbuf[1] = (r >> 16) & 0xff; + outbuf[2] = (r >> 8) & 0xff; + outbuf[3] = r & 0xff; + outbuf[4] = (l >> 24) & 0xff; + outbuf[5] = (l >> 16) & 0xff; + outbuf[6] = (l >> 8) & 0xff; + outbuf[7] = l & 0xff; +} + +static void +encrypt_block (void *context , byte *outbuf, const byte *inbuf) +{ + CAST5_context *c = (CAST5_context *) context; + do_encrypt_block (c, outbuf, inbuf); + _gcry_burn_stack (20+4*sizeof(void*)); +} + + +static void +do_decrypt_block (CAST5_context *c, byte *outbuf, const byte *inbuf ) +{ + u32 l, r, t; + u32 I; + u32 *Km; + byte *Kr; + + Km = c->Km; + Kr = c->Kr; + + l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + + t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); + t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); + t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); + t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); + t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); + t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); + t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); + t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); + t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); + t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); + t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); + t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); + t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); + t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); + t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); + t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); + + outbuf[0] = (r >> 24) & 0xff; + outbuf[1] = (r >> 16) & 0xff; + outbuf[2] = (r >> 8) & 0xff; + outbuf[3] = r & 0xff; + outbuf[4] = (l >> 24) & 0xff; + outbuf[5] = (l >> 16) & 0xff; + outbuf[6] = (l >> 8) & 0xff; + outbuf[7] = l & 0xff; +} + +static void +decrypt_block (void *context, byte *outbuf, const byte *inbuf) +{ + CAST5_context *c = (CAST5_context *) context; + do_decrypt_block (c, outbuf, inbuf); + _gcry_burn_stack (20+4*sizeof(void*)); +} + + + + +static void +key_schedule( u32 *x, u32 *z, u32 *k ) +{ + +#define xi(i) ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff) +#define zi(i) ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff) + + z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)]; + z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)]; + z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)]; + z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)]; + k[0] = s5[zi( 8)]^s6[zi( 9)]^s7[zi( 7)]^s8[zi( 6)]^s5[zi( 2)]; + k[1] = s5[zi(10)]^s6[zi(11)]^s7[zi( 5)]^s8[zi( 4)]^s6[zi( 6)]; + k[2] = s5[zi(12)]^s6[zi(13)]^s7[zi( 3)]^s8[zi( 2)]^s7[zi( 9)]; + k[3] = s5[zi(14)]^s6[zi(15)]^s7[zi( 1)]^s8[zi( 0)]^s8[zi(12)]; + + x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)]; + x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)]; + x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)]; + x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)]; + k[4] = s5[xi( 3)]^s6[xi( 2)]^s7[xi(12)]^s8[xi(13)]^s5[xi( 8)]; + k[5] = s5[xi( 1)]^s6[xi( 0)]^s7[xi(14)]^s8[xi(15)]^s6[xi(13)]; + k[6] = s5[xi( 7)]^s6[xi( 6)]^s7[xi( 8)]^s8[xi( 9)]^s7[xi( 3)]; + k[7] = s5[xi( 5)]^s6[xi( 4)]^s7[xi(10)]^s8[xi(11)]^s8[xi( 7)]; + + z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)]; + z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)]; + z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)]; + z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)]; + k[8] = s5[zi( 3)]^s6[zi( 2)]^s7[zi(12)]^s8[zi(13)]^s5[zi( 9)]; + k[9] = s5[zi( 1)]^s6[zi( 0)]^s7[zi(14)]^s8[zi(15)]^s6[zi(12)]; + k[10]= s5[zi( 7)]^s6[zi( 6)]^s7[zi( 8)]^s8[zi( 9)]^s7[zi( 2)]; + k[11]= s5[zi( 5)]^s6[zi( 4)]^s7[zi(10)]^s8[zi(11)]^s8[zi( 6)]; + + x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)]; + x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)]; + x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)]; + x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)]; + k[12]= s5[xi( 8)]^s6[xi( 9)]^s7[xi( 7)]^s8[xi( 6)]^s5[xi( 3)]; + k[13]= s5[xi(10)]^s6[xi(11)]^s7[xi( 5)]^s8[xi( 4)]^s6[xi( 7)]; + k[14]= s5[xi(12)]^s6[xi(13)]^s7[xi( 3)]^s8[xi( 2)]^s7[xi( 8)]; + k[15]= s5[xi(14)]^s6[xi(15)]^s7[xi( 1)]^s8[xi( 0)]^s8[xi(13)]; + +#undef xi +#undef zi +} + + +static gcry_err_code_t +do_cast_setkey( CAST5_context *c, const byte *key, unsigned keylen ) +{ + static int initialized; + static const char* selftest_failed; + int i; + u32 x[4]; + u32 z[4]; + u32 k[16]; + + if( !initialized ) + { + initialized = 1; + selftest_failed = selftest(); + if( selftest_failed ) + log_error ("CAST5 selftest failed (%s).\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + if( keylen != 16 ) + return GPG_ERR_INV_KEYLEN; + + x[0] = key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3]; + x[1] = key[4] << 24 | key[5] << 16 | key[6] << 8 | key[7]; + x[2] = key[8] << 24 | key[9] << 16 | key[10] << 8 | key[11]; + x[3] = key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15]; + + key_schedule( x, z, k ); + for(i=0; i < 16; i++ ) + c->Km[i] = k[i]; + key_schedule( x, z, k ); + for(i=0; i < 16; i++ ) + c->Kr[i] = k[i] & 0x1f; + + memset(&x,0, sizeof x); + memset(&z,0, sizeof z); + memset(&k,0, sizeof k); + +#undef xi +#undef zi + return GPG_ERR_NO_ERROR; +} + +static gcry_err_code_t +cast_setkey (void *context, const byte *key, unsigned keylen ) +{ + CAST5_context *c = (CAST5_context *) context; + gcry_err_code_t rc = do_cast_setkey (c, key, keylen); + _gcry_burn_stack (96+7*sizeof(void*)); + return rc; +} + + +gcry_cipher_spec_t _gcry_cipher_spec_cast5 = + { + "CAST5", NULL, NULL, CAST5_BLOCKSIZE, 128, sizeof (CAST5_context), + cast_setkey, encrypt_block, decrypt_block + , +#ifdef GRUB_UTIL + .modname = "gcry_cast5", +#endif + }; + + +GRUB_MOD_INIT(gcry_cast5) +{ + grub_cipher_register (&_gcry_cipher_spec_cast5); +} + +GRUB_MOD_FINI(gcry_cast5) +{ + grub_cipher_unregister (&_gcry_cipher_spec_cast5); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/cipher.h b/grub-core/lib/libgcrypt-grub/cipher/cipher.h new file mode 100644 index 0000000..73c6779 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/cipher.h @@ -0,0 +1,2 @@ +#include <grub/crypto.h> +#include <cipher_wrap.h> diff --git a/grub-core/lib/libgcrypt-grub/cipher/crc.c b/grub-core/lib/libgcrypt-grub/cipher/crc.c new file mode 100644 index 0000000..a929432 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/crc.c @@ -0,0 +1,826 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* crc.c - Cyclic redundancy checks. + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + + +#include "g10lib.h" +#include "cipher.h" + +#include "bithelp.h" +#include "bufhelp.h" + + +typedef struct +{ + u32 CRC; + byte buf[4]; +} +CRC_CONTEXT; + + +/* + * Code generated by universal_crc by Danjel McGougan + * + * CRC parameters used: + * bits: 32 + * poly: 0x04c11db7 + * init: 0xffffffff + * xor: 0xffffffff + * reverse: true + * non-direct: false + * + * CRC of the string "123456789" is 0xcbf43926 + */ + +static const u32 crc32_table[1024] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, + 0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, + 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7, + 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb, + 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf, + 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, + 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a, + 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e, + 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761, + 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, + 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d, + 0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530, + 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034, + 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, + 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6, + 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2, + 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce, + 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, + 0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93, + 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f, + 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b, + 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, + 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c, + 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768, + 0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35, + 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, + 0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539, + 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88, + 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c, + 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, + 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9, + 0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd, + 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1, + 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, + 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, + 0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522, + 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026, + 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, + 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773, + 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277, + 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d, + 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, + 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81, + 0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc, + 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8, + 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, + 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f, + 0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b, + 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27, + 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, + 0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a, + 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876, + 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72, + 0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, + 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685, + 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1, + 0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d, + 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, + 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91, + 0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d, + 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9, + 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, + 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd, + 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9, + 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315, + 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, + 0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399, + 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45, + 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221, + 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, + 0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835, + 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151, + 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d, + 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, + 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1, + 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d, + 0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609, + 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, + 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, + 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9, + 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05, + 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, + 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, + 0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75, + 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711, + 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, + 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5, + 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281, + 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d, + 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, + 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, + 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d, + 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819, + 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, + 0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d, + 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69, + 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5, + 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, + 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9, + 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625, + 0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41, + 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, + 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555, + 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31, + 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed, + 0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, + 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9, + 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701, + 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056, + 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, + 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e, + 0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9, + 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0, + 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, + 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68, + 0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f, + 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018, + 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, + 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3, + 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084, + 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c, + 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, + 0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b, + 0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3, + 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4, + 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, + 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002, + 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755, + 0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72, + 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, + 0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca, + 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5, + 0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82, + 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, + 0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a, + 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d, + 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5, + 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, + 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc, + 0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04, + 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953, + 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, + 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b, + 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc, + 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8, + 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, + 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50, + 0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677, + 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120, + 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, + 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, + 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981, + 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639, + 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, + 0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, + 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6, + 0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1 +}; + +/* CRC32 */ + +static inline u32 +crc32_next (u32 crc, byte data) +{ + return (crc >> 8) ^ crc32_table[(crc & 0xff) ^ data]; +} + +/* + * Process 4 bytes in one go + */ +static inline u32 +crc32_next4 (u32 crc, u32 data) +{ + crc ^= data; + crc = crc32_table[(crc & 0xff) + 0x300] ^ + crc32_table[((crc >> 8) & 0xff) + 0x200] ^ + crc32_table[((crc >> 16) & 0xff) + 0x100] ^ + crc32_table[(crc >> 24) & 0xff]; + return crc; +} + +static void +crc32_init (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + ctx->CRC = 0 ^ 0xffffffffL; +} + +static void +crc32_write (void *context, const void *inbuf_arg, size_t inlen) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + const byte *inbuf = inbuf_arg; + u32 crc; + + if (!inbuf || !inlen) + return; + + crc = ctx->CRC; + + while (inlen >= 16) + { + inlen -= 16; + crc = crc32_next4(crc, buf_get_le32(&inbuf[0])); + crc = crc32_next4(crc, buf_get_le32(&inbuf[4])); + crc = crc32_next4(crc, buf_get_le32(&inbuf[8])); + crc = crc32_next4(crc, buf_get_le32(&inbuf[12])); + inbuf += 16; + } + + while (inlen >= 4) + { + inlen -= 4; + crc = crc32_next4(crc, buf_get_le32(inbuf)); + inbuf += 4; + } + + while (inlen--) + { + crc = crc32_next(crc, *inbuf++); + } + + ctx->CRC = crc; +} + +static byte * +crc32_read (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + return ctx->buf; +} + +static void +crc32_final (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + ctx->CRC ^= 0xffffffffL; + buf_put_be32 (ctx->buf, ctx->CRC); +} + +/* CRC32 a'la RFC 1510 */ +/* CRC of the string "123456789" is 0x2dfd2d88 */ + +static void +crc32rfc1510_init (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + ctx->CRC = 0; +} + +static void +crc32rfc1510_final (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + buf_put_be32(ctx->buf, ctx->CRC); +} + +/* CRC24 a'la RFC 2440 */ +/* + * Code generated by universal_crc by Danjel McGougan + * + * CRC parameters used: + * bits: 24 + * poly: 0x864cfb + * init: 0xb704ce + * xor: 0x000000 + * reverse: false + * non-direct: false + * + * CRC of the string "123456789" is 0x21cf02 + */ + +static const u32 crc24_table[1024] = +{ + 0x00000000, 0x00fb4c86, 0x000dd58a, 0x00f6990c, + 0x00e1e693, 0x001aaa15, 0x00ec3319, 0x00177f9f, + 0x003981a1, 0x00c2cd27, 0x0034542b, 0x00cf18ad, + 0x00d86732, 0x00232bb4, 0x00d5b2b8, 0x002efe3e, + 0x00894ec5, 0x00720243, 0x00849b4f, 0x007fd7c9, + 0x0068a856, 0x0093e4d0, 0x00657ddc, 0x009e315a, + 0x00b0cf64, 0x004b83e2, 0x00bd1aee, 0x00465668, + 0x005129f7, 0x00aa6571, 0x005cfc7d, 0x00a7b0fb, + 0x00e9d10c, 0x00129d8a, 0x00e40486, 0x001f4800, + 0x0008379f, 0x00f37b19, 0x0005e215, 0x00feae93, + 0x00d050ad, 0x002b1c2b, 0x00dd8527, 0x0026c9a1, + 0x0031b63e, 0x00cafab8, 0x003c63b4, 0x00c72f32, + 0x00609fc9, 0x009bd34f, 0x006d4a43, 0x009606c5, + 0x0081795a, 0x007a35dc, 0x008cacd0, 0x0077e056, + 0x00591e68, 0x00a252ee, 0x0054cbe2, 0x00af8764, + 0x00b8f8fb, 0x0043b47d, 0x00b52d71, 0x004e61f7, + 0x00d2a319, 0x0029ef9f, 0x00df7693, 0x00243a15, + 0x0033458a, 0x00c8090c, 0x003e9000, 0x00c5dc86, + 0x00eb22b8, 0x00106e3e, 0x00e6f732, 0x001dbbb4, + 0x000ac42b, 0x00f188ad, 0x000711a1, 0x00fc5d27, + 0x005beddc, 0x00a0a15a, 0x00563856, 0x00ad74d0, + 0x00ba0b4f, 0x004147c9, 0x00b7dec5, 0x004c9243, + 0x00626c7d, 0x009920fb, 0x006fb9f7, 0x0094f571, + 0x00838aee, 0x0078c668, 0x008e5f64, 0x007513e2, + 0x003b7215, 0x00c03e93, 0x0036a79f, 0x00cdeb19, + 0x00da9486, 0x0021d800, 0x00d7410c, 0x002c0d8a, + 0x0002f3b4, 0x00f9bf32, 0x000f263e, 0x00f46ab8, + 0x00e31527, 0x001859a1, 0x00eec0ad, 0x00158c2b, + 0x00b23cd0, 0x00497056, 0x00bfe95a, 0x0044a5dc, + 0x0053da43, 0x00a896c5, 0x005e0fc9, 0x00a5434f, + 0x008bbd71, 0x0070f1f7, 0x008668fb, 0x007d247d, + 0x006a5be2, 0x00911764, 0x00678e68, 0x009cc2ee, + 0x00a44733, 0x005f0bb5, 0x00a992b9, 0x0052de3f, + 0x0045a1a0, 0x00beed26, 0x0048742a, 0x00b338ac, + 0x009dc692, 0x00668a14, 0x00901318, 0x006b5f9e, + 0x007c2001, 0x00876c87, 0x0071f58b, 0x008ab90d, + 0x002d09f6, 0x00d64570, 0x0020dc7c, 0x00db90fa, + 0x00ccef65, 0x0037a3e3, 0x00c13aef, 0x003a7669, + 0x00148857, 0x00efc4d1, 0x00195ddd, 0x00e2115b, + 0x00f56ec4, 0x000e2242, 0x00f8bb4e, 0x0003f7c8, + 0x004d963f, 0x00b6dab9, 0x004043b5, 0x00bb0f33, + 0x00ac70ac, 0x00573c2a, 0x00a1a526, 0x005ae9a0, + 0x0074179e, 0x008f5b18, 0x0079c214, 0x00828e92, + 0x0095f10d, 0x006ebd8b, 0x00982487, 0x00636801, + 0x00c4d8fa, 0x003f947c, 0x00c90d70, 0x003241f6, + 0x00253e69, 0x00de72ef, 0x0028ebe3, 0x00d3a765, + 0x00fd595b, 0x000615dd, 0x00f08cd1, 0x000bc057, + 0x001cbfc8, 0x00e7f34e, 0x00116a42, 0x00ea26c4, + 0x0076e42a, 0x008da8ac, 0x007b31a0, 0x00807d26, + 0x009702b9, 0x006c4e3f, 0x009ad733, 0x00619bb5, + 0x004f658b, 0x00b4290d, 0x0042b001, 0x00b9fc87, + 0x00ae8318, 0x0055cf9e, 0x00a35692, 0x00581a14, + 0x00ffaaef, 0x0004e669, 0x00f27f65, 0x000933e3, + 0x001e4c7c, 0x00e500fa, 0x001399f6, 0x00e8d570, + 0x00c62b4e, 0x003d67c8, 0x00cbfec4, 0x0030b242, + 0x0027cddd, 0x00dc815b, 0x002a1857, 0x00d154d1, + 0x009f3526, 0x006479a0, 0x0092e0ac, 0x0069ac2a, + 0x007ed3b5, 0x00859f33, 0x0073063f, 0x00884ab9, + 0x00a6b487, 0x005df801, 0x00ab610d, 0x00502d8b, + 0x00475214, 0x00bc1e92, 0x004a879e, 0x00b1cb18, + 0x00167be3, 0x00ed3765, 0x001bae69, 0x00e0e2ef, + 0x00f79d70, 0x000cd1f6, 0x00fa48fa, 0x0001047c, + 0x002ffa42, 0x00d4b6c4, 0x00222fc8, 0x00d9634e, + 0x00ce1cd1, 0x00355057, 0x00c3c95b, 0x003885dd, + 0x00000000, 0x00488f66, 0x00901ecd, 0x00d891ab, + 0x00db711c, 0x0093fe7a, 0x004b6fd1, 0x0003e0b7, + 0x00b6e338, 0x00fe6c5e, 0x0026fdf5, 0x006e7293, + 0x006d9224, 0x00251d42, 0x00fd8ce9, 0x00b5038f, + 0x006cc771, 0x00244817, 0x00fcd9bc, 0x00b456da, + 0x00b7b66d, 0x00ff390b, 0x0027a8a0, 0x006f27c6, + 0x00da2449, 0x0092ab2f, 0x004a3a84, 0x0002b5e2, + 0x00015555, 0x0049da33, 0x00914b98, 0x00d9c4fe, + 0x00d88ee3, 0x00900185, 0x0048902e, 0x00001f48, + 0x0003ffff, 0x004b7099, 0x0093e132, 0x00db6e54, + 0x006e6ddb, 0x0026e2bd, 0x00fe7316, 0x00b6fc70, + 0x00b51cc7, 0x00fd93a1, 0x0025020a, 0x006d8d6c, + 0x00b44992, 0x00fcc6f4, 0x0024575f, 0x006cd839, + 0x006f388e, 0x0027b7e8, 0x00ff2643, 0x00b7a925, + 0x0002aaaa, 0x004a25cc, 0x0092b467, 0x00da3b01, + 0x00d9dbb6, 0x009154d0, 0x0049c57b, 0x00014a1d, + 0x004b5141, 0x0003de27, 0x00db4f8c, 0x0093c0ea, + 0x0090205d, 0x00d8af3b, 0x00003e90, 0x0048b1f6, + 0x00fdb279, 0x00b53d1f, 0x006dacb4, 0x002523d2, + 0x0026c365, 0x006e4c03, 0x00b6dda8, 0x00fe52ce, + 0x00279630, 0x006f1956, 0x00b788fd, 0x00ff079b, + 0x00fce72c, 0x00b4684a, 0x006cf9e1, 0x00247687, + 0x00917508, 0x00d9fa6e, 0x00016bc5, 0x0049e4a3, + 0x004a0414, 0x00028b72, 0x00da1ad9, 0x009295bf, + 0x0093dfa2, 0x00db50c4, 0x0003c16f, 0x004b4e09, + 0x0048aebe, 0x000021d8, 0x00d8b073, 0x00903f15, + 0x00253c9a, 0x006db3fc, 0x00b52257, 0x00fdad31, + 0x00fe4d86, 0x00b6c2e0, 0x006e534b, 0x0026dc2d, + 0x00ff18d3, 0x00b797b5, 0x006f061e, 0x00278978, + 0x002469cf, 0x006ce6a9, 0x00b47702, 0x00fcf864, + 0x0049fbeb, 0x0001748d, 0x00d9e526, 0x00916a40, + 0x00928af7, 0x00da0591, 0x0002943a, 0x004a1b5c, + 0x0096a282, 0x00de2de4, 0x0006bc4f, 0x004e3329, + 0x004dd39e, 0x00055cf8, 0x00ddcd53, 0x00954235, + 0x002041ba, 0x0068cedc, 0x00b05f77, 0x00f8d011, + 0x00fb30a6, 0x00b3bfc0, 0x006b2e6b, 0x0023a10d, + 0x00fa65f3, 0x00b2ea95, 0x006a7b3e, 0x0022f458, + 0x002114ef, 0x00699b89, 0x00b10a22, 0x00f98544, + 0x004c86cb, 0x000409ad, 0x00dc9806, 0x00941760, + 0x0097f7d7, 0x00df78b1, 0x0007e91a, 0x004f667c, + 0x004e2c61, 0x0006a307, 0x00de32ac, 0x0096bdca, + 0x00955d7d, 0x00ddd21b, 0x000543b0, 0x004dccd6, + 0x00f8cf59, 0x00b0403f, 0x0068d194, 0x00205ef2, + 0x0023be45, 0x006b3123, 0x00b3a088, 0x00fb2fee, + 0x0022eb10, 0x006a6476, 0x00b2f5dd, 0x00fa7abb, + 0x00f99a0c, 0x00b1156a, 0x006984c1, 0x00210ba7, + 0x00940828, 0x00dc874e, 0x000416e5, 0x004c9983, + 0x004f7934, 0x0007f652, 0x00df67f9, 0x0097e89f, + 0x00ddf3c3, 0x00957ca5, 0x004ded0e, 0x00056268, + 0x000682df, 0x004e0db9, 0x00969c12, 0x00de1374, + 0x006b10fb, 0x00239f9d, 0x00fb0e36, 0x00b38150, + 0x00b061e7, 0x00f8ee81, 0x00207f2a, 0x0068f04c, + 0x00b134b2, 0x00f9bbd4, 0x00212a7f, 0x0069a519, + 0x006a45ae, 0x0022cac8, 0x00fa5b63, 0x00b2d405, + 0x0007d78a, 0x004f58ec, 0x0097c947, 0x00df4621, + 0x00dca696, 0x009429f0, 0x004cb85b, 0x0004373d, + 0x00057d20, 0x004df246, 0x009563ed, 0x00ddec8b, + 0x00de0c3c, 0x0096835a, 0x004e12f1, 0x00069d97, + 0x00b39e18, 0x00fb117e, 0x002380d5, 0x006b0fb3, + 0x0068ef04, 0x00206062, 0x00f8f1c9, 0x00b07eaf, + 0x0069ba51, 0x00213537, 0x00f9a49c, 0x00b12bfa, + 0x00b2cb4d, 0x00fa442b, 0x0022d580, 0x006a5ae6, + 0x00df5969, 0x0097d60f, 0x004f47a4, 0x0007c8c2, + 0x00042875, 0x004ca713, 0x009436b8, 0x00dcb9de, + 0x00000000, 0x00d70983, 0x00555f80, 0x00825603, + 0x0051f286, 0x0086fb05, 0x0004ad06, 0x00d3a485, + 0x0059a88b, 0x008ea108, 0x000cf70b, 0x00dbfe88, + 0x00085a0d, 0x00df538e, 0x005d058d, 0x008a0c0e, + 0x00491c91, 0x009e1512, 0x001c4311, 0x00cb4a92, + 0x0018ee17, 0x00cfe794, 0x004db197, 0x009ab814, + 0x0010b41a, 0x00c7bd99, 0x0045eb9a, 0x0092e219, + 0x0041469c, 0x00964f1f, 0x0014191c, 0x00c3109f, + 0x006974a4, 0x00be7d27, 0x003c2b24, 0x00eb22a7, + 0x00388622, 0x00ef8fa1, 0x006dd9a2, 0x00bad021, + 0x0030dc2f, 0x00e7d5ac, 0x006583af, 0x00b28a2c, + 0x00612ea9, 0x00b6272a, 0x00347129, 0x00e378aa, + 0x00206835, 0x00f761b6, 0x007537b5, 0x00a23e36, + 0x00719ab3, 0x00a69330, 0x0024c533, 0x00f3ccb0, + 0x0079c0be, 0x00aec93d, 0x002c9f3e, 0x00fb96bd, + 0x00283238, 0x00ff3bbb, 0x007d6db8, 0x00aa643b, + 0x0029a4ce, 0x00fead4d, 0x007cfb4e, 0x00abf2cd, + 0x00785648, 0x00af5fcb, 0x002d09c8, 0x00fa004b, + 0x00700c45, 0x00a705c6, 0x002553c5, 0x00f25a46, + 0x0021fec3, 0x00f6f740, 0x0074a143, 0x00a3a8c0, + 0x0060b85f, 0x00b7b1dc, 0x0035e7df, 0x00e2ee5c, + 0x00314ad9, 0x00e6435a, 0x00641559, 0x00b31cda, + 0x003910d4, 0x00ee1957, 0x006c4f54, 0x00bb46d7, + 0x0068e252, 0x00bfebd1, 0x003dbdd2, 0x00eab451, + 0x0040d06a, 0x0097d9e9, 0x00158fea, 0x00c28669, + 0x001122ec, 0x00c62b6f, 0x00447d6c, 0x009374ef, + 0x001978e1, 0x00ce7162, 0x004c2761, 0x009b2ee2, + 0x00488a67, 0x009f83e4, 0x001dd5e7, 0x00cadc64, + 0x0009ccfb, 0x00dec578, 0x005c937b, 0x008b9af8, + 0x00583e7d, 0x008f37fe, 0x000d61fd, 0x00da687e, + 0x00506470, 0x00876df3, 0x00053bf0, 0x00d23273, + 0x000196f6, 0x00d69f75, 0x0054c976, 0x0083c0f5, + 0x00a9041b, 0x007e0d98, 0x00fc5b9b, 0x002b5218, + 0x00f8f69d, 0x002fff1e, 0x00ada91d, 0x007aa09e, + 0x00f0ac90, 0x0027a513, 0x00a5f310, 0x0072fa93, + 0x00a15e16, 0x00765795, 0x00f40196, 0x00230815, + 0x00e0188a, 0x00371109, 0x00b5470a, 0x00624e89, + 0x00b1ea0c, 0x0066e38f, 0x00e4b58c, 0x0033bc0f, + 0x00b9b001, 0x006eb982, 0x00ecef81, 0x003be602, + 0x00e84287, 0x003f4b04, 0x00bd1d07, 0x006a1484, + 0x00c070bf, 0x0017793c, 0x00952f3f, 0x004226bc, + 0x00918239, 0x00468bba, 0x00c4ddb9, 0x0013d43a, + 0x0099d834, 0x004ed1b7, 0x00cc87b4, 0x001b8e37, + 0x00c82ab2, 0x001f2331, 0x009d7532, 0x004a7cb1, + 0x00896c2e, 0x005e65ad, 0x00dc33ae, 0x000b3a2d, + 0x00d89ea8, 0x000f972b, 0x008dc128, 0x005ac8ab, + 0x00d0c4a5, 0x0007cd26, 0x00859b25, 0x005292a6, + 0x00813623, 0x00563fa0, 0x00d469a3, 0x00036020, + 0x0080a0d5, 0x0057a956, 0x00d5ff55, 0x0002f6d6, + 0x00d15253, 0x00065bd0, 0x00840dd3, 0x00530450, + 0x00d9085e, 0x000e01dd, 0x008c57de, 0x005b5e5d, + 0x0088fad8, 0x005ff35b, 0x00dda558, 0x000aacdb, + 0x00c9bc44, 0x001eb5c7, 0x009ce3c4, 0x004bea47, + 0x00984ec2, 0x004f4741, 0x00cd1142, 0x001a18c1, + 0x009014cf, 0x00471d4c, 0x00c54b4f, 0x001242cc, + 0x00c1e649, 0x0016efca, 0x0094b9c9, 0x0043b04a, + 0x00e9d471, 0x003eddf2, 0x00bc8bf1, 0x006b8272, + 0x00b826f7, 0x006f2f74, 0x00ed7977, 0x003a70f4, + 0x00b07cfa, 0x00677579, 0x00e5237a, 0x00322af9, + 0x00e18e7c, 0x003687ff, 0x00b4d1fc, 0x0063d87f, + 0x00a0c8e0, 0x0077c163, 0x00f59760, 0x00229ee3, + 0x00f13a66, 0x002633e5, 0x00a465e6, 0x00736c65, + 0x00f9606b, 0x002e69e8, 0x00ac3feb, 0x007b3668, + 0x00a892ed, 0x007f9b6e, 0x00fdcd6d, 0x002ac4ee, + 0x00000000, 0x00520936, 0x00a4126c, 0x00f61b5a, + 0x004825d8, 0x001a2cee, 0x00ec37b4, 0x00be3e82, + 0x006b0636, 0x00390f00, 0x00cf145a, 0x009d1d6c, + 0x002323ee, 0x00712ad8, 0x00873182, 0x00d538b4, + 0x00d60c6c, 0x0084055a, 0x00721e00, 0x00201736, + 0x009e29b4, 0x00cc2082, 0x003a3bd8, 0x006832ee, + 0x00bd0a5a, 0x00ef036c, 0x00191836, 0x004b1100, + 0x00f52f82, 0x00a726b4, 0x00513dee, 0x000334d8, + 0x00ac19d8, 0x00fe10ee, 0x00080bb4, 0x005a0282, + 0x00e43c00, 0x00b63536, 0x00402e6c, 0x0012275a, + 0x00c71fee, 0x009516d8, 0x00630d82, 0x003104b4, + 0x008f3a36, 0x00dd3300, 0x002b285a, 0x0079216c, + 0x007a15b4, 0x00281c82, 0x00de07d8, 0x008c0eee, + 0x0032306c, 0x0060395a, 0x00962200, 0x00c42b36, + 0x00111382, 0x00431ab4, 0x00b501ee, 0x00e708d8, + 0x0059365a, 0x000b3f6c, 0x00fd2436, 0x00af2d00, + 0x00a37f36, 0x00f17600, 0x00076d5a, 0x0055646c, + 0x00eb5aee, 0x00b953d8, 0x004f4882, 0x001d41b4, + 0x00c87900, 0x009a7036, 0x006c6b6c, 0x003e625a, + 0x00805cd8, 0x00d255ee, 0x00244eb4, 0x00764782, + 0x0075735a, 0x00277a6c, 0x00d16136, 0x00836800, + 0x003d5682, 0x006f5fb4, 0x009944ee, 0x00cb4dd8, + 0x001e756c, 0x004c7c5a, 0x00ba6700, 0x00e86e36, + 0x005650b4, 0x00045982, 0x00f242d8, 0x00a04bee, + 0x000f66ee, 0x005d6fd8, 0x00ab7482, 0x00f97db4, + 0x00474336, 0x00154a00, 0x00e3515a, 0x00b1586c, + 0x006460d8, 0x003669ee, 0x00c072b4, 0x00927b82, + 0x002c4500, 0x007e4c36, 0x0088576c, 0x00da5e5a, + 0x00d96a82, 0x008b63b4, 0x007d78ee, 0x002f71d8, + 0x00914f5a, 0x00c3466c, 0x00355d36, 0x00675400, + 0x00b26cb4, 0x00e06582, 0x00167ed8, 0x004477ee, + 0x00fa496c, 0x00a8405a, 0x005e5b00, 0x000c5236, + 0x0046ff6c, 0x0014f65a, 0x00e2ed00, 0x00b0e436, + 0x000edab4, 0x005cd382, 0x00aac8d8, 0x00f8c1ee, + 0x002df95a, 0x007ff06c, 0x0089eb36, 0x00dbe200, + 0x0065dc82, 0x0037d5b4, 0x00c1ceee, 0x0093c7d8, + 0x0090f300, 0x00c2fa36, 0x0034e16c, 0x0066e85a, + 0x00d8d6d8, 0x008adfee, 0x007cc4b4, 0x002ecd82, + 0x00fbf536, 0x00a9fc00, 0x005fe75a, 0x000dee6c, + 0x00b3d0ee, 0x00e1d9d8, 0x0017c282, 0x0045cbb4, + 0x00eae6b4, 0x00b8ef82, 0x004ef4d8, 0x001cfdee, + 0x00a2c36c, 0x00f0ca5a, 0x0006d100, 0x0054d836, + 0x0081e082, 0x00d3e9b4, 0x0025f2ee, 0x0077fbd8, + 0x00c9c55a, 0x009bcc6c, 0x006dd736, 0x003fde00, + 0x003cead8, 0x006ee3ee, 0x0098f8b4, 0x00caf182, + 0x0074cf00, 0x0026c636, 0x00d0dd6c, 0x0082d45a, + 0x0057ecee, 0x0005e5d8, 0x00f3fe82, 0x00a1f7b4, + 0x001fc936, 0x004dc000, 0x00bbdb5a, 0x00e9d26c, + 0x00e5805a, 0x00b7896c, 0x00419236, 0x00139b00, + 0x00ada582, 0x00ffacb4, 0x0009b7ee, 0x005bbed8, + 0x008e866c, 0x00dc8f5a, 0x002a9400, 0x00789d36, + 0x00c6a3b4, 0x0094aa82, 0x0062b1d8, 0x0030b8ee, + 0x00338c36, 0x00618500, 0x00979e5a, 0x00c5976c, + 0x007ba9ee, 0x0029a0d8, 0x00dfbb82, 0x008db2b4, + 0x00588a00, 0x000a8336, 0x00fc986c, 0x00ae915a, + 0x0010afd8, 0x0042a6ee, 0x00b4bdb4, 0x00e6b482, + 0x00499982, 0x001b90b4, 0x00ed8bee, 0x00bf82d8, + 0x0001bc5a, 0x0053b56c, 0x00a5ae36, 0x00f7a700, + 0x00229fb4, 0x00709682, 0x00868dd8, 0x00d484ee, + 0x006aba6c, 0x0038b35a, 0x00cea800, 0x009ca136, + 0x009f95ee, 0x00cd9cd8, 0x003b8782, 0x00698eb4, + 0x00d7b036, 0x0085b900, 0x0073a25a, 0x0021ab6c, + 0x00f493d8, 0x00a69aee, 0x005081b4, 0x00028882, + 0x00bcb600, 0x00eebf36, 0x0018a46c, 0x004aad5a +}; + +static inline +u32 crc24_init (void) +{ + return 0xce04b7; +} + +static inline +u32 crc24_next (u32 crc, byte data) +{ + return (crc >> 8) ^ crc24_table[(crc & 0xff) ^ data]; +} + +/* + * Process 4 bytes in one go + */ +static inline +u32 crc24_next4 (u32 crc, u32 data) +{ + crc ^= data; + crc = crc24_table[(crc & 0xff) + 0x300] ^ + crc24_table[((crc >> 8) & 0xff) + 0x200] ^ + crc24_table[((crc >> 16) & 0xff) + 0x100] ^ + crc24_table[(crc >> 24) & 0xff]; + return crc; +} + +static inline +u32 crc24_final (u32 crc) +{ + return crc & 0xffffff; +} + +static void +crc24rfc2440_init (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + ctx->CRC = crc24_init(); +} + +static void +crc24rfc2440_write (void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + u32 crc; + + if (!inbuf || !inlen) + return; + + crc = ctx->CRC; + + while (inlen >= 16) + { + inlen -= 16; + crc = crc24_next4(crc, buf_get_le32(&inbuf[0])); + crc = crc24_next4(crc, buf_get_le32(&inbuf[4])); + crc = crc24_next4(crc, buf_get_le32(&inbuf[8])); + crc = crc24_next4(crc, buf_get_le32(&inbuf[12])); + inbuf += 16; + } + + while (inlen >= 4) + { + inlen -= 4; + crc = crc24_next4(crc, buf_get_le32(inbuf)); + inbuf += 4; + } + + while (inlen--) + { + crc = crc24_next(crc, *inbuf++); + } + + ctx->CRC = crc; +} + +static void +crc24rfc2440_final (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + ctx->CRC = crc24_final(ctx->CRC); + buf_put_le32 (ctx->buf, ctx->CRC); +} + +gcry_md_spec_t _gcry_digest_spec_crc32 = + { + "CRC32", NULL, 0, NULL, 4, + crc32_init, crc32_write, crc32_final, crc32_read, + sizeof (CRC_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_crc", +#endif + .blocksize = 64 + }; + +gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510 = + { + "CRC32RFC1510", NULL, 0, NULL, 4, + crc32rfc1510_init, crc32_write, + crc32rfc1510_final, crc32_read, + sizeof (CRC_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_crc", +#endif + .blocksize = 64 + }; + +gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440 = + { + "CRC24RFC2440", NULL, 0, NULL, 3, + crc24rfc2440_init, crc24rfc2440_write, + crc24rfc2440_final, crc32_read, + sizeof (CRC_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_crc", +#endif + .blocksize = 64 + }; + + +GRUB_MOD_INIT(gcry_crc) +{ + COMPILE_TIME_ASSERT(sizeof (CRC_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + COMPILE_TIME_ASSERT(sizeof (CRC_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + COMPILE_TIME_ASSERT(sizeof (CRC_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + grub_md_register (&_gcry_digest_spec_crc32); + grub_md_register (&_gcry_digest_spec_crc32_rfc1510); + grub_md_register (&_gcry_digest_spec_crc24_rfc2440); +} + +GRUB_MOD_FINI(gcry_crc) +{ + grub_md_unregister (&_gcry_digest_spec_crc32); + grub_md_unregister (&_gcry_digest_spec_crc32_rfc1510); + grub_md_unregister (&_gcry_digest_spec_crc24_rfc2440); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/crypto.lst b/grub-core/lib/libgcrypt-grub/cipher/crypto.lst new file mode 100644 index 0000000..77d9efc --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/crypto.lst @@ -0,0 +1,45 @@ +RIJNDAEL: gcry_rijndael +RIJNDAEL192: gcry_rijndael +RIJNDAEL256: gcry_rijndael +AES128: gcry_rijndael +AES-128: gcry_rijndael +AES-192: gcry_rijndael +AES-256: gcry_rijndael +ADLER32: adler32 +CRC64: crc64 +ARCFOUR: gcry_arcfour +BLOWFISH: gcry_blowfish +CAMELLIA128: gcry_camellia +CAMELLIA192: gcry_camellia +CAMELLIA256: gcry_camellia +CAST5: gcry_cast5 +CRC32: gcry_crc +CRC32RFC1510: gcry_crc +CRC24RFC2440: gcry_crc +DES: gcry_des +3DES: gcry_des +DSA: gcry_dsa +IDEA: gcry_idea +MD4: gcry_md4 +MD5: gcry_md5 +RFC2268_40: gcry_rfc2268 +AES: gcry_rijndael +AES192: gcry_rijndael +AES256: gcry_rijndael +RIPEMD160: gcry_rmd160 +RSA: gcry_rsa +SEED: gcry_seed +SERPENT128: gcry_serpent +SERPENT192: gcry_serpent +SERPENT256: gcry_serpent +SHA1: gcry_sha1 +SHA224: gcry_sha256 +SHA256: gcry_sha256 +SHA512: gcry_sha512 +SHA384: gcry_sha512 +TIGER192: gcry_tiger +TIGER: gcry_tiger +TIGER2: gcry_tiger +TWOFISH: gcry_twofish +TWOFISH128: gcry_twofish +WHIRLPOOL: gcry_whirlpool diff --git a/grub-core/lib/libgcrypt-grub/cipher/des.c b/grub-core/lib/libgcrypt-grub/cipher/des.c new file mode 100644 index 0000000..09521e8 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/des.c @@ -0,0 +1,929 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* des.c - DES and Triple-DES encryption/decryption Algorithm + * Copyright (C) 1998, 1999, 2001, 2002, 2003, + * 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * For a description of triple encryption, see: + * Bruce Schneier: Applied Cryptography. Second Edition. + * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. + * This implementation is according to the definition of DES in FIPS + * PUB 46-2 from December 1993. + */ + + +/* + * Written by Michael Roth <mroth@nessie.de>, September 1998 + */ + + +/* + * U S A G E + * =========== + * + * For DES or Triple-DES encryption/decryption you must initialize a proper + * encryption context with a key. + * + * A DES key is 64bit wide but only 56bits of the key are used. The remaining + * bits are parity bits and they will _not_ checked in this implementation, but + * simply ignored. + * + * For Triple-DES you could use either two 64bit keys or three 64bit keys. + * The parity bits will _not_ checked, too. + * + * After initializing a context with a key you could use this context to + * encrypt or decrypt data in 64bit blocks in Electronic Codebook Mode. + * + * (In the examples below the slashes at the beginning and ending of comments + * are omited.) + * + * DES Example + * ----------- + * unsigned char key[8]; + * unsigned char plaintext[8]; + * unsigned char ciphertext[8]; + * unsigned char recoverd[8]; + * des_ctx context; + * + * * Fill 'key' and 'plaintext' with some data * + * .... + * + * * Set up the DES encryption context * + * des_setkey(context, key); + * + * * Encrypt the plaintext * + * des_ecb_encrypt(context, plaintext, ciphertext); + * + * * To recover the orginal plaintext from ciphertext use: * + * des_ecb_decrypt(context, ciphertext, recoverd); + * + * + * Triple-DES Example + * ------------------ + * unsigned char key1[8]; + * unsigned char key2[8]; + * unsigned char key3[8]; + * unsigned char plaintext[8]; + * unsigned char ciphertext[8]; + * unsigned char recoverd[8]; + * tripledes_ctx context; + * + * * If you would like to use two 64bit keys, fill 'key1' and'key2' + * then setup the encryption context: * + * tripledes_set2keys(context, key1, key2); + * + * * To use three 64bit keys with Triple-DES use: * + * tripledes_set3keys(context, key1, key2, key3); + * + * * Encrypting plaintext with Triple-DES * + * tripledes_ecb_encrypt(context, plaintext, ciphertext); + * + * * Decrypting ciphertext to recover the plaintext with Triple-DES * + * tripledes_ecb_decrypt(context, ciphertext, recoverd); + * + * + * Selftest + * -------- + * char *error_msg; + * + * * To perform a selftest of this DES/Triple-DES implementation use the + * function selftest(). It will return an error string if there are + * some problems with this library. * + * + * if ( (error_msg = selftest()) ) + * { + * fprintf(stderr, "An error in the DES/Triple-DES implementation occurred: %s\n", error_msg); + * abort(); + * } + */ + + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + +#if defined(__GNUC__) && defined(__GNU_LIBRARY__) +#define working_memcmp memcmp +#else +/* + * According to the SunOS man page, memcmp returns indeterminate sign + * depending on whether characters are signed or not. + */ +static int +working_memcmp( const char *a, const char *b, size_t n ) +{ + for( ; n; n--, a++, b++ ) + if( *a != *b ) + return (int)(*(byte*)a) - (int)(*(byte*)b); + return 0; +} +#endif + +/* + * Encryption/Decryption context of DES + */ +typedef struct _des_ctx + { + u32 encrypt_subkeys[32]; + u32 decrypt_subkeys[32]; + } +des_ctx[1]; + +/* + * Encryption/Decryption context of Triple-DES + */ +typedef struct _tripledes_ctx + { + u32 encrypt_subkeys[96]; + u32 decrypt_subkeys[96]; + struct { + int no_weak_key; + } flags; + } +tripledes_ctx[1]; + +static void des_key_schedule (const byte *, u32 *); +static int des_setkey (struct _des_ctx *, const byte *); +static int des_ecb_crypt (struct _des_ctx *, const byte *, byte *, int); +static int tripledes_ecb_crypt (struct _tripledes_ctx *, + const byte *, byte *, int); +static int is_weak_key ( const byte *key ); + +static int initialized; + + + + +/* + * The s-box values are permuted according to the 'primitive function P' + * and are rotated one bit to the left. + */ +static u32 sbox1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static u32 sbox2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static u32 sbox3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static u32 sbox4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static u32 sbox5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static u32 sbox6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static u32 sbox7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static u32 sbox8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + + +/* + * These two tables are part of the 'permuted choice 1' function. + * In this implementation several speed improvements are done. + */ +static u32 leftkey_swap[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static u32 rightkey_swap[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + + + +/* + * Numbers of left shifts per round for encryption subkeys. + * To calculate the decryption subkeys we just reverse the + * ordering of the calculated encryption subkeys. So their + * is no need for a decryption rotate tab. + */ +static byte encrypt_rotate_tab[16] = +{ + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + + + +/* + * Table with weak DES keys sorted in ascending order. + * In DES their are 64 known keys which are weak. They are weak + * because they produce only one, two or four different + * subkeys in the subkey scheduling process. + * The keys in this table have all their parity bits cleared. + */ +static byte weak_keys[64][8] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*w*/ + { 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e }, + { 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0 }, + { 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe }, + { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e }, /*sw*/ + { 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00 }, + { 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe }, + { 0x00, 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0 }, + { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0 }, /*sw*/ + { 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe }, + { 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00 }, + { 0x00, 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e }, + { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe }, /*sw*/ + { 0x00, 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0 }, + { 0x00, 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e }, + { 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00 }, + { 0x1e, 0x00, 0x00, 0x1e, 0x0e, 0x00, 0x00, 0x0e }, + { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 }, /*sw*/ + { 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0, 0xfe }, + { 0x1e, 0x00, 0xfe, 0xe0, 0x0e, 0x00, 0xfe, 0xf0 }, + { 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00 }, + { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e }, /*w*/ + { 0x1e, 0x1e, 0xe0, 0xe0, 0x0e, 0x0e, 0xf0, 0xf0 }, + { 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe, 0xfe }, + { 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00, 0xfe }, + { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 }, /*sw*/ + { 0x1e, 0xe0, 0xe0, 0x1e, 0x0e, 0xf0, 0xf0, 0x0e }, + { 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe, 0x00 }, + { 0x1e, 0xfe, 0x00, 0xe0, 0x0e, 0xfe, 0x00, 0xf0 }, + { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, /*sw*/ + { 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0, 0x00 }, + { 0x1e, 0xfe, 0xfe, 0x1e, 0x0e, 0xfe, 0xfe, 0x0e }, + { 0xe0, 0x00, 0x00, 0xe0, 0xf0, 0x00, 0x00, 0xf0 }, + { 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e, 0xfe }, + { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 }, /*sw*/ + { 0xe0, 0x00, 0xfe, 0x1e, 0xf0, 0x00, 0xfe, 0x0e }, + { 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00, 0xfe }, + { 0xe0, 0x1e, 0x1e, 0xe0, 0xf0, 0x0e, 0x0e, 0xf0 }, + { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e }, /*sw*/ + { 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe, 0x00 }, + { 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00 }, + { 0xe0, 0xe0, 0x1e, 0x1e, 0xf0, 0xf0, 0x0e, 0x0e }, + { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 }, /*w*/ + { 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe, 0xfe }, + { 0xe0, 0xfe, 0x00, 0x1e, 0xf0, 0xfe, 0x00, 0x0e }, + { 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e, 0x00 }, + { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe }, /*sw*/ + { 0xe0, 0xfe, 0xfe, 0xe0, 0xf0, 0xfe, 0xfe, 0xf0 }, + { 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe }, + { 0xfe, 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0 }, + { 0xfe, 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e }, + { 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00 }, /*sw*/ + { 0xfe, 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0 }, + { 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe }, + { 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00 }, + { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e }, /*sw*/ + { 0xfe, 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e }, + { 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00 }, + { 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe }, + { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 }, /*sw*/ + { 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00 }, + { 0xfe, 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e }, + { 0xfe, 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0 }, + { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe } /*w*/ +}; + + + +/* + * Macro to swap bits across two words. + */ +#define DO_PERMUTATION(a, temp, b, offset, mask) \ + temp = ((a>>offset) ^ b) & mask; \ + b ^= temp; \ + a ^= temp<<offset; + + +/* + * This performs the 'initial permutation' of the data to be encrypted + * or decrypted. Additionally the resulting two words are rotated one bit + * to the left. + */ +#define INITIAL_PERMUTATION(left, temp, right) \ + DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ + DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ + DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ + DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ + right = (right << 1) | (right >> 31); \ + temp = (left ^ right) & 0xaaaaaaaa; \ + right ^= temp; \ + left ^= temp; \ + left = (left << 1) | (left >> 31); + +/* + * The 'inverse initial permutation'. + */ +#define FINAL_PERMUTATION(left, temp, right) \ + left = (left << 31) | (left >> 1); \ + temp = (left ^ right) & 0xaaaaaaaa; \ + left ^= temp; \ + right ^= temp; \ + right = (right << 31) | (right >> 1); \ + DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ + DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ + DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ + DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) + + +/* + * A full DES round including 'expansion function', 'sbox substitution' + * and 'primitive function P' but without swapping the left and right word. + * Please note: The data in 'from' and 'to' is already rotated one bit to + * the left, done in the initial permutation. + */ +#define DES_ROUND(from, to, work, subkey) \ + work = from ^ *subkey++; \ + to ^= sbox8[ work & 0x3f ]; \ + to ^= sbox6[ (work>>8) & 0x3f ]; \ + to ^= sbox4[ (work>>16) & 0x3f ]; \ + to ^= sbox2[ (work>>24) & 0x3f ]; \ + work = ((from << 28) | (from >> 4)) ^ *subkey++; \ + to ^= sbox7[ work & 0x3f ]; \ + to ^= sbox5[ (work>>8) & 0x3f ]; \ + to ^= sbox3[ (work>>16) & 0x3f ]; \ + to ^= sbox1[ (work>>24) & 0x3f ]; + +/* + * Macros to convert 8 bytes from/to 32bit words. + */ +#define READ_64BIT_DATA(data, left, right) \ + left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ + right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; + +#define WRITE_64BIT_DATA(data, left, right) \ + data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ + data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ + data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ + data[6] = (right >> 8) &0xff; data[7] = right &0xff; + +/* + * Handy macros for encryption and decryption of data + */ +#define des_ecb_encrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 0) +#define des_ecb_decrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 1) +#define tripledes_ecb_encrypt(ctx, from, to) tripledes_ecb_crypt(ctx,from,to,0) +#define tripledes_ecb_decrypt(ctx, from, to) tripledes_ecb_crypt(ctx,from,to,1) + + + + + + +/* + * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for + * 16 encryption rounds. + * To calculate subkeys for decryption the caller + * have to reorder the generated subkeys. + * + * rawkey: 8 Bytes of key data + * subkey: Array of at least 32 u32s. Will be filled + * with calculated subkeys. + * + */ +static void +des_key_schedule (const byte * rawkey, u32 * subkey) +{ + u32 left, right, work; + int round; + + READ_64BIT_DATA (rawkey, left, right) + + DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) + DO_PERMUTATION (right, work, left, 0, 0x10101010) + + left = ((leftkey_swap[(left >> 0) & 0xf] << 3) + | (leftkey_swap[(left >> 8) & 0xf] << 2) + | (leftkey_swap[(left >> 16) & 0xf] << 1) + | (leftkey_swap[(left >> 24) & 0xf]) + | (leftkey_swap[(left >> 5) & 0xf] << 7) + | (leftkey_swap[(left >> 13) & 0xf] << 6) + | (leftkey_swap[(left >> 21) & 0xf] << 5) + | (leftkey_swap[(left >> 29) & 0xf] << 4)); + + left &= 0x0fffffff; + + right = ((rightkey_swap[(right >> 1) & 0xf] << 3) + | (rightkey_swap[(right >> 9) & 0xf] << 2) + | (rightkey_swap[(right >> 17) & 0xf] << 1) + | (rightkey_swap[(right >> 25) & 0xf]) + | (rightkey_swap[(right >> 4) & 0xf] << 7) + | (rightkey_swap[(right >> 12) & 0xf] << 6) + | (rightkey_swap[(right >> 20) & 0xf] << 5) + | (rightkey_swap[(right >> 28) & 0xf] << 4)); + + right &= 0x0fffffff; + + for (round = 0; round < 16; ++round) + { + left = ((left << encrypt_rotate_tab[round]) + | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; + right = ((right << encrypt_rotate_tab[round]) + | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; + + *subkey++ = (((left << 4) & 0x24000000) + | ((left << 28) & 0x10000000) + | ((left << 14) & 0x08000000) + | ((left << 18) & 0x02080000) + | ((left << 6) & 0x01000000) + | ((left << 9) & 0x00200000) + | ((left >> 1) & 0x00100000) + | ((left << 10) & 0x00040000) + | ((left << 2) & 0x00020000) + | ((left >> 10) & 0x00010000) + | ((right >> 13) & 0x00002000) + | ((right >> 4) & 0x00001000) + | ((right << 6) & 0x00000800) + | ((right >> 1) & 0x00000400) + | ((right >> 14) & 0x00000200) + | (right & 0x00000100) + | ((right >> 5) & 0x00000020) + | ((right >> 10) & 0x00000010) + | ((right >> 3) & 0x00000008) + | ((right >> 18) & 0x00000004) + | ((right >> 26) & 0x00000002) + | ((right >> 24) & 0x00000001)); + + *subkey++ = (((left << 15) & 0x20000000) + | ((left << 17) & 0x10000000) + | ((left << 10) & 0x08000000) + | ((left << 22) & 0x04000000) + | ((left >> 2) & 0x02000000) + | ((left << 1) & 0x01000000) + | ((left << 16) & 0x00200000) + | ((left << 11) & 0x00100000) + | ((left << 3) & 0x00080000) + | ((left >> 6) & 0x00040000) + | ((left << 15) & 0x00020000) + | ((left >> 4) & 0x00010000) + | ((right >> 2) & 0x00002000) + | ((right << 8) & 0x00001000) + | ((right >> 14) & 0x00000808) + | ((right >> 9) & 0x00000400) + | ((right) & 0x00000200) + | ((right << 7) & 0x00000100) + | ((right >> 7) & 0x00000020) + | ((right >> 3) & 0x00000011) + | ((right << 2) & 0x00000004) + | ((right >> 21) & 0x00000002)); + } +} + + +/* + * Fill a DES context with subkeys calculated from a 64bit key. + * Does not check parity bits, but simply ignore them. + * Does not check for weak keys. + */ +static int +des_setkey (struct _des_ctx *ctx, const byte * key) +{ + static const char *selftest_failed; + int i; + + if (!fips_mode () && !initialized) + { + initialized = 1; + selftest_failed = selftest (); + + if (selftest_failed) + log_error ("%s\n", selftest_failed); + } + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + des_key_schedule (key, ctx->encrypt_subkeys); + _gcry_burn_stack (32); + + for(i=0; i<32; i+=2) + { + ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; + ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; + } + + return 0; +} + + + +/* + * Electronic Codebook Mode DES encryption/decryption of data according + * to 'mode'. + */ +static int +des_ecb_crypt (struct _des_ctx *ctx, const byte * from, byte * to, int mode) +{ + u32 left, right, work; + u32 *keys; + + keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; + + READ_64BIT_DATA (from, left, right) + INITIAL_PERMUTATION (left, work, right) + + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + + FINAL_PERMUTATION (right, work, left) + WRITE_64BIT_DATA (to, right, left) + + return 0; +} + + + +/* + * Fill a Triple-DES context with subkeys calculated from two 64bit keys. + * Does not check the parity bits of the keys, but simply ignore them. + * Does not check for weak keys. + */ + + + +/* + * Fill a Triple-DES context with subkeys calculated from three 64bit keys. + * Does not check the parity bits of the keys, but simply ignore them. + * Does not check for weak keys. + */ +static int +tripledes_set3keys (struct _tripledes_ctx *ctx, + const byte * key1, + const byte * key2, + const byte * key3) +{ + static const char *selftest_failed; + int i; + + if (!fips_mode () && !initialized) + { + initialized = 1; + selftest_failed = selftest (); + + if (selftest_failed) + log_error ("%s\n", selftest_failed); + } + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + des_key_schedule (key1, ctx->encrypt_subkeys); + des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); + des_key_schedule (key3, &(ctx->encrypt_subkeys[64])); + _gcry_burn_stack (32); + + for(i=0; i<32; i+=2) + { + ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[94-i]; + ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[95-i]; + + ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i]; + ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i]; + + ctx->decrypt_subkeys[i+64] = ctx->encrypt_subkeys[30-i]; + ctx->decrypt_subkeys[i+65] = ctx->encrypt_subkeys[31-i]; + } + + return 0; +} + + + +/* + * Electronic Codebook Mode Triple-DES encryption/decryption of data + * according to 'mode'. Sometimes this mode is named 'EDE' mode + * (Encryption-Decryption-Encryption). + */ +static int +tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from, + byte * to, int mode) +{ + u32 left, right, work; + u32 *keys; + + keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; + + READ_64BIT_DATA (from, left, right) + INITIAL_PERMUTATION (left, work, right) + + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + + FINAL_PERMUTATION (right, work, left) + WRITE_64BIT_DATA (to, right, left) + + return 0; +} + + + + + +/* + * Check whether the 8 byte key is weak. + * Does not check the parity bits of the key but simple ignore them. + */ +static int +is_weak_key ( const byte *key ) +{ + byte work[8]; + int i, left, right, middle, cmp_result; + + /* clear parity bits */ + for(i=0; i<8; ++i) + work[i] = key[i] & 0xfe; + + /* binary search in the weak key table */ + left = 0; + right = 63; + while(left <= right) + { + middle = (left + right) / 2; + + if ( !(cmp_result=working_memcmp(work, weak_keys[middle], 8)) ) + return -1; + + if ( cmp_result > 0 ) + left = middle + 1; + else + right = middle - 1; + } + + return 0; +} + + + +/* + * Performs a selftest of this DES/Triple-DES implementation. + * Returns an string with the error text on failure. + * Returns NULL if all is ok. + */ + + +static gcry_err_code_t +do_tripledes_setkey ( void *context, const byte *key, unsigned keylen ) +{ + struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; + + if( keylen != 24 ) + return GPG_ERR_INV_KEYLEN; + + tripledes_set3keys ( ctx, key, key+8, key+16); + + if (ctx->flags.no_weak_key) + ; /* Detection has been disabled. */ + else if (is_weak_key (key) || is_weak_key (key+8) || is_weak_key (key+16)) + { + _gcry_burn_stack (64); + return GPG_ERR_WEAK_KEY; + } + _gcry_burn_stack (64); + + return GPG_ERR_NO_ERROR; +} + + + + +static void +do_tripledes_encrypt( void *context, byte *outbuf, const byte *inbuf ) +{ + struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; + + tripledes_ecb_encrypt ( ctx, inbuf, outbuf ); + _gcry_burn_stack (32); +} + +static void +do_tripledes_decrypt( void *context, byte *outbuf, const byte *inbuf ) +{ + struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; + tripledes_ecb_decrypt ( ctx, inbuf, outbuf ); + _gcry_burn_stack (32); +} + +static gcry_err_code_t +do_des_setkey (void *context, const byte *key, unsigned keylen) +{ + struct _des_ctx *ctx = (struct _des_ctx *) context; + + if (keylen != 8) + return GPG_ERR_INV_KEYLEN; + + des_setkey (ctx, key); + + if (is_weak_key (key)) { + _gcry_burn_stack (64); + return GPG_ERR_WEAK_KEY; + } + _gcry_burn_stack (64); + + return GPG_ERR_NO_ERROR; +} + + +static void +do_des_encrypt( void *context, byte *outbuf, const byte *inbuf ) +{ + struct _des_ctx *ctx = (struct _des_ctx *) context; + + des_ecb_encrypt ( ctx, inbuf, outbuf ); + _gcry_burn_stack (32); +} + +static void +do_des_decrypt( void *context, byte *outbuf, const byte *inbuf ) +{ + struct _des_ctx *ctx = (struct _des_ctx *) context; + + des_ecb_decrypt ( ctx, inbuf, outbuf ); + _gcry_burn_stack (32); +} + + + + +/* + Self-test section. + */ + + +/* Selftest for TripleDES. */ + + + +/* Run a full self-test for ALGO and return 0 on success. */ + + + +gcry_cipher_spec_t _gcry_cipher_spec_des = + { + "DES", NULL, NULL, 8, 64, sizeof (struct _des_ctx), + do_des_setkey, do_des_encrypt, do_des_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_des", +#endif + }; + +static gcry_cipher_oid_spec_t oids_tripledes[] = + { + { "1.2.840.113549.3.7", GCRY_CIPHER_MODE_CBC }, + /* Teletrust specific OID for 3DES. */ + { "1.3.36.3.1.3.2.1", GCRY_CIPHER_MODE_CBC }, + /* pbeWithSHAAnd3_KeyTripleDES_CBC */ + { "1.2.840.113549.1.12.1.3", GCRY_CIPHER_MODE_CBC }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_tripledes = + { + "3DES", NULL, oids_tripledes, 8, 192, sizeof (struct _tripledes_ctx), + do_tripledes_setkey, do_tripledes_encrypt, do_tripledes_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_des", +#endif + }; + + + +GRUB_MOD_INIT(gcry_des) +{ + grub_cipher_register (&_gcry_cipher_spec_des); + grub_cipher_register (&_gcry_cipher_spec_tripledes); +} + +GRUB_MOD_FINI(gcry_des) +{ + grub_cipher_unregister (&_gcry_cipher_spec_des); + grub_cipher_unregister (&_gcry_cipher_spec_tripledes); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/dsa.c b/grub-core/lib/libgcrypt-grub/cipher/dsa.c new file mode 100644 index 0000000..52079c5 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/dsa.c @@ -0,0 +1,292 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* dsa.c - DSA signature algorithm + * Copyright (C) 1998, 2000, 2001, 2002, 2003, + * 2006, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + + +#include "g10lib.h" +#include "mpi.h" +#include "cipher.h" + +typedef struct +{ + gcry_mpi_t p; /* prime */ + gcry_mpi_t q; /* group order */ + gcry_mpi_t g; /* group generator */ + gcry_mpi_t y; /* g^x mod p */ +} DSA_public_key; + + +typedef struct +{ + gcry_mpi_t p; /* prime */ + gcry_mpi_t q; /* group order */ + gcry_mpi_t g; /* group generator */ + gcry_mpi_t y; /* g^x mod p */ + gcry_mpi_t x; /* secret exponent */ +} DSA_secret_key; + + +/* A structure used to hold domain parameters. */ +typedef struct +{ + gcry_mpi_t p; /* prime */ + gcry_mpi_t q; /* group order */ + gcry_mpi_t g; /* group generator */ +} dsa_domain_t; + + +/* A sample 1024 bit DSA key used for the selftests. */ +/* A sample 1024 bit DSA key used for the selftests (public only). */ + + + + +static int check_secret_key (DSA_secret_key *sk); +static int verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, + DSA_public_key *pkey); + + + + + + + +/* + * Generate a random secret exponent k less than q. + */ + + +/* Check that a freshly generated key actually works. Returns 0 on success. */ + + + +/* + Generate a DSA key pair with a key of size NBITS. If transient_key + is true the key is generated using the standard RNG and not the + very secure one. + + Returns: 2 structures filled with all needed values + and an array with the n-1 factors of (p-1) + */ + + +/* Generate a DSA key pair with a key of size NBITS using the + algorithm given in FIPS-186-3. If USE_FIPS186_2 is true, + FIPS-186-2 is used and thus the length is restricted to 1024/160. + If DERIVEPARMS is not NULL it may contain a seed value. If domain + parameters are specified in DOMAIN, DERIVEPARMS may not be given + and NBITS and QBITS must match the specified domain parameters. */ + + + +/* + Test whether the secret key is valid. + Returns: if this is a valid key. + */ +static int +check_secret_key( DSA_secret_key *sk ) +{ + int rc; + gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs(sk->y) ); + + gcry_mpi_powm( y, sk->g, sk->x, sk->p ); + rc = !mpi_cmp( y, sk->y ); + mpi_free( y ); + return rc; +} + + + +/* + Make a DSA signature from HASH and put it into r and s. + */ + + +/* + Returns true if the signature composed from R and S is valid. + */ +static int +verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t hash, DSA_public_key *pkey ) +{ + int rc; + gcry_mpi_t w, u1, u2, v; + gcry_mpi_t base[3]; + gcry_mpi_t ex[3]; + + if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) ) + return 0; /* assertion 0 < r < q failed */ + if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) ) + return 0; /* assertion 0 < s < q failed */ + + w = mpi_alloc( mpi_get_nlimbs(pkey->q) ); + u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) ); + u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) ); + v = mpi_alloc( mpi_get_nlimbs(pkey->p) ); + + /* w = s^(-1) mod q */ + mpi_invm( w, s, pkey->q ); + + /* u1 = (hash * w) mod q */ + mpi_mulm( u1, hash, w, pkey->q ); + + /* u2 = r * w mod q */ + mpi_mulm( u2, r, w, pkey->q ); + + /* v = g^u1 * y^u2 mod p mod q */ + base[0] = pkey->g; ex[0] = u1; + base[1] = pkey->y; ex[1] = u2; + base[2] = NULL; ex[2] = NULL; + mpi_mulpowm( v, base, ex, pkey->p ); + mpi_fdiv_r( v, v, pkey->q ); + + rc = !mpi_cmp( v, r ); + + mpi_free(w); + mpi_free(u1); + mpi_free(u2); + mpi_free(v); + + return rc; +} + + +/********************************************* + ************** interface ****************** + *********************************************/ + +#define dsa_generate 0 + +#define dsa_generate 0 + + +static gcry_err_code_t +dsa_check_secret_key (int algo, gcry_mpi_t *skey) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + DSA_secret_key sk; + + (void)algo; + + if ((! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]) || (! skey[4])) + err = GPG_ERR_BAD_MPI; + else + { + sk.p = skey[0]; + sk.q = skey[1]; + sk.g = skey[2]; + sk.y = skey[3]; + sk.x = skey[4]; + if (! check_secret_key (&sk)) + err = GPG_ERR_BAD_SECKEY; + } + + return err; +} + + +#define dsa_sign 0 +static gcry_err_code_t +dsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, + int (*cmp) (void *, gcry_mpi_t), void *opaquev) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + DSA_public_key pk; + + (void)algo; + (void)cmp; + (void)opaquev; + + if ((! data[0]) || (! data[1]) || (! hash) + || (! pkey[0]) || (! pkey[1]) || (! pkey[2]) || (! pkey[3])) + err = GPG_ERR_BAD_MPI; + else + { + pk.p = pkey[0]; + pk.q = pkey[1]; + pk.g = pkey[2]; + pk.y = pkey[3]; + if (! verify (data[0], data[1], hash, &pk)) + err = GPG_ERR_BAD_SIGNATURE; + } + return err; +} + + +static unsigned int +dsa_get_nbits (int algo, gcry_mpi_t *pkey) +{ + (void)algo; + + return mpi_get_nbits (pkey[0]); +} + + + +/* + Self-test section. + */ + + + + + +/* Run a full self-test for ALGO and return 0 on success. */ + + + + +static const char *dsa_names[] = + { + "dsa", + "openpgp-dsa", + NULL, + }; + +gcry_pk_spec_t _gcry_pubkey_spec_dsa = + { + "DSA", dsa_names, + "pqgy", "pqgyx", "", "rs", "pqgy", + GCRY_PK_USAGE_SIGN, + dsa_generate, + dsa_check_secret_key, + NULL, + NULL, + dsa_sign, + dsa_verify, + dsa_get_nbits + , +#ifdef GRUB_UTIL + .modname = "gcry_dsa", +#endif + }; + + +GRUB_MOD_INIT(gcry_dsa) +{ + grub_crypto_pk_dsa = &_gcry_pubkey_spec_dsa; +} + +GRUB_MOD_FINI(gcry_dsa) +{ + grub_crypto_pk_dsa = 0; +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/g10lib.h b/grub-core/lib/libgcrypt-grub/cipher/g10lib.h new file mode 100644 index 0000000..49cc16a --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/g10lib.h @@ -0,0 +1 @@ +#include <cipher_wrap.h> diff --git a/grub-core/lib/libgcrypt-grub/cipher/hash-common.h b/grub-core/lib/libgcrypt-grub/cipher/hash-common.h new file mode 100644 index 0000000..79d3675 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/hash-common.h @@ -0,0 +1,36 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +/* hash-common.h - Declarations of common code for hash algorithms. + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GCRY_HASH_COMMON_H +#define GCRY_HASH_COMMON_H + + +const char * _gcry_hash_selftest_check_one +/**/ (int algo, + int datamode, const void *data, size_t datalen, + const void *expect, size_t expectlen); + + + + + +#endif /*GCRY_HASH_COMMON_H*/ diff --git a/grub-core/lib/libgcrypt-grub/cipher/idea.c b/grub-core/lib/libgcrypt-grub/cipher/idea.c new file mode 100644 index 0000000..52a818f --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/idea.c @@ -0,0 +1,322 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* idea.c - IDEA function + * Copyright 1997, 1998, 1999, 2001 Werner Koch (dd9jn) + * Copyright 2013 g10 Code GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * WERNER KOCH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of Werner Koch shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Werner Koch. + * + * Patents on IDEA have expired: + * Europe: EP0482154 on 2011-05-16, + * Japan: JP3225440 on 2011-05-16, + * U.S.: 5,214,703 on 2012-01-07. + */ + +/* + * Please see http://www.noepatents.org/ to learn why software patents + * are bad for society and what you can do to fight them. + * + * The code herein is based on the one from: + * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. + * ISBN 0-471-11709-9. + */ + + + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + + +#define IDEA_KEYSIZE 16 +#define IDEA_BLOCKSIZE 8 +#define IDEA_ROUNDS 8 +#define IDEA_KEYLEN (6*IDEA_ROUNDS+4) + +typedef struct { + u16 ek[IDEA_KEYLEN]; + u16 dk[IDEA_KEYLEN]; + int have_dk; +} IDEA_context; + + + +static u16 +mul_inv( u16 x ) +{ + u16 t0, t1; + u16 q, y; + + if( x < 2 ) + return x; + t1 = 0x10001UL / x; + y = 0x10001UL % x; + if( y == 1 ) + return (1-t1) & 0xffff; + + t0 = 1; + do { + q = x / y; + x = x % y; + t0 += q * t1; + if( x == 1 ) + return t0; + q = y / x; + y = y % x; + t1 += q * t0; + } while( y != 1 ); + return (1-t1) & 0xffff; +} + + + +static void +expand_key( const byte *userkey, u16 *ek ) +{ + int i,j; + + for(j=0; j < 8; j++ ) { + ek[j] = (*userkey << 8) + userkey[1]; + userkey += 2; + } + for(i=0; j < IDEA_KEYLEN; j++ ) { + i++; + ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7; + ek += i & 8; + i &= 7; + } +} + + +static void +invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] ) +{ + int i; + u16 t1, t2, t3; + u16 temp[IDEA_KEYLEN]; + u16 *p = temp + IDEA_KEYLEN; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t3; + *--p = t2; + *--p = t1; + + for(i=0; i < IDEA_ROUNDS-1; i++ ) { + t1 = *ek++; + *--p = *ek++; + *--p = t1; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t2; + *--p = t3; + *--p = t1; + } + t1 = *ek++; + *--p = *ek++; + *--p = t1; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t3; + *--p = t2; + *--p = t1; + memcpy(dk, temp, sizeof(temp) ); + memset(temp, 0, sizeof(temp) ); /* burn temp */ +} + + +static void +cipher( byte *outbuf, const byte *inbuf, u16 *key ) +{ + u16 s2, s3; + u16 in[4]; + int r = IDEA_ROUNDS; +#define x1 (in[0]) +#define x2 (in[1]) +#define x3 (in[2]) +#define x4 (in[3]) +#define MUL(x,y) \ + do {u16 _t16; u32 _t32; \ + if( (_t16 = (y)) ) { \ + if( (x = (x)&0xffff) ) { \ + _t32 = (u32)x * _t16; \ + x = _t32 & 0xffff; \ + _t16 = _t32 >> 16; \ + x = ((x)-_t16) + (x<_t16?1:0); \ + } \ + else { \ + x = 1 - _t16; \ + } \ + } \ + else { \ + x = 1 - x; \ + } \ + } while(0) + + memcpy (in, inbuf, sizeof in); +#ifndef WORDS_BIGENDIAN + x1 = (x1>>8) | (x1<<8); + x2 = (x2>>8) | (x2<<8); + x3 = (x3>>8) | (x3<<8); + x4 = (x4>>8) | (x4<<8); +#endif + do { + MUL(x1, *key++); + x2 += *key++; + x3 += *key++; + MUL(x4, *key++ ); + + s3 = x3; + x3 ^= x1; + MUL(x3, *key++); + s2 = x2; + x2 ^=x4; + x2 += x3; + MUL(x2, *key++); + x3 += x2; + + x1 ^= x2; + x4 ^= x3; + + x2 ^= s3; + x3 ^= s2; + } while( --r ); + MUL(x1, *key++); + x3 += *key++; + x2 += *key++; + MUL(x4, *key); + +#ifndef WORDS_BIGENDIAN + x1 = (x1>>8) | (x1<<8); + x2 = (x2>>8) | (x2<<8); + x3 = (x3>>8) | (x3<<8); + x4 = (x4>>8) | (x4<<8); +#endif + memcpy (outbuf+0, &x1, 2); + memcpy (outbuf+2, &x3, 2); + memcpy (outbuf+4, &x2, 2); + memcpy (outbuf+6, &x4, 2); +#undef MUL +#undef x1 +#undef x2 +#undef x3 +#undef x4 +} + + +static int +do_setkey( IDEA_context *c, const byte *key, unsigned int keylen ) +{ + static int initialized = 0; + static const char *selftest_failed = 0; + + if( !initialized ) { + initialized = 1; + selftest_failed = selftest(); + if( selftest_failed ) + log_error( "%s\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + assert(keylen == 16); + c->have_dk = 0; + expand_key( key, c->ek ); + invert_key( c->ek, c->dk ); + return 0; +} + +static gcry_err_code_t +idea_setkey (void *context, const byte *key, unsigned int keylen) +{ + IDEA_context *ctx = context; + int rc = do_setkey (ctx, key, keylen); + _gcry_burn_stack (23+6*sizeof(void*)); + return rc; +} + +static void +encrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) +{ + cipher( outbuf, inbuf, c->ek ); +} + +static void +idea_encrypt (void *context, byte *out, const byte *in) +{ + IDEA_context *ctx = context; + encrypt_block (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + +static void +decrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) +{ + if( !c->have_dk ) { + c->have_dk = 1; + invert_key( c->ek, c->dk ); + } + cipher( outbuf, inbuf, c->dk ); +} + +static void +idea_decrypt (void *context, byte *out, const byte *in) +{ + IDEA_context *ctx = context; + decrypt_block (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + + + + +gcry_cipher_spec_t _gcry_cipher_spec_idea = +{ + "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128, + sizeof (IDEA_context), + idea_setkey, idea_encrypt, idea_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_idea", +#endif +}; + + +GRUB_MOD_INIT(gcry_idea) +{ + grub_cipher_register (&_gcry_cipher_spec_idea); +} + +GRUB_MOD_FINI(gcry_idea) +{ + grub_cipher_unregister (&_gcry_cipher_spec_idea); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/init.c b/grub-core/lib/libgcrypt-grub/cipher/init.c new file mode 100644 index 0000000..a02fe0f --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/init.c @@ -0,0 +1,91 @@ +#include <grub/crypto.h> +extern void grub_gcry_arcfour_init (void); +extern void grub_gcry_arcfour_fini (void); +extern void grub_gcry_blowfish_init (void); +extern void grub_gcry_blowfish_fini (void); +extern void grub_gcry_camellia_init (void); +extern void grub_gcry_camellia_fini (void); +extern void grub_gcry_cast5_init (void); +extern void grub_gcry_cast5_fini (void); +extern void grub_gcry_crc_init (void); +extern void grub_gcry_crc_fini (void); +extern void grub_gcry_des_init (void); +extern void grub_gcry_des_fini (void); +extern void grub_gcry_idea_init (void); +extern void grub_gcry_idea_fini (void); +extern void grub_gcry_md4_init (void); +extern void grub_gcry_md4_fini (void); +extern void grub_gcry_md5_init (void); +extern void grub_gcry_md5_fini (void); +extern void grub_gcry_rfc2268_init (void); +extern void grub_gcry_rfc2268_fini (void); +extern void grub_gcry_rijndael_init (void); +extern void grub_gcry_rijndael_fini (void); +extern void grub_gcry_rmd160_init (void); +extern void grub_gcry_rmd160_fini (void); +extern void grub_gcry_seed_init (void); +extern void grub_gcry_seed_fini (void); +extern void grub_gcry_serpent_init (void); +extern void grub_gcry_serpent_fini (void); +extern void grub_gcry_sha1_init (void); +extern void grub_gcry_sha1_fini (void); +extern void grub_gcry_sha256_init (void); +extern void grub_gcry_sha256_fini (void); +extern void grub_gcry_sha512_init (void); +extern void grub_gcry_sha512_fini (void); +extern void grub_gcry_tiger_init (void); +extern void grub_gcry_tiger_fini (void); +extern void grub_gcry_twofish_init (void); +extern void grub_gcry_twofish_fini (void); +extern void grub_gcry_whirlpool_init (void); +extern void grub_gcry_whirlpool_fini (void); + +void +grub_gcry_init_all (void) +{ + grub_gcry_arcfour_init (); + grub_gcry_blowfish_init (); + grub_gcry_camellia_init (); + grub_gcry_cast5_init (); + grub_gcry_crc_init (); + grub_gcry_des_init (); + grub_gcry_idea_init (); + grub_gcry_md4_init (); + grub_gcry_md5_init (); + grub_gcry_rfc2268_init (); + grub_gcry_rijndael_init (); + grub_gcry_rmd160_init (); + grub_gcry_seed_init (); + grub_gcry_serpent_init (); + grub_gcry_sha1_init (); + grub_gcry_sha256_init (); + grub_gcry_sha512_init (); + grub_gcry_tiger_init (); + grub_gcry_twofish_init (); + grub_gcry_whirlpool_init (); +} + +void +grub_gcry_fini_all (void) +{ + grub_gcry_arcfour_fini (); + grub_gcry_blowfish_fini (); + grub_gcry_camellia_fini (); + grub_gcry_cast5_fini (); + grub_gcry_crc_fini (); + grub_gcry_des_fini (); + grub_gcry_idea_fini (); + grub_gcry_md4_fini (); + grub_gcry_md5_fini (); + grub_gcry_rfc2268_fini (); + grub_gcry_rijndael_fini (); + grub_gcry_rmd160_fini (); + grub_gcry_seed_fini (); + grub_gcry_serpent_fini (); + grub_gcry_sha1_fini (); + grub_gcry_sha256_fini (); + grub_gcry_sha512_fini (); + grub_gcry_tiger_fini (); + grub_gcry_twofish_fini (); + grub_gcry_whirlpool_fini (); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/md4.c b/grub-core/lib/libgcrypt-grub/cipher/md4.c new file mode 100644 index 0000000..deb291a --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/md4.c @@ -0,0 +1,344 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* md4.c - MD4 Message-Digest Algorithm + * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Based on md5.c in libgcrypt, but rewritten to compute md4 checksums + * using a public domain md4 implementation with the following comments: + * + * Modified by Wei Dai from Andrew M. Kuchling's md4.c + * The original code and all modifications are in the public domain. + * + * This is the original introductory comment: + * + * md4.c : MD4 hash algorithm. + * + * Part of the Python Cryptography Toolkit, version 1.1 + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +/* MD4 test suite: + * MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0 + * MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24 + * MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d + * MD4 ("message digest") = d9130a8164549fe818874806e1c7014b + * MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9 + * MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = + * 043f8582f241db351ce627e153e7f0e4 + * MD4 ("123456789012345678901234567890123456789012345678901234567890123456 + * 78901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536 + */ + + +#include "g10lib.h" +#include "cipher.h" + +#include "bithelp.h" + + +typedef struct { + u32 A,B,C,D; /* chaining variables */ + u32 nblocks; + byte buf[64]; + int count; +} MD4_CONTEXT; + + +static void +md4_init( void *context ) +{ + MD4_CONTEXT *ctx = context; + + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->nblocks = 0; + ctx->count = 0; +} + +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + + +/**************** + * transform 64 bytes + */ +static void +transform ( MD4_CONTEXT *ctx, const unsigned char *data ) +{ + u32 in[16]; + register u32 A = ctx->A; + register u32 B = ctx->B; + register u32 C = ctx->C; + register u32 D = ctx->D; + +#ifdef WORDS_BIGENDIAN + { + int i; + byte *p2; + const byte *p1; + for(i=0, p1=data, p2=(byte*)in; i < 16; i++, p2 += 4 ) + { + p2[3] = *p1++; + p2[2] = *p1++; + p2[1] = *p1++; + p2[0] = *p1++; + } + } +#else + memcpy (in, data, 64); +#endif + + /* Round 1. */ +#define function(a,b,c,d,k,s) a=rol(a+F(b,c,d)+in[k],s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 1, 7); + function(C,D,A,B, 2,11); + function(B,C,D,A, 3,19); + function(A,B,C,D, 4, 3); + function(D,A,B,C, 5, 7); + function(C,D,A,B, 6,11); + function(B,C,D,A, 7,19); + function(A,B,C,D, 8, 3); + function(D,A,B,C, 9, 7); + function(C,D,A,B,10,11); + function(B,C,D,A,11,19); + function(A,B,C,D,12, 3); + function(D,A,B,C,13, 7); + function(C,D,A,B,14,11); + function(B,C,D,A,15,19); + +#undef function + + /* Round 2. */ +#define function(a,b,c,d,k,s) a=rol(a+G(b,c,d)+in[k]+0x5a827999,s); + + function(A,B,C,D, 0, 3); + function(D,A,B,C, 4, 5); + function(C,D,A,B, 8, 9); + function(B,C,D,A,12,13); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 5, 5); + function(C,D,A,B, 9, 9); + function(B,C,D,A,13,13); + function(A,B,C,D, 2, 3); + function(D,A,B,C, 6, 5); + function(C,D,A,B,10, 9); + function(B,C,D,A,14,13); + function(A,B,C,D, 3, 3); + function(D,A,B,C, 7, 5); + function(C,D,A,B,11, 9); + function(B,C,D,A,15,13); + +#undef function + + /* Round 3. */ +#define function(a,b,c,d,k,s) a=rol(a+H(b,c,d)+in[k]+0x6ed9eba1,s); + + function(A,B,C,D, 0, 3); + function(D,A,B,C, 8, 9); + function(C,D,A,B, 4,11); + function(B,C,D,A,12,15); + function(A,B,C,D, 2, 3); + function(D,A,B,C,10, 9); + function(C,D,A,B, 6,11); + function(B,C,D,A,14,15); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 9, 9); + function(C,D,A,B, 5,11); + function(B,C,D,A,13,15); + function(A,B,C,D, 3, 3); + function(D,A,B,C,11, 9); + function(C,D,A,B, 7,11); + function(B,C,D,A,15,15); + + + /* Put checksum in context given as argument. */ + ctx->A += A; + ctx->B += B; + ctx->C += C; + ctx->D += D; +} + + + +/* The routine updates the message-digest context to + * account for the presence of each of the characters inBuf[0..inLen-1] + * in the message whose digest is being computed. + */ +static void +md4_write ( void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + MD4_CONTEXT *hd = context; + + if( hd->count == 64 ) /* flush the buffer */ + { + transform( hd, hd->buf ); + _gcry_burn_stack (80+6*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + + if( hd->count ) + { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + md4_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + _gcry_burn_stack (80+6*sizeof(void*)); + + while( inlen >= 64 ) + { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; +} + + + +/* The routine final terminates the message-digest computation and + * ends with the desired message digest in mdContext->digest[0...15]. + * The handle is prepared for a new MD4 cycle. + * Returns 16 bytes representing the digest. + */ + +static void +md4_final( void *context ) +{ + MD4_CONTEXT *hd = context; + u32 t, msb, lsb; + byte *p; + + md4_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) /* enough room */ + { + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else /* need one extra block */ + { + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + md4_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + _gcry_burn_stack (80+6*sizeof(void*)); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ + *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0) +#else /* little endian */ +#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0) +#endif + X(A); + X(B); + X(C); + X(D); +#undef X + +} + +static byte * +md4_read (void *context) +{ + MD4_CONTEXT *hd = context; + return hd->buf; +} + +static byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */ + { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, + 0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 }; + +static gcry_md_oid_spec_t oid_spec_md4[] = + { + /* iso.member-body.us.rsadsi.digestAlgorithm.md4 */ + { "1.2.840.113549.2.4" }, + { NULL }, + }; + +gcry_md_spec_t _gcry_digest_spec_md4 = + { + "MD4", asn, DIM (asn), oid_spec_md4,16, + md4_init, md4_write, md4_final, md4_read, + sizeof (MD4_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_md4", +#endif + .blocksize = 64 + }; + + +GRUB_MOD_INIT(gcry_md4) +{ + COMPILE_TIME_ASSERT(sizeof (MD4_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + grub_md_register (&_gcry_digest_spec_md4); +} + +GRUB_MOD_FINI(gcry_md4) +{ + grub_md_unregister (&_gcry_digest_spec_md4); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/md5.c b/grub-core/lib/libgcrypt-grub/cipher/md5.c new file mode 100644 index 0000000..e5b6acc --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/md5.c @@ -0,0 +1,372 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* md5.c - MD5 Message-Digest Algorithm + * Copyright (C) 1995,1996,1998,1999,2001,2002, + * 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * According to the definition of MD5 in RFC 1321 from April 1992. + * NOTE: This is *not* the same file as the one from glibc. + * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. + * heavily modified for GnuPG by Werner Koch <wk@gnupg.org> + */ + +/* Test values: + * "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E + * "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61 + * "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72 + * "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0 + */ + + +#include "g10lib.h" +#include "cipher.h" + +#include "bithelp.h" + + +typedef struct { + u32 A,B,C,D; /* chaining variables */ + u32 nblocks; + byte buf[64]; + int count; +} MD5_CONTEXT; + + +static void +md5_init( void *context ) +{ + MD5_CONTEXT *ctx = context; + + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->nblocks = 0; + ctx->count = 0; +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + + +/**************** + * transform n*64 bytes + */ +static void +transform ( MD5_CONTEXT *ctx, const unsigned char *data ) +{ + u32 correct_words[16]; + register u32 A = ctx->A; + register u32 B = ctx->B; + register u32 C = ctx->C; + register u32 D = ctx->D; + u32 *cwp = correct_words; + +#ifdef WORDS_BIGENDIAN + { + int i; + byte *p2; + const byte *p1; + for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) + { + p2[3] = *p1++; + p2[2] = *p1++; + p2[1] = *p1++; + p2[0] = *p1++; + } + } +#else + memcpy( correct_words, data, 64 ); +#endif + + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++) + T; \ + a = rol(a, s); \ + a += b; \ + } \ + while (0) + + /* Before we start, one word about the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + a = rol(a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Put checksum in context given as argument. */ + ctx->A += A; + ctx->B += B; + ctx->C += C; + ctx->D += D; +} + + + +/* The routine updates the message-digest context to + * account for the presence of each of the characters inBuf[0..inLen-1] + * in the message whose digest is being computed. + */ +static void +md5_write( void *context, const void *inbuf_arg , size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + MD5_CONTEXT *hd = context; + + if( hd->count == 64 ) /* flush the buffer */ + { + transform( hd, hd->buf ); + _gcry_burn_stack (80+6*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + + if( hd->count ) + { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + md5_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + _gcry_burn_stack (80+6*sizeof(void*)); + + while( inlen >= 64 ) + { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + +} + + + +/* The routine final terminates the message-digest computation and + * ends with the desired message digest in mdContext->digest[0...15]. + * The handle is prepared for a new MD5 cycle. + * Returns 16 bytes representing the digest. + */ + +static void +md5_final( void *context) +{ + MD5_CONTEXT *hd = context; + u32 t, msb, lsb; + byte *p; + + md5_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) /* enough room */ + { + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else /* need one extra block */ + { + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + md5_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + _gcry_burn_stack (80+6*sizeof(void*)); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ + *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0) +#else /* little endian */ +#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0) +#endif + X(A); + X(B); + X(C); + X(D); +#undef X + +} + +static byte * +md5_read( void *context ) +{ + MD5_CONTEXT *hd = (MD5_CONTEXT *) context; + return hd->buf; +} + +static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */ + { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, + 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; + +static gcry_md_oid_spec_t oid_spec_md5[] = + { + /* iso.member-body.us.rsadsi.pkcs.pkcs-1.4 (md5WithRSAEncryption) */ + { "1.2.840.113549.1.1.4" }, + /* RSADSI digestAlgorithm MD5 */ + { "1.2.840.113549.2.5" }, + { NULL }, + }; + +gcry_md_spec_t _gcry_digest_spec_md5 = + { + "MD5", asn, DIM (asn), oid_spec_md5, 16, + md5_init, md5_write, md5_final, md5_read, + sizeof (MD5_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_md5", +#endif + .blocksize = 64 + }; + + +GRUB_MOD_INIT(gcry_md5) +{ + COMPILE_TIME_ASSERT(sizeof (MD5_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + grub_md_register (&_gcry_digest_spec_md5); +} + +GRUB_MOD_FINI(gcry_md5) +{ + grub_md_unregister (&_gcry_digest_spec_md5); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/memory.h b/grub-core/lib/libgcrypt-grub/cipher/memory.h new file mode 100644 index 0000000..49cc16a --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/memory.h @@ -0,0 +1 @@ +#include <cipher_wrap.h> diff --git a/grub-core/lib/libgcrypt-grub/cipher/rfc2268.c b/grub-core/lib/libgcrypt-grub/cipher/rfc2268.c new file mode 100644 index 0000000..c5c4a4b --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/rfc2268.c @@ -0,0 +1,285 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* rfc2268.c - The cipher described in rfc2268; aka Ron's Cipher 2. + * Copyright (C) 2003 Nikos Mavroyanopoulos + * Copyright (C) 2004 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* This implementation was written by Nikos Mavroyanopoulos for GNUTLS + * as a Libgcrypt module (gnutls/lib/x509/rc2.c) and later adapted for + * direct use by Libgcrypt by Werner Koch. This implementation is + * only useful for pkcs#12 decryption. + * + * The implementation here is based on Peter Gutmann's RRC.2 paper. + */ + + +#include "g10lib.h" +#include "types.h" +#include "cipher.h" + +#define RFC2268_BLOCKSIZE 8 + +typedef struct +{ + u16 S[64]; +} RFC2268_context; + +static const unsigned char rfc2268_sbox[] = { + 217, 120, 249, 196, 25, 221, 181, 237, + 40, 233, 253, 121, 74, 160, 216, 157, + 198, 126, 55, 131, 43, 118, 83, 142, + 98, 76, 100, 136, 68, 139, 251, 162, + 23, 154, 89, 245, 135, 179, 79, 19, + 97, 69, 109, 141, 9, 129, 125, 50, + 189, 143, 64, 235, 134, 183, 123, 11, + 240, 149, 33, 34, 92, 107, 78, 130, + 84, 214, 101, 147, 206, 96, 178, 28, + 115, 86, 192, 20, 167, 140, 241, 220, + 18, 117, 202, 31, 59, 190, 228, 209, + 66, 61, 212, 48, 163, 60, 182, 38, + 111, 191, 14, 218, 70, 105, 7, 87, + 39, 242, 29, 155, 188, 148, 67, 3, + 248, 17, 199, 246, 144, 239, 62, 231, + 6, 195, 213, 47, 200, 102, 30, 215, + 8, 232, 234, 222, 128, 82, 238, 247, + 132, 170, 114, 172, 53, 77, 106, 42, + 150, 26, 210, 113, 90, 21, 73, 116, + 75, 159, 208, 94, 4, 24, 164, 236, + 194, 224, 65, 110, 15, 81, 203, 204, + 36, 145, 175, 80, 161, 244, 112, 57, + 153, 124, 58, 133, 35, 184, 180, 122, + 252, 2, 54, 91, 37, 85, 151, 49, + 45, 93, 250, 152, 227, 138, 146, 174, + 5, 223, 41, 16, 103, 108, 186, 201, + 211, 0, 230, 207, 225, 158, 168, 44, + 99, 22, 1, 63, 88, 226, 137, 169, + 13, 56, 52, 27, 171, 51, 255, 176, + 187, 72, 12, 95, 185, 177, 205, 46, + 197, 243, 219, 71, 229, 165, 156, 119, + 10, 166, 32, 104, 254, 127, 193, 173 +}; + +#define rotl16(x,n) (((x) << ((u16)(n))) | ((x) >> (16 - (u16)(n)))) +#define rotr16(x,n) (((x) >> ((u16)(n))) | ((x) << (16 - (u16)(n)))) + + + +static void +do_encrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) +{ + RFC2268_context *ctx = context; + register int i, j; + u16 word0 = 0, word1 = 0, word2 = 0, word3 = 0; + + word0 = (word0 << 8) | inbuf[1]; + word0 = (word0 << 8) | inbuf[0]; + word1 = (word1 << 8) | inbuf[3]; + word1 = (word1 << 8) | inbuf[2]; + word2 = (word2 << 8) | inbuf[5]; + word2 = (word2 << 8) | inbuf[4]; + word3 = (word3 << 8) | inbuf[7]; + word3 = (word3 << 8) | inbuf[6]; + + for (i = 0; i < 16; i++) + { + j = i * 4; + /* For some reason I cannot combine those steps. */ + word0 += (word1 & ~word3) + (word2 & word3) + ctx->S[j]; + word0 = rotl16(word0, 1); + + word1 += (word2 & ~word0) + (word3 & word0) + ctx->S[j + 1]; + word1 = rotl16(word1, 2); + + word2 += (word3 & ~word1) + (word0 & word1) + ctx->S[j + 2]; + word2 = rotl16(word2, 3); + + word3 += (word0 & ~word2) + (word1 & word2) + ctx->S[j + 3]; + word3 = rotl16(word3, 5); + + if (i == 4 || i == 10) + { + word0 += ctx->S[word3 & 63]; + word1 += ctx->S[word0 & 63]; + word2 += ctx->S[word1 & 63]; + word3 += ctx->S[word2 & 63]; + } + + } + + outbuf[0] = word0 & 255; + outbuf[1] = word0 >> 8; + outbuf[2] = word1 & 255; + outbuf[3] = word1 >> 8; + outbuf[4] = word2 & 255; + outbuf[5] = word2 >> 8; + outbuf[6] = word3 & 255; + outbuf[7] = word3 >> 8; +} + +static void +do_decrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) +{ + RFC2268_context *ctx = context; + register int i, j; + u16 word0 = 0, word1 = 0, word2 = 0, word3 = 0; + + word0 = (word0 << 8) | inbuf[1]; + word0 = (word0 << 8) | inbuf[0]; + word1 = (word1 << 8) | inbuf[3]; + word1 = (word1 << 8) | inbuf[2]; + word2 = (word2 << 8) | inbuf[5]; + word2 = (word2 << 8) | inbuf[4]; + word3 = (word3 << 8) | inbuf[7]; + word3 = (word3 << 8) | inbuf[6]; + + for (i = 15; i >= 0; i--) + { + j = i * 4; + + word3 = rotr16(word3, 5); + word3 -= (word0 & ~word2) + (word1 & word2) + ctx->S[j + 3]; + + word2 = rotr16(word2, 3); + word2 -= (word3 & ~word1) + (word0 & word1) + ctx->S[j + 2]; + + word1 = rotr16(word1, 2); + word1 -= (word2 & ~word0) + (word3 & word0) + ctx->S[j + 1]; + + word0 = rotr16(word0, 1); + word0 -= (word1 & ~word3) + (word2 & word3) + ctx->S[j]; + + if (i == 5 || i == 11) + { + word3 = word3 - ctx->S[word2 & 63]; + word2 = word2 - ctx->S[word1 & 63]; + word1 = word1 - ctx->S[word0 & 63]; + word0 = word0 - ctx->S[word3 & 63]; + } + + } + + outbuf[0] = word0 & 255; + outbuf[1] = word0 >> 8; + outbuf[2] = word1 & 255; + outbuf[3] = word1 >> 8; + outbuf[4] = word2 & 255; + outbuf[5] = word2 >> 8; + outbuf[6] = word3 & 255; + outbuf[7] = word3 >> 8; +} + + +static gpg_err_code_t +setkey_core (void *context, const unsigned char *key, unsigned int keylen, int with_phase2) +{ + static int initialized; + static const char *selftest_failed; + RFC2268_context *ctx = context; + unsigned int i; + unsigned char *S, x; + int len; + int bits = keylen * 8; + + if (!initialized) + { + initialized = 1; + selftest_failed = selftest (); + if (selftest_failed) + log_error ("RFC2268 selftest failed (%s).\n", selftest_failed); + } + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + if (keylen < 40 / 8) /* We want at least 40 bits. */ + return GPG_ERR_INV_KEYLEN; + + S = (unsigned char *) ctx->S; + + for (i = 0; i < keylen; i++) + S[i] = key[i]; + + for (i = keylen; i < 128; i++) + S[i] = rfc2268_sbox[(S[i - keylen] + S[i - 1]) & 255]; + + S[0] = rfc2268_sbox[S[0]]; + + /* Phase 2 - reduce effective key size to "bits". This was not + * discussed in Gutmann's paper. I've copied that from the public + * domain code posted in sci.crypt. */ + if (with_phase2) + { + len = (bits + 7) >> 3; + i = 128 - len; + x = rfc2268_sbox[S[i] & (255 >> (7 & -bits))]; + S[i] = x; + + while (i--) + { + x = rfc2268_sbox[x ^ S[i + len]]; + S[i] = x; + } + } + + /* Make the expanded key, endian independent. */ + for (i = 0; i < 64; i++) + ctx->S[i] = ( (u16) S[i * 2] | (((u16) S[i * 2 + 1]) << 8)); + + return 0; +} + +static gpg_err_code_t +do_setkey (void *context, const unsigned char *key, unsigned int keylen) +{ + return setkey_core (context, key, keylen, 1); +} + + + + +static gcry_cipher_oid_spec_t oids_rfc2268_40[] = + { + /*{ "1.2.840.113549.3.2", GCRY_CIPHER_MODE_CBC },*/ + /* pbeWithSHAAnd40BitRC2_CBC */ + { "1.2.840.113549.1.12.1.6", GCRY_CIPHER_MODE_CBC }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_40 = { + "RFC2268_40", NULL, oids_rfc2268_40, + RFC2268_BLOCKSIZE, 40, sizeof(RFC2268_context), + do_setkey, do_encrypt, do_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_rfc2268", +#endif +}; + + +GRUB_MOD_INIT(gcry_rfc2268) +{ + grub_cipher_register (&_gcry_cipher_spec_rfc2268_40); +} + +GRUB_MOD_FINI(gcry_rfc2268) +{ + grub_cipher_unregister (&_gcry_cipher_spec_rfc2268_40); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/rijndael-tables.h b/grub-core/lib/libgcrypt-grub/cipher/rijndael-tables.h new file mode 100644 index 0000000..8027db6 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/rijndael-tables.h @@ -0,0 +1,1689 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +/* rijndael-tables.h - Rijndael (AES) for GnuPG, + * Copyright (C) 2000, 2001, 2002, 2003, 2007, + * 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* To keep the actual implementation at a readable size we use this + include file to define the tables. */ + +static const unsigned char S[256] = + { + 99, 124, 119, 123, 242, 107, 111, 197, + 48, 1, 103, 43, 254, 215, 171, 118, + 202, 130, 201, 125, 250, 89, 71, 240, + 173, 212, 162, 175, 156, 164, 114, 192, + 183, 253, 147, 38, 54, 63, 247, 204, + 52, 165, 229, 241, 113, 216, 49, 21, + 4, 199, 35, 195, 24, 150, 5, 154, + 7, 18, 128, 226, 235, 39, 178, 117, + 9, 131, 44, 26, 27, 110, 90, 160, + 82, 59, 214, 179, 41, 227, 47, 132, + 83, 209, 0, 237, 32, 252, 177, 91, + 106, 203, 190, 57, 74, 76, 88, 207, + 208, 239, 170, 251, 67, 77, 51, 133, + 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, + 188, 182, 218, 33, 16, 255, 243, 210, + 205, 12, 19, 236, 95, 151, 68, 23, + 196, 167, 126, 61, 100, 93, 25, 115, + 96, 129, 79, 220, 34, 42, 144, 136, + 70, 238, 184, 20, 222, 94, 11, 219, + 224, 50, 58, 10, 73, 6, 36, 92, + 194, 211, 172, 98, 145, 149, 228, 121, + 231, 200, 55, 109, 141, 213, 78, 169, + 108, 86, 244, 234, 101, 122, 174, 8, + 186, 120, 37, 46, 28, 166, 180, 198, + 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, + 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, + 155, 30, 135, 233, 206, 85, 40, 223, + 140, 161, 137, 13, 191, 230, 66, 104, + 65, 153, 45, 15, 176, 84, 187, 22 + }; + + +static const unsigned char T1[256][4] = + { + { 0xc6,0x63,0x63,0xa5 }, { 0xf8,0x7c,0x7c,0x84 }, + { 0xee,0x77,0x77,0x99 }, { 0xf6,0x7b,0x7b,0x8d }, + { 0xff,0xf2,0xf2,0x0d }, { 0xd6,0x6b,0x6b,0xbd }, + { 0xde,0x6f,0x6f,0xb1 }, { 0x91,0xc5,0xc5,0x54 }, + { 0x60,0x30,0x30,0x50 }, { 0x02,0x01,0x01,0x03 }, + { 0xce,0x67,0x67,0xa9 }, { 0x56,0x2b,0x2b,0x7d }, + { 0xe7,0xfe,0xfe,0x19 }, { 0xb5,0xd7,0xd7,0x62 }, + { 0x4d,0xab,0xab,0xe6 }, { 0xec,0x76,0x76,0x9a }, + { 0x8f,0xca,0xca,0x45 }, { 0x1f,0x82,0x82,0x9d }, + { 0x89,0xc9,0xc9,0x40 }, { 0xfa,0x7d,0x7d,0x87 }, + { 0xef,0xfa,0xfa,0x15 }, { 0xb2,0x59,0x59,0xeb }, + { 0x8e,0x47,0x47,0xc9 }, { 0xfb,0xf0,0xf0,0x0b }, + { 0x41,0xad,0xad,0xec }, { 0xb3,0xd4,0xd4,0x67 }, + { 0x5f,0xa2,0xa2,0xfd }, { 0x45,0xaf,0xaf,0xea }, + { 0x23,0x9c,0x9c,0xbf }, { 0x53,0xa4,0xa4,0xf7 }, + { 0xe4,0x72,0x72,0x96 }, { 0x9b,0xc0,0xc0,0x5b }, + { 0x75,0xb7,0xb7,0xc2 }, { 0xe1,0xfd,0xfd,0x1c }, + { 0x3d,0x93,0x93,0xae }, { 0x4c,0x26,0x26,0x6a }, + { 0x6c,0x36,0x36,0x5a }, { 0x7e,0x3f,0x3f,0x41 }, + { 0xf5,0xf7,0xf7,0x02 }, { 0x83,0xcc,0xcc,0x4f }, + { 0x68,0x34,0x34,0x5c }, { 0x51,0xa5,0xa5,0xf4 }, + { 0xd1,0xe5,0xe5,0x34 }, { 0xf9,0xf1,0xf1,0x08 }, + { 0xe2,0x71,0x71,0x93 }, { 0xab,0xd8,0xd8,0x73 }, + { 0x62,0x31,0x31,0x53 }, { 0x2a,0x15,0x15,0x3f }, + { 0x08,0x04,0x04,0x0c }, { 0x95,0xc7,0xc7,0x52 }, + { 0x46,0x23,0x23,0x65 }, { 0x9d,0xc3,0xc3,0x5e }, + { 0x30,0x18,0x18,0x28 }, { 0x37,0x96,0x96,0xa1 }, + { 0x0a,0x05,0x05,0x0f }, { 0x2f,0x9a,0x9a,0xb5 }, + { 0x0e,0x07,0x07,0x09 }, { 0x24,0x12,0x12,0x36 }, + { 0x1b,0x80,0x80,0x9b }, { 0xdf,0xe2,0xe2,0x3d }, + { 0xcd,0xeb,0xeb,0x26 }, { 0x4e,0x27,0x27,0x69 }, + { 0x7f,0xb2,0xb2,0xcd }, { 0xea,0x75,0x75,0x9f }, + { 0x12,0x09,0x09,0x1b }, { 0x1d,0x83,0x83,0x9e }, + { 0x58,0x2c,0x2c,0x74 }, { 0x34,0x1a,0x1a,0x2e }, + { 0x36,0x1b,0x1b,0x2d }, { 0xdc,0x6e,0x6e,0xb2 }, + { 0xb4,0x5a,0x5a,0xee }, { 0x5b,0xa0,0xa0,0xfb }, + { 0xa4,0x52,0x52,0xf6 }, { 0x76,0x3b,0x3b,0x4d }, + { 0xb7,0xd6,0xd6,0x61 }, { 0x7d,0xb3,0xb3,0xce }, + { 0x52,0x29,0x29,0x7b }, { 0xdd,0xe3,0xe3,0x3e }, + { 0x5e,0x2f,0x2f,0x71 }, { 0x13,0x84,0x84,0x97 }, + { 0xa6,0x53,0x53,0xf5 }, { 0xb9,0xd1,0xd1,0x68 }, + { 0x00,0x00,0x00,0x00 }, { 0xc1,0xed,0xed,0x2c }, + { 0x40,0x20,0x20,0x60 }, { 0xe3,0xfc,0xfc,0x1f }, + { 0x79,0xb1,0xb1,0xc8 }, { 0xb6,0x5b,0x5b,0xed }, + { 0xd4,0x6a,0x6a,0xbe }, { 0x8d,0xcb,0xcb,0x46 }, + { 0x67,0xbe,0xbe,0xd9 }, { 0x72,0x39,0x39,0x4b }, + { 0x94,0x4a,0x4a,0xde }, { 0x98,0x4c,0x4c,0xd4 }, + { 0xb0,0x58,0x58,0xe8 }, { 0x85,0xcf,0xcf,0x4a }, + { 0xbb,0xd0,0xd0,0x6b }, { 0xc5,0xef,0xef,0x2a }, + { 0x4f,0xaa,0xaa,0xe5 }, { 0xed,0xfb,0xfb,0x16 }, + { 0x86,0x43,0x43,0xc5 }, { 0x9a,0x4d,0x4d,0xd7 }, + { 0x66,0x33,0x33,0x55 }, { 0x11,0x85,0x85,0x94 }, + { 0x8a,0x45,0x45,0xcf }, { 0xe9,0xf9,0xf9,0x10 }, + { 0x04,0x02,0x02,0x06 }, { 0xfe,0x7f,0x7f,0x81 }, + { 0xa0,0x50,0x50,0xf0 }, { 0x78,0x3c,0x3c,0x44 }, + { 0x25,0x9f,0x9f,0xba }, { 0x4b,0xa8,0xa8,0xe3 }, + { 0xa2,0x51,0x51,0xf3 }, { 0x5d,0xa3,0xa3,0xfe }, + { 0x80,0x40,0x40,0xc0 }, { 0x05,0x8f,0x8f,0x8a }, + { 0x3f,0x92,0x92,0xad }, { 0x21,0x9d,0x9d,0xbc }, + { 0x70,0x38,0x38,0x48 }, { 0xf1,0xf5,0xf5,0x04 }, + { 0x63,0xbc,0xbc,0xdf }, { 0x77,0xb6,0xb6,0xc1 }, + { 0xaf,0xda,0xda,0x75 }, { 0x42,0x21,0x21,0x63 }, + { 0x20,0x10,0x10,0x30 }, { 0xe5,0xff,0xff,0x1a }, + { 0xfd,0xf3,0xf3,0x0e }, { 0xbf,0xd2,0xd2,0x6d }, + { 0x81,0xcd,0xcd,0x4c }, { 0x18,0x0c,0x0c,0x14 }, + { 0x26,0x13,0x13,0x35 }, { 0xc3,0xec,0xec,0x2f }, + { 0xbe,0x5f,0x5f,0xe1 }, { 0x35,0x97,0x97,0xa2 }, + { 0x88,0x44,0x44,0xcc }, { 0x2e,0x17,0x17,0x39 }, + { 0x93,0xc4,0xc4,0x57 }, { 0x55,0xa7,0xa7,0xf2 }, + { 0xfc,0x7e,0x7e,0x82 }, { 0x7a,0x3d,0x3d,0x47 }, + { 0xc8,0x64,0x64,0xac }, { 0xba,0x5d,0x5d,0xe7 }, + { 0x32,0x19,0x19,0x2b }, { 0xe6,0x73,0x73,0x95 }, + { 0xc0,0x60,0x60,0xa0 }, { 0x19,0x81,0x81,0x98 }, + { 0x9e,0x4f,0x4f,0xd1 }, { 0xa3,0xdc,0xdc,0x7f }, + { 0x44,0x22,0x22,0x66 }, { 0x54,0x2a,0x2a,0x7e }, + { 0x3b,0x90,0x90,0xab }, { 0x0b,0x88,0x88,0x83 }, + { 0x8c,0x46,0x46,0xca }, { 0xc7,0xee,0xee,0x29 }, + { 0x6b,0xb8,0xb8,0xd3 }, { 0x28,0x14,0x14,0x3c }, + { 0xa7,0xde,0xde,0x79 }, { 0xbc,0x5e,0x5e,0xe2 }, + { 0x16,0x0b,0x0b,0x1d }, { 0xad,0xdb,0xdb,0x76 }, + { 0xdb,0xe0,0xe0,0x3b }, { 0x64,0x32,0x32,0x56 }, + { 0x74,0x3a,0x3a,0x4e }, { 0x14,0x0a,0x0a,0x1e }, + { 0x92,0x49,0x49,0xdb }, { 0x0c,0x06,0x06,0x0a }, + { 0x48,0x24,0x24,0x6c }, { 0xb8,0x5c,0x5c,0xe4 }, + { 0x9f,0xc2,0xc2,0x5d }, { 0xbd,0xd3,0xd3,0x6e }, + { 0x43,0xac,0xac,0xef }, { 0xc4,0x62,0x62,0xa6 }, + { 0x39,0x91,0x91,0xa8 }, { 0x31,0x95,0x95,0xa4 }, + { 0xd3,0xe4,0xe4,0x37 }, { 0xf2,0x79,0x79,0x8b }, + { 0xd5,0xe7,0xe7,0x32 }, { 0x8b,0xc8,0xc8,0x43 }, + { 0x6e,0x37,0x37,0x59 }, { 0xda,0x6d,0x6d,0xb7 }, + { 0x01,0x8d,0x8d,0x8c }, { 0xb1,0xd5,0xd5,0x64 }, + { 0x9c,0x4e,0x4e,0xd2 }, { 0x49,0xa9,0xa9,0xe0 }, + { 0xd8,0x6c,0x6c,0xb4 }, { 0xac,0x56,0x56,0xfa }, + { 0xf3,0xf4,0xf4,0x07 }, { 0xcf,0xea,0xea,0x25 }, + { 0xca,0x65,0x65,0xaf }, { 0xf4,0x7a,0x7a,0x8e }, + { 0x47,0xae,0xae,0xe9 }, { 0x10,0x08,0x08,0x18 }, + { 0x6f,0xba,0xba,0xd5 }, { 0xf0,0x78,0x78,0x88 }, + { 0x4a,0x25,0x25,0x6f }, { 0x5c,0x2e,0x2e,0x72 }, + { 0x38,0x1c,0x1c,0x24 }, { 0x57,0xa6,0xa6,0xf1 }, + { 0x73,0xb4,0xb4,0xc7 }, { 0x97,0xc6,0xc6,0x51 }, + { 0xcb,0xe8,0xe8,0x23 }, { 0xa1,0xdd,0xdd,0x7c }, + { 0xe8,0x74,0x74,0x9c }, { 0x3e,0x1f,0x1f,0x21 }, + { 0x96,0x4b,0x4b,0xdd }, { 0x61,0xbd,0xbd,0xdc }, + { 0x0d,0x8b,0x8b,0x86 }, { 0x0f,0x8a,0x8a,0x85 }, + { 0xe0,0x70,0x70,0x90 }, { 0x7c,0x3e,0x3e,0x42 }, + { 0x71,0xb5,0xb5,0xc4 }, { 0xcc,0x66,0x66,0xaa }, + { 0x90,0x48,0x48,0xd8 }, { 0x06,0x03,0x03,0x05 }, + { 0xf7,0xf6,0xf6,0x01 }, { 0x1c,0x0e,0x0e,0x12 }, + { 0xc2,0x61,0x61,0xa3 }, { 0x6a,0x35,0x35,0x5f }, + { 0xae,0x57,0x57,0xf9 }, { 0x69,0xb9,0xb9,0xd0 }, + { 0x17,0x86,0x86,0x91 }, { 0x99,0xc1,0xc1,0x58 }, + { 0x3a,0x1d,0x1d,0x27 }, { 0x27,0x9e,0x9e,0xb9 }, + { 0xd9,0xe1,0xe1,0x38 }, { 0xeb,0xf8,0xf8,0x13 }, + { 0x2b,0x98,0x98,0xb3 }, { 0x22,0x11,0x11,0x33 }, + { 0xd2,0x69,0x69,0xbb }, { 0xa9,0xd9,0xd9,0x70 }, + { 0x07,0x8e,0x8e,0x89 }, { 0x33,0x94,0x94,0xa7 }, + { 0x2d,0x9b,0x9b,0xb6 }, { 0x3c,0x1e,0x1e,0x22 }, + { 0x15,0x87,0x87,0x92 }, { 0xc9,0xe9,0xe9,0x20 }, + { 0x87,0xce,0xce,0x49 }, { 0xaa,0x55,0x55,0xff }, + { 0x50,0x28,0x28,0x78 }, { 0xa5,0xdf,0xdf,0x7a }, + { 0x03,0x8c,0x8c,0x8f }, { 0x59,0xa1,0xa1,0xf8 }, + { 0x09,0x89,0x89,0x80 }, { 0x1a,0x0d,0x0d,0x17 }, + { 0x65,0xbf,0xbf,0xda }, { 0xd7,0xe6,0xe6,0x31 }, + { 0x84,0x42,0x42,0xc6 }, { 0xd0,0x68,0x68,0xb8 }, + { 0x82,0x41,0x41,0xc3 }, { 0x29,0x99,0x99,0xb0 }, + { 0x5a,0x2d,0x2d,0x77 }, { 0x1e,0x0f,0x0f,0x11 }, + { 0x7b,0xb0,0xb0,0xcb }, { 0xa8,0x54,0x54,0xfc }, + { 0x6d,0xbb,0xbb,0xd6 }, { 0x2c,0x16,0x16,0x3a } + }; + +static const unsigned char T2[256][4] = + { + { 0xa5,0xc6,0x63,0x63 }, { 0x84,0xf8,0x7c,0x7c }, + { 0x99,0xee,0x77,0x77 }, { 0x8d,0xf6,0x7b,0x7b }, + { 0x0d,0xff,0xf2,0xf2 }, { 0xbd,0xd6,0x6b,0x6b }, + { 0xb1,0xde,0x6f,0x6f }, { 0x54,0x91,0xc5,0xc5 }, + { 0x50,0x60,0x30,0x30 }, { 0x03,0x02,0x01,0x01 }, + { 0xa9,0xce,0x67,0x67 }, { 0x7d,0x56,0x2b,0x2b }, + { 0x19,0xe7,0xfe,0xfe }, { 0x62,0xb5,0xd7,0xd7 }, + { 0xe6,0x4d,0xab,0xab }, { 0x9a,0xec,0x76,0x76 }, + { 0x45,0x8f,0xca,0xca }, { 0x9d,0x1f,0x82,0x82 }, + { 0x40,0x89,0xc9,0xc9 }, { 0x87,0xfa,0x7d,0x7d }, + { 0x15,0xef,0xfa,0xfa }, { 0xeb,0xb2,0x59,0x59 }, + { 0xc9,0x8e,0x47,0x47 }, { 0x0b,0xfb,0xf0,0xf0 }, + { 0xec,0x41,0xad,0xad }, { 0x67,0xb3,0xd4,0xd4 }, + { 0xfd,0x5f,0xa2,0xa2 }, { 0xea,0x45,0xaf,0xaf }, + { 0xbf,0x23,0x9c,0x9c }, { 0xf7,0x53,0xa4,0xa4 }, + { 0x96,0xe4,0x72,0x72 }, { 0x5b,0x9b,0xc0,0xc0 }, + { 0xc2,0x75,0xb7,0xb7 }, { 0x1c,0xe1,0xfd,0xfd }, + { 0xae,0x3d,0x93,0x93 }, { 0x6a,0x4c,0x26,0x26 }, + { 0x5a,0x6c,0x36,0x36 }, { 0x41,0x7e,0x3f,0x3f }, + { 0x02,0xf5,0xf7,0xf7 }, { 0x4f,0x83,0xcc,0xcc }, + { 0x5c,0x68,0x34,0x34 }, { 0xf4,0x51,0xa5,0xa5 }, + { 0x34,0xd1,0xe5,0xe5 }, { 0x08,0xf9,0xf1,0xf1 }, + { 0x93,0xe2,0x71,0x71 }, { 0x73,0xab,0xd8,0xd8 }, + { 0x53,0x62,0x31,0x31 }, { 0x3f,0x2a,0x15,0x15 }, + { 0x0c,0x08,0x04,0x04 }, { 0x52,0x95,0xc7,0xc7 }, + { 0x65,0x46,0x23,0x23 }, { 0x5e,0x9d,0xc3,0xc3 }, + { 0x28,0x30,0x18,0x18 }, { 0xa1,0x37,0x96,0x96 }, + { 0x0f,0x0a,0x05,0x05 }, { 0xb5,0x2f,0x9a,0x9a }, + { 0x09,0x0e,0x07,0x07 }, { 0x36,0x24,0x12,0x12 }, + { 0x9b,0x1b,0x80,0x80 }, { 0x3d,0xdf,0xe2,0xe2 }, + { 0x26,0xcd,0xeb,0xeb }, { 0x69,0x4e,0x27,0x27 }, + { 0xcd,0x7f,0xb2,0xb2 }, { 0x9f,0xea,0x75,0x75 }, + { 0x1b,0x12,0x09,0x09 }, { 0x9e,0x1d,0x83,0x83 }, + { 0x74,0x58,0x2c,0x2c }, { 0x2e,0x34,0x1a,0x1a }, + { 0x2d,0x36,0x1b,0x1b }, { 0xb2,0xdc,0x6e,0x6e }, + { 0xee,0xb4,0x5a,0x5a }, { 0xfb,0x5b,0xa0,0xa0 }, + { 0xf6,0xa4,0x52,0x52 }, { 0x4d,0x76,0x3b,0x3b }, + { 0x61,0xb7,0xd6,0xd6 }, { 0xce,0x7d,0xb3,0xb3 }, + { 0x7b,0x52,0x29,0x29 }, { 0x3e,0xdd,0xe3,0xe3 }, + { 0x71,0x5e,0x2f,0x2f }, { 0x97,0x13,0x84,0x84 }, + { 0xf5,0xa6,0x53,0x53 }, { 0x68,0xb9,0xd1,0xd1 }, + { 0x00,0x00,0x00,0x00 }, { 0x2c,0xc1,0xed,0xed }, + { 0x60,0x40,0x20,0x20 }, { 0x1f,0xe3,0xfc,0xfc }, + { 0xc8,0x79,0xb1,0xb1 }, { 0xed,0xb6,0x5b,0x5b }, + { 0xbe,0xd4,0x6a,0x6a }, { 0x46,0x8d,0xcb,0xcb }, + { 0xd9,0x67,0xbe,0xbe }, { 0x4b,0x72,0x39,0x39 }, + { 0xde,0x94,0x4a,0x4a }, { 0xd4,0x98,0x4c,0x4c }, + { 0xe8,0xb0,0x58,0x58 }, { 0x4a,0x85,0xcf,0xcf }, + { 0x6b,0xbb,0xd0,0xd0 }, { 0x2a,0xc5,0xef,0xef }, + { 0xe5,0x4f,0xaa,0xaa }, { 0x16,0xed,0xfb,0xfb }, + { 0xc5,0x86,0x43,0x43 }, { 0xd7,0x9a,0x4d,0x4d }, + { 0x55,0x66,0x33,0x33 }, { 0x94,0x11,0x85,0x85 }, + { 0xcf,0x8a,0x45,0x45 }, { 0x10,0xe9,0xf9,0xf9 }, + { 0x06,0x04,0x02,0x02 }, { 0x81,0xfe,0x7f,0x7f }, + { 0xf0,0xa0,0x50,0x50 }, { 0x44,0x78,0x3c,0x3c }, + { 0xba,0x25,0x9f,0x9f }, { 0xe3,0x4b,0xa8,0xa8 }, + { 0xf3,0xa2,0x51,0x51 }, { 0xfe,0x5d,0xa3,0xa3 }, + { 0xc0,0x80,0x40,0x40 }, { 0x8a,0x05,0x8f,0x8f }, + { 0xad,0x3f,0x92,0x92 }, { 0xbc,0x21,0x9d,0x9d }, + { 0x48,0x70,0x38,0x38 }, { 0x04,0xf1,0xf5,0xf5 }, + { 0xdf,0x63,0xbc,0xbc }, { 0xc1,0x77,0xb6,0xb6 }, + { 0x75,0xaf,0xda,0xda }, { 0x63,0x42,0x21,0x21 }, + { 0x30,0x20,0x10,0x10 }, { 0x1a,0xe5,0xff,0xff }, + { 0x0e,0xfd,0xf3,0xf3 }, { 0x6d,0xbf,0xd2,0xd2 }, + { 0x4c,0x81,0xcd,0xcd }, { 0x14,0x18,0x0c,0x0c }, + { 0x35,0x26,0x13,0x13 }, { 0x2f,0xc3,0xec,0xec }, + { 0xe1,0xbe,0x5f,0x5f }, { 0xa2,0x35,0x97,0x97 }, + { 0xcc,0x88,0x44,0x44 }, { 0x39,0x2e,0x17,0x17 }, + { 0x57,0x93,0xc4,0xc4 }, { 0xf2,0x55,0xa7,0xa7 }, + { 0x82,0xfc,0x7e,0x7e }, { 0x47,0x7a,0x3d,0x3d }, + { 0xac,0xc8,0x64,0x64 }, { 0xe7,0xba,0x5d,0x5d }, + { 0x2b,0x32,0x19,0x19 }, { 0x95,0xe6,0x73,0x73 }, + { 0xa0,0xc0,0x60,0x60 }, { 0x98,0x19,0x81,0x81 }, + { 0xd1,0x9e,0x4f,0x4f }, { 0x7f,0xa3,0xdc,0xdc }, + { 0x66,0x44,0x22,0x22 }, { 0x7e,0x54,0x2a,0x2a }, + { 0xab,0x3b,0x90,0x90 }, { 0x83,0x0b,0x88,0x88 }, + { 0xca,0x8c,0x46,0x46 }, { 0x29,0xc7,0xee,0xee }, + { 0xd3,0x6b,0xb8,0xb8 }, { 0x3c,0x28,0x14,0x14 }, + { 0x79,0xa7,0xde,0xde }, { 0xe2,0xbc,0x5e,0x5e }, + { 0x1d,0x16,0x0b,0x0b }, { 0x76,0xad,0xdb,0xdb }, + { 0x3b,0xdb,0xe0,0xe0 }, { 0x56,0x64,0x32,0x32 }, + { 0x4e,0x74,0x3a,0x3a }, { 0x1e,0x14,0x0a,0x0a }, + { 0xdb,0x92,0x49,0x49 }, { 0x0a,0x0c,0x06,0x06 }, + { 0x6c,0x48,0x24,0x24 }, { 0xe4,0xb8,0x5c,0x5c }, + { 0x5d,0x9f,0xc2,0xc2 }, { 0x6e,0xbd,0xd3,0xd3 }, + { 0xef,0x43,0xac,0xac }, { 0xa6,0xc4,0x62,0x62 }, + { 0xa8,0x39,0x91,0x91 }, { 0xa4,0x31,0x95,0x95 }, + { 0x37,0xd3,0xe4,0xe4 }, { 0x8b,0xf2,0x79,0x79 }, + { 0x32,0xd5,0xe7,0xe7 }, { 0x43,0x8b,0xc8,0xc8 }, + { 0x59,0x6e,0x37,0x37 }, { 0xb7,0xda,0x6d,0x6d }, + { 0x8c,0x01,0x8d,0x8d }, { 0x64,0xb1,0xd5,0xd5 }, + { 0xd2,0x9c,0x4e,0x4e }, { 0xe0,0x49,0xa9,0xa9 }, + { 0xb4,0xd8,0x6c,0x6c }, { 0xfa,0xac,0x56,0x56 }, + { 0x07,0xf3,0xf4,0xf4 }, { 0x25,0xcf,0xea,0xea }, + { 0xaf,0xca,0x65,0x65 }, { 0x8e,0xf4,0x7a,0x7a }, + { 0xe9,0x47,0xae,0xae }, { 0x18,0x10,0x08,0x08 }, + { 0xd5,0x6f,0xba,0xba }, { 0x88,0xf0,0x78,0x78 }, + { 0x6f,0x4a,0x25,0x25 }, { 0x72,0x5c,0x2e,0x2e }, + { 0x24,0x38,0x1c,0x1c }, { 0xf1,0x57,0xa6,0xa6 }, + { 0xc7,0x73,0xb4,0xb4 }, { 0x51,0x97,0xc6,0xc6 }, + { 0x23,0xcb,0xe8,0xe8 }, { 0x7c,0xa1,0xdd,0xdd }, + { 0x9c,0xe8,0x74,0x74 }, { 0x21,0x3e,0x1f,0x1f }, + { 0xdd,0x96,0x4b,0x4b }, { 0xdc,0x61,0xbd,0xbd }, + { 0x86,0x0d,0x8b,0x8b }, { 0x85,0x0f,0x8a,0x8a }, + { 0x90,0xe0,0x70,0x70 }, { 0x42,0x7c,0x3e,0x3e }, + { 0xc4,0x71,0xb5,0xb5 }, { 0xaa,0xcc,0x66,0x66 }, + { 0xd8,0x90,0x48,0x48 }, { 0x05,0x06,0x03,0x03 }, + { 0x01,0xf7,0xf6,0xf6 }, { 0x12,0x1c,0x0e,0x0e }, + { 0xa3,0xc2,0x61,0x61 }, { 0x5f,0x6a,0x35,0x35 }, + { 0xf9,0xae,0x57,0x57 }, { 0xd0,0x69,0xb9,0xb9 }, + { 0x91,0x17,0x86,0x86 }, { 0x58,0x99,0xc1,0xc1 }, + { 0x27,0x3a,0x1d,0x1d }, { 0xb9,0x27,0x9e,0x9e }, + { 0x38,0xd9,0xe1,0xe1 }, { 0x13,0xeb,0xf8,0xf8 }, + { 0xb3,0x2b,0x98,0x98 }, { 0x33,0x22,0x11,0x11 }, + { 0xbb,0xd2,0x69,0x69 }, { 0x70,0xa9,0xd9,0xd9 }, + { 0x89,0x07,0x8e,0x8e }, { 0xa7,0x33,0x94,0x94 }, + { 0xb6,0x2d,0x9b,0x9b }, { 0x22,0x3c,0x1e,0x1e }, + { 0x92,0x15,0x87,0x87 }, { 0x20,0xc9,0xe9,0xe9 }, + { 0x49,0x87,0xce,0xce }, { 0xff,0xaa,0x55,0x55 }, + { 0x78,0x50,0x28,0x28 }, { 0x7a,0xa5,0xdf,0xdf }, + { 0x8f,0x03,0x8c,0x8c }, { 0xf8,0x59,0xa1,0xa1 }, + { 0x80,0x09,0x89,0x89 }, { 0x17,0x1a,0x0d,0x0d }, + { 0xda,0x65,0xbf,0xbf }, { 0x31,0xd7,0xe6,0xe6 }, + { 0xc6,0x84,0x42,0x42 }, { 0xb8,0xd0,0x68,0x68 }, + { 0xc3,0x82,0x41,0x41 }, { 0xb0,0x29,0x99,0x99 }, + { 0x77,0x5a,0x2d,0x2d }, { 0x11,0x1e,0x0f,0x0f }, + { 0xcb,0x7b,0xb0,0xb0 }, { 0xfc,0xa8,0x54,0x54 }, + { 0xd6,0x6d,0xbb,0xbb }, { 0x3a,0x2c,0x16,0x16 } + }; + +static const unsigned char T3[256][4] = + { + { 0x63,0xa5,0xc6,0x63 }, { 0x7c,0x84,0xf8,0x7c }, + { 0x77,0x99,0xee,0x77 }, { 0x7b,0x8d,0xf6,0x7b }, + { 0xf2,0x0d,0xff,0xf2 }, { 0x6b,0xbd,0xd6,0x6b }, + { 0x6f,0xb1,0xde,0x6f }, { 0xc5,0x54,0x91,0xc5 }, + { 0x30,0x50,0x60,0x30 }, { 0x01,0x03,0x02,0x01 }, + { 0x67,0xa9,0xce,0x67 }, { 0x2b,0x7d,0x56,0x2b }, + { 0xfe,0x19,0xe7,0xfe }, { 0xd7,0x62,0xb5,0xd7 }, + { 0xab,0xe6,0x4d,0xab }, { 0x76,0x9a,0xec,0x76 }, + { 0xca,0x45,0x8f,0xca }, { 0x82,0x9d,0x1f,0x82 }, + { 0xc9,0x40,0x89,0xc9 }, { 0x7d,0x87,0xfa,0x7d }, + { 0xfa,0x15,0xef,0xfa }, { 0x59,0xeb,0xb2,0x59 }, + { 0x47,0xc9,0x8e,0x47 }, { 0xf0,0x0b,0xfb,0xf0 }, + { 0xad,0xec,0x41,0xad }, { 0xd4,0x67,0xb3,0xd4 }, + { 0xa2,0xfd,0x5f,0xa2 }, { 0xaf,0xea,0x45,0xaf }, + { 0x9c,0xbf,0x23,0x9c }, { 0xa4,0xf7,0x53,0xa4 }, + { 0x72,0x96,0xe4,0x72 }, { 0xc0,0x5b,0x9b,0xc0 }, + { 0xb7,0xc2,0x75,0xb7 }, { 0xfd,0x1c,0xe1,0xfd }, + { 0x93,0xae,0x3d,0x93 }, { 0x26,0x6a,0x4c,0x26 }, + { 0x36,0x5a,0x6c,0x36 }, { 0x3f,0x41,0x7e,0x3f }, + { 0xf7,0x02,0xf5,0xf7 }, { 0xcc,0x4f,0x83,0xcc }, + { 0x34,0x5c,0x68,0x34 }, { 0xa5,0xf4,0x51,0xa5 }, + { 0xe5,0x34,0xd1,0xe5 }, { 0xf1,0x08,0xf9,0xf1 }, + { 0x71,0x93,0xe2,0x71 }, { 0xd8,0x73,0xab,0xd8 }, + { 0x31,0x53,0x62,0x31 }, { 0x15,0x3f,0x2a,0x15 }, + { 0x04,0x0c,0x08,0x04 }, { 0xc7,0x52,0x95,0xc7 }, + { 0x23,0x65,0x46,0x23 }, { 0xc3,0x5e,0x9d,0xc3 }, + { 0x18,0x28,0x30,0x18 }, { 0x96,0xa1,0x37,0x96 }, + { 0x05,0x0f,0x0a,0x05 }, { 0x9a,0xb5,0x2f,0x9a }, + { 0x07,0x09,0x0e,0x07 }, { 0x12,0x36,0x24,0x12 }, + { 0x80,0x9b,0x1b,0x80 }, { 0xe2,0x3d,0xdf,0xe2 }, + { 0xeb,0x26,0xcd,0xeb }, { 0x27,0x69,0x4e,0x27 }, + { 0xb2,0xcd,0x7f,0xb2 }, { 0x75,0x9f,0xea,0x75 }, + { 0x09,0x1b,0x12,0x09 }, { 0x83,0x9e,0x1d,0x83 }, + { 0x2c,0x74,0x58,0x2c }, { 0x1a,0x2e,0x34,0x1a }, + { 0x1b,0x2d,0x36,0x1b }, { 0x6e,0xb2,0xdc,0x6e }, + { 0x5a,0xee,0xb4,0x5a }, { 0xa0,0xfb,0x5b,0xa0 }, + { 0x52,0xf6,0xa4,0x52 }, { 0x3b,0x4d,0x76,0x3b }, + { 0xd6,0x61,0xb7,0xd6 }, { 0xb3,0xce,0x7d,0xb3 }, + { 0x29,0x7b,0x52,0x29 }, { 0xe3,0x3e,0xdd,0xe3 }, + { 0x2f,0x71,0x5e,0x2f }, { 0x84,0x97,0x13,0x84 }, + { 0x53,0xf5,0xa6,0x53 }, { 0xd1,0x68,0xb9,0xd1 }, + { 0x00,0x00,0x00,0x00 }, { 0xed,0x2c,0xc1,0xed }, + { 0x20,0x60,0x40,0x20 }, { 0xfc,0x1f,0xe3,0xfc }, + { 0xb1,0xc8,0x79,0xb1 }, { 0x5b,0xed,0xb6,0x5b }, + { 0x6a,0xbe,0xd4,0x6a }, { 0xcb,0x46,0x8d,0xcb }, + { 0xbe,0xd9,0x67,0xbe }, { 0x39,0x4b,0x72,0x39 }, + { 0x4a,0xde,0x94,0x4a }, { 0x4c,0xd4,0x98,0x4c }, + { 0x58,0xe8,0xb0,0x58 }, { 0xcf,0x4a,0x85,0xcf }, + { 0xd0,0x6b,0xbb,0xd0 }, { 0xef,0x2a,0xc5,0xef }, + { 0xaa,0xe5,0x4f,0xaa }, { 0xfb,0x16,0xed,0xfb }, + { 0x43,0xc5,0x86,0x43 }, { 0x4d,0xd7,0x9a,0x4d }, + { 0x33,0x55,0x66,0x33 }, { 0x85,0x94,0x11,0x85 }, + { 0x45,0xcf,0x8a,0x45 }, { 0xf9,0x10,0xe9,0xf9 }, + { 0x02,0x06,0x04,0x02 }, { 0x7f,0x81,0xfe,0x7f }, + { 0x50,0xf0,0xa0,0x50 }, { 0x3c,0x44,0x78,0x3c }, + { 0x9f,0xba,0x25,0x9f }, { 0xa8,0xe3,0x4b,0xa8 }, + { 0x51,0xf3,0xa2,0x51 }, { 0xa3,0xfe,0x5d,0xa3 }, + { 0x40,0xc0,0x80,0x40 }, { 0x8f,0x8a,0x05,0x8f }, + { 0x92,0xad,0x3f,0x92 }, { 0x9d,0xbc,0x21,0x9d }, + { 0x38,0x48,0x70,0x38 }, { 0xf5,0x04,0xf1,0xf5 }, + { 0xbc,0xdf,0x63,0xbc }, { 0xb6,0xc1,0x77,0xb6 }, + { 0xda,0x75,0xaf,0xda }, { 0x21,0x63,0x42,0x21 }, + { 0x10,0x30,0x20,0x10 }, { 0xff,0x1a,0xe5,0xff }, + { 0xf3,0x0e,0xfd,0xf3 }, { 0xd2,0x6d,0xbf,0xd2 }, + { 0xcd,0x4c,0x81,0xcd }, { 0x0c,0x14,0x18,0x0c }, + { 0x13,0x35,0x26,0x13 }, { 0xec,0x2f,0xc3,0xec }, + { 0x5f,0xe1,0xbe,0x5f }, { 0x97,0xa2,0x35,0x97 }, + { 0x44,0xcc,0x88,0x44 }, { 0x17,0x39,0x2e,0x17 }, + { 0xc4,0x57,0x93,0xc4 }, { 0xa7,0xf2,0x55,0xa7 }, + { 0x7e,0x82,0xfc,0x7e }, { 0x3d,0x47,0x7a,0x3d }, + { 0x64,0xac,0xc8,0x64 }, { 0x5d,0xe7,0xba,0x5d }, + { 0x19,0x2b,0x32,0x19 }, { 0x73,0x95,0xe6,0x73 }, + { 0x60,0xa0,0xc0,0x60 }, { 0x81,0x98,0x19,0x81 }, + { 0x4f,0xd1,0x9e,0x4f }, { 0xdc,0x7f,0xa3,0xdc }, + { 0x22,0x66,0x44,0x22 }, { 0x2a,0x7e,0x54,0x2a }, + { 0x90,0xab,0x3b,0x90 }, { 0x88,0x83,0x0b,0x88 }, + { 0x46,0xca,0x8c,0x46 }, { 0xee,0x29,0xc7,0xee }, + { 0xb8,0xd3,0x6b,0xb8 }, { 0x14,0x3c,0x28,0x14 }, + { 0xde,0x79,0xa7,0xde }, { 0x5e,0xe2,0xbc,0x5e }, + { 0x0b,0x1d,0x16,0x0b }, { 0xdb,0x76,0xad,0xdb }, + { 0xe0,0x3b,0xdb,0xe0 }, { 0x32,0x56,0x64,0x32 }, + { 0x3a,0x4e,0x74,0x3a }, { 0x0a,0x1e,0x14,0x0a }, + { 0x49,0xdb,0x92,0x49 }, { 0x06,0x0a,0x0c,0x06 }, + { 0x24,0x6c,0x48,0x24 }, { 0x5c,0xe4,0xb8,0x5c }, + { 0xc2,0x5d,0x9f,0xc2 }, { 0xd3,0x6e,0xbd,0xd3 }, + { 0xac,0xef,0x43,0xac }, { 0x62,0xa6,0xc4,0x62 }, + { 0x91,0xa8,0x39,0x91 }, { 0x95,0xa4,0x31,0x95 }, + { 0xe4,0x37,0xd3,0xe4 }, { 0x79,0x8b,0xf2,0x79 }, + { 0xe7,0x32,0xd5,0xe7 }, { 0xc8,0x43,0x8b,0xc8 }, + { 0x37,0x59,0x6e,0x37 }, { 0x6d,0xb7,0xda,0x6d }, + { 0x8d,0x8c,0x01,0x8d }, { 0xd5,0x64,0xb1,0xd5 }, + { 0x4e,0xd2,0x9c,0x4e }, { 0xa9,0xe0,0x49,0xa9 }, + { 0x6c,0xb4,0xd8,0x6c }, { 0x56,0xfa,0xac,0x56 }, + { 0xf4,0x07,0xf3,0xf4 }, { 0xea,0x25,0xcf,0xea }, + { 0x65,0xaf,0xca,0x65 }, { 0x7a,0x8e,0xf4,0x7a }, + { 0xae,0xe9,0x47,0xae }, { 0x08,0x18,0x10,0x08 }, + { 0xba,0xd5,0x6f,0xba }, { 0x78,0x88,0xf0,0x78 }, + { 0x25,0x6f,0x4a,0x25 }, { 0x2e,0x72,0x5c,0x2e }, + { 0x1c,0x24,0x38,0x1c }, { 0xa6,0xf1,0x57,0xa6 }, + { 0xb4,0xc7,0x73,0xb4 }, { 0xc6,0x51,0x97,0xc6 }, + { 0xe8,0x23,0xcb,0xe8 }, { 0xdd,0x7c,0xa1,0xdd }, + { 0x74,0x9c,0xe8,0x74 }, { 0x1f,0x21,0x3e,0x1f }, + { 0x4b,0xdd,0x96,0x4b }, { 0xbd,0xdc,0x61,0xbd }, + { 0x8b,0x86,0x0d,0x8b }, { 0x8a,0x85,0x0f,0x8a }, + { 0x70,0x90,0xe0,0x70 }, { 0x3e,0x42,0x7c,0x3e }, + { 0xb5,0xc4,0x71,0xb5 }, { 0x66,0xaa,0xcc,0x66 }, + { 0x48,0xd8,0x90,0x48 }, { 0x03,0x05,0x06,0x03 }, + { 0xf6,0x01,0xf7,0xf6 }, { 0x0e,0x12,0x1c,0x0e }, + { 0x61,0xa3,0xc2,0x61 }, { 0x35,0x5f,0x6a,0x35 }, + { 0x57,0xf9,0xae,0x57 }, { 0xb9,0xd0,0x69,0xb9 }, + { 0x86,0x91,0x17,0x86 }, { 0xc1,0x58,0x99,0xc1 }, + { 0x1d,0x27,0x3a,0x1d }, { 0x9e,0xb9,0x27,0x9e }, + { 0xe1,0x38,0xd9,0xe1 }, { 0xf8,0x13,0xeb,0xf8 }, + { 0x98,0xb3,0x2b,0x98 }, { 0x11,0x33,0x22,0x11 }, + { 0x69,0xbb,0xd2,0x69 }, { 0xd9,0x70,0xa9,0xd9 }, + { 0x8e,0x89,0x07,0x8e }, { 0x94,0xa7,0x33,0x94 }, + { 0x9b,0xb6,0x2d,0x9b }, { 0x1e,0x22,0x3c,0x1e }, + { 0x87,0x92,0x15,0x87 }, { 0xe9,0x20,0xc9,0xe9 }, + { 0xce,0x49,0x87,0xce }, { 0x55,0xff,0xaa,0x55 }, + { 0x28,0x78,0x50,0x28 }, { 0xdf,0x7a,0xa5,0xdf }, + { 0x8c,0x8f,0x03,0x8c }, { 0xa1,0xf8,0x59,0xa1 }, + { 0x89,0x80,0x09,0x89 }, { 0x0d,0x17,0x1a,0x0d }, + { 0xbf,0xda,0x65,0xbf }, { 0xe6,0x31,0xd7,0xe6 }, + { 0x42,0xc6,0x84,0x42 }, { 0x68,0xb8,0xd0,0x68 }, + { 0x41,0xc3,0x82,0x41 }, { 0x99,0xb0,0x29,0x99 }, + { 0x2d,0x77,0x5a,0x2d }, { 0x0f,0x11,0x1e,0x0f }, + { 0xb0,0xcb,0x7b,0xb0 }, { 0x54,0xfc,0xa8,0x54 }, + { 0xbb,0xd6,0x6d,0xbb }, { 0x16,0x3a,0x2c,0x16 } + }; + +static const unsigned char T4[256][4] = + { + { 0x63,0x63,0xa5,0xc6 }, { 0x7c,0x7c,0x84,0xf8 }, + { 0x77,0x77,0x99,0xee }, { 0x7b,0x7b,0x8d,0xf6 }, + { 0xf2,0xf2,0x0d,0xff }, { 0x6b,0x6b,0xbd,0xd6 }, + { 0x6f,0x6f,0xb1,0xde }, { 0xc5,0xc5,0x54,0x91 }, + { 0x30,0x30,0x50,0x60 }, { 0x01,0x01,0x03,0x02 }, + { 0x67,0x67,0xa9,0xce }, { 0x2b,0x2b,0x7d,0x56 }, + { 0xfe,0xfe,0x19,0xe7 }, { 0xd7,0xd7,0x62,0xb5 }, + { 0xab,0xab,0xe6,0x4d }, { 0x76,0x76,0x9a,0xec }, + { 0xca,0xca,0x45,0x8f }, { 0x82,0x82,0x9d,0x1f }, + { 0xc9,0xc9,0x40,0x89 }, { 0x7d,0x7d,0x87,0xfa }, + { 0xfa,0xfa,0x15,0xef }, { 0x59,0x59,0xeb,0xb2 }, + { 0x47,0x47,0xc9,0x8e }, { 0xf0,0xf0,0x0b,0xfb }, + { 0xad,0xad,0xec,0x41 }, { 0xd4,0xd4,0x67,0xb3 }, + { 0xa2,0xa2,0xfd,0x5f }, { 0xaf,0xaf,0xea,0x45 }, + { 0x9c,0x9c,0xbf,0x23 }, { 0xa4,0xa4,0xf7,0x53 }, + { 0x72,0x72,0x96,0xe4 }, { 0xc0,0xc0,0x5b,0x9b }, + { 0xb7,0xb7,0xc2,0x75 }, { 0xfd,0xfd,0x1c,0xe1 }, + { 0x93,0x93,0xae,0x3d }, { 0x26,0x26,0x6a,0x4c }, + { 0x36,0x36,0x5a,0x6c }, { 0x3f,0x3f,0x41,0x7e }, + { 0xf7,0xf7,0x02,0xf5 }, { 0xcc,0xcc,0x4f,0x83 }, + { 0x34,0x34,0x5c,0x68 }, { 0xa5,0xa5,0xf4,0x51 }, + { 0xe5,0xe5,0x34,0xd1 }, { 0xf1,0xf1,0x08,0xf9 }, + { 0x71,0x71,0x93,0xe2 }, { 0xd8,0xd8,0x73,0xab }, + { 0x31,0x31,0x53,0x62 }, { 0x15,0x15,0x3f,0x2a }, + { 0x04,0x04,0x0c,0x08 }, { 0xc7,0xc7,0x52,0x95 }, + { 0x23,0x23,0x65,0x46 }, { 0xc3,0xc3,0x5e,0x9d }, + { 0x18,0x18,0x28,0x30 }, { 0x96,0x96,0xa1,0x37 }, + { 0x05,0x05,0x0f,0x0a }, { 0x9a,0x9a,0xb5,0x2f }, + { 0x07,0x07,0x09,0x0e }, { 0x12,0x12,0x36,0x24 }, + { 0x80,0x80,0x9b,0x1b }, { 0xe2,0xe2,0x3d,0xdf }, + { 0xeb,0xeb,0x26,0xcd }, { 0x27,0x27,0x69,0x4e }, + { 0xb2,0xb2,0xcd,0x7f }, { 0x75,0x75,0x9f,0xea }, + { 0x09,0x09,0x1b,0x12 }, { 0x83,0x83,0x9e,0x1d }, + { 0x2c,0x2c,0x74,0x58 }, { 0x1a,0x1a,0x2e,0x34 }, + { 0x1b,0x1b,0x2d,0x36 }, { 0x6e,0x6e,0xb2,0xdc }, + { 0x5a,0x5a,0xee,0xb4 }, { 0xa0,0xa0,0xfb,0x5b }, + { 0x52,0x52,0xf6,0xa4 }, { 0x3b,0x3b,0x4d,0x76 }, + { 0xd6,0xd6,0x61,0xb7 }, { 0xb3,0xb3,0xce,0x7d }, + { 0x29,0x29,0x7b,0x52 }, { 0xe3,0xe3,0x3e,0xdd }, + { 0x2f,0x2f,0x71,0x5e }, { 0x84,0x84,0x97,0x13 }, + { 0x53,0x53,0xf5,0xa6 }, { 0xd1,0xd1,0x68,0xb9 }, + { 0x00,0x00,0x00,0x00 }, { 0xed,0xed,0x2c,0xc1 }, + { 0x20,0x20,0x60,0x40 }, { 0xfc,0xfc,0x1f,0xe3 }, + { 0xb1,0xb1,0xc8,0x79 }, { 0x5b,0x5b,0xed,0xb6 }, + { 0x6a,0x6a,0xbe,0xd4 }, { 0xcb,0xcb,0x46,0x8d }, + { 0xbe,0xbe,0xd9,0x67 }, { 0x39,0x39,0x4b,0x72 }, + { 0x4a,0x4a,0xde,0x94 }, { 0x4c,0x4c,0xd4,0x98 }, + { 0x58,0x58,0xe8,0xb0 }, { 0xcf,0xcf,0x4a,0x85 }, + { 0xd0,0xd0,0x6b,0xbb }, { 0xef,0xef,0x2a,0xc5 }, + { 0xaa,0xaa,0xe5,0x4f }, { 0xfb,0xfb,0x16,0xed }, + { 0x43,0x43,0xc5,0x86 }, { 0x4d,0x4d,0xd7,0x9a }, + { 0x33,0x33,0x55,0x66 }, { 0x85,0x85,0x94,0x11 }, + { 0x45,0x45,0xcf,0x8a }, { 0xf9,0xf9,0x10,0xe9 }, + { 0x02,0x02,0x06,0x04 }, { 0x7f,0x7f,0x81,0xfe }, + { 0x50,0x50,0xf0,0xa0 }, { 0x3c,0x3c,0x44,0x78 }, + { 0x9f,0x9f,0xba,0x25 }, { 0xa8,0xa8,0xe3,0x4b }, + { 0x51,0x51,0xf3,0xa2 }, { 0xa3,0xa3,0xfe,0x5d }, + { 0x40,0x40,0xc0,0x80 }, { 0x8f,0x8f,0x8a,0x05 }, + { 0x92,0x92,0xad,0x3f }, { 0x9d,0x9d,0xbc,0x21 }, + { 0x38,0x38,0x48,0x70 }, { 0xf5,0xf5,0x04,0xf1 }, + { 0xbc,0xbc,0xdf,0x63 }, { 0xb6,0xb6,0xc1,0x77 }, + { 0xda,0xda,0x75,0xaf }, { 0x21,0x21,0x63,0x42 }, + { 0x10,0x10,0x30,0x20 }, { 0xff,0xff,0x1a,0xe5 }, + { 0xf3,0xf3,0x0e,0xfd }, { 0xd2,0xd2,0x6d,0xbf }, + { 0xcd,0xcd,0x4c,0x81 }, { 0x0c,0x0c,0x14,0x18 }, + { 0x13,0x13,0x35,0x26 }, { 0xec,0xec,0x2f,0xc3 }, + { 0x5f,0x5f,0xe1,0xbe }, { 0x97,0x97,0xa2,0x35 }, + { 0x44,0x44,0xcc,0x88 }, { 0x17,0x17,0x39,0x2e }, + { 0xc4,0xc4,0x57,0x93 }, { 0xa7,0xa7,0xf2,0x55 }, + { 0x7e,0x7e,0x82,0xfc }, { 0x3d,0x3d,0x47,0x7a }, + { 0x64,0x64,0xac,0xc8 }, { 0x5d,0x5d,0xe7,0xba }, + { 0x19,0x19,0x2b,0x32 }, { 0x73,0x73,0x95,0xe6 }, + { 0x60,0x60,0xa0,0xc0 }, { 0x81,0x81,0x98,0x19 }, + { 0x4f,0x4f,0xd1,0x9e }, { 0xdc,0xdc,0x7f,0xa3 }, + { 0x22,0x22,0x66,0x44 }, { 0x2a,0x2a,0x7e,0x54 }, + { 0x90,0x90,0xab,0x3b }, { 0x88,0x88,0x83,0x0b }, + { 0x46,0x46,0xca,0x8c }, { 0xee,0xee,0x29,0xc7 }, + { 0xb8,0xb8,0xd3,0x6b }, { 0x14,0x14,0x3c,0x28 }, + { 0xde,0xde,0x79,0xa7 }, { 0x5e,0x5e,0xe2,0xbc }, + { 0x0b,0x0b,0x1d,0x16 }, { 0xdb,0xdb,0x76,0xad }, + { 0xe0,0xe0,0x3b,0xdb }, { 0x32,0x32,0x56,0x64 }, + { 0x3a,0x3a,0x4e,0x74 }, { 0x0a,0x0a,0x1e,0x14 }, + { 0x49,0x49,0xdb,0x92 }, { 0x06,0x06,0x0a,0x0c }, + { 0x24,0x24,0x6c,0x48 }, { 0x5c,0x5c,0xe4,0xb8 }, + { 0xc2,0xc2,0x5d,0x9f }, { 0xd3,0xd3,0x6e,0xbd }, + { 0xac,0xac,0xef,0x43 }, { 0x62,0x62,0xa6,0xc4 }, + { 0x91,0x91,0xa8,0x39 }, { 0x95,0x95,0xa4,0x31 }, + { 0xe4,0xe4,0x37,0xd3 }, { 0x79,0x79,0x8b,0xf2 }, + { 0xe7,0xe7,0x32,0xd5 }, { 0xc8,0xc8,0x43,0x8b }, + { 0x37,0x37,0x59,0x6e }, { 0x6d,0x6d,0xb7,0xda }, + { 0x8d,0x8d,0x8c,0x01 }, { 0xd5,0xd5,0x64,0xb1 }, + { 0x4e,0x4e,0xd2,0x9c }, { 0xa9,0xa9,0xe0,0x49 }, + { 0x6c,0x6c,0xb4,0xd8 }, { 0x56,0x56,0xfa,0xac }, + { 0xf4,0xf4,0x07,0xf3 }, { 0xea,0xea,0x25,0xcf }, + { 0x65,0x65,0xaf,0xca }, { 0x7a,0x7a,0x8e,0xf4 }, + { 0xae,0xae,0xe9,0x47 }, { 0x08,0x08,0x18,0x10 }, + { 0xba,0xba,0xd5,0x6f }, { 0x78,0x78,0x88,0xf0 }, + { 0x25,0x25,0x6f,0x4a }, { 0x2e,0x2e,0x72,0x5c }, + { 0x1c,0x1c,0x24,0x38 }, { 0xa6,0xa6,0xf1,0x57 }, + { 0xb4,0xb4,0xc7,0x73 }, { 0xc6,0xc6,0x51,0x97 }, + { 0xe8,0xe8,0x23,0xcb }, { 0xdd,0xdd,0x7c,0xa1 }, + { 0x74,0x74,0x9c,0xe8 }, { 0x1f,0x1f,0x21,0x3e }, + { 0x4b,0x4b,0xdd,0x96 }, { 0xbd,0xbd,0xdc,0x61 }, + { 0x8b,0x8b,0x86,0x0d }, { 0x8a,0x8a,0x85,0x0f }, + { 0x70,0x70,0x90,0xe0 }, { 0x3e,0x3e,0x42,0x7c }, + { 0xb5,0xb5,0xc4,0x71 }, { 0x66,0x66,0xaa,0xcc }, + { 0x48,0x48,0xd8,0x90 }, { 0x03,0x03,0x05,0x06 }, + { 0xf6,0xf6,0x01,0xf7 }, { 0x0e,0x0e,0x12,0x1c }, + { 0x61,0x61,0xa3,0xc2 }, { 0x35,0x35,0x5f,0x6a }, + { 0x57,0x57,0xf9,0xae }, { 0xb9,0xb9,0xd0,0x69 }, + { 0x86,0x86,0x91,0x17 }, { 0xc1,0xc1,0x58,0x99 }, + { 0x1d,0x1d,0x27,0x3a }, { 0x9e,0x9e,0xb9,0x27 }, + { 0xe1,0xe1,0x38,0xd9 }, { 0xf8,0xf8,0x13,0xeb }, + { 0x98,0x98,0xb3,0x2b }, { 0x11,0x11,0x33,0x22 }, + { 0x69,0x69,0xbb,0xd2 }, { 0xd9,0xd9,0x70,0xa9 }, + { 0x8e,0x8e,0x89,0x07 }, { 0x94,0x94,0xa7,0x33 }, + { 0x9b,0x9b,0xb6,0x2d }, { 0x1e,0x1e,0x22,0x3c }, + { 0x87,0x87,0x92,0x15 }, { 0xe9,0xe9,0x20,0xc9 }, + { 0xce,0xce,0x49,0x87 }, { 0x55,0x55,0xff,0xaa }, + { 0x28,0x28,0x78,0x50 }, { 0xdf,0xdf,0x7a,0xa5 }, + { 0x8c,0x8c,0x8f,0x03 }, { 0xa1,0xa1,0xf8,0x59 }, + { 0x89,0x89,0x80,0x09 }, { 0x0d,0x0d,0x17,0x1a }, + { 0xbf,0xbf,0xda,0x65 }, { 0xe6,0xe6,0x31,0xd7 }, + { 0x42,0x42,0xc6,0x84 }, { 0x68,0x68,0xb8,0xd0 }, + { 0x41,0x41,0xc3,0x82 }, { 0x99,0x99,0xb0,0x29 }, + { 0x2d,0x2d,0x77,0x5a }, { 0x0f,0x0f,0x11,0x1e }, + { 0xb0,0xb0,0xcb,0x7b }, { 0x54,0x54,0xfc,0xa8 }, + { 0xbb,0xbb,0xd6,0x6d }, { 0x16,0x16,0x3a,0x2c } + }; + +static const unsigned char T5[256][4] = + { + { 0x51,0xf4,0xa7,0x50 }, { 0x7e,0x41,0x65,0x53 }, + { 0x1a,0x17,0xa4,0xc3 }, { 0x3a,0x27,0x5e,0x96 }, + { 0x3b,0xab,0x6b,0xcb }, { 0x1f,0x9d,0x45,0xf1 }, + { 0xac,0xfa,0x58,0xab }, { 0x4b,0xe3,0x03,0x93 }, + { 0x20,0x30,0xfa,0x55 }, { 0xad,0x76,0x6d,0xf6 }, + { 0x88,0xcc,0x76,0x91 }, { 0xf5,0x02,0x4c,0x25 }, + { 0x4f,0xe5,0xd7,0xfc }, { 0xc5,0x2a,0xcb,0xd7 }, + { 0x26,0x35,0x44,0x80 }, { 0xb5,0x62,0xa3,0x8f }, + { 0xde,0xb1,0x5a,0x49 }, { 0x25,0xba,0x1b,0x67 }, + { 0x45,0xea,0x0e,0x98 }, { 0x5d,0xfe,0xc0,0xe1 }, + { 0xc3,0x2f,0x75,0x02 }, { 0x81,0x4c,0xf0,0x12 }, + { 0x8d,0x46,0x97,0xa3 }, { 0x6b,0xd3,0xf9,0xc6 }, + { 0x03,0x8f,0x5f,0xe7 }, { 0x15,0x92,0x9c,0x95 }, + { 0xbf,0x6d,0x7a,0xeb }, { 0x95,0x52,0x59,0xda }, + { 0xd4,0xbe,0x83,0x2d }, { 0x58,0x74,0x21,0xd3 }, + { 0x49,0xe0,0x69,0x29 }, { 0x8e,0xc9,0xc8,0x44 }, + { 0x75,0xc2,0x89,0x6a }, { 0xf4,0x8e,0x79,0x78 }, + { 0x99,0x58,0x3e,0x6b }, { 0x27,0xb9,0x71,0xdd }, + { 0xbe,0xe1,0x4f,0xb6 }, { 0xf0,0x88,0xad,0x17 }, + { 0xc9,0x20,0xac,0x66 }, { 0x7d,0xce,0x3a,0xb4 }, + { 0x63,0xdf,0x4a,0x18 }, { 0xe5,0x1a,0x31,0x82 }, + { 0x97,0x51,0x33,0x60 }, { 0x62,0x53,0x7f,0x45 }, + { 0xb1,0x64,0x77,0xe0 }, { 0xbb,0x6b,0xae,0x84 }, + { 0xfe,0x81,0xa0,0x1c }, { 0xf9,0x08,0x2b,0x94 }, + { 0x70,0x48,0x68,0x58 }, { 0x8f,0x45,0xfd,0x19 }, + { 0x94,0xde,0x6c,0x87 }, { 0x52,0x7b,0xf8,0xb7 }, + { 0xab,0x73,0xd3,0x23 }, { 0x72,0x4b,0x02,0xe2 }, + { 0xe3,0x1f,0x8f,0x57 }, { 0x66,0x55,0xab,0x2a }, + { 0xb2,0xeb,0x28,0x07 }, { 0x2f,0xb5,0xc2,0x03 }, + { 0x86,0xc5,0x7b,0x9a }, { 0xd3,0x37,0x08,0xa5 }, + { 0x30,0x28,0x87,0xf2 }, { 0x23,0xbf,0xa5,0xb2 }, + { 0x02,0x03,0x6a,0xba }, { 0xed,0x16,0x82,0x5c }, + { 0x8a,0xcf,0x1c,0x2b }, { 0xa7,0x79,0xb4,0x92 }, + { 0xf3,0x07,0xf2,0xf0 }, { 0x4e,0x69,0xe2,0xa1 }, + { 0x65,0xda,0xf4,0xcd }, { 0x06,0x05,0xbe,0xd5 }, + { 0xd1,0x34,0x62,0x1f }, { 0xc4,0xa6,0xfe,0x8a }, + { 0x34,0x2e,0x53,0x9d }, { 0xa2,0xf3,0x55,0xa0 }, + { 0x05,0x8a,0xe1,0x32 }, { 0xa4,0xf6,0xeb,0x75 }, + { 0x0b,0x83,0xec,0x39 }, { 0x40,0x60,0xef,0xaa }, + { 0x5e,0x71,0x9f,0x06 }, { 0xbd,0x6e,0x10,0x51 }, + { 0x3e,0x21,0x8a,0xf9 }, { 0x96,0xdd,0x06,0x3d }, + { 0xdd,0x3e,0x05,0xae }, { 0x4d,0xe6,0xbd,0x46 }, + { 0x91,0x54,0x8d,0xb5 }, { 0x71,0xc4,0x5d,0x05 }, + { 0x04,0x06,0xd4,0x6f }, { 0x60,0x50,0x15,0xff }, + { 0x19,0x98,0xfb,0x24 }, { 0xd6,0xbd,0xe9,0x97 }, + { 0x89,0x40,0x43,0xcc }, { 0x67,0xd9,0x9e,0x77 }, + { 0xb0,0xe8,0x42,0xbd }, { 0x07,0x89,0x8b,0x88 }, + { 0xe7,0x19,0x5b,0x38 }, { 0x79,0xc8,0xee,0xdb }, + { 0xa1,0x7c,0x0a,0x47 }, { 0x7c,0x42,0x0f,0xe9 }, + { 0xf8,0x84,0x1e,0xc9 }, { 0x00,0x00,0x00,0x00 }, + { 0x09,0x80,0x86,0x83 }, { 0x32,0x2b,0xed,0x48 }, + { 0x1e,0x11,0x70,0xac }, { 0x6c,0x5a,0x72,0x4e }, + { 0xfd,0x0e,0xff,0xfb }, { 0x0f,0x85,0x38,0x56 }, + { 0x3d,0xae,0xd5,0x1e }, { 0x36,0x2d,0x39,0x27 }, + { 0x0a,0x0f,0xd9,0x64 }, { 0x68,0x5c,0xa6,0x21 }, + { 0x9b,0x5b,0x54,0xd1 }, { 0x24,0x36,0x2e,0x3a }, + { 0x0c,0x0a,0x67,0xb1 }, { 0x93,0x57,0xe7,0x0f }, + { 0xb4,0xee,0x96,0xd2 }, { 0x1b,0x9b,0x91,0x9e }, + { 0x80,0xc0,0xc5,0x4f }, { 0x61,0xdc,0x20,0xa2 }, + { 0x5a,0x77,0x4b,0x69 }, { 0x1c,0x12,0x1a,0x16 }, + { 0xe2,0x93,0xba,0x0a }, { 0xc0,0xa0,0x2a,0xe5 }, + { 0x3c,0x22,0xe0,0x43 }, { 0x12,0x1b,0x17,0x1d }, + { 0x0e,0x09,0x0d,0x0b }, { 0xf2,0x8b,0xc7,0xad }, + { 0x2d,0xb6,0xa8,0xb9 }, { 0x14,0x1e,0xa9,0xc8 }, + { 0x57,0xf1,0x19,0x85 }, { 0xaf,0x75,0x07,0x4c }, + { 0xee,0x99,0xdd,0xbb }, { 0xa3,0x7f,0x60,0xfd }, + { 0xf7,0x01,0x26,0x9f }, { 0x5c,0x72,0xf5,0xbc }, + { 0x44,0x66,0x3b,0xc5 }, { 0x5b,0xfb,0x7e,0x34 }, + { 0x8b,0x43,0x29,0x76 }, { 0xcb,0x23,0xc6,0xdc }, + { 0xb6,0xed,0xfc,0x68 }, { 0xb8,0xe4,0xf1,0x63 }, + { 0xd7,0x31,0xdc,0xca }, { 0x42,0x63,0x85,0x10 }, + { 0x13,0x97,0x22,0x40 }, { 0x84,0xc6,0x11,0x20 }, + { 0x85,0x4a,0x24,0x7d }, { 0xd2,0xbb,0x3d,0xf8 }, + { 0xae,0xf9,0x32,0x11 }, { 0xc7,0x29,0xa1,0x6d }, + { 0x1d,0x9e,0x2f,0x4b }, { 0xdc,0xb2,0x30,0xf3 }, + { 0x0d,0x86,0x52,0xec }, { 0x77,0xc1,0xe3,0xd0 }, + { 0x2b,0xb3,0x16,0x6c }, { 0xa9,0x70,0xb9,0x99 }, + { 0x11,0x94,0x48,0xfa }, { 0x47,0xe9,0x64,0x22 }, + { 0xa8,0xfc,0x8c,0xc4 }, { 0xa0,0xf0,0x3f,0x1a }, + { 0x56,0x7d,0x2c,0xd8 }, { 0x22,0x33,0x90,0xef }, + { 0x87,0x49,0x4e,0xc7 }, { 0xd9,0x38,0xd1,0xc1 }, + { 0x8c,0xca,0xa2,0xfe }, { 0x98,0xd4,0x0b,0x36 }, + { 0xa6,0xf5,0x81,0xcf }, { 0xa5,0x7a,0xde,0x28 }, + { 0xda,0xb7,0x8e,0x26 }, { 0x3f,0xad,0xbf,0xa4 }, + { 0x2c,0x3a,0x9d,0xe4 }, { 0x50,0x78,0x92,0x0d }, + { 0x6a,0x5f,0xcc,0x9b }, { 0x54,0x7e,0x46,0x62 }, + { 0xf6,0x8d,0x13,0xc2 }, { 0x90,0xd8,0xb8,0xe8 }, + { 0x2e,0x39,0xf7,0x5e }, { 0x82,0xc3,0xaf,0xf5 }, + { 0x9f,0x5d,0x80,0xbe }, { 0x69,0xd0,0x93,0x7c }, + { 0x6f,0xd5,0x2d,0xa9 }, { 0xcf,0x25,0x12,0xb3 }, + { 0xc8,0xac,0x99,0x3b }, { 0x10,0x18,0x7d,0xa7 }, + { 0xe8,0x9c,0x63,0x6e }, { 0xdb,0x3b,0xbb,0x7b }, + { 0xcd,0x26,0x78,0x09 }, { 0x6e,0x59,0x18,0xf4 }, + { 0xec,0x9a,0xb7,0x01 }, { 0x83,0x4f,0x9a,0xa8 }, + { 0xe6,0x95,0x6e,0x65 }, { 0xaa,0xff,0xe6,0x7e }, + { 0x21,0xbc,0xcf,0x08 }, { 0xef,0x15,0xe8,0xe6 }, + { 0xba,0xe7,0x9b,0xd9 }, { 0x4a,0x6f,0x36,0xce }, + { 0xea,0x9f,0x09,0xd4 }, { 0x29,0xb0,0x7c,0xd6 }, + { 0x31,0xa4,0xb2,0xaf }, { 0x2a,0x3f,0x23,0x31 }, + { 0xc6,0xa5,0x94,0x30 }, { 0x35,0xa2,0x66,0xc0 }, + { 0x74,0x4e,0xbc,0x37 }, { 0xfc,0x82,0xca,0xa6 }, + { 0xe0,0x90,0xd0,0xb0 }, { 0x33,0xa7,0xd8,0x15 }, + { 0xf1,0x04,0x98,0x4a }, { 0x41,0xec,0xda,0xf7 }, + { 0x7f,0xcd,0x50,0x0e }, { 0x17,0x91,0xf6,0x2f }, + { 0x76,0x4d,0xd6,0x8d }, { 0x43,0xef,0xb0,0x4d }, + { 0xcc,0xaa,0x4d,0x54 }, { 0xe4,0x96,0x04,0xdf }, + { 0x9e,0xd1,0xb5,0xe3 }, { 0x4c,0x6a,0x88,0x1b }, + { 0xc1,0x2c,0x1f,0xb8 }, { 0x46,0x65,0x51,0x7f }, + { 0x9d,0x5e,0xea,0x04 }, { 0x01,0x8c,0x35,0x5d }, + { 0xfa,0x87,0x74,0x73 }, { 0xfb,0x0b,0x41,0x2e }, + { 0xb3,0x67,0x1d,0x5a }, { 0x92,0xdb,0xd2,0x52 }, + { 0xe9,0x10,0x56,0x33 }, { 0x6d,0xd6,0x47,0x13 }, + { 0x9a,0xd7,0x61,0x8c }, { 0x37,0xa1,0x0c,0x7a }, + { 0x59,0xf8,0x14,0x8e }, { 0xeb,0x13,0x3c,0x89 }, + { 0xce,0xa9,0x27,0xee }, { 0xb7,0x61,0xc9,0x35 }, + { 0xe1,0x1c,0xe5,0xed }, { 0x7a,0x47,0xb1,0x3c }, + { 0x9c,0xd2,0xdf,0x59 }, { 0x55,0xf2,0x73,0x3f }, + { 0x18,0x14,0xce,0x79 }, { 0x73,0xc7,0x37,0xbf }, + { 0x53,0xf7,0xcd,0xea }, { 0x5f,0xfd,0xaa,0x5b }, + { 0xdf,0x3d,0x6f,0x14 }, { 0x78,0x44,0xdb,0x86 }, + { 0xca,0xaf,0xf3,0x81 }, { 0xb9,0x68,0xc4,0x3e }, + { 0x38,0x24,0x34,0x2c }, { 0xc2,0xa3,0x40,0x5f }, + { 0x16,0x1d,0xc3,0x72 }, { 0xbc,0xe2,0x25,0x0c }, + { 0x28,0x3c,0x49,0x8b }, { 0xff,0x0d,0x95,0x41 }, + { 0x39,0xa8,0x01,0x71 }, { 0x08,0x0c,0xb3,0xde }, + { 0xd8,0xb4,0xe4,0x9c }, { 0x64,0x56,0xc1,0x90 }, + { 0x7b,0xcb,0x84,0x61 }, { 0xd5,0x32,0xb6,0x70 }, + { 0x48,0x6c,0x5c,0x74 }, { 0xd0,0xb8,0x57,0x42 } + }; + +static const unsigned char T6[256][4] = + { + { 0x50,0x51,0xf4,0xa7 }, { 0x53,0x7e,0x41,0x65 }, + { 0xc3,0x1a,0x17,0xa4 }, { 0x96,0x3a,0x27,0x5e }, + { 0xcb,0x3b,0xab,0x6b }, { 0xf1,0x1f,0x9d,0x45 }, + { 0xab,0xac,0xfa,0x58 }, { 0x93,0x4b,0xe3,0x03 }, + { 0x55,0x20,0x30,0xfa }, { 0xf6,0xad,0x76,0x6d }, + { 0x91,0x88,0xcc,0x76 }, { 0x25,0xf5,0x02,0x4c }, + { 0xfc,0x4f,0xe5,0xd7 }, { 0xd7,0xc5,0x2a,0xcb }, + { 0x80,0x26,0x35,0x44 }, { 0x8f,0xb5,0x62,0xa3 }, + { 0x49,0xde,0xb1,0x5a }, { 0x67,0x25,0xba,0x1b }, + { 0x98,0x45,0xea,0x0e }, { 0xe1,0x5d,0xfe,0xc0 }, + { 0x02,0xc3,0x2f,0x75 }, { 0x12,0x81,0x4c,0xf0 }, + { 0xa3,0x8d,0x46,0x97 }, { 0xc6,0x6b,0xd3,0xf9 }, + { 0xe7,0x03,0x8f,0x5f }, { 0x95,0x15,0x92,0x9c }, + { 0xeb,0xbf,0x6d,0x7a }, { 0xda,0x95,0x52,0x59 }, + { 0x2d,0xd4,0xbe,0x83 }, { 0xd3,0x58,0x74,0x21 }, + { 0x29,0x49,0xe0,0x69 }, { 0x44,0x8e,0xc9,0xc8 }, + { 0x6a,0x75,0xc2,0x89 }, { 0x78,0xf4,0x8e,0x79 }, + { 0x6b,0x99,0x58,0x3e }, { 0xdd,0x27,0xb9,0x71 }, + { 0xb6,0xbe,0xe1,0x4f }, { 0x17,0xf0,0x88,0xad }, + { 0x66,0xc9,0x20,0xac }, { 0xb4,0x7d,0xce,0x3a }, + { 0x18,0x63,0xdf,0x4a }, { 0x82,0xe5,0x1a,0x31 }, + { 0x60,0x97,0x51,0x33 }, { 0x45,0x62,0x53,0x7f }, + { 0xe0,0xb1,0x64,0x77 }, { 0x84,0xbb,0x6b,0xae }, + { 0x1c,0xfe,0x81,0xa0 }, { 0x94,0xf9,0x08,0x2b }, + { 0x58,0x70,0x48,0x68 }, { 0x19,0x8f,0x45,0xfd }, + { 0x87,0x94,0xde,0x6c }, { 0xb7,0x52,0x7b,0xf8 }, + { 0x23,0xab,0x73,0xd3 }, { 0xe2,0x72,0x4b,0x02 }, + { 0x57,0xe3,0x1f,0x8f }, { 0x2a,0x66,0x55,0xab }, + { 0x07,0xb2,0xeb,0x28 }, { 0x03,0x2f,0xb5,0xc2 }, + { 0x9a,0x86,0xc5,0x7b }, { 0xa5,0xd3,0x37,0x08 }, + { 0xf2,0x30,0x28,0x87 }, { 0xb2,0x23,0xbf,0xa5 }, + { 0xba,0x02,0x03,0x6a }, { 0x5c,0xed,0x16,0x82 }, + { 0x2b,0x8a,0xcf,0x1c }, { 0x92,0xa7,0x79,0xb4 }, + { 0xf0,0xf3,0x07,0xf2 }, { 0xa1,0x4e,0x69,0xe2 }, + { 0xcd,0x65,0xda,0xf4 }, { 0xd5,0x06,0x05,0xbe }, + { 0x1f,0xd1,0x34,0x62 }, { 0x8a,0xc4,0xa6,0xfe }, + { 0x9d,0x34,0x2e,0x53 }, { 0xa0,0xa2,0xf3,0x55 }, + { 0x32,0x05,0x8a,0xe1 }, { 0x75,0xa4,0xf6,0xeb }, + { 0x39,0x0b,0x83,0xec }, { 0xaa,0x40,0x60,0xef }, + { 0x06,0x5e,0x71,0x9f }, { 0x51,0xbd,0x6e,0x10 }, + { 0xf9,0x3e,0x21,0x8a }, { 0x3d,0x96,0xdd,0x06 }, + { 0xae,0xdd,0x3e,0x05 }, { 0x46,0x4d,0xe6,0xbd }, + { 0xb5,0x91,0x54,0x8d }, { 0x05,0x71,0xc4,0x5d }, + { 0x6f,0x04,0x06,0xd4 }, { 0xff,0x60,0x50,0x15 }, + { 0x24,0x19,0x98,0xfb }, { 0x97,0xd6,0xbd,0xe9 }, + { 0xcc,0x89,0x40,0x43 }, { 0x77,0x67,0xd9,0x9e }, + { 0xbd,0xb0,0xe8,0x42 }, { 0x88,0x07,0x89,0x8b }, + { 0x38,0xe7,0x19,0x5b }, { 0xdb,0x79,0xc8,0xee }, + { 0x47,0xa1,0x7c,0x0a }, { 0xe9,0x7c,0x42,0x0f }, + { 0xc9,0xf8,0x84,0x1e }, { 0x00,0x00,0x00,0x00 }, + { 0x83,0x09,0x80,0x86 }, { 0x48,0x32,0x2b,0xed }, + { 0xac,0x1e,0x11,0x70 }, { 0x4e,0x6c,0x5a,0x72 }, + { 0xfb,0xfd,0x0e,0xff }, { 0x56,0x0f,0x85,0x38 }, + { 0x1e,0x3d,0xae,0xd5 }, { 0x27,0x36,0x2d,0x39 }, + { 0x64,0x0a,0x0f,0xd9 }, { 0x21,0x68,0x5c,0xa6 }, + { 0xd1,0x9b,0x5b,0x54 }, { 0x3a,0x24,0x36,0x2e }, + { 0xb1,0x0c,0x0a,0x67 }, { 0x0f,0x93,0x57,0xe7 }, + { 0xd2,0xb4,0xee,0x96 }, { 0x9e,0x1b,0x9b,0x91 }, + { 0x4f,0x80,0xc0,0xc5 }, { 0xa2,0x61,0xdc,0x20 }, + { 0x69,0x5a,0x77,0x4b }, { 0x16,0x1c,0x12,0x1a }, + { 0x0a,0xe2,0x93,0xba }, { 0xe5,0xc0,0xa0,0x2a }, + { 0x43,0x3c,0x22,0xe0 }, { 0x1d,0x12,0x1b,0x17 }, + { 0x0b,0x0e,0x09,0x0d }, { 0xad,0xf2,0x8b,0xc7 }, + { 0xb9,0x2d,0xb6,0xa8 }, { 0xc8,0x14,0x1e,0xa9 }, + { 0x85,0x57,0xf1,0x19 }, { 0x4c,0xaf,0x75,0x07 }, + { 0xbb,0xee,0x99,0xdd }, { 0xfd,0xa3,0x7f,0x60 }, + { 0x9f,0xf7,0x01,0x26 }, { 0xbc,0x5c,0x72,0xf5 }, + { 0xc5,0x44,0x66,0x3b }, { 0x34,0x5b,0xfb,0x7e }, + { 0x76,0x8b,0x43,0x29 }, { 0xdc,0xcb,0x23,0xc6 }, + { 0x68,0xb6,0xed,0xfc }, { 0x63,0xb8,0xe4,0xf1 }, + { 0xca,0xd7,0x31,0xdc }, { 0x10,0x42,0x63,0x85 }, + { 0x40,0x13,0x97,0x22 }, { 0x20,0x84,0xc6,0x11 }, + { 0x7d,0x85,0x4a,0x24 }, { 0xf8,0xd2,0xbb,0x3d }, + { 0x11,0xae,0xf9,0x32 }, { 0x6d,0xc7,0x29,0xa1 }, + { 0x4b,0x1d,0x9e,0x2f }, { 0xf3,0xdc,0xb2,0x30 }, + { 0xec,0x0d,0x86,0x52 }, { 0xd0,0x77,0xc1,0xe3 }, + { 0x6c,0x2b,0xb3,0x16 }, { 0x99,0xa9,0x70,0xb9 }, + { 0xfa,0x11,0x94,0x48 }, { 0x22,0x47,0xe9,0x64 }, + { 0xc4,0xa8,0xfc,0x8c }, { 0x1a,0xa0,0xf0,0x3f }, + { 0xd8,0x56,0x7d,0x2c }, { 0xef,0x22,0x33,0x90 }, + { 0xc7,0x87,0x49,0x4e }, { 0xc1,0xd9,0x38,0xd1 }, + { 0xfe,0x8c,0xca,0xa2 }, { 0x36,0x98,0xd4,0x0b }, + { 0xcf,0xa6,0xf5,0x81 }, { 0x28,0xa5,0x7a,0xde }, + { 0x26,0xda,0xb7,0x8e }, { 0xa4,0x3f,0xad,0xbf }, + { 0xe4,0x2c,0x3a,0x9d }, { 0x0d,0x50,0x78,0x92 }, + { 0x9b,0x6a,0x5f,0xcc }, { 0x62,0x54,0x7e,0x46 }, + { 0xc2,0xf6,0x8d,0x13 }, { 0xe8,0x90,0xd8,0xb8 }, + { 0x5e,0x2e,0x39,0xf7 }, { 0xf5,0x82,0xc3,0xaf }, + { 0xbe,0x9f,0x5d,0x80 }, { 0x7c,0x69,0xd0,0x93 }, + { 0xa9,0x6f,0xd5,0x2d }, { 0xb3,0xcf,0x25,0x12 }, + { 0x3b,0xc8,0xac,0x99 }, { 0xa7,0x10,0x18,0x7d }, + { 0x6e,0xe8,0x9c,0x63 }, { 0x7b,0xdb,0x3b,0xbb }, + { 0x09,0xcd,0x26,0x78 }, { 0xf4,0x6e,0x59,0x18 }, + { 0x01,0xec,0x9a,0xb7 }, { 0xa8,0x83,0x4f,0x9a }, + { 0x65,0xe6,0x95,0x6e }, { 0x7e,0xaa,0xff,0xe6 }, + { 0x08,0x21,0xbc,0xcf }, { 0xe6,0xef,0x15,0xe8 }, + { 0xd9,0xba,0xe7,0x9b }, { 0xce,0x4a,0x6f,0x36 }, + { 0xd4,0xea,0x9f,0x09 }, { 0xd6,0x29,0xb0,0x7c }, + { 0xaf,0x31,0xa4,0xb2 }, { 0x31,0x2a,0x3f,0x23 }, + { 0x30,0xc6,0xa5,0x94 }, { 0xc0,0x35,0xa2,0x66 }, + { 0x37,0x74,0x4e,0xbc }, { 0xa6,0xfc,0x82,0xca }, + { 0xb0,0xe0,0x90,0xd0 }, { 0x15,0x33,0xa7,0xd8 }, + { 0x4a,0xf1,0x04,0x98 }, { 0xf7,0x41,0xec,0xda }, + { 0x0e,0x7f,0xcd,0x50 }, { 0x2f,0x17,0x91,0xf6 }, + { 0x8d,0x76,0x4d,0xd6 }, { 0x4d,0x43,0xef,0xb0 }, + { 0x54,0xcc,0xaa,0x4d }, { 0xdf,0xe4,0x96,0x04 }, + { 0xe3,0x9e,0xd1,0xb5 }, { 0x1b,0x4c,0x6a,0x88 }, + { 0xb8,0xc1,0x2c,0x1f }, { 0x7f,0x46,0x65,0x51 }, + { 0x04,0x9d,0x5e,0xea }, { 0x5d,0x01,0x8c,0x35 }, + { 0x73,0xfa,0x87,0x74 }, { 0x2e,0xfb,0x0b,0x41 }, + { 0x5a,0xb3,0x67,0x1d }, { 0x52,0x92,0xdb,0xd2 }, + { 0x33,0xe9,0x10,0x56 }, { 0x13,0x6d,0xd6,0x47 }, + { 0x8c,0x9a,0xd7,0x61 }, { 0x7a,0x37,0xa1,0x0c }, + { 0x8e,0x59,0xf8,0x14 }, { 0x89,0xeb,0x13,0x3c }, + { 0xee,0xce,0xa9,0x27 }, { 0x35,0xb7,0x61,0xc9 }, + { 0xed,0xe1,0x1c,0xe5 }, { 0x3c,0x7a,0x47,0xb1 }, + { 0x59,0x9c,0xd2,0xdf }, { 0x3f,0x55,0xf2,0x73 }, + { 0x79,0x18,0x14,0xce }, { 0xbf,0x73,0xc7,0x37 }, + { 0xea,0x53,0xf7,0xcd }, { 0x5b,0x5f,0xfd,0xaa }, + { 0x14,0xdf,0x3d,0x6f }, { 0x86,0x78,0x44,0xdb }, + { 0x81,0xca,0xaf,0xf3 }, { 0x3e,0xb9,0x68,0xc4 }, + { 0x2c,0x38,0x24,0x34 }, { 0x5f,0xc2,0xa3,0x40 }, + { 0x72,0x16,0x1d,0xc3 }, { 0x0c,0xbc,0xe2,0x25 }, + { 0x8b,0x28,0x3c,0x49 }, { 0x41,0xff,0x0d,0x95 }, + { 0x71,0x39,0xa8,0x01 }, { 0xde,0x08,0x0c,0xb3 }, + { 0x9c,0xd8,0xb4,0xe4 }, { 0x90,0x64,0x56,0xc1 }, + { 0x61,0x7b,0xcb,0x84 }, { 0x70,0xd5,0x32,0xb6 }, + { 0x74,0x48,0x6c,0x5c }, { 0x42,0xd0,0xb8,0x57 } + }; + +static const unsigned char T7[256][4] = + { + { 0xa7,0x50,0x51,0xf4 }, { 0x65,0x53,0x7e,0x41 }, + { 0xa4,0xc3,0x1a,0x17 }, { 0x5e,0x96,0x3a,0x27 }, + { 0x6b,0xcb,0x3b,0xab }, { 0x45,0xf1,0x1f,0x9d }, + { 0x58,0xab,0xac,0xfa }, { 0x03,0x93,0x4b,0xe3 }, + { 0xfa,0x55,0x20,0x30 }, { 0x6d,0xf6,0xad,0x76 }, + { 0x76,0x91,0x88,0xcc }, { 0x4c,0x25,0xf5,0x02 }, + { 0xd7,0xfc,0x4f,0xe5 }, { 0xcb,0xd7,0xc5,0x2a }, + { 0x44,0x80,0x26,0x35 }, { 0xa3,0x8f,0xb5,0x62 }, + { 0x5a,0x49,0xde,0xb1 }, { 0x1b,0x67,0x25,0xba }, + { 0x0e,0x98,0x45,0xea }, { 0xc0,0xe1,0x5d,0xfe }, + { 0x75,0x02,0xc3,0x2f }, { 0xf0,0x12,0x81,0x4c }, + { 0x97,0xa3,0x8d,0x46 }, { 0xf9,0xc6,0x6b,0xd3 }, + { 0x5f,0xe7,0x03,0x8f }, { 0x9c,0x95,0x15,0x92 }, + { 0x7a,0xeb,0xbf,0x6d }, { 0x59,0xda,0x95,0x52 }, + { 0x83,0x2d,0xd4,0xbe }, { 0x21,0xd3,0x58,0x74 }, + { 0x69,0x29,0x49,0xe0 }, { 0xc8,0x44,0x8e,0xc9 }, + { 0x89,0x6a,0x75,0xc2 }, { 0x79,0x78,0xf4,0x8e }, + { 0x3e,0x6b,0x99,0x58 }, { 0x71,0xdd,0x27,0xb9 }, + { 0x4f,0xb6,0xbe,0xe1 }, { 0xad,0x17,0xf0,0x88 }, + { 0xac,0x66,0xc9,0x20 }, { 0x3a,0xb4,0x7d,0xce }, + { 0x4a,0x18,0x63,0xdf }, { 0x31,0x82,0xe5,0x1a }, + { 0x33,0x60,0x97,0x51 }, { 0x7f,0x45,0x62,0x53 }, + { 0x77,0xe0,0xb1,0x64 }, { 0xae,0x84,0xbb,0x6b }, + { 0xa0,0x1c,0xfe,0x81 }, { 0x2b,0x94,0xf9,0x08 }, + { 0x68,0x58,0x70,0x48 }, { 0xfd,0x19,0x8f,0x45 }, + { 0x6c,0x87,0x94,0xde }, { 0xf8,0xb7,0x52,0x7b }, + { 0xd3,0x23,0xab,0x73 }, { 0x02,0xe2,0x72,0x4b }, + { 0x8f,0x57,0xe3,0x1f }, { 0xab,0x2a,0x66,0x55 }, + { 0x28,0x07,0xb2,0xeb }, { 0xc2,0x03,0x2f,0xb5 }, + { 0x7b,0x9a,0x86,0xc5 }, { 0x08,0xa5,0xd3,0x37 }, + { 0x87,0xf2,0x30,0x28 }, { 0xa5,0xb2,0x23,0xbf }, + { 0x6a,0xba,0x02,0x03 }, { 0x82,0x5c,0xed,0x16 }, + { 0x1c,0x2b,0x8a,0xcf }, { 0xb4,0x92,0xa7,0x79 }, + { 0xf2,0xf0,0xf3,0x07 }, { 0xe2,0xa1,0x4e,0x69 }, + { 0xf4,0xcd,0x65,0xda }, { 0xbe,0xd5,0x06,0x05 }, + { 0x62,0x1f,0xd1,0x34 }, { 0xfe,0x8a,0xc4,0xa6 }, + { 0x53,0x9d,0x34,0x2e }, { 0x55,0xa0,0xa2,0xf3 }, + { 0xe1,0x32,0x05,0x8a }, { 0xeb,0x75,0xa4,0xf6 }, + { 0xec,0x39,0x0b,0x83 }, { 0xef,0xaa,0x40,0x60 }, + { 0x9f,0x06,0x5e,0x71 }, { 0x10,0x51,0xbd,0x6e }, + { 0x8a,0xf9,0x3e,0x21 }, { 0x06,0x3d,0x96,0xdd }, + { 0x05,0xae,0xdd,0x3e }, { 0xbd,0x46,0x4d,0xe6 }, + { 0x8d,0xb5,0x91,0x54 }, { 0x5d,0x05,0x71,0xc4 }, + { 0xd4,0x6f,0x04,0x06 }, { 0x15,0xff,0x60,0x50 }, + { 0xfb,0x24,0x19,0x98 }, { 0xe9,0x97,0xd6,0xbd }, + { 0x43,0xcc,0x89,0x40 }, { 0x9e,0x77,0x67,0xd9 }, + { 0x42,0xbd,0xb0,0xe8 }, { 0x8b,0x88,0x07,0x89 }, + { 0x5b,0x38,0xe7,0x19 }, { 0xee,0xdb,0x79,0xc8 }, + { 0x0a,0x47,0xa1,0x7c }, { 0x0f,0xe9,0x7c,0x42 }, + { 0x1e,0xc9,0xf8,0x84 }, { 0x00,0x00,0x00,0x00 }, + { 0x86,0x83,0x09,0x80 }, { 0xed,0x48,0x32,0x2b }, + { 0x70,0xac,0x1e,0x11 }, { 0x72,0x4e,0x6c,0x5a }, + { 0xff,0xfb,0xfd,0x0e }, { 0x38,0x56,0x0f,0x85 }, + { 0xd5,0x1e,0x3d,0xae }, { 0x39,0x27,0x36,0x2d }, + { 0xd9,0x64,0x0a,0x0f }, { 0xa6,0x21,0x68,0x5c }, + { 0x54,0xd1,0x9b,0x5b }, { 0x2e,0x3a,0x24,0x36 }, + { 0x67,0xb1,0x0c,0x0a }, { 0xe7,0x0f,0x93,0x57 }, + { 0x96,0xd2,0xb4,0xee }, { 0x91,0x9e,0x1b,0x9b }, + { 0xc5,0x4f,0x80,0xc0 }, { 0x20,0xa2,0x61,0xdc }, + { 0x4b,0x69,0x5a,0x77 }, { 0x1a,0x16,0x1c,0x12 }, + { 0xba,0x0a,0xe2,0x93 }, { 0x2a,0xe5,0xc0,0xa0 }, + { 0xe0,0x43,0x3c,0x22 }, { 0x17,0x1d,0x12,0x1b }, + { 0x0d,0x0b,0x0e,0x09 }, { 0xc7,0xad,0xf2,0x8b }, + { 0xa8,0xb9,0x2d,0xb6 }, { 0xa9,0xc8,0x14,0x1e }, + { 0x19,0x85,0x57,0xf1 }, { 0x07,0x4c,0xaf,0x75 }, + { 0xdd,0xbb,0xee,0x99 }, { 0x60,0xfd,0xa3,0x7f }, + { 0x26,0x9f,0xf7,0x01 }, { 0xf5,0xbc,0x5c,0x72 }, + { 0x3b,0xc5,0x44,0x66 }, { 0x7e,0x34,0x5b,0xfb }, + { 0x29,0x76,0x8b,0x43 }, { 0xc6,0xdc,0xcb,0x23 }, + { 0xfc,0x68,0xb6,0xed }, { 0xf1,0x63,0xb8,0xe4 }, + { 0xdc,0xca,0xd7,0x31 }, { 0x85,0x10,0x42,0x63 }, + { 0x22,0x40,0x13,0x97 }, { 0x11,0x20,0x84,0xc6 }, + { 0x24,0x7d,0x85,0x4a }, { 0x3d,0xf8,0xd2,0xbb }, + { 0x32,0x11,0xae,0xf9 }, { 0xa1,0x6d,0xc7,0x29 }, + { 0x2f,0x4b,0x1d,0x9e }, { 0x30,0xf3,0xdc,0xb2 }, + { 0x52,0xec,0x0d,0x86 }, { 0xe3,0xd0,0x77,0xc1 }, + { 0x16,0x6c,0x2b,0xb3 }, { 0xb9,0x99,0xa9,0x70 }, + { 0x48,0xfa,0x11,0x94 }, { 0x64,0x22,0x47,0xe9 }, + { 0x8c,0xc4,0xa8,0xfc }, { 0x3f,0x1a,0xa0,0xf0 }, + { 0x2c,0xd8,0x56,0x7d }, { 0x90,0xef,0x22,0x33 }, + { 0x4e,0xc7,0x87,0x49 }, { 0xd1,0xc1,0xd9,0x38 }, + { 0xa2,0xfe,0x8c,0xca }, { 0x0b,0x36,0x98,0xd4 }, + { 0x81,0xcf,0xa6,0xf5 }, { 0xde,0x28,0xa5,0x7a }, + { 0x8e,0x26,0xda,0xb7 }, { 0xbf,0xa4,0x3f,0xad }, + { 0x9d,0xe4,0x2c,0x3a }, { 0x92,0x0d,0x50,0x78 }, + { 0xcc,0x9b,0x6a,0x5f }, { 0x46,0x62,0x54,0x7e }, + { 0x13,0xc2,0xf6,0x8d }, { 0xb8,0xe8,0x90,0xd8 }, + { 0xf7,0x5e,0x2e,0x39 }, { 0xaf,0xf5,0x82,0xc3 }, + { 0x80,0xbe,0x9f,0x5d }, { 0x93,0x7c,0x69,0xd0 }, + { 0x2d,0xa9,0x6f,0xd5 }, { 0x12,0xb3,0xcf,0x25 }, + { 0x99,0x3b,0xc8,0xac }, { 0x7d,0xa7,0x10,0x18 }, + { 0x63,0x6e,0xe8,0x9c }, { 0xbb,0x7b,0xdb,0x3b }, + { 0x78,0x09,0xcd,0x26 }, { 0x18,0xf4,0x6e,0x59 }, + { 0xb7,0x01,0xec,0x9a }, { 0x9a,0xa8,0x83,0x4f }, + { 0x6e,0x65,0xe6,0x95 }, { 0xe6,0x7e,0xaa,0xff }, + { 0xcf,0x08,0x21,0xbc }, { 0xe8,0xe6,0xef,0x15 }, + { 0x9b,0xd9,0xba,0xe7 }, { 0x36,0xce,0x4a,0x6f }, + { 0x09,0xd4,0xea,0x9f }, { 0x7c,0xd6,0x29,0xb0 }, + { 0xb2,0xaf,0x31,0xa4 }, { 0x23,0x31,0x2a,0x3f }, + { 0x94,0x30,0xc6,0xa5 }, { 0x66,0xc0,0x35,0xa2 }, + { 0xbc,0x37,0x74,0x4e }, { 0xca,0xa6,0xfc,0x82 }, + { 0xd0,0xb0,0xe0,0x90 }, { 0xd8,0x15,0x33,0xa7 }, + { 0x98,0x4a,0xf1,0x04 }, { 0xda,0xf7,0x41,0xec }, + { 0x50,0x0e,0x7f,0xcd }, { 0xf6,0x2f,0x17,0x91 }, + { 0xd6,0x8d,0x76,0x4d }, { 0xb0,0x4d,0x43,0xef }, + { 0x4d,0x54,0xcc,0xaa }, { 0x04,0xdf,0xe4,0x96 }, + { 0xb5,0xe3,0x9e,0xd1 }, { 0x88,0x1b,0x4c,0x6a }, + { 0x1f,0xb8,0xc1,0x2c }, { 0x51,0x7f,0x46,0x65 }, + { 0xea,0x04,0x9d,0x5e }, { 0x35,0x5d,0x01,0x8c }, + { 0x74,0x73,0xfa,0x87 }, { 0x41,0x2e,0xfb,0x0b }, + { 0x1d,0x5a,0xb3,0x67 }, { 0xd2,0x52,0x92,0xdb }, + { 0x56,0x33,0xe9,0x10 }, { 0x47,0x13,0x6d,0xd6 }, + { 0x61,0x8c,0x9a,0xd7 }, { 0x0c,0x7a,0x37,0xa1 }, + { 0x14,0x8e,0x59,0xf8 }, { 0x3c,0x89,0xeb,0x13 }, + { 0x27,0xee,0xce,0xa9 }, { 0xc9,0x35,0xb7,0x61 }, + { 0xe5,0xed,0xe1,0x1c }, { 0xb1,0x3c,0x7a,0x47 }, + { 0xdf,0x59,0x9c,0xd2 }, { 0x73,0x3f,0x55,0xf2 }, + { 0xce,0x79,0x18,0x14 }, { 0x37,0xbf,0x73,0xc7 }, + { 0xcd,0xea,0x53,0xf7 }, { 0xaa,0x5b,0x5f,0xfd }, + { 0x6f,0x14,0xdf,0x3d }, { 0xdb,0x86,0x78,0x44 }, + { 0xf3,0x81,0xca,0xaf }, { 0xc4,0x3e,0xb9,0x68 }, + { 0x34,0x2c,0x38,0x24 }, { 0x40,0x5f,0xc2,0xa3 }, + { 0xc3,0x72,0x16,0x1d }, { 0x25,0x0c,0xbc,0xe2 }, + { 0x49,0x8b,0x28,0x3c }, { 0x95,0x41,0xff,0x0d }, + { 0x01,0x71,0x39,0xa8 }, { 0xb3,0xde,0x08,0x0c }, + { 0xe4,0x9c,0xd8,0xb4 }, { 0xc1,0x90,0x64,0x56 }, + { 0x84,0x61,0x7b,0xcb }, { 0xb6,0x70,0xd5,0x32 }, + { 0x5c,0x74,0x48,0x6c }, { 0x57,0x42,0xd0,0xb8 } + }; + +static const unsigned char T8[256][4] = + { + { 0xf4,0xa7,0x50,0x51 }, { 0x41,0x65,0x53,0x7e }, + { 0x17,0xa4,0xc3,0x1a }, { 0x27,0x5e,0x96,0x3a }, + { 0xab,0x6b,0xcb,0x3b }, { 0x9d,0x45,0xf1,0x1f }, + { 0xfa,0x58,0xab,0xac }, { 0xe3,0x03,0x93,0x4b }, + { 0x30,0xfa,0x55,0x20 }, { 0x76,0x6d,0xf6,0xad }, + { 0xcc,0x76,0x91,0x88 }, { 0x02,0x4c,0x25,0xf5 }, + { 0xe5,0xd7,0xfc,0x4f }, { 0x2a,0xcb,0xd7,0xc5 }, + { 0x35,0x44,0x80,0x26 }, { 0x62,0xa3,0x8f,0xb5 }, + { 0xb1,0x5a,0x49,0xde }, { 0xba,0x1b,0x67,0x25 }, + { 0xea,0x0e,0x98,0x45 }, { 0xfe,0xc0,0xe1,0x5d }, + { 0x2f,0x75,0x02,0xc3 }, { 0x4c,0xf0,0x12,0x81 }, + { 0x46,0x97,0xa3,0x8d }, { 0xd3,0xf9,0xc6,0x6b }, + { 0x8f,0x5f,0xe7,0x03 }, { 0x92,0x9c,0x95,0x15 }, + { 0x6d,0x7a,0xeb,0xbf }, { 0x52,0x59,0xda,0x95 }, + { 0xbe,0x83,0x2d,0xd4 }, { 0x74,0x21,0xd3,0x58 }, + { 0xe0,0x69,0x29,0x49 }, { 0xc9,0xc8,0x44,0x8e }, + { 0xc2,0x89,0x6a,0x75 }, { 0x8e,0x79,0x78,0xf4 }, + { 0x58,0x3e,0x6b,0x99 }, { 0xb9,0x71,0xdd,0x27 }, + { 0xe1,0x4f,0xb6,0xbe }, { 0x88,0xad,0x17,0xf0 }, + { 0x20,0xac,0x66,0xc9 }, { 0xce,0x3a,0xb4,0x7d }, + { 0xdf,0x4a,0x18,0x63 }, { 0x1a,0x31,0x82,0xe5 }, + { 0x51,0x33,0x60,0x97 }, { 0x53,0x7f,0x45,0x62 }, + { 0x64,0x77,0xe0,0xb1 }, { 0x6b,0xae,0x84,0xbb }, + { 0x81,0xa0,0x1c,0xfe }, { 0x08,0x2b,0x94,0xf9 }, + { 0x48,0x68,0x58,0x70 }, { 0x45,0xfd,0x19,0x8f }, + { 0xde,0x6c,0x87,0x94 }, { 0x7b,0xf8,0xb7,0x52 }, + { 0x73,0xd3,0x23,0xab }, { 0x4b,0x02,0xe2,0x72 }, + { 0x1f,0x8f,0x57,0xe3 }, { 0x55,0xab,0x2a,0x66 }, + { 0xeb,0x28,0x07,0xb2 }, { 0xb5,0xc2,0x03,0x2f }, + { 0xc5,0x7b,0x9a,0x86 }, { 0x37,0x08,0xa5,0xd3 }, + { 0x28,0x87,0xf2,0x30 }, { 0xbf,0xa5,0xb2,0x23 }, + { 0x03,0x6a,0xba,0x02 }, { 0x16,0x82,0x5c,0xed }, + { 0xcf,0x1c,0x2b,0x8a }, { 0x79,0xb4,0x92,0xa7 }, + { 0x07,0xf2,0xf0,0xf3 }, { 0x69,0xe2,0xa1,0x4e }, + { 0xda,0xf4,0xcd,0x65 }, { 0x05,0xbe,0xd5,0x06 }, + { 0x34,0x62,0x1f,0xd1 }, { 0xa6,0xfe,0x8a,0xc4 }, + { 0x2e,0x53,0x9d,0x34 }, { 0xf3,0x55,0xa0,0xa2 }, + { 0x8a,0xe1,0x32,0x05 }, { 0xf6,0xeb,0x75,0xa4 }, + { 0x83,0xec,0x39,0x0b }, { 0x60,0xef,0xaa,0x40 }, + { 0x71,0x9f,0x06,0x5e }, { 0x6e,0x10,0x51,0xbd }, + { 0x21,0x8a,0xf9,0x3e }, { 0xdd,0x06,0x3d,0x96 }, + { 0x3e,0x05,0xae,0xdd }, { 0xe6,0xbd,0x46,0x4d }, + { 0x54,0x8d,0xb5,0x91 }, { 0xc4,0x5d,0x05,0x71 }, + { 0x06,0xd4,0x6f,0x04 }, { 0x50,0x15,0xff,0x60 }, + { 0x98,0xfb,0x24,0x19 }, { 0xbd,0xe9,0x97,0xd6 }, + { 0x40,0x43,0xcc,0x89 }, { 0xd9,0x9e,0x77,0x67 }, + { 0xe8,0x42,0xbd,0xb0 }, { 0x89,0x8b,0x88,0x07 }, + { 0x19,0x5b,0x38,0xe7 }, { 0xc8,0xee,0xdb,0x79 }, + { 0x7c,0x0a,0x47,0xa1 }, { 0x42,0x0f,0xe9,0x7c }, + { 0x84,0x1e,0xc9,0xf8 }, { 0x00,0x00,0x00,0x00 }, + { 0x80,0x86,0x83,0x09 }, { 0x2b,0xed,0x48,0x32 }, + { 0x11,0x70,0xac,0x1e }, { 0x5a,0x72,0x4e,0x6c }, + { 0x0e,0xff,0xfb,0xfd }, { 0x85,0x38,0x56,0x0f }, + { 0xae,0xd5,0x1e,0x3d }, { 0x2d,0x39,0x27,0x36 }, + { 0x0f,0xd9,0x64,0x0a }, { 0x5c,0xa6,0x21,0x68 }, + { 0x5b,0x54,0xd1,0x9b }, { 0x36,0x2e,0x3a,0x24 }, + { 0x0a,0x67,0xb1,0x0c }, { 0x57,0xe7,0x0f,0x93 }, + { 0xee,0x96,0xd2,0xb4 }, { 0x9b,0x91,0x9e,0x1b }, + { 0xc0,0xc5,0x4f,0x80 }, { 0xdc,0x20,0xa2,0x61 }, + { 0x77,0x4b,0x69,0x5a }, { 0x12,0x1a,0x16,0x1c }, + { 0x93,0xba,0x0a,0xe2 }, { 0xa0,0x2a,0xe5,0xc0 }, + { 0x22,0xe0,0x43,0x3c }, { 0x1b,0x17,0x1d,0x12 }, + { 0x09,0x0d,0x0b,0x0e }, { 0x8b,0xc7,0xad,0xf2 }, + { 0xb6,0xa8,0xb9,0x2d }, { 0x1e,0xa9,0xc8,0x14 }, + { 0xf1,0x19,0x85,0x57 }, { 0x75,0x07,0x4c,0xaf }, + { 0x99,0xdd,0xbb,0xee }, { 0x7f,0x60,0xfd,0xa3 }, + { 0x01,0x26,0x9f,0xf7 }, { 0x72,0xf5,0xbc,0x5c }, + { 0x66,0x3b,0xc5,0x44 }, { 0xfb,0x7e,0x34,0x5b }, + { 0x43,0x29,0x76,0x8b }, { 0x23,0xc6,0xdc,0xcb }, + { 0xed,0xfc,0x68,0xb6 }, { 0xe4,0xf1,0x63,0xb8 }, + { 0x31,0xdc,0xca,0xd7 }, { 0x63,0x85,0x10,0x42 }, + { 0x97,0x22,0x40,0x13 }, { 0xc6,0x11,0x20,0x84 }, + { 0x4a,0x24,0x7d,0x85 }, { 0xbb,0x3d,0xf8,0xd2 }, + { 0xf9,0x32,0x11,0xae }, { 0x29,0xa1,0x6d,0xc7 }, + { 0x9e,0x2f,0x4b,0x1d }, { 0xb2,0x30,0xf3,0xdc }, + { 0x86,0x52,0xec,0x0d }, { 0xc1,0xe3,0xd0,0x77 }, + { 0xb3,0x16,0x6c,0x2b }, { 0x70,0xb9,0x99,0xa9 }, + { 0x94,0x48,0xfa,0x11 }, { 0xe9,0x64,0x22,0x47 }, + { 0xfc,0x8c,0xc4,0xa8 }, { 0xf0,0x3f,0x1a,0xa0 }, + { 0x7d,0x2c,0xd8,0x56 }, { 0x33,0x90,0xef,0x22 }, + { 0x49,0x4e,0xc7,0x87 }, { 0x38,0xd1,0xc1,0xd9 }, + { 0xca,0xa2,0xfe,0x8c }, { 0xd4,0x0b,0x36,0x98 }, + { 0xf5,0x81,0xcf,0xa6 }, { 0x7a,0xde,0x28,0xa5 }, + { 0xb7,0x8e,0x26,0xda }, { 0xad,0xbf,0xa4,0x3f }, + { 0x3a,0x9d,0xe4,0x2c }, { 0x78,0x92,0x0d,0x50 }, + { 0x5f,0xcc,0x9b,0x6a }, { 0x7e,0x46,0x62,0x54 }, + { 0x8d,0x13,0xc2,0xf6 }, { 0xd8,0xb8,0xe8,0x90 }, + { 0x39,0xf7,0x5e,0x2e }, { 0xc3,0xaf,0xf5,0x82 }, + { 0x5d,0x80,0xbe,0x9f }, { 0xd0,0x93,0x7c,0x69 }, + { 0xd5,0x2d,0xa9,0x6f }, { 0x25,0x12,0xb3,0xcf }, + { 0xac,0x99,0x3b,0xc8 }, { 0x18,0x7d,0xa7,0x10 }, + { 0x9c,0x63,0x6e,0xe8 }, { 0x3b,0xbb,0x7b,0xdb }, + { 0x26,0x78,0x09,0xcd }, { 0x59,0x18,0xf4,0x6e }, + { 0x9a,0xb7,0x01,0xec }, { 0x4f,0x9a,0xa8,0x83 }, + { 0x95,0x6e,0x65,0xe6 }, { 0xff,0xe6,0x7e,0xaa }, + { 0xbc,0xcf,0x08,0x21 }, { 0x15,0xe8,0xe6,0xef }, + { 0xe7,0x9b,0xd9,0xba }, { 0x6f,0x36,0xce,0x4a }, + { 0x9f,0x09,0xd4,0xea }, { 0xb0,0x7c,0xd6,0x29 }, + { 0xa4,0xb2,0xaf,0x31 }, { 0x3f,0x23,0x31,0x2a }, + { 0xa5,0x94,0x30,0xc6 }, { 0xa2,0x66,0xc0,0x35 }, + { 0x4e,0xbc,0x37,0x74 }, { 0x82,0xca,0xa6,0xfc }, + { 0x90,0xd0,0xb0,0xe0 }, { 0xa7,0xd8,0x15,0x33 }, + { 0x04,0x98,0x4a,0xf1 }, { 0xec,0xda,0xf7,0x41 }, + { 0xcd,0x50,0x0e,0x7f }, { 0x91,0xf6,0x2f,0x17 }, + { 0x4d,0xd6,0x8d,0x76 }, { 0xef,0xb0,0x4d,0x43 }, + { 0xaa,0x4d,0x54,0xcc }, { 0x96,0x04,0xdf,0xe4 }, + { 0xd1,0xb5,0xe3,0x9e }, { 0x6a,0x88,0x1b,0x4c }, + { 0x2c,0x1f,0xb8,0xc1 }, { 0x65,0x51,0x7f,0x46 }, + { 0x5e,0xea,0x04,0x9d }, { 0x8c,0x35,0x5d,0x01 }, + { 0x87,0x74,0x73,0xfa }, { 0x0b,0x41,0x2e,0xfb }, + { 0x67,0x1d,0x5a,0xb3 }, { 0xdb,0xd2,0x52,0x92 }, + { 0x10,0x56,0x33,0xe9 }, { 0xd6,0x47,0x13,0x6d }, + { 0xd7,0x61,0x8c,0x9a }, { 0xa1,0x0c,0x7a,0x37 }, + { 0xf8,0x14,0x8e,0x59 }, { 0x13,0x3c,0x89,0xeb }, + { 0xa9,0x27,0xee,0xce }, { 0x61,0xc9,0x35,0xb7 }, + { 0x1c,0xe5,0xed,0xe1 }, { 0x47,0xb1,0x3c,0x7a }, + { 0xd2,0xdf,0x59,0x9c }, { 0xf2,0x73,0x3f,0x55 }, + { 0x14,0xce,0x79,0x18 }, { 0xc7,0x37,0xbf,0x73 }, + { 0xf7,0xcd,0xea,0x53 }, { 0xfd,0xaa,0x5b,0x5f }, + { 0x3d,0x6f,0x14,0xdf }, { 0x44,0xdb,0x86,0x78 }, + { 0xaf,0xf3,0x81,0xca }, { 0x68,0xc4,0x3e,0xb9 }, + { 0x24,0x34,0x2c,0x38 }, { 0xa3,0x40,0x5f,0xc2 }, + { 0x1d,0xc3,0x72,0x16 }, { 0xe2,0x25,0x0c,0xbc }, + { 0x3c,0x49,0x8b,0x28 }, { 0x0d,0x95,0x41,0xff }, + { 0xa8,0x01,0x71,0x39 }, { 0x0c,0xb3,0xde,0x08 }, + { 0xb4,0xe4,0x9c,0xd8 }, { 0x56,0xc1,0x90,0x64 }, + { 0xcb,0x84,0x61,0x7b }, { 0x32,0xb6,0x70,0xd5 }, + { 0x6c,0x5c,0x74,0x48 }, { 0xb8,0x57,0x42,0xd0 } + }; + +static const unsigned char S5[256] = + { + 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38, + 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, + 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87, + 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, + 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d, + 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, + 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2, + 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, + 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16, + 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, + 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda, + 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, + 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a, + 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, + 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02, + 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, + 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea, + 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, + 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85, + 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, + 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89, + 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, + 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20, + 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, + 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31, + 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, + 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d, + 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, + 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0, + 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, + 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26, + 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d + }; + +static const unsigned char U1[256][4] = + { + { 0x00,0x00,0x00,0x00 }, { 0x0e,0x09,0x0d,0x0b }, + { 0x1c,0x12,0x1a,0x16 }, { 0x12,0x1b,0x17,0x1d }, + { 0x38,0x24,0x34,0x2c }, { 0x36,0x2d,0x39,0x27 }, + { 0x24,0x36,0x2e,0x3a }, { 0x2a,0x3f,0x23,0x31 }, + { 0x70,0x48,0x68,0x58 }, { 0x7e,0x41,0x65,0x53 }, + { 0x6c,0x5a,0x72,0x4e }, { 0x62,0x53,0x7f,0x45 }, + { 0x48,0x6c,0x5c,0x74 }, { 0x46,0x65,0x51,0x7f }, + { 0x54,0x7e,0x46,0x62 }, { 0x5a,0x77,0x4b,0x69 }, + { 0xe0,0x90,0xd0,0xb0 }, { 0xee,0x99,0xdd,0xbb }, + { 0xfc,0x82,0xca,0xa6 }, { 0xf2,0x8b,0xc7,0xad }, + { 0xd8,0xb4,0xe4,0x9c }, { 0xd6,0xbd,0xe9,0x97 }, + { 0xc4,0xa6,0xfe,0x8a }, { 0xca,0xaf,0xf3,0x81 }, + { 0x90,0xd8,0xb8,0xe8 }, { 0x9e,0xd1,0xb5,0xe3 }, + { 0x8c,0xca,0xa2,0xfe }, { 0x82,0xc3,0xaf,0xf5 }, + { 0xa8,0xfc,0x8c,0xc4 }, { 0xa6,0xf5,0x81,0xcf }, + { 0xb4,0xee,0x96,0xd2 }, { 0xba,0xe7,0x9b,0xd9 }, + { 0xdb,0x3b,0xbb,0x7b }, { 0xd5,0x32,0xb6,0x70 }, + { 0xc7,0x29,0xa1,0x6d }, { 0xc9,0x20,0xac,0x66 }, + { 0xe3,0x1f,0x8f,0x57 }, { 0xed,0x16,0x82,0x5c }, + { 0xff,0x0d,0x95,0x41 }, { 0xf1,0x04,0x98,0x4a }, + { 0xab,0x73,0xd3,0x23 }, { 0xa5,0x7a,0xde,0x28 }, + { 0xb7,0x61,0xc9,0x35 }, { 0xb9,0x68,0xc4,0x3e }, + { 0x93,0x57,0xe7,0x0f }, { 0x9d,0x5e,0xea,0x04 }, + { 0x8f,0x45,0xfd,0x19 }, { 0x81,0x4c,0xf0,0x12 }, + { 0x3b,0xab,0x6b,0xcb }, { 0x35,0xa2,0x66,0xc0 }, + { 0x27,0xb9,0x71,0xdd }, { 0x29,0xb0,0x7c,0xd6 }, + { 0x03,0x8f,0x5f,0xe7 }, { 0x0d,0x86,0x52,0xec }, + { 0x1f,0x9d,0x45,0xf1 }, { 0x11,0x94,0x48,0xfa }, + { 0x4b,0xe3,0x03,0x93 }, { 0x45,0xea,0x0e,0x98 }, + { 0x57,0xf1,0x19,0x85 }, { 0x59,0xf8,0x14,0x8e }, + { 0x73,0xc7,0x37,0xbf }, { 0x7d,0xce,0x3a,0xb4 }, + { 0x6f,0xd5,0x2d,0xa9 }, { 0x61,0xdc,0x20,0xa2 }, + { 0xad,0x76,0x6d,0xf6 }, { 0xa3,0x7f,0x60,0xfd }, + { 0xb1,0x64,0x77,0xe0 }, { 0xbf,0x6d,0x7a,0xeb }, + { 0x95,0x52,0x59,0xda }, { 0x9b,0x5b,0x54,0xd1 }, + { 0x89,0x40,0x43,0xcc }, { 0x87,0x49,0x4e,0xc7 }, + { 0xdd,0x3e,0x05,0xae }, { 0xd3,0x37,0x08,0xa5 }, + { 0xc1,0x2c,0x1f,0xb8 }, { 0xcf,0x25,0x12,0xb3 }, + { 0xe5,0x1a,0x31,0x82 }, { 0xeb,0x13,0x3c,0x89 }, + { 0xf9,0x08,0x2b,0x94 }, { 0xf7,0x01,0x26,0x9f }, + { 0x4d,0xe6,0xbd,0x46 }, { 0x43,0xef,0xb0,0x4d }, + { 0x51,0xf4,0xa7,0x50 }, { 0x5f,0xfd,0xaa,0x5b }, + { 0x75,0xc2,0x89,0x6a }, { 0x7b,0xcb,0x84,0x61 }, + { 0x69,0xd0,0x93,0x7c }, { 0x67,0xd9,0x9e,0x77 }, + { 0x3d,0xae,0xd5,0x1e }, { 0x33,0xa7,0xd8,0x15 }, + { 0x21,0xbc,0xcf,0x08 }, { 0x2f,0xb5,0xc2,0x03 }, + { 0x05,0x8a,0xe1,0x32 }, { 0x0b,0x83,0xec,0x39 }, + { 0x19,0x98,0xfb,0x24 }, { 0x17,0x91,0xf6,0x2f }, + { 0x76,0x4d,0xd6,0x8d }, { 0x78,0x44,0xdb,0x86 }, + { 0x6a,0x5f,0xcc,0x9b }, { 0x64,0x56,0xc1,0x90 }, + { 0x4e,0x69,0xe2,0xa1 }, { 0x40,0x60,0xef,0xaa }, + { 0x52,0x7b,0xf8,0xb7 }, { 0x5c,0x72,0xf5,0xbc }, + { 0x06,0x05,0xbe,0xd5 }, { 0x08,0x0c,0xb3,0xde }, + { 0x1a,0x17,0xa4,0xc3 }, { 0x14,0x1e,0xa9,0xc8 }, + { 0x3e,0x21,0x8a,0xf9 }, { 0x30,0x28,0x87,0xf2 }, + { 0x22,0x33,0x90,0xef }, { 0x2c,0x3a,0x9d,0xe4 }, + { 0x96,0xdd,0x06,0x3d }, { 0x98,0xd4,0x0b,0x36 }, + { 0x8a,0xcf,0x1c,0x2b }, { 0x84,0xc6,0x11,0x20 }, + { 0xae,0xf9,0x32,0x11 }, { 0xa0,0xf0,0x3f,0x1a }, + { 0xb2,0xeb,0x28,0x07 }, { 0xbc,0xe2,0x25,0x0c }, + { 0xe6,0x95,0x6e,0x65 }, { 0xe8,0x9c,0x63,0x6e }, + { 0xfa,0x87,0x74,0x73 }, { 0xf4,0x8e,0x79,0x78 }, + { 0xde,0xb1,0x5a,0x49 }, { 0xd0,0xb8,0x57,0x42 }, + { 0xc2,0xa3,0x40,0x5f }, { 0xcc,0xaa,0x4d,0x54 }, + { 0x41,0xec,0xda,0xf7 }, { 0x4f,0xe5,0xd7,0xfc }, + { 0x5d,0xfe,0xc0,0xe1 }, { 0x53,0xf7,0xcd,0xea }, + { 0x79,0xc8,0xee,0xdb }, { 0x77,0xc1,0xe3,0xd0 }, + { 0x65,0xda,0xf4,0xcd }, { 0x6b,0xd3,0xf9,0xc6 }, + { 0x31,0xa4,0xb2,0xaf }, { 0x3f,0xad,0xbf,0xa4 }, + { 0x2d,0xb6,0xa8,0xb9 }, { 0x23,0xbf,0xa5,0xb2 }, + { 0x09,0x80,0x86,0x83 }, { 0x07,0x89,0x8b,0x88 }, + { 0x15,0x92,0x9c,0x95 }, { 0x1b,0x9b,0x91,0x9e }, + { 0xa1,0x7c,0x0a,0x47 }, { 0xaf,0x75,0x07,0x4c }, + { 0xbd,0x6e,0x10,0x51 }, { 0xb3,0x67,0x1d,0x5a }, + { 0x99,0x58,0x3e,0x6b }, { 0x97,0x51,0x33,0x60 }, + { 0x85,0x4a,0x24,0x7d }, { 0x8b,0x43,0x29,0x76 }, + { 0xd1,0x34,0x62,0x1f }, { 0xdf,0x3d,0x6f,0x14 }, + { 0xcd,0x26,0x78,0x09 }, { 0xc3,0x2f,0x75,0x02 }, + { 0xe9,0x10,0x56,0x33 }, { 0xe7,0x19,0x5b,0x38 }, + { 0xf5,0x02,0x4c,0x25 }, { 0xfb,0x0b,0x41,0x2e }, + { 0x9a,0xd7,0x61,0x8c }, { 0x94,0xde,0x6c,0x87 }, + { 0x86,0xc5,0x7b,0x9a }, { 0x88,0xcc,0x76,0x91 }, + { 0xa2,0xf3,0x55,0xa0 }, { 0xac,0xfa,0x58,0xab }, + { 0xbe,0xe1,0x4f,0xb6 }, { 0xb0,0xe8,0x42,0xbd }, + { 0xea,0x9f,0x09,0xd4 }, { 0xe4,0x96,0x04,0xdf }, + { 0xf6,0x8d,0x13,0xc2 }, { 0xf8,0x84,0x1e,0xc9 }, + { 0xd2,0xbb,0x3d,0xf8 }, { 0xdc,0xb2,0x30,0xf3 }, + { 0xce,0xa9,0x27,0xee }, { 0xc0,0xa0,0x2a,0xe5 }, + { 0x7a,0x47,0xb1,0x3c }, { 0x74,0x4e,0xbc,0x37 }, + { 0x66,0x55,0xab,0x2a }, { 0x68,0x5c,0xa6,0x21 }, + { 0x42,0x63,0x85,0x10 }, { 0x4c,0x6a,0x88,0x1b }, + { 0x5e,0x71,0x9f,0x06 }, { 0x50,0x78,0x92,0x0d }, + { 0x0a,0x0f,0xd9,0x64 }, { 0x04,0x06,0xd4,0x6f }, + { 0x16,0x1d,0xc3,0x72 }, { 0x18,0x14,0xce,0x79 }, + { 0x32,0x2b,0xed,0x48 }, { 0x3c,0x22,0xe0,0x43 }, + { 0x2e,0x39,0xf7,0x5e }, { 0x20,0x30,0xfa,0x55 }, + { 0xec,0x9a,0xb7,0x01 }, { 0xe2,0x93,0xba,0x0a }, + { 0xf0,0x88,0xad,0x17 }, { 0xfe,0x81,0xa0,0x1c }, + { 0xd4,0xbe,0x83,0x2d }, { 0xda,0xb7,0x8e,0x26 }, + { 0xc8,0xac,0x99,0x3b }, { 0xc6,0xa5,0x94,0x30 }, + { 0x9c,0xd2,0xdf,0x59 }, { 0x92,0xdb,0xd2,0x52 }, + { 0x80,0xc0,0xc5,0x4f }, { 0x8e,0xc9,0xc8,0x44 }, + { 0xa4,0xf6,0xeb,0x75 }, { 0xaa,0xff,0xe6,0x7e }, + { 0xb8,0xe4,0xf1,0x63 }, { 0xb6,0xed,0xfc,0x68 }, + { 0x0c,0x0a,0x67,0xb1 }, { 0x02,0x03,0x6a,0xba }, + { 0x10,0x18,0x7d,0xa7 }, { 0x1e,0x11,0x70,0xac }, + { 0x34,0x2e,0x53,0x9d }, { 0x3a,0x27,0x5e,0x96 }, + { 0x28,0x3c,0x49,0x8b }, { 0x26,0x35,0x44,0x80 }, + { 0x7c,0x42,0x0f,0xe9 }, { 0x72,0x4b,0x02,0xe2 }, + { 0x60,0x50,0x15,0xff }, { 0x6e,0x59,0x18,0xf4 }, + { 0x44,0x66,0x3b,0xc5 }, { 0x4a,0x6f,0x36,0xce }, + { 0x58,0x74,0x21,0xd3 }, { 0x56,0x7d,0x2c,0xd8 }, + { 0x37,0xa1,0x0c,0x7a }, { 0x39,0xa8,0x01,0x71 }, + { 0x2b,0xb3,0x16,0x6c }, { 0x25,0xba,0x1b,0x67 }, + { 0x0f,0x85,0x38,0x56 }, { 0x01,0x8c,0x35,0x5d }, + { 0x13,0x97,0x22,0x40 }, { 0x1d,0x9e,0x2f,0x4b }, + { 0x47,0xe9,0x64,0x22 }, { 0x49,0xe0,0x69,0x29 }, + { 0x5b,0xfb,0x7e,0x34 }, { 0x55,0xf2,0x73,0x3f }, + { 0x7f,0xcd,0x50,0x0e }, { 0x71,0xc4,0x5d,0x05 }, + { 0x63,0xdf,0x4a,0x18 }, { 0x6d,0xd6,0x47,0x13 }, + { 0xd7,0x31,0xdc,0xca }, { 0xd9,0x38,0xd1,0xc1 }, + { 0xcb,0x23,0xc6,0xdc }, { 0xc5,0x2a,0xcb,0xd7 }, + { 0xef,0x15,0xe8,0xe6 }, { 0xe1,0x1c,0xe5,0xed }, + { 0xf3,0x07,0xf2,0xf0 }, { 0xfd,0x0e,0xff,0xfb }, + { 0xa7,0x79,0xb4,0x92 }, { 0xa9,0x70,0xb9,0x99 }, + { 0xbb,0x6b,0xae,0x84 }, { 0xb5,0x62,0xa3,0x8f }, + { 0x9f,0x5d,0x80,0xbe }, { 0x91,0x54,0x8d,0xb5 }, + { 0x83,0x4f,0x9a,0xa8 }, { 0x8d,0x46,0x97,0xa3 } + }; + +static const unsigned char U2[256][4] = + { + { 0x00,0x00,0x00,0x00 }, { 0x0b,0x0e,0x09,0x0d }, + { 0x16,0x1c,0x12,0x1a }, { 0x1d,0x12,0x1b,0x17 }, + { 0x2c,0x38,0x24,0x34 }, { 0x27,0x36,0x2d,0x39 }, + { 0x3a,0x24,0x36,0x2e }, { 0x31,0x2a,0x3f,0x23 }, + { 0x58,0x70,0x48,0x68 }, { 0x53,0x7e,0x41,0x65 }, + { 0x4e,0x6c,0x5a,0x72 }, { 0x45,0x62,0x53,0x7f }, + { 0x74,0x48,0x6c,0x5c }, { 0x7f,0x46,0x65,0x51 }, + { 0x62,0x54,0x7e,0x46 }, { 0x69,0x5a,0x77,0x4b }, + { 0xb0,0xe0,0x90,0xd0 }, { 0xbb,0xee,0x99,0xdd }, + { 0xa6,0xfc,0x82,0xca }, { 0xad,0xf2,0x8b,0xc7 }, + { 0x9c,0xd8,0xb4,0xe4 }, { 0x97,0xd6,0xbd,0xe9 }, + { 0x8a,0xc4,0xa6,0xfe }, { 0x81,0xca,0xaf,0xf3 }, + { 0xe8,0x90,0xd8,0xb8 }, { 0xe3,0x9e,0xd1,0xb5 }, + { 0xfe,0x8c,0xca,0xa2 }, { 0xf5,0x82,0xc3,0xaf }, + { 0xc4,0xa8,0xfc,0x8c }, { 0xcf,0xa6,0xf5,0x81 }, + { 0xd2,0xb4,0xee,0x96 }, { 0xd9,0xba,0xe7,0x9b }, + { 0x7b,0xdb,0x3b,0xbb }, { 0x70,0xd5,0x32,0xb6 }, + { 0x6d,0xc7,0x29,0xa1 }, { 0x66,0xc9,0x20,0xac }, + { 0x57,0xe3,0x1f,0x8f }, { 0x5c,0xed,0x16,0x82 }, + { 0x41,0xff,0x0d,0x95 }, { 0x4a,0xf1,0x04,0x98 }, + { 0x23,0xab,0x73,0xd3 }, { 0x28,0xa5,0x7a,0xde }, + { 0x35,0xb7,0x61,0xc9 }, { 0x3e,0xb9,0x68,0xc4 }, + { 0x0f,0x93,0x57,0xe7 }, { 0x04,0x9d,0x5e,0xea }, + { 0x19,0x8f,0x45,0xfd }, { 0x12,0x81,0x4c,0xf0 }, + { 0xcb,0x3b,0xab,0x6b }, { 0xc0,0x35,0xa2,0x66 }, + { 0xdd,0x27,0xb9,0x71 }, { 0xd6,0x29,0xb0,0x7c }, + { 0xe7,0x03,0x8f,0x5f }, { 0xec,0x0d,0x86,0x52 }, + { 0xf1,0x1f,0x9d,0x45 }, { 0xfa,0x11,0x94,0x48 }, + { 0x93,0x4b,0xe3,0x03 }, { 0x98,0x45,0xea,0x0e }, + { 0x85,0x57,0xf1,0x19 }, { 0x8e,0x59,0xf8,0x14 }, + { 0xbf,0x73,0xc7,0x37 }, { 0xb4,0x7d,0xce,0x3a }, + { 0xa9,0x6f,0xd5,0x2d }, { 0xa2,0x61,0xdc,0x20 }, + { 0xf6,0xad,0x76,0x6d }, { 0xfd,0xa3,0x7f,0x60 }, + { 0xe0,0xb1,0x64,0x77 }, { 0xeb,0xbf,0x6d,0x7a }, + { 0xda,0x95,0x52,0x59 }, { 0xd1,0x9b,0x5b,0x54 }, + { 0xcc,0x89,0x40,0x43 }, { 0xc7,0x87,0x49,0x4e }, + { 0xae,0xdd,0x3e,0x05 }, { 0xa5,0xd3,0x37,0x08 }, + { 0xb8,0xc1,0x2c,0x1f }, { 0xb3,0xcf,0x25,0x12 }, + { 0x82,0xe5,0x1a,0x31 }, { 0x89,0xeb,0x13,0x3c }, + { 0x94,0xf9,0x08,0x2b }, { 0x9f,0xf7,0x01,0x26 }, + { 0x46,0x4d,0xe6,0xbd }, { 0x4d,0x43,0xef,0xb0 }, + { 0x50,0x51,0xf4,0xa7 }, { 0x5b,0x5f,0xfd,0xaa }, + { 0x6a,0x75,0xc2,0x89 }, { 0x61,0x7b,0xcb,0x84 }, + { 0x7c,0x69,0xd0,0x93 }, { 0x77,0x67,0xd9,0x9e }, + { 0x1e,0x3d,0xae,0xd5 }, { 0x15,0x33,0xa7,0xd8 }, + { 0x08,0x21,0xbc,0xcf }, { 0x03,0x2f,0xb5,0xc2 }, + { 0x32,0x05,0x8a,0xe1 }, { 0x39,0x0b,0x83,0xec }, + { 0x24,0x19,0x98,0xfb }, { 0x2f,0x17,0x91,0xf6 }, + { 0x8d,0x76,0x4d,0xd6 }, { 0x86,0x78,0x44,0xdb }, + { 0x9b,0x6a,0x5f,0xcc }, { 0x90,0x64,0x56,0xc1 }, + { 0xa1,0x4e,0x69,0xe2 }, { 0xaa,0x40,0x60,0xef }, + { 0xb7,0x52,0x7b,0xf8 }, { 0xbc,0x5c,0x72,0xf5 }, + { 0xd5,0x06,0x05,0xbe }, { 0xde,0x08,0x0c,0xb3 }, + { 0xc3,0x1a,0x17,0xa4 }, { 0xc8,0x14,0x1e,0xa9 }, + { 0xf9,0x3e,0x21,0x8a }, { 0xf2,0x30,0x28,0x87 }, + { 0xef,0x22,0x33,0x90 }, { 0xe4,0x2c,0x3a,0x9d }, + { 0x3d,0x96,0xdd,0x06 }, { 0x36,0x98,0xd4,0x0b }, + { 0x2b,0x8a,0xcf,0x1c }, { 0x20,0x84,0xc6,0x11 }, + { 0x11,0xae,0xf9,0x32 }, { 0x1a,0xa0,0xf0,0x3f }, + { 0x07,0xb2,0xeb,0x28 }, { 0x0c,0xbc,0xe2,0x25 }, + { 0x65,0xe6,0x95,0x6e }, { 0x6e,0xe8,0x9c,0x63 }, + { 0x73,0xfa,0x87,0x74 }, { 0x78,0xf4,0x8e,0x79 }, + { 0x49,0xde,0xb1,0x5a }, { 0x42,0xd0,0xb8,0x57 }, + { 0x5f,0xc2,0xa3,0x40 }, { 0x54,0xcc,0xaa,0x4d }, + { 0xf7,0x41,0xec,0xda }, { 0xfc,0x4f,0xe5,0xd7 }, + { 0xe1,0x5d,0xfe,0xc0 }, { 0xea,0x53,0xf7,0xcd }, + { 0xdb,0x79,0xc8,0xee }, { 0xd0,0x77,0xc1,0xe3 }, + { 0xcd,0x65,0xda,0xf4 }, { 0xc6,0x6b,0xd3,0xf9 }, + { 0xaf,0x31,0xa4,0xb2 }, { 0xa4,0x3f,0xad,0xbf }, + { 0xb9,0x2d,0xb6,0xa8 }, { 0xb2,0x23,0xbf,0xa5 }, + { 0x83,0x09,0x80,0x86 }, { 0x88,0x07,0x89,0x8b }, + { 0x95,0x15,0x92,0x9c }, { 0x9e,0x1b,0x9b,0x91 }, + { 0x47,0xa1,0x7c,0x0a }, { 0x4c,0xaf,0x75,0x07 }, + { 0x51,0xbd,0x6e,0x10 }, { 0x5a,0xb3,0x67,0x1d }, + { 0x6b,0x99,0x58,0x3e }, { 0x60,0x97,0x51,0x33 }, + { 0x7d,0x85,0x4a,0x24 }, { 0x76,0x8b,0x43,0x29 }, + { 0x1f,0xd1,0x34,0x62 }, { 0x14,0xdf,0x3d,0x6f }, + { 0x09,0xcd,0x26,0x78 }, { 0x02,0xc3,0x2f,0x75 }, + { 0x33,0xe9,0x10,0x56 }, { 0x38,0xe7,0x19,0x5b }, + { 0x25,0xf5,0x02,0x4c }, { 0x2e,0xfb,0x0b,0x41 }, + { 0x8c,0x9a,0xd7,0x61 }, { 0x87,0x94,0xde,0x6c }, + { 0x9a,0x86,0xc5,0x7b }, { 0x91,0x88,0xcc,0x76 }, + { 0xa0,0xa2,0xf3,0x55 }, { 0xab,0xac,0xfa,0x58 }, + { 0xb6,0xbe,0xe1,0x4f }, { 0xbd,0xb0,0xe8,0x42 }, + { 0xd4,0xea,0x9f,0x09 }, { 0xdf,0xe4,0x96,0x04 }, + { 0xc2,0xf6,0x8d,0x13 }, { 0xc9,0xf8,0x84,0x1e }, + { 0xf8,0xd2,0xbb,0x3d }, { 0xf3,0xdc,0xb2,0x30 }, + { 0xee,0xce,0xa9,0x27 }, { 0xe5,0xc0,0xa0,0x2a }, + { 0x3c,0x7a,0x47,0xb1 }, { 0x37,0x74,0x4e,0xbc }, + { 0x2a,0x66,0x55,0xab }, { 0x21,0x68,0x5c,0xa6 }, + { 0x10,0x42,0x63,0x85 }, { 0x1b,0x4c,0x6a,0x88 }, + { 0x06,0x5e,0x71,0x9f }, { 0x0d,0x50,0x78,0x92 }, + { 0x64,0x0a,0x0f,0xd9 }, { 0x6f,0x04,0x06,0xd4 }, + { 0x72,0x16,0x1d,0xc3 }, { 0x79,0x18,0x14,0xce }, + { 0x48,0x32,0x2b,0xed }, { 0x43,0x3c,0x22,0xe0 }, + { 0x5e,0x2e,0x39,0xf7 }, { 0x55,0x20,0x30,0xfa }, + { 0x01,0xec,0x9a,0xb7 }, { 0x0a,0xe2,0x93,0xba }, + { 0x17,0xf0,0x88,0xad }, { 0x1c,0xfe,0x81,0xa0 }, + { 0x2d,0xd4,0xbe,0x83 }, { 0x26,0xda,0xb7,0x8e }, + { 0x3b,0xc8,0xac,0x99 }, { 0x30,0xc6,0xa5,0x94 }, + { 0x59,0x9c,0xd2,0xdf }, { 0x52,0x92,0xdb,0xd2 }, + { 0x4f,0x80,0xc0,0xc5 }, { 0x44,0x8e,0xc9,0xc8 }, + { 0x75,0xa4,0xf6,0xeb }, { 0x7e,0xaa,0xff,0xe6 }, + { 0x63,0xb8,0xe4,0xf1 }, { 0x68,0xb6,0xed,0xfc }, + { 0xb1,0x0c,0x0a,0x67 }, { 0xba,0x02,0x03,0x6a }, + { 0xa7,0x10,0x18,0x7d }, { 0xac,0x1e,0x11,0x70 }, + { 0x9d,0x34,0x2e,0x53 }, { 0x96,0x3a,0x27,0x5e }, + { 0x8b,0x28,0x3c,0x49 }, { 0x80,0x26,0x35,0x44 }, + { 0xe9,0x7c,0x42,0x0f }, { 0xe2,0x72,0x4b,0x02 }, + { 0xff,0x60,0x50,0x15 }, { 0xf4,0x6e,0x59,0x18 }, + { 0xc5,0x44,0x66,0x3b }, { 0xce,0x4a,0x6f,0x36 }, + { 0xd3,0x58,0x74,0x21 }, { 0xd8,0x56,0x7d,0x2c }, + { 0x7a,0x37,0xa1,0x0c }, { 0x71,0x39,0xa8,0x01 }, + { 0x6c,0x2b,0xb3,0x16 }, { 0x67,0x25,0xba,0x1b }, + { 0x56,0x0f,0x85,0x38 }, { 0x5d,0x01,0x8c,0x35 }, + { 0x40,0x13,0x97,0x22 }, { 0x4b,0x1d,0x9e,0x2f }, + { 0x22,0x47,0xe9,0x64 }, { 0x29,0x49,0xe0,0x69 }, + { 0x34,0x5b,0xfb,0x7e }, { 0x3f,0x55,0xf2,0x73 }, + { 0x0e,0x7f,0xcd,0x50 }, { 0x05,0x71,0xc4,0x5d }, + { 0x18,0x63,0xdf,0x4a }, { 0x13,0x6d,0xd6,0x47 }, + { 0xca,0xd7,0x31,0xdc }, { 0xc1,0xd9,0x38,0xd1 }, + { 0xdc,0xcb,0x23,0xc6 }, { 0xd7,0xc5,0x2a,0xcb }, + { 0xe6,0xef,0x15,0xe8 }, { 0xed,0xe1,0x1c,0xe5 }, + { 0xf0,0xf3,0x07,0xf2 }, { 0xfb,0xfd,0x0e,0xff }, + { 0x92,0xa7,0x79,0xb4 }, { 0x99,0xa9,0x70,0xb9 }, + { 0x84,0xbb,0x6b,0xae }, { 0x8f,0xb5,0x62,0xa3 }, + { 0xbe,0x9f,0x5d,0x80 }, { 0xb5,0x91,0x54,0x8d }, + { 0xa8,0x83,0x4f,0x9a }, { 0xa3,0x8d,0x46,0x97 } + }; + +static const unsigned char U3[256][4] = + { + { 0x00,0x00,0x00,0x00 }, { 0x0d,0x0b,0x0e,0x09 }, + { 0x1a,0x16,0x1c,0x12 }, { 0x17,0x1d,0x12,0x1b }, + { 0x34,0x2c,0x38,0x24 }, { 0x39,0x27,0x36,0x2d }, + { 0x2e,0x3a,0x24,0x36 }, { 0x23,0x31,0x2a,0x3f }, + { 0x68,0x58,0x70,0x48 }, { 0x65,0x53,0x7e,0x41 }, + { 0x72,0x4e,0x6c,0x5a }, { 0x7f,0x45,0x62,0x53 }, + { 0x5c,0x74,0x48,0x6c }, { 0x51,0x7f,0x46,0x65 }, + { 0x46,0x62,0x54,0x7e }, { 0x4b,0x69,0x5a,0x77 }, + { 0xd0,0xb0,0xe0,0x90 }, { 0xdd,0xbb,0xee,0x99 }, + { 0xca,0xa6,0xfc,0x82 }, { 0xc7,0xad,0xf2,0x8b }, + { 0xe4,0x9c,0xd8,0xb4 }, { 0xe9,0x97,0xd6,0xbd }, + { 0xfe,0x8a,0xc4,0xa6 }, { 0xf3,0x81,0xca,0xaf }, + { 0xb8,0xe8,0x90,0xd8 }, { 0xb5,0xe3,0x9e,0xd1 }, + { 0xa2,0xfe,0x8c,0xca }, { 0xaf,0xf5,0x82,0xc3 }, + { 0x8c,0xc4,0xa8,0xfc }, { 0x81,0xcf,0xa6,0xf5 }, + { 0x96,0xd2,0xb4,0xee }, { 0x9b,0xd9,0xba,0xe7 }, + { 0xbb,0x7b,0xdb,0x3b }, { 0xb6,0x70,0xd5,0x32 }, + { 0xa1,0x6d,0xc7,0x29 }, { 0xac,0x66,0xc9,0x20 }, + { 0x8f,0x57,0xe3,0x1f }, { 0x82,0x5c,0xed,0x16 }, + { 0x95,0x41,0xff,0x0d }, { 0x98,0x4a,0xf1,0x04 }, + { 0xd3,0x23,0xab,0x73 }, { 0xde,0x28,0xa5,0x7a }, + { 0xc9,0x35,0xb7,0x61 }, { 0xc4,0x3e,0xb9,0x68 }, + { 0xe7,0x0f,0x93,0x57 }, { 0xea,0x04,0x9d,0x5e }, + { 0xfd,0x19,0x8f,0x45 }, { 0xf0,0x12,0x81,0x4c }, + { 0x6b,0xcb,0x3b,0xab }, { 0x66,0xc0,0x35,0xa2 }, + { 0x71,0xdd,0x27,0xb9 }, { 0x7c,0xd6,0x29,0xb0 }, + { 0x5f,0xe7,0x03,0x8f }, { 0x52,0xec,0x0d,0x86 }, + { 0x45,0xf1,0x1f,0x9d }, { 0x48,0xfa,0x11,0x94 }, + { 0x03,0x93,0x4b,0xe3 }, { 0x0e,0x98,0x45,0xea }, + { 0x19,0x85,0x57,0xf1 }, { 0x14,0x8e,0x59,0xf8 }, + { 0x37,0xbf,0x73,0xc7 }, { 0x3a,0xb4,0x7d,0xce }, + { 0x2d,0xa9,0x6f,0xd5 }, { 0x20,0xa2,0x61,0xdc }, + { 0x6d,0xf6,0xad,0x76 }, { 0x60,0xfd,0xa3,0x7f }, + { 0x77,0xe0,0xb1,0x64 }, { 0x7a,0xeb,0xbf,0x6d }, + { 0x59,0xda,0x95,0x52 }, { 0x54,0xd1,0x9b,0x5b }, + { 0x43,0xcc,0x89,0x40 }, { 0x4e,0xc7,0x87,0x49 }, + { 0x05,0xae,0xdd,0x3e }, { 0x08,0xa5,0xd3,0x37 }, + { 0x1f,0xb8,0xc1,0x2c }, { 0x12,0xb3,0xcf,0x25 }, + { 0x31,0x82,0xe5,0x1a }, { 0x3c,0x89,0xeb,0x13 }, + { 0x2b,0x94,0xf9,0x08 }, { 0x26,0x9f,0xf7,0x01 }, + { 0xbd,0x46,0x4d,0xe6 }, { 0xb0,0x4d,0x43,0xef }, + { 0xa7,0x50,0x51,0xf4 }, { 0xaa,0x5b,0x5f,0xfd }, + { 0x89,0x6a,0x75,0xc2 }, { 0x84,0x61,0x7b,0xcb }, + { 0x93,0x7c,0x69,0xd0 }, { 0x9e,0x77,0x67,0xd9 }, + { 0xd5,0x1e,0x3d,0xae }, { 0xd8,0x15,0x33,0xa7 }, + { 0xcf,0x08,0x21,0xbc }, { 0xc2,0x03,0x2f,0xb5 }, + { 0xe1,0x32,0x05,0x8a }, { 0xec,0x39,0x0b,0x83 }, + { 0xfb,0x24,0x19,0x98 }, { 0xf6,0x2f,0x17,0x91 }, + { 0xd6,0x8d,0x76,0x4d }, { 0xdb,0x86,0x78,0x44 }, + { 0xcc,0x9b,0x6a,0x5f }, { 0xc1,0x90,0x64,0x56 }, + { 0xe2,0xa1,0x4e,0x69 }, { 0xef,0xaa,0x40,0x60 }, + { 0xf8,0xb7,0x52,0x7b }, { 0xf5,0xbc,0x5c,0x72 }, + { 0xbe,0xd5,0x06,0x05 }, { 0xb3,0xde,0x08,0x0c }, + { 0xa4,0xc3,0x1a,0x17 }, { 0xa9,0xc8,0x14,0x1e }, + { 0x8a,0xf9,0x3e,0x21 }, { 0x87,0xf2,0x30,0x28 }, + { 0x90,0xef,0x22,0x33 }, { 0x9d,0xe4,0x2c,0x3a }, + { 0x06,0x3d,0x96,0xdd }, { 0x0b,0x36,0x98,0xd4 }, + { 0x1c,0x2b,0x8a,0xcf }, { 0x11,0x20,0x84,0xc6 }, + { 0x32,0x11,0xae,0xf9 }, { 0x3f,0x1a,0xa0,0xf0 }, + { 0x28,0x07,0xb2,0xeb }, { 0x25,0x0c,0xbc,0xe2 }, + { 0x6e,0x65,0xe6,0x95 }, { 0x63,0x6e,0xe8,0x9c }, + { 0x74,0x73,0xfa,0x87 }, { 0x79,0x78,0xf4,0x8e }, + { 0x5a,0x49,0xde,0xb1 }, { 0x57,0x42,0xd0,0xb8 }, + { 0x40,0x5f,0xc2,0xa3 }, { 0x4d,0x54,0xcc,0xaa }, + { 0xda,0xf7,0x41,0xec }, { 0xd7,0xfc,0x4f,0xe5 }, + { 0xc0,0xe1,0x5d,0xfe }, { 0xcd,0xea,0x53,0xf7 }, + { 0xee,0xdb,0x79,0xc8 }, { 0xe3,0xd0,0x77,0xc1 }, + { 0xf4,0xcd,0x65,0xda }, { 0xf9,0xc6,0x6b,0xd3 }, + { 0xb2,0xaf,0x31,0xa4 }, { 0xbf,0xa4,0x3f,0xad }, + { 0xa8,0xb9,0x2d,0xb6 }, { 0xa5,0xb2,0x23,0xbf }, + { 0x86,0x83,0x09,0x80 }, { 0x8b,0x88,0x07,0x89 }, + { 0x9c,0x95,0x15,0x92 }, { 0x91,0x9e,0x1b,0x9b }, + { 0x0a,0x47,0xa1,0x7c }, { 0x07,0x4c,0xaf,0x75 }, + { 0x10,0x51,0xbd,0x6e }, { 0x1d,0x5a,0xb3,0x67 }, + { 0x3e,0x6b,0x99,0x58 }, { 0x33,0x60,0x97,0x51 }, + { 0x24,0x7d,0x85,0x4a }, { 0x29,0x76,0x8b,0x43 }, + { 0x62,0x1f,0xd1,0x34 }, { 0x6f,0x14,0xdf,0x3d }, + { 0x78,0x09,0xcd,0x26 }, { 0x75,0x02,0xc3,0x2f }, + { 0x56,0x33,0xe9,0x10 }, { 0x5b,0x38,0xe7,0x19 }, + { 0x4c,0x25,0xf5,0x02 }, { 0x41,0x2e,0xfb,0x0b }, + { 0x61,0x8c,0x9a,0xd7 }, { 0x6c,0x87,0x94,0xde }, + { 0x7b,0x9a,0x86,0xc5 }, { 0x76,0x91,0x88,0xcc }, + { 0x55,0xa0,0xa2,0xf3 }, { 0x58,0xab,0xac,0xfa }, + { 0x4f,0xb6,0xbe,0xe1 }, { 0x42,0xbd,0xb0,0xe8 }, + { 0x09,0xd4,0xea,0x9f }, { 0x04,0xdf,0xe4,0x96 }, + { 0x13,0xc2,0xf6,0x8d }, { 0x1e,0xc9,0xf8,0x84 }, + { 0x3d,0xf8,0xd2,0xbb }, { 0x30,0xf3,0xdc,0xb2 }, + { 0x27,0xee,0xce,0xa9 }, { 0x2a,0xe5,0xc0,0xa0 }, + { 0xb1,0x3c,0x7a,0x47 }, { 0xbc,0x37,0x74,0x4e }, + { 0xab,0x2a,0x66,0x55 }, { 0xa6,0x21,0x68,0x5c }, + { 0x85,0x10,0x42,0x63 }, { 0x88,0x1b,0x4c,0x6a }, + { 0x9f,0x06,0x5e,0x71 }, { 0x92,0x0d,0x50,0x78 }, + { 0xd9,0x64,0x0a,0x0f }, { 0xd4,0x6f,0x04,0x06 }, + { 0xc3,0x72,0x16,0x1d }, { 0xce,0x79,0x18,0x14 }, + { 0xed,0x48,0x32,0x2b }, { 0xe0,0x43,0x3c,0x22 }, + { 0xf7,0x5e,0x2e,0x39 }, { 0xfa,0x55,0x20,0x30 }, + { 0xb7,0x01,0xec,0x9a }, { 0xba,0x0a,0xe2,0x93 }, + { 0xad,0x17,0xf0,0x88 }, { 0xa0,0x1c,0xfe,0x81 }, + { 0x83,0x2d,0xd4,0xbe }, { 0x8e,0x26,0xda,0xb7 }, + { 0x99,0x3b,0xc8,0xac }, { 0x94,0x30,0xc6,0xa5 }, + { 0xdf,0x59,0x9c,0xd2 }, { 0xd2,0x52,0x92,0xdb }, + { 0xc5,0x4f,0x80,0xc0 }, { 0xc8,0x44,0x8e,0xc9 }, + { 0xeb,0x75,0xa4,0xf6 }, { 0xe6,0x7e,0xaa,0xff }, + { 0xf1,0x63,0xb8,0xe4 }, { 0xfc,0x68,0xb6,0xed }, + { 0x67,0xb1,0x0c,0x0a }, { 0x6a,0xba,0x02,0x03 }, + { 0x7d,0xa7,0x10,0x18 }, { 0x70,0xac,0x1e,0x11 }, + { 0x53,0x9d,0x34,0x2e }, { 0x5e,0x96,0x3a,0x27 }, + { 0x49,0x8b,0x28,0x3c }, { 0x44,0x80,0x26,0x35 }, + { 0x0f,0xe9,0x7c,0x42 }, { 0x02,0xe2,0x72,0x4b }, + { 0x15,0xff,0x60,0x50 }, { 0x18,0xf4,0x6e,0x59 }, + { 0x3b,0xc5,0x44,0x66 }, { 0x36,0xce,0x4a,0x6f }, + { 0x21,0xd3,0x58,0x74 }, { 0x2c,0xd8,0x56,0x7d }, + { 0x0c,0x7a,0x37,0xa1 }, { 0x01,0x71,0x39,0xa8 }, + { 0x16,0x6c,0x2b,0xb3 }, { 0x1b,0x67,0x25,0xba }, + { 0x38,0x56,0x0f,0x85 }, { 0x35,0x5d,0x01,0x8c }, + { 0x22,0x40,0x13,0x97 }, { 0x2f,0x4b,0x1d,0x9e }, + { 0x64,0x22,0x47,0xe9 }, { 0x69,0x29,0x49,0xe0 }, + { 0x7e,0x34,0x5b,0xfb }, { 0x73,0x3f,0x55,0xf2 }, + { 0x50,0x0e,0x7f,0xcd }, { 0x5d,0x05,0x71,0xc4 }, + { 0x4a,0x18,0x63,0xdf }, { 0x47,0x13,0x6d,0xd6 }, + { 0xdc,0xca,0xd7,0x31 }, { 0xd1,0xc1,0xd9,0x38 }, + { 0xc6,0xdc,0xcb,0x23 }, { 0xcb,0xd7,0xc5,0x2a }, + { 0xe8,0xe6,0xef,0x15 }, { 0xe5,0xed,0xe1,0x1c }, + { 0xf2,0xf0,0xf3,0x07 }, { 0xff,0xfb,0xfd,0x0e }, + { 0xb4,0x92,0xa7,0x79 }, { 0xb9,0x99,0xa9,0x70 }, + { 0xae,0x84,0xbb,0x6b }, { 0xa3,0x8f,0xb5,0x62 }, + { 0x80,0xbe,0x9f,0x5d }, { 0x8d,0xb5,0x91,0x54 }, + { 0x9a,0xa8,0x83,0x4f }, { 0x97,0xa3,0x8d,0x46 } + }; + +static const unsigned char U4[256][4] = + { + { 0x00,0x00,0x00,0x00 }, { 0x09,0x0d,0x0b,0x0e }, + { 0x12,0x1a,0x16,0x1c }, { 0x1b,0x17,0x1d,0x12 }, + { 0x24,0x34,0x2c,0x38 }, { 0x2d,0x39,0x27,0x36 }, + { 0x36,0x2e,0x3a,0x24 }, { 0x3f,0x23,0x31,0x2a }, + { 0x48,0x68,0x58,0x70 }, { 0x41,0x65,0x53,0x7e }, + { 0x5a,0x72,0x4e,0x6c }, { 0x53,0x7f,0x45,0x62 }, + { 0x6c,0x5c,0x74,0x48 }, { 0x65,0x51,0x7f,0x46 }, + { 0x7e,0x46,0x62,0x54 }, { 0x77,0x4b,0x69,0x5a }, + { 0x90,0xd0,0xb0,0xe0 }, { 0x99,0xdd,0xbb,0xee }, + { 0x82,0xca,0xa6,0xfc }, { 0x8b,0xc7,0xad,0xf2 }, + { 0xb4,0xe4,0x9c,0xd8 }, { 0xbd,0xe9,0x97,0xd6 }, + { 0xa6,0xfe,0x8a,0xc4 }, { 0xaf,0xf3,0x81,0xca }, + { 0xd8,0xb8,0xe8,0x90 }, { 0xd1,0xb5,0xe3,0x9e }, + { 0xca,0xa2,0xfe,0x8c }, { 0xc3,0xaf,0xf5,0x82 }, + { 0xfc,0x8c,0xc4,0xa8 }, { 0xf5,0x81,0xcf,0xa6 }, + { 0xee,0x96,0xd2,0xb4 }, { 0xe7,0x9b,0xd9,0xba }, + { 0x3b,0xbb,0x7b,0xdb }, { 0x32,0xb6,0x70,0xd5 }, + { 0x29,0xa1,0x6d,0xc7 }, { 0x20,0xac,0x66,0xc9 }, + { 0x1f,0x8f,0x57,0xe3 }, { 0x16,0x82,0x5c,0xed }, + { 0x0d,0x95,0x41,0xff }, { 0x04,0x98,0x4a,0xf1 }, + { 0x73,0xd3,0x23,0xab }, { 0x7a,0xde,0x28,0xa5 }, + { 0x61,0xc9,0x35,0xb7 }, { 0x68,0xc4,0x3e,0xb9 }, + { 0x57,0xe7,0x0f,0x93 }, { 0x5e,0xea,0x04,0x9d }, + { 0x45,0xfd,0x19,0x8f }, { 0x4c,0xf0,0x12,0x81 }, + { 0xab,0x6b,0xcb,0x3b }, { 0xa2,0x66,0xc0,0x35 }, + { 0xb9,0x71,0xdd,0x27 }, { 0xb0,0x7c,0xd6,0x29 }, + { 0x8f,0x5f,0xe7,0x03 }, { 0x86,0x52,0xec,0x0d }, + { 0x9d,0x45,0xf1,0x1f }, { 0x94,0x48,0xfa,0x11 }, + { 0xe3,0x03,0x93,0x4b }, { 0xea,0x0e,0x98,0x45 }, + { 0xf1,0x19,0x85,0x57 }, { 0xf8,0x14,0x8e,0x59 }, + { 0xc7,0x37,0xbf,0x73 }, { 0xce,0x3a,0xb4,0x7d }, + { 0xd5,0x2d,0xa9,0x6f }, { 0xdc,0x20,0xa2,0x61 }, + { 0x76,0x6d,0xf6,0xad }, { 0x7f,0x60,0xfd,0xa3 }, + { 0x64,0x77,0xe0,0xb1 }, { 0x6d,0x7a,0xeb,0xbf }, + { 0x52,0x59,0xda,0x95 }, { 0x5b,0x54,0xd1,0x9b }, + { 0x40,0x43,0xcc,0x89 }, { 0x49,0x4e,0xc7,0x87 }, + { 0x3e,0x05,0xae,0xdd }, { 0x37,0x08,0xa5,0xd3 }, + { 0x2c,0x1f,0xb8,0xc1 }, { 0x25,0x12,0xb3,0xcf }, + { 0x1a,0x31,0x82,0xe5 }, { 0x13,0x3c,0x89,0xeb }, + { 0x08,0x2b,0x94,0xf9 }, { 0x01,0x26,0x9f,0xf7 }, + { 0xe6,0xbd,0x46,0x4d }, { 0xef,0xb0,0x4d,0x43 }, + { 0xf4,0xa7,0x50,0x51 }, { 0xfd,0xaa,0x5b,0x5f }, + { 0xc2,0x89,0x6a,0x75 }, { 0xcb,0x84,0x61,0x7b }, + { 0xd0,0x93,0x7c,0x69 }, { 0xd9,0x9e,0x77,0x67 }, + { 0xae,0xd5,0x1e,0x3d }, { 0xa7,0xd8,0x15,0x33 }, + { 0xbc,0xcf,0x08,0x21 }, { 0xb5,0xc2,0x03,0x2f }, + { 0x8a,0xe1,0x32,0x05 }, { 0x83,0xec,0x39,0x0b }, + { 0x98,0xfb,0x24,0x19 }, { 0x91,0xf6,0x2f,0x17 }, + { 0x4d,0xd6,0x8d,0x76 }, { 0x44,0xdb,0x86,0x78 }, + { 0x5f,0xcc,0x9b,0x6a }, { 0x56,0xc1,0x90,0x64 }, + { 0x69,0xe2,0xa1,0x4e }, { 0x60,0xef,0xaa,0x40 }, + { 0x7b,0xf8,0xb7,0x52 }, { 0x72,0xf5,0xbc,0x5c }, + { 0x05,0xbe,0xd5,0x06 }, { 0x0c,0xb3,0xde,0x08 }, + { 0x17,0xa4,0xc3,0x1a }, { 0x1e,0xa9,0xc8,0x14 }, + { 0x21,0x8a,0xf9,0x3e }, { 0x28,0x87,0xf2,0x30 }, + { 0x33,0x90,0xef,0x22 }, { 0x3a,0x9d,0xe4,0x2c }, + { 0xdd,0x06,0x3d,0x96 }, { 0xd4,0x0b,0x36,0x98 }, + { 0xcf,0x1c,0x2b,0x8a }, { 0xc6,0x11,0x20,0x84 }, + { 0xf9,0x32,0x11,0xae }, { 0xf0,0x3f,0x1a,0xa0 }, + { 0xeb,0x28,0x07,0xb2 }, { 0xe2,0x25,0x0c,0xbc }, + { 0x95,0x6e,0x65,0xe6 }, { 0x9c,0x63,0x6e,0xe8 }, + { 0x87,0x74,0x73,0xfa }, { 0x8e,0x79,0x78,0xf4 }, + { 0xb1,0x5a,0x49,0xde }, { 0xb8,0x57,0x42,0xd0 }, + { 0xa3,0x40,0x5f,0xc2 }, { 0xaa,0x4d,0x54,0xcc }, + { 0xec,0xda,0xf7,0x41 }, { 0xe5,0xd7,0xfc,0x4f }, + { 0xfe,0xc0,0xe1,0x5d }, { 0xf7,0xcd,0xea,0x53 }, + { 0xc8,0xee,0xdb,0x79 }, { 0xc1,0xe3,0xd0,0x77 }, + { 0xda,0xf4,0xcd,0x65 }, { 0xd3,0xf9,0xc6,0x6b }, + { 0xa4,0xb2,0xaf,0x31 }, { 0xad,0xbf,0xa4,0x3f }, + { 0xb6,0xa8,0xb9,0x2d }, { 0xbf,0xa5,0xb2,0x23 }, + { 0x80,0x86,0x83,0x09 }, { 0x89,0x8b,0x88,0x07 }, + { 0x92,0x9c,0x95,0x15 }, { 0x9b,0x91,0x9e,0x1b }, + { 0x7c,0x0a,0x47,0xa1 }, { 0x75,0x07,0x4c,0xaf }, + { 0x6e,0x10,0x51,0xbd }, { 0x67,0x1d,0x5a,0xb3 }, + { 0x58,0x3e,0x6b,0x99 }, { 0x51,0x33,0x60,0x97 }, + { 0x4a,0x24,0x7d,0x85 }, { 0x43,0x29,0x76,0x8b }, + { 0x34,0x62,0x1f,0xd1 }, { 0x3d,0x6f,0x14,0xdf }, + { 0x26,0x78,0x09,0xcd }, { 0x2f,0x75,0x02,0xc3 }, + { 0x10,0x56,0x33,0xe9 }, { 0x19,0x5b,0x38,0xe7 }, + { 0x02,0x4c,0x25,0xf5 }, { 0x0b,0x41,0x2e,0xfb }, + { 0xd7,0x61,0x8c,0x9a }, { 0xde,0x6c,0x87,0x94 }, + { 0xc5,0x7b,0x9a,0x86 }, { 0xcc,0x76,0x91,0x88 }, + { 0xf3,0x55,0xa0,0xa2 }, { 0xfa,0x58,0xab,0xac }, + { 0xe1,0x4f,0xb6,0xbe }, { 0xe8,0x42,0xbd,0xb0 }, + { 0x9f,0x09,0xd4,0xea }, { 0x96,0x04,0xdf,0xe4 }, + { 0x8d,0x13,0xc2,0xf6 }, { 0x84,0x1e,0xc9,0xf8 }, + { 0xbb,0x3d,0xf8,0xd2 }, { 0xb2,0x30,0xf3,0xdc }, + { 0xa9,0x27,0xee,0xce }, { 0xa0,0x2a,0xe5,0xc0 }, + { 0x47,0xb1,0x3c,0x7a }, { 0x4e,0xbc,0x37,0x74 }, + { 0x55,0xab,0x2a,0x66 }, { 0x5c,0xa6,0x21,0x68 }, + { 0x63,0x85,0x10,0x42 }, { 0x6a,0x88,0x1b,0x4c }, + { 0x71,0x9f,0x06,0x5e }, { 0x78,0x92,0x0d,0x50 }, + { 0x0f,0xd9,0x64,0x0a }, { 0x06,0xd4,0x6f,0x04 }, + { 0x1d,0xc3,0x72,0x16 }, { 0x14,0xce,0x79,0x18 }, + { 0x2b,0xed,0x48,0x32 }, { 0x22,0xe0,0x43,0x3c }, + { 0x39,0xf7,0x5e,0x2e }, { 0x30,0xfa,0x55,0x20 }, + { 0x9a,0xb7,0x01,0xec }, { 0x93,0xba,0x0a,0xe2 }, + { 0x88,0xad,0x17,0xf0 }, { 0x81,0xa0,0x1c,0xfe }, + { 0xbe,0x83,0x2d,0xd4 }, { 0xb7,0x8e,0x26,0xda }, + { 0xac,0x99,0x3b,0xc8 }, { 0xa5,0x94,0x30,0xc6 }, + { 0xd2,0xdf,0x59,0x9c }, { 0xdb,0xd2,0x52,0x92 }, + { 0xc0,0xc5,0x4f,0x80 }, { 0xc9,0xc8,0x44,0x8e }, + { 0xf6,0xeb,0x75,0xa4 }, { 0xff,0xe6,0x7e,0xaa }, + { 0xe4,0xf1,0x63,0xb8 }, { 0xed,0xfc,0x68,0xb6 }, + { 0x0a,0x67,0xb1,0x0c }, { 0x03,0x6a,0xba,0x02 }, + { 0x18,0x7d,0xa7,0x10 }, { 0x11,0x70,0xac,0x1e }, + { 0x2e,0x53,0x9d,0x34 }, { 0x27,0x5e,0x96,0x3a }, + { 0x3c,0x49,0x8b,0x28 }, { 0x35,0x44,0x80,0x26 }, + { 0x42,0x0f,0xe9,0x7c }, { 0x4b,0x02,0xe2,0x72 }, + { 0x50,0x15,0xff,0x60 }, { 0x59,0x18,0xf4,0x6e }, + { 0x66,0x3b,0xc5,0x44 }, { 0x6f,0x36,0xce,0x4a }, + { 0x74,0x21,0xd3,0x58 }, { 0x7d,0x2c,0xd8,0x56 }, + { 0xa1,0x0c,0x7a,0x37 }, { 0xa8,0x01,0x71,0x39 }, + { 0xb3,0x16,0x6c,0x2b }, { 0xba,0x1b,0x67,0x25 }, + { 0x85,0x38,0x56,0x0f }, { 0x8c,0x35,0x5d,0x01 }, + { 0x97,0x22,0x40,0x13 }, { 0x9e,0x2f,0x4b,0x1d }, + { 0xe9,0x64,0x22,0x47 }, { 0xe0,0x69,0x29,0x49 }, + { 0xfb,0x7e,0x34,0x5b }, { 0xf2,0x73,0x3f,0x55 }, + { 0xcd,0x50,0x0e,0x7f }, { 0xc4,0x5d,0x05,0x71 }, + { 0xdf,0x4a,0x18,0x63 }, { 0xd6,0x47,0x13,0x6d }, + { 0x31,0xdc,0xca,0xd7 }, { 0x38,0xd1,0xc1,0xd9 }, + { 0x23,0xc6,0xdc,0xcb }, { 0x2a,0xcb,0xd7,0xc5 }, + { 0x15,0xe8,0xe6,0xef }, { 0x1c,0xe5,0xed,0xe1 }, + { 0x07,0xf2,0xf0,0xf3 }, { 0x0e,0xff,0xfb,0xfd }, + { 0x79,0xb4,0x92,0xa7 }, { 0x70,0xb9,0x99,0xa9 }, + { 0x6b,0xae,0x84,0xbb }, { 0x62,0xa3,0x8f,0xb5 }, + { 0x5d,0x80,0xbe,0x9f }, { 0x54,0x8d,0xb5,0x91 }, + { 0x4f,0x9a,0xa8,0x83 }, { 0x46,0x97,0xa3,0x8d } + }; + +static const u32 rcon[30] = + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, + 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 + }; diff --git a/grub-core/lib/libgcrypt-grub/cipher/rijndael.c b/grub-core/lib/libgcrypt-grub/cipher/rijndael.c new file mode 100644 index 0000000..92e4d2c --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/rijndael.c @@ -0,0 +1,1478 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* Rijndael (AES) for GnuPG + * Copyright (C) 2000, 2001, 2002, 2003, 2007, + * 2008, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + ******************************************************************* + * The code here is based on the optimized implementation taken from + * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ on Oct 2, 2000, + * which carries this notice: + *------------------------------------------ + * rijndael-alg-fst.c v2.3 April '2000 + * + * Optimised ANSI C code + * + * authors: v1.0: Antoon Bosselaers + * v2.0: Vincent Rijmen + * v2.3: Paulo Barreto + * + * This code is placed in the public domain. + *------------------------------------------ + * + * The SP800-38a document is available at: + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + * + */ + + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + +#define MAXKC (256/32) +#define MAXROUNDS 14 +#define BLOCKSIZE (128/8) + + +/* Helper macro to force alignment to 16 bytes. */ +#ifdef __GNUC__ +# define ATTR_ALIGNED_16 __attribute__ ((aligned (16))) +#else +# define ATTR_ALIGNED_16 +#endif + + +/* USE_PADLOCK indicates whether to compile the padlock specific + code. */ +#undef USE_PADLOCK +#ifdef ENABLE_PADLOCK_SUPPORT +# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) +# define USE_PADLOCK 1 +# endif +#endif /*ENABLE_PADLOCK_SUPPORT*/ + +/* USE_AESNI inidicates whether to compile with Intel AES-NI code. We + need the vector-size attribute which seems to be available since + gcc 3. However, to be on the safe side we require at least gcc 4. */ +#undef USE_AESNI +#ifdef ENABLE_AESNI_SUPPORT +# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4 +# define USE_AESNI 1 +# endif +#endif /* ENABLE_AESNI_SUPPORT */ + +#ifdef USE_AESNI + typedef int m128i_t __attribute__ ((__vector_size__ (16))); +#endif /*USE_AESNI*/ + +/* Define an u32 variant for the sake of gcc 4.4's strict aliasing. */ +#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 4 ) +typedef u32 __attribute__ ((__may_alias__)) u32_a_t; +#else +typedef u32 u32_a_t; +#endif + + + +/* Our context object. */ +typedef struct +{ + /* The first fields are the keyschedule arrays. This is so that + they are aligned on a 16 byte boundary if using gcc. This + alignment is required for the AES-NI code and a good idea in any + case. The alignment is guaranteed due to the way cipher.c + allocates the space for the context. The PROPERLY_ALIGNED_TYPE + hack is used to force a minimal alignment if not using gcc of if + the alignment requirement is higher that 16 bytes. */ + union + { + PROPERLY_ALIGNED_TYPE dummy; + byte keyschedule[MAXROUNDS+1][4][4]; +#ifdef USE_PADLOCK + /* The key as passed to the padlock engine. It is only used if + the padlock engine is used (USE_PADLOCK, below). */ + unsigned char padlock_key[16] __attribute__ ((aligned (16))); +#endif /*USE_PADLOCK*/ + } u1; + union + { + PROPERLY_ALIGNED_TYPE dummy; + byte keyschedule[MAXROUNDS+1][4][4]; + } u2; + int rounds; /* Key-length-dependent number of rounds. */ + int decryption_prepared; /* The decryption key schedule is available. */ +#ifdef USE_PADLOCK + int use_padlock; /* Padlock shall be used. */ +#endif /*USE_PADLOCK*/ +#ifdef USE_AESNI + int use_aesni; /* AES-NI shall be used. */ +#endif /*USE_AESNI*/ +} RIJNDAEL_context ATTR_ALIGNED_16; + +/* Macros defining alias for the keyschedules. */ +#define keyschenc u1.keyschedule +#define keyschdec u2.keyschedule +#define padlockkey u1.padlock_key + +/* Two macros to be called prior and after the use of AESNI + instructions. There should be no external function calls between + the use of these macros. There purpose is to make sure that the + SSE regsiters are cleared and won't reveal any information about + the key or the data. */ +#ifdef USE_AESNI +# define aesni_prepare() do { } while (0) +# define aesni_cleanup() \ + do { asm volatile ("pxor %%xmm0, %%xmm0\n\t" \ + "pxor %%xmm1, %%xmm1\n" :: ); \ + } while (0) +# define aesni_cleanup_2_4() \ + do { asm volatile ("pxor %%xmm2, %%xmm2\n\t" \ + "pxor %%xmm3, %%xmm3\n" \ + "pxor %%xmm4, %%xmm4\n":: ); \ + } while (0) +#else +# define aesni_prepare() do { } while (0) +# define aesni_cleanup() do { } while (0) +#endif + + +/* All the numbers. */ +#include "rijndael-tables.h" + + + +/* Function prototypes. */ +#ifdef USE_AESNI +/* We don't want to inline these functions to help gcc allocate enough + registers. */ +static void do_aesni_ctr (const RIJNDAEL_context *ctx, unsigned char *ctr, + unsigned char *b, const unsigned char *a) + __attribute__ ((__noinline__)); +static void do_aesni_ctr_4 (const RIJNDAEL_context *ctx, unsigned char *ctr, + unsigned char *b, const unsigned char *a) + __attribute__ ((__noinline__)); +#endif /*USE_AESNI*/ + + + + +/* Perform the key setup. */ +static gcry_err_code_t +do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) +{ + static int initialized = 0; + static const char *selftest_failed=0; + int rounds; + int i,j, r, t, rconpointer = 0; + int KC; + union + { + PROPERLY_ALIGNED_TYPE dummy; + byte k[MAXKC][4]; + } k; +#define k k.k + union + { + PROPERLY_ALIGNED_TYPE dummy; + byte tk[MAXKC][4]; + } tk; +#define tk tk.tk + + /* The on-the-fly self tests are only run in non-fips mode. In fips + mode explicit self-tests are required. Actually the on-the-fly + self-tests are not fully thread-safe and it might happen that a + failed self-test won't get noticed in another thread. + + FIXME: We might want to have a central registry of succeeded + self-tests. */ + if (!fips_mode () && !initialized) + { + initialized = 1; + selftest_failed = selftest (); + if (selftest_failed) + log_error ("%s\n", selftest_failed ); + } + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + ctx->decryption_prepared = 0; +#ifdef USE_PADLOCK + ctx->use_padlock = 0; +#endif +#ifdef USE_AESNI + ctx->use_aesni = 0; +#endif + + if( keylen == 128/8 ) + { + rounds = 10; + KC = 4; + + if (0) + ; +#ifdef USE_PADLOCK + else if ((_gcry_get_hw_features () & HWF_PADLOCK_AES)) + { + ctx->use_padlock = 1; + memcpy (ctx->padlockkey, key, keylen); + } +#endif +#ifdef USE_AESNI + else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI)) + { + ctx->use_aesni = 1; + } +#endif + } + else if ( keylen == 192/8 ) + { + rounds = 12; + KC = 6; + + if (0) + { + ; + } +#ifdef USE_AESNI + else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI)) + { + ctx->use_aesni = 1; + } +#endif + } + else if ( keylen == 256/8 ) + { + rounds = 14; + KC = 8; + + if (0) + { + ; + } +#ifdef USE_AESNI + else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI)) + { + ctx->use_aesni = 1; + } +#endif + } + else + return GPG_ERR_INV_KEYLEN; + + ctx->rounds = rounds; + + /* NB: We don't yet support Padlock hardware key generation. */ + + if (0) + ; +#ifdef USE_AESNI_is_disabled_here + else if (ctx->use_aesni && ctx->rounds == 10) + { + /* Note: This code works for AES-128 but it is not much better + than using the standard key schedule. We disable it for + now and don't put any effort into implementing this for + AES-192 and AES-256. */ + asm volatile ("movl %[key], %%esi\n\t" + "movdqu (%%esi), %%xmm1\n\t" /* xmm1 := key */ + "movl %[ksch], %%esi\n\t" + "movdqa %%xmm1, (%%esi)\n\t" /* ksch[0] := xmm1 */ + "aeskeygenassist $0x01, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x10(%%esi)\n\t" /* ksch[1] := xmm1 */ + "aeskeygenassist $0x02, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x20(%%esi)\n\t" /* ksch[2] := xmm1 */ + "aeskeygenassist $0x04, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x30(%%esi)\n\t" /* ksch[3] := xmm1 */ + "aeskeygenassist $0x08, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x40(%%esi)\n\t" /* ksch[4] := xmm1 */ + "aeskeygenassist $0x10, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x50(%%esi)\n\t" /* ksch[5] := xmm1 */ + "aeskeygenassist $0x20, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x60(%%esi)\n\t" /* ksch[6] := xmm1 */ + "aeskeygenassist $0x40, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x70(%%esi)\n\t" /* ksch[7] := xmm1 */ + "aeskeygenassist $0x80, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x80(%%esi)\n\t" /* ksch[8] := xmm1 */ + "aeskeygenassist $0x1b, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x90(%%esi)\n\t" /* ksch[9] := xmm1 */ + "aeskeygenassist $0x36, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0xa0(%%esi)\n\t" /* ksch[10] := xmm1 */ + "jmp .Lleave%=\n" + + ".Lexpand128_%=:\n\t" + "pshufd $0xff, %%xmm2, %%xmm2\n\t" + "movdqa %%xmm1, %%xmm3\n\t" + "pslldq $4, %%xmm3\n\t" + "pxor %%xmm3, %%xmm1\n\t" + "pslldq $4, %%xmm3\n\t" + "pxor %%xmm3, %%xmm1\n\t" + "pslldq $4, %%xmm3\n\t" + "pxor %%xmm3, %%xmm2\n\t" + "pxor %%xmm2, %%xmm1\n\t" + "ret\n" + + ".Lleave%=:\n\t" + "pxor %%xmm1, %%xmm1\n\t" + "pxor %%xmm2, %%xmm2\n\t" + "pxor %%xmm3, %%xmm3\n" + : + : [key] "g" (key), [ksch] "g" (ctx->keyschenc) + : "%esi", "cc", "memory" ); + } +#endif /*USE_AESNI*/ + else + { +#define W (ctx->keyschenc) + for (i = 0; i < keylen; i++) + { + k[i >> 2][i & 3] = key[i]; + } + + for (j = KC-1; j >= 0; j--) + { + *((u32_a_t*)tk[j]) = *((u32_a_t*)k[j]); + } + r = 0; + t = 0; + /* Copy values into round key array. */ + for (j = 0; (j < KC) && (r < rounds + 1); ) + { + for (; (j < KC) && (t < 4); j++, t++) + { + *((u32_a_t*)W[r][t]) = *((u32_a_t*)tk[j]); + } + if (t == 4) + { + r++; + t = 0; + } + } + + while (r < rounds + 1) + { + /* While not enough round key material calculated calculate + new values. */ + tk[0][0] ^= S[tk[KC-1][1]]; + tk[0][1] ^= S[tk[KC-1][2]]; + tk[0][2] ^= S[tk[KC-1][3]]; + tk[0][3] ^= S[tk[KC-1][0]]; + tk[0][0] ^= rcon[rconpointer++]; + + if (KC != 8) + { + for (j = 1; j < KC; j++) + { + *((u32_a_t*)tk[j]) ^= *((u32_a_t*)tk[j-1]); + } + } + else + { + for (j = 1; j < KC/2; j++) + { + *((u32_a_t*)tk[j]) ^= *((u32_a_t*)tk[j-1]); + } + tk[KC/2][0] ^= S[tk[KC/2 - 1][0]]; + tk[KC/2][1] ^= S[tk[KC/2 - 1][1]]; + tk[KC/2][2] ^= S[tk[KC/2 - 1][2]]; + tk[KC/2][3] ^= S[tk[KC/2 - 1][3]]; + for (j = KC/2 + 1; j < KC; j++) + { + *((u32_a_t*)tk[j]) ^= *((u32_a_t*)tk[j-1]); + } + } + + /* Copy values into round key array. */ + for (j = 0; (j < KC) && (r < rounds + 1); ) + { + for (; (j < KC) && (t < 4); j++, t++) + { + *((u32_a_t*)W[r][t]) = *((u32_a_t*)tk[j]); + } + if (t == 4) + { + r++; + t = 0; + } + } + } +#undef W + } + + return 0; +#undef tk +#undef k +} + + +static gcry_err_code_t +rijndael_setkey (void *context, const byte *key, const unsigned keylen) +{ + RIJNDAEL_context *ctx = context; + + int rc = do_setkey (ctx, key, keylen); + _gcry_burn_stack ( 100 + 16*sizeof(int)); + return rc; +} + + +/* Make a decryption key from an encryption key. */ +static void +prepare_decryption( RIJNDAEL_context *ctx ) +{ + int r; + +#ifdef USE_AESNI + if (ctx->use_aesni) + { + /* The AES-NI decrypt instructions use the Equivalent Inverse + Cipher, thus we can't use the the standard decrypt key + preparation. */ + m128i_t *ekey = (m128i_t*)ctx->keyschenc; + m128i_t *dkey = (m128i_t*)ctx->keyschdec; + int rr; + + dkey[0] = ekey[ctx->rounds]; + for (r=1, rr=ctx->rounds-1; r < ctx->rounds; r++, rr--) + { + asm volatile + ("movdqu %[ekey], %%xmm1\n\t" + /*"aesimc %%xmm1, %%xmm1\n\t"*/ + ".byte 0x66, 0x0f, 0x38, 0xdb, 0xc9\n\t" + "movdqu %%xmm1, %[dkey]" + : [dkey] "=m" (dkey[r]) + : [ekey] "m" (ekey[rr]) ); + } + dkey[r] = ekey[0]; + } + else +#endif /*USE_AESNI*/ + { + union + { + PROPERLY_ALIGNED_TYPE dummy; + byte *w; + } w; +#define w w.w + + for (r=0; r < MAXROUNDS+1; r++ ) + { + *((u32_a_t*)ctx->keyschdec[r][0]) = *((u32_a_t*)ctx->keyschenc[r][0]); + *((u32_a_t*)ctx->keyschdec[r][1]) = *((u32_a_t*)ctx->keyschenc[r][1]); + *((u32_a_t*)ctx->keyschdec[r][2]) = *((u32_a_t*)ctx->keyschenc[r][2]); + *((u32_a_t*)ctx->keyschdec[r][3]) = *((u32_a_t*)ctx->keyschenc[r][3]); + } +#define W (ctx->keyschdec) + for (r = 1; r < ctx->rounds; r++) + { + w = W[r][0]; + *((u32_a_t*)w) = *((u32_a_t*)U1[w[0]]) ^ *((u32_a_t*)U2[w[1]]) + ^ *((u32_a_t*)U3[w[2]]) ^ *((u32_a_t*)U4[w[3]]); + + w = W[r][1]; + *((u32_a_t*)w) = *((u32_a_t*)U1[w[0]]) ^ *((u32_a_t*)U2[w[1]]) + ^ *((u32_a_t*)U3[w[2]]) ^ *((u32_a_t*)U4[w[3]]); + + w = W[r][2]; + *((u32_a_t*)w) = *((u32_a_t*)U1[w[0]]) ^ *((u32_a_t*)U2[w[1]]) + ^ *((u32_a_t*)U3[w[2]]) ^ *((u32_a_t*)U4[w[3]]); + + w = W[r][3]; + *((u32_a_t*)w) = *((u32_a_t*)U1[w[0]]) ^ *((u32_a_t*)U2[w[1]]) + ^ *((u32_a_t*)U3[w[2]]) ^ *((u32_a_t*)U4[w[3]]); + } +#undef W +#undef w + } +} + + +/* Encrypt one block. A and B need to be aligned on a 4 byte + boundary. A and B may be the same. */ +static void +do_encrypt_aligned (const RIJNDAEL_context *ctx, + unsigned char *b, const unsigned char *a) +{ +#define rk (ctx->keyschenc) + int rounds = ctx->rounds; + int r; + union + { + u32 tempu32[4]; /* Force correct alignment. */ + byte temp[4][4]; + } u; + + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(a )) ^ *((u32_a_t*)rk[0][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(a+ 4)) ^ *((u32_a_t*)rk[0][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(a+ 8)) ^ *((u32_a_t*)rk[0][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(a+12)) ^ *((u32_a_t*)rk[0][3]); + *((u32_a_t*)(b )) = (*((u32_a_t*)T1[u.temp[0][0]]) + ^ *((u32_a_t*)T2[u.temp[1][1]]) + ^ *((u32_a_t*)T3[u.temp[2][2]]) + ^ *((u32_a_t*)T4[u.temp[3][3]])); + *((u32_a_t*)(b + 4)) = (*((u32_a_t*)T1[u.temp[1][0]]) + ^ *((u32_a_t*)T2[u.temp[2][1]]) + ^ *((u32_a_t*)T3[u.temp[3][2]]) + ^ *((u32_a_t*)T4[u.temp[0][3]])); + *((u32_a_t*)(b + 8)) = (*((u32_a_t*)T1[u.temp[2][0]]) + ^ *((u32_a_t*)T2[u.temp[3][1]]) + ^ *((u32_a_t*)T3[u.temp[0][2]]) + ^ *((u32_a_t*)T4[u.temp[1][3]])); + *((u32_a_t*)(b +12)) = (*((u32_a_t*)T1[u.temp[3][0]]) + ^ *((u32_a_t*)T2[u.temp[0][1]]) + ^ *((u32_a_t*)T3[u.temp[1][2]]) + ^ *((u32_a_t*)T4[u.temp[2][3]])); + + for (r = 1; r < rounds-1; r++) + { + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(b )) ^ *((u32_a_t*)rk[r][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(b+ 4)) ^ *((u32_a_t*)rk[r][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(b+ 8)) ^ *((u32_a_t*)rk[r][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(b+12)) ^ *((u32_a_t*)rk[r][3]); + + *((u32_a_t*)(b )) = (*((u32_a_t*)T1[u.temp[0][0]]) + ^ *((u32_a_t*)T2[u.temp[1][1]]) + ^ *((u32_a_t*)T3[u.temp[2][2]]) + ^ *((u32_a_t*)T4[u.temp[3][3]])); + *((u32_a_t*)(b + 4)) = (*((u32_a_t*)T1[u.temp[1][0]]) + ^ *((u32_a_t*)T2[u.temp[2][1]]) + ^ *((u32_a_t*)T3[u.temp[3][2]]) + ^ *((u32_a_t*)T4[u.temp[0][3]])); + *((u32_a_t*)(b + 8)) = (*((u32_a_t*)T1[u.temp[2][0]]) + ^ *((u32_a_t*)T2[u.temp[3][1]]) + ^ *((u32_a_t*)T3[u.temp[0][2]]) + ^ *((u32_a_t*)T4[u.temp[1][3]])); + *((u32_a_t*)(b +12)) = (*((u32_a_t*)T1[u.temp[3][0]]) + ^ *((u32_a_t*)T2[u.temp[0][1]]) + ^ *((u32_a_t*)T3[u.temp[1][2]]) + ^ *((u32_a_t*)T4[u.temp[2][3]])); + } + + /* Last round is special. */ + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(b )) ^ *((u32_a_t*)rk[rounds-1][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(b+ 4)) ^ *((u32_a_t*)rk[rounds-1][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(b+ 8)) ^ *((u32_a_t*)rk[rounds-1][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(b+12)) ^ *((u32_a_t*)rk[rounds-1][3]); + b[ 0] = T1[u.temp[0][0]][1]; + b[ 1] = T1[u.temp[1][1]][1]; + b[ 2] = T1[u.temp[2][2]][1]; + b[ 3] = T1[u.temp[3][3]][1]; + b[ 4] = T1[u.temp[1][0]][1]; + b[ 5] = T1[u.temp[2][1]][1]; + b[ 6] = T1[u.temp[3][2]][1]; + b[ 7] = T1[u.temp[0][3]][1]; + b[ 8] = T1[u.temp[2][0]][1]; + b[ 9] = T1[u.temp[3][1]][1]; + b[10] = T1[u.temp[0][2]][1]; + b[11] = T1[u.temp[1][3]][1]; + b[12] = T1[u.temp[3][0]][1]; + b[13] = T1[u.temp[0][1]][1]; + b[14] = T1[u.temp[1][2]][1]; + b[15] = T1[u.temp[2][3]][1]; + *((u32_a_t*)(b )) ^= *((u32_a_t*)rk[rounds][0]); + *((u32_a_t*)(b+ 4)) ^= *((u32_a_t*)rk[rounds][1]); + *((u32_a_t*)(b+ 8)) ^= *((u32_a_t*)rk[rounds][2]); + *((u32_a_t*)(b+12)) ^= *((u32_a_t*)rk[rounds][3]); +#undef rk +} + + +static void +do_encrypt (const RIJNDAEL_context *ctx, + unsigned char *bx, const unsigned char *ax) +{ + /* BX and AX are not necessary correctly aligned. Thus we might + need to copy them here. We try to align to a 16 bytes. */ + if (((size_t)ax & 0x0f) || ((size_t)bx & 0x0f)) + { + union + { + u32 dummy[4]; + byte a[16] ATTR_ALIGNED_16; + } a; + union + { + u32 dummy[4]; + byte b[16] ATTR_ALIGNED_16; + } b; + + memcpy (a.a, ax, 16); + do_encrypt_aligned (ctx, b.b, a.a); + memcpy (bx, b.b, 16); + } + else + { + do_encrypt_aligned (ctx, bx, ax); + } +} + + +/* Encrypt or decrypt one block using the padlock engine. A and B may + be the same. */ +#ifdef USE_PADLOCK +static void +do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag, + unsigned char *bx, const unsigned char *ax) +{ + /* BX and AX are not necessary correctly aligned. Thus we need to + copy them here. */ + unsigned char a[16] __attribute__ ((aligned (16))); + unsigned char b[16] __attribute__ ((aligned (16))); + unsigned int cword[4] __attribute__ ((aligned (16))); + + /* The control word fields are: + 127:12 11:10 9 8 7 6 5 4 3:0 + RESERVED KSIZE CRYPT INTER KEYGN CIPHR ALIGN DGEST ROUND */ + cword[0] = (ctx->rounds & 15); /* (The mask is just a safeguard.) */ + cword[1] = 0; + cword[2] = 0; + cword[3] = 0; + if (decrypt_flag) + cword[0] |= 0x00000200; + + memcpy (a, ax, 16); + + asm volatile + ("pushfl\n\t" /* Force key reload. */ + "popfl\n\t" + "xchg %3, %%ebx\n\t" /* Load key. */ + "movl $1, %%ecx\n\t" /* Init counter for just one block. */ + ".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XSTORE ECB. */ + "xchg %3, %%ebx\n" /* Restore GOT register. */ + : /* No output */ + : "S" (a), "D" (b), "d" (cword), "r" (ctx->padlockkey) + : "%ecx", "cc", "memory" + ); + + memcpy (bx, b, 16); + +} +#endif /*USE_PADLOCK*/ + + +#ifdef USE_AESNI +/* Encrypt one block using the Intel AES-NI instructions. A and B may + be the same; they need to be properly aligned to 16 bytes. + + Our problem here is that gcc does not allow the "x" constraint for + SSE registers in asm unless you compile with -msse. The common + wisdom is to use a separate file for SSE instructions and build it + separately. This would require a lot of extra build system stuff, + similar to what we do in mpi/ for the asm stuff. What we do + instead is to use standard registers and a bit more of plain asm + which copies the data and key stuff to the SSE registers and later + back. If we decide to implement some block modes with parallelized + AES instructions, it might indeed be better to use plain asm ala + mpi/. */ +static void +do_aesni_enc_aligned (const RIJNDAEL_context *ctx, + unsigned char *b, const unsigned char *a) +{ +#define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" +#define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" + /* Note: For now we relax the alignment requirement for A and B: It + does not make much difference because in many case we would need + to memcpy them to an extra buffer; using the movdqu is much faster + that memcpy and movdqa. For CFB we know that the IV is properly + aligned but that is a special case. We should better implement + CFB direct in asm. */ + asm volatile ("movdqu %[src], %%xmm0\n\t" /* xmm0 := *a */ + "movl %[key], %%esi\n\t" /* esi := keyschenc */ + "movdqa (%%esi), %%xmm1\n\t" /* xmm1 := key[0] */ + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ + "movdqa 0x10(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x20(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x30(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x40(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x50(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x60(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x70(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x80(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x90(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xa0(%%esi), %%xmm1\n\t" + "cmp $10, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xb0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xc0(%%esi), %%xmm1\n\t" + "cmp $12, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xd0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xe0(%%esi), %%xmm1\n" + + ".Lenclast%=:\n\t" + aesenclast_xmm1_xmm0 + "movdqu %%xmm0, %[dst]\n" + : [dst] "=m" (*b) + : [src] "m" (*a), + [key] "r" (ctx->keyschenc), + [rounds] "r" (ctx->rounds) + : "%esi", "cc", "memory"); +#undef aesenc_xmm1_xmm0 +#undef aesenclast_xmm1_xmm0 +} + + +static void +do_aesni_dec_aligned (const RIJNDAEL_context *ctx, + unsigned char *b, const unsigned char *a) +{ +#define aesdec_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc1\n\t" +#define aesdeclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc1\n\t" + asm volatile ("movdqu %[src], %%xmm0\n\t" /* xmm0 := *a */ + "movl %[key], %%esi\n\t" + "movdqa (%%esi), %%xmm1\n\t" + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ + "movdqa 0x10(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x20(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x30(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x40(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x50(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x60(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x70(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x80(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x90(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0xa0(%%esi), %%xmm1\n\t" + "cmp $10, %[rounds]\n\t" + "jz .Ldeclast%=\n\t" + aesdec_xmm1_xmm0 + "movdqa 0xb0(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0xc0(%%esi), %%xmm1\n\t" + "cmp $12, %[rounds]\n\t" + "jz .Ldeclast%=\n\t" + aesdec_xmm1_xmm0 + "movdqa 0xd0(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0xe0(%%esi), %%xmm1\n" + + ".Ldeclast%=:\n\t" + aesdeclast_xmm1_xmm0 + "movdqu %%xmm0, %[dst]\n" + : [dst] "=m" (*b) + : [src] "m" (*a), + [key] "r" (ctx->keyschdec), + [rounds] "r" (ctx->rounds) + : "%esi", "cc", "memory"); +#undef aesdec_xmm1_xmm0 +#undef aesdeclast_xmm1_xmm0 +} + + +/* Perform a CFB encryption or decryption round using the + initialization vector IV and the input block A. Write the result + to the output block B and update IV. IV needs to be 16 byte + aligned. */ +static void +do_aesni_cfb (const RIJNDAEL_context *ctx, int decrypt_flag, + unsigned char *iv, unsigned char *b, const unsigned char *a) +{ +#define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" +#define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" + asm volatile ("movdqa %[iv], %%xmm0\n\t" /* xmm0 := IV */ + "movl %[key], %%esi\n\t" /* esi := keyschenc */ + "movdqa (%%esi), %%xmm1\n\t" /* xmm1 := key[0] */ + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ + "movdqa 0x10(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x20(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x30(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x40(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x50(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x60(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x70(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x80(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x90(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xa0(%%esi), %%xmm1\n\t" + "cmp $10, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xb0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xc0(%%esi), %%xmm1\n\t" + "cmp $12, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xd0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xe0(%%esi), %%xmm1\n" + + ".Lenclast%=:\n\t" + aesenclast_xmm1_xmm0 + "movdqu %[src], %%xmm1\n\t" /* Save input. */ + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 = input ^ IV */ + + "cmp $1, %[decrypt]\n\t" + "jz .Ldecrypt_%=\n\t" + "movdqa %%xmm0, %[iv]\n\t" /* [encrypt] Store IV. */ + "jmp .Lleave_%=\n" + ".Ldecrypt_%=:\n\t" + "movdqa %%xmm1, %[iv]\n" /* [decrypt] Store IV. */ + ".Lleave_%=:\n\t" + "movdqu %%xmm0, %[dst]\n" /* Store output. */ + : [iv] "+m" (*iv), [dst] "=m" (*b) + : [src] "m" (*a), + [key] "g" (ctx->keyschenc), + [rounds] "g" (ctx->rounds), + [decrypt] "m" (decrypt_flag) + : "%esi", "cc", "memory"); +#undef aesenc_xmm1_xmm0 +#undef aesenclast_xmm1_xmm0 +} + +/* Perform a CTR encryption round using the counter CTR and the input + block A. Write the result to the output block B and update CTR. + CTR needs to be a 16 byte aligned little-endian value. */ +static void +do_aesni_ctr (const RIJNDAEL_context *ctx, + unsigned char *ctr, unsigned char *b, const unsigned char *a) +{ +#define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" +#define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" + static unsigned char be_mask[16] __attribute__ ((aligned (16))) = + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + + asm volatile ("movdqa %[ctr], %%xmm0\n\t" /* xmm0, xmm2 := CTR */ + "movaps %%xmm0, %%xmm2\n\t" + "mov $1, %%esi\n\t" /* xmm2++ (big-endian) */ + "movd %%esi, %%xmm1\n\t" + "pshufb %[mask], %%xmm2\n\t" + "paddq %%xmm1, %%xmm2\n\t" + "pshufb %[mask], %%xmm2\n\t" + "movdqa %%xmm2, %[ctr]\n" /* Update CTR. */ + + "movl %[key], %%esi\n\t" /* esi := keyschenc */ + "movdqa (%%esi), %%xmm1\n\t" /* xmm1 := key[0] */ + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ + "movdqa 0x10(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x20(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x30(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x40(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x50(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x60(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x70(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x80(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x90(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xa0(%%esi), %%xmm1\n\t" + "cmp $10, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xb0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xc0(%%esi), %%xmm1\n\t" + "cmp $12, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xd0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xe0(%%esi), %%xmm1\n" + + ".Lenclast%=:\n\t" + aesenclast_xmm1_xmm0 + "movdqu %[src], %%xmm1\n\t" /* xmm1 := input */ + "pxor %%xmm1, %%xmm0\n\t" /* EncCTR ^= input */ + "movdqu %%xmm0, %[dst]" /* Store EncCTR. */ + + : [ctr] "+m" (*ctr), [dst] "=m" (*b) + : [src] "m" (*a), + [key] "g" (ctx->keyschenc), + [rounds] "g" (ctx->rounds), + [mask] "m" (*be_mask) + : "%esi", "cc", "memory"); +#undef aesenc_xmm1_xmm0 +#undef aesenclast_xmm1_xmm0 +} + + +/* Four blocks at a time variant of do_aesni_ctr. */ +static void +do_aesni_ctr_4 (const RIJNDAEL_context *ctx, + unsigned char *ctr, unsigned char *b, const unsigned char *a) +{ +#define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" +#define aesenc_xmm1_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd1\n\t" +#define aesenc_xmm1_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd9\n\t" +#define aesenc_xmm1_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe1\n\t" +#define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" +#define aesenclast_xmm1_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd1\n\t" +#define aesenclast_xmm1_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd9\n\t" +#define aesenclast_xmm1_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe1\n\t" + + static unsigned char be_mask[16] __attribute__ ((aligned (16))) = + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + + /* Register usage: + esi keyschedule + xmm0 CTR-0 + xmm1 temp / round key + xmm2 CTR-1 + xmm3 CTR-2 + xmm4 CTR-3 + xmm5 temp + */ + + asm volatile ("movdqa %[ctr], %%xmm0\n\t" /* xmm0, xmm2 := CTR */ + "movaps %%xmm0, %%xmm2\n\t" + "mov $1, %%esi\n\t" /* xmm1 := 1 */ + "movd %%esi, %%xmm1\n\t" + "pshufb %[mask], %%xmm2\n\t" /* xmm2 := le(xmm2) */ + "paddq %%xmm1, %%xmm2\n\t" /* xmm2++ */ + "movaps %%xmm2, %%xmm3\n\t" /* xmm3 := xmm2 */ + "paddq %%xmm1, %%xmm3\n\t" /* xmm3++ */ + "movaps %%xmm3, %%xmm4\n\t" /* xmm4 := xmm3 */ + "paddq %%xmm1, %%xmm4\n\t" /* xmm4++ */ + "movaps %%xmm4, %%xmm5\n\t" /* xmm5 := xmm4 */ + "paddq %%xmm1, %%xmm5\n\t" /* xmm5++ */ + "pshufb %[mask], %%xmm2\n\t" /* xmm2 := be(xmm2) */ + "pshufb %[mask], %%xmm3\n\t" /* xmm3 := be(xmm3) */ + "pshufb %[mask], %%xmm4\n\t" /* xmm4 := be(xmm4) */ + "pshufb %[mask], %%xmm5\n\t" /* xmm5 := be(xmm5) */ + "movdqa %%xmm5, %[ctr]\n" /* Update CTR. */ + + "movl %[key], %%esi\n\t" /* esi := keyschenc */ + "movdqa (%%esi), %%xmm1\n\t" /* xmm1 := key[0] */ + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ + "pxor %%xmm1, %%xmm2\n\t" /* xmm2 ^= key[0] */ + "pxor %%xmm1, %%xmm3\n\t" /* xmm3 ^= key[0] */ + "pxor %%xmm1, %%xmm4\n\t" /* xmm4 ^= key[0] */ + "movdqa 0x10(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x20(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x30(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x40(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x50(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x60(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x70(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x80(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x90(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0xa0(%%esi), %%xmm1\n\t" + "cmp $10, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0xb0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0xc0(%%esi), %%xmm1\n\t" + "cmp $12, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0xd0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0xe0(%%esi), %%xmm1\n" + + ".Lenclast%=:\n\t" + aesenclast_xmm1_xmm0 + aesenclast_xmm1_xmm2 + aesenclast_xmm1_xmm3 + aesenclast_xmm1_xmm4 + + "movdqu %[src], %%xmm1\n\t" /* Get block 1. */ + "pxor %%xmm1, %%xmm0\n\t" /* EncCTR-1 ^= input */ + "movdqu %%xmm0, %[dst]\n\t" /* Store block 1 */ + + "movdqu (16)%[src], %%xmm1\n\t" /* Get block 2. */ + "pxor %%xmm1, %%xmm2\n\t" /* EncCTR-2 ^= input */ + "movdqu %%xmm2, (16)%[dst]\n\t" /* Store block 2. */ + + "movdqu (32)%[src], %%xmm1\n\t" /* Get block 3. */ + "pxor %%xmm1, %%xmm3\n\t" /* EncCTR-3 ^= input */ + "movdqu %%xmm3, (32)%[dst]\n\t" /* Store block 3. */ + + "movdqu (48)%[src], %%xmm1\n\t" /* Get block 4. */ + "pxor %%xmm1, %%xmm4\n\t" /* EncCTR-4 ^= input */ + "movdqu %%xmm4, (48)%[dst]" /* Store block 4. */ + + : [ctr] "+m" (*ctr), [dst] "=m" (*b) + : [src] "m" (*a), + [key] "g" (ctx->keyschenc), + [rounds] "g" (ctx->rounds), + [mask] "m" (*be_mask) + : "%esi", "cc", "memory"); +#undef aesenc_xmm1_xmm0 +#undef aesenc_xmm1_xmm2 +#undef aesenc_xmm1_xmm3 +#undef aesenc_xmm1_xmm4 +#undef aesenclast_xmm1_xmm0 +#undef aesenclast_xmm1_xmm2 +#undef aesenclast_xmm1_xmm3 +#undef aesenclast_xmm1_xmm4 +} + + +static void +do_aesni (RIJNDAEL_context *ctx, int decrypt_flag, + unsigned char *bx, const unsigned char *ax) +{ + + if (decrypt_flag) + { + if (!ctx->decryption_prepared ) + { + prepare_decryption ( ctx ); + ctx->decryption_prepared = 1; + } + do_aesni_dec_aligned (ctx, bx, ax); + } + else + do_aesni_enc_aligned (ctx, bx, ax); +} +#endif /*USE_AESNI*/ + + +static void +rijndael_encrypt (void *context, byte *b, const byte *a) +{ + RIJNDAEL_context *ctx = context; + + if (0) + ; +#ifdef USE_PADLOCK + else if (ctx->use_padlock) + { + do_padlock (ctx, 0, b, a); + _gcry_burn_stack (48 + 15 /* possible padding for alignment */); + } +#endif /*USE_PADLOCK*/ +#ifdef USE_AESNI + else if (ctx->use_aesni) + { + aesni_prepare (); + do_aesni (ctx, 0, b, a); + aesni_cleanup (); + } +#endif /*USE_AESNI*/ + else + { + do_encrypt (ctx, b, a); + _gcry_burn_stack (56 + 2*sizeof(int)); + } +} + + +/* Bulk encryption of complete blocks in CFB mode. Caller needs to + make sure that IV is aligned on an unsigned long boundary. This + function is only intended for the bulk encryption feature of + cipher.c. */ + + +/* Bulk encryption of complete blocks in CBC mode. Caller needs to + make sure that IV is aligned on an unsigned long boundary. This + function is only intended for the bulk encryption feature of + cipher.c. */ + + +/* Bulk encryption of complete blocks in CTR mode. Caller needs to + make sure that CTR is aligned on a 16 byte boundary if AESNI; the + minimum alignment is for an u32. This function is only intended + for the bulk encryption feature of cipher.c. CTR is expected to be + of size BLOCKSIZE. */ + + + +/* Decrypt one block. A and B need to be aligned on a 4 byte boundary + and the decryption must have been prepared. A and B may be the + same. */ +static void +do_decrypt_aligned (RIJNDAEL_context *ctx, + unsigned char *b, const unsigned char *a) +{ +#define rk (ctx->keyschdec) + int rounds = ctx->rounds; + int r; + union + { + u32 tempu32[4]; /* Force correct alignment. */ + byte temp[4][4]; + } u; + + + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(a )) ^ *((u32_a_t*)rk[rounds][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(a+ 4)) ^ *((u32_a_t*)rk[rounds][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(a+ 8)) ^ *((u32_a_t*)rk[rounds][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(a+12)) ^ *((u32_a_t*)rk[rounds][3]); + + *((u32_a_t*)(b )) = (*((u32_a_t*)T5[u.temp[0][0]]) + ^ *((u32_a_t*)T6[u.temp[3][1]]) + ^ *((u32_a_t*)T7[u.temp[2][2]]) + ^ *((u32_a_t*)T8[u.temp[1][3]])); + *((u32_a_t*)(b+ 4)) = (*((u32_a_t*)T5[u.temp[1][0]]) + ^ *((u32_a_t*)T6[u.temp[0][1]]) + ^ *((u32_a_t*)T7[u.temp[3][2]]) + ^ *((u32_a_t*)T8[u.temp[2][3]])); + *((u32_a_t*)(b+ 8)) = (*((u32_a_t*)T5[u.temp[2][0]]) + ^ *((u32_a_t*)T6[u.temp[1][1]]) + ^ *((u32_a_t*)T7[u.temp[0][2]]) + ^ *((u32_a_t*)T8[u.temp[3][3]])); + *((u32_a_t*)(b+12)) = (*((u32_a_t*)T5[u.temp[3][0]]) + ^ *((u32_a_t*)T6[u.temp[2][1]]) + ^ *((u32_a_t*)T7[u.temp[1][2]]) + ^ *((u32_a_t*)T8[u.temp[0][3]])); + + for (r = rounds-1; r > 1; r--) + { + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(b )) ^ *((u32_a_t*)rk[r][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(b+ 4)) ^ *((u32_a_t*)rk[r][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(b+ 8)) ^ *((u32_a_t*)rk[r][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(b+12)) ^ *((u32_a_t*)rk[r][3]); + *((u32_a_t*)(b )) = (*((u32_a_t*)T5[u.temp[0][0]]) + ^ *((u32_a_t*)T6[u.temp[3][1]]) + ^ *((u32_a_t*)T7[u.temp[2][2]]) + ^ *((u32_a_t*)T8[u.temp[1][3]])); + *((u32_a_t*)(b+ 4)) = (*((u32_a_t*)T5[u.temp[1][0]]) + ^ *((u32_a_t*)T6[u.temp[0][1]]) + ^ *((u32_a_t*)T7[u.temp[3][2]]) + ^ *((u32_a_t*)T8[u.temp[2][3]])); + *((u32_a_t*)(b+ 8)) = (*((u32_a_t*)T5[u.temp[2][0]]) + ^ *((u32_a_t*)T6[u.temp[1][1]]) + ^ *((u32_a_t*)T7[u.temp[0][2]]) + ^ *((u32_a_t*)T8[u.temp[3][3]])); + *((u32_a_t*)(b+12)) = (*((u32_a_t*)T5[u.temp[3][0]]) + ^ *((u32_a_t*)T6[u.temp[2][1]]) + ^ *((u32_a_t*)T7[u.temp[1][2]]) + ^ *((u32_a_t*)T8[u.temp[0][3]])); + } + + /* Last round is special. */ + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(b )) ^ *((u32_a_t*)rk[1][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(b+ 4)) ^ *((u32_a_t*)rk[1][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(b+ 8)) ^ *((u32_a_t*)rk[1][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(b+12)) ^ *((u32_a_t*)rk[1][3]); + b[ 0] = S5[u.temp[0][0]]; + b[ 1] = S5[u.temp[3][1]]; + b[ 2] = S5[u.temp[2][2]]; + b[ 3] = S5[u.temp[1][3]]; + b[ 4] = S5[u.temp[1][0]]; + b[ 5] = S5[u.temp[0][1]]; + b[ 6] = S5[u.temp[3][2]]; + b[ 7] = S5[u.temp[2][3]]; + b[ 8] = S5[u.temp[2][0]]; + b[ 9] = S5[u.temp[1][1]]; + b[10] = S5[u.temp[0][2]]; + b[11] = S5[u.temp[3][3]]; + b[12] = S5[u.temp[3][0]]; + b[13] = S5[u.temp[2][1]]; + b[14] = S5[u.temp[1][2]]; + b[15] = S5[u.temp[0][3]]; + *((u32_a_t*)(b )) ^= *((u32_a_t*)rk[0][0]); + *((u32_a_t*)(b+ 4)) ^= *((u32_a_t*)rk[0][1]); + *((u32_a_t*)(b+ 8)) ^= *((u32_a_t*)rk[0][2]); + *((u32_a_t*)(b+12)) ^= *((u32_a_t*)rk[0][3]); +#undef rk +} + + +/* Decrypt one block. AX and BX may be the same. */ +static void +do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax) +{ + if ( !ctx->decryption_prepared ) + { + prepare_decryption ( ctx ); + _gcry_burn_stack (64); + ctx->decryption_prepared = 1; + } + + /* BX and AX are not necessary correctly aligned. Thus we might + need to copy them here. We try to align to a 16 bytes. */ + if (((size_t)ax & 0x0f) || ((size_t)bx & 0x0f)) + { + union + { + u32 dummy[4]; + byte a[16] ATTR_ALIGNED_16; + } a; + union + { + u32 dummy[4]; + byte b[16] ATTR_ALIGNED_16; + } b; + + memcpy (a.a, ax, 16); + do_decrypt_aligned (ctx, b.b, a.a); + memcpy (bx, b.b, 16); + } + else + { + do_decrypt_aligned (ctx, bx, ax); + } +} + + + + +static void +rijndael_decrypt (void *context, byte *b, const byte *a) +{ + RIJNDAEL_context *ctx = context; + + if (0) + ; +#ifdef USE_PADLOCK + else if (ctx->use_padlock) + { + do_padlock (ctx, 1, b, a); + _gcry_burn_stack (48 + 2*sizeof(int) /* FIXME */); + } +#endif /*USE_PADLOCK*/ +#ifdef USE_AESNI + else if (ctx->use_aesni) + { + aesni_prepare (); + do_aesni (ctx, 1, b, a); + aesni_cleanup (); + } +#endif /*USE_AESNI*/ + else + { + do_decrypt (ctx, b, a); + _gcry_burn_stack (56+2*sizeof(int)); + } +} + + +/* Bulk decryption of complete blocks in CFB mode. Caller needs to + make sure that IV is aligned on an unisgned lonhg boundary. This + function is only intended for the bulk encryption feature of + cipher.c. */ + + +/* Bulk decryption of complete blocks in CBC mode. Caller needs to + make sure that IV is aligned on an unsigned long boundary. This + function is only intended for the bulk encryption feature of + cipher.c. */ + + + + +/* Run the self-tests for AES 128. Returns NULL on success. */ + +/* Run the self-tests for AES 192. Returns NULL on success. */ + + +/* Run the self-tests for AES 256. Returns NULL on success. */ + +/* Run all the self-tests and return NULL on success. This function + is used for the on-the-fly self-tests. */ + + +/* SP800-38a.pdf for AES-128. */ + + +/* Complete selftest for AES-128 with all modes and driver code. */ + +/* Complete selftest for AES-192. */ + + +/* Complete selftest for AES-256. */ + + + +/* Run a full self-test for ALGO and return 0 on success. */ + + + + +static const char *rijndael_names[] = + { + "RIJNDAEL", + "AES128", + "AES-128", + NULL + }; + +static gcry_cipher_oid_spec_t rijndael_oids[] = + { + { "2.16.840.1.101.3.4.1.1", GCRY_CIPHER_MODE_ECB }, + { "2.16.840.1.101.3.4.1.2", GCRY_CIPHER_MODE_CBC }, + { "2.16.840.1.101.3.4.1.3", GCRY_CIPHER_MODE_OFB }, + { "2.16.840.1.101.3.4.1.4", GCRY_CIPHER_MODE_CFB }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_aes = + { + "AES", rijndael_names, rijndael_oids, 16, 128, sizeof (RIJNDAEL_context), + rijndael_setkey, rijndael_encrypt, rijndael_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_rijndael", +#endif + }; + +static const char *rijndael192_names[] = + { + "RIJNDAEL192", + "AES-192", + NULL + }; + +static gcry_cipher_oid_spec_t rijndael192_oids[] = + { + { "2.16.840.1.101.3.4.1.21", GCRY_CIPHER_MODE_ECB }, + { "2.16.840.1.101.3.4.1.22", GCRY_CIPHER_MODE_CBC }, + { "2.16.840.1.101.3.4.1.23", GCRY_CIPHER_MODE_OFB }, + { "2.16.840.1.101.3.4.1.24", GCRY_CIPHER_MODE_CFB }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_aes192 = + { + "AES192", rijndael192_names, rijndael192_oids, 16, 192, sizeof (RIJNDAEL_context), + rijndael_setkey, rijndael_encrypt, rijndael_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_rijndael", +#endif + }; + +static const char *rijndael256_names[] = + { + "RIJNDAEL256", + "AES-256", + NULL + }; + +static gcry_cipher_oid_spec_t rijndael256_oids[] = + { + { "2.16.840.1.101.3.4.1.41", GCRY_CIPHER_MODE_ECB }, + { "2.16.840.1.101.3.4.1.42", GCRY_CIPHER_MODE_CBC }, + { "2.16.840.1.101.3.4.1.43", GCRY_CIPHER_MODE_OFB }, + { "2.16.840.1.101.3.4.1.44", GCRY_CIPHER_MODE_CFB }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_aes256 = + { + "AES256", rijndael256_names, rijndael256_oids, 16, 256, + sizeof (RIJNDAEL_context), + rijndael_setkey, rijndael_encrypt, rijndael_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_rijndael", +#endif + }; + + + +GRUB_MOD_INIT(gcry_rijndael) +{ + grub_cipher_register (&_gcry_cipher_spec_aes); + grub_cipher_register (&_gcry_cipher_spec_aes192); + grub_cipher_register (&_gcry_cipher_spec_aes256); +} + +GRUB_MOD_FINI(gcry_rijndael) +{ + grub_cipher_unregister (&_gcry_cipher_spec_aes); + grub_cipher_unregister (&_gcry_cipher_spec_aes192); + grub_cipher_unregister (&_gcry_cipher_spec_aes256); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/rmd.h b/grub-core/lib/libgcrypt-grub/cipher/rmd.h new file mode 100644 index 0000000..75bb21f --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/rmd.h @@ -0,0 +1,39 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +/* rmd.h - RIPE-MD hash functions + * Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef G10_RMD_H +#define G10_RMD_H + + +/* We need this here because random.c must have direct access. */ +typedef struct +{ + u32 h0,h1,h2,h3,h4; + u32 nblocks; + byte buf[64]; + int count; +} RMD160_CONTEXT; + +void _gcry_rmd160_init ( void *context ); +void _gcry_rmd160_mixblock ( RMD160_CONTEXT *hd, void *blockof64byte ); + +#endif /*G10_RMD_H*/ diff --git a/grub-core/lib/libgcrypt-grub/cipher/rmd160.c b/grub-core/lib/libgcrypt-grub/cipher/rmd160.c new file mode 100644 index 0000000..620fe98 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/rmd160.c @@ -0,0 +1,565 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* rmd160.c - RIPE-MD160 + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include "g10lib.h" +#include "rmd.h" +#include "cipher.h" /* Only used for the rmd160_hash_buffer() prototype. */ + +#include "bithelp.h" + +/********************************* + * RIPEMD-160 is not patented, see (as of 25.10.97) + * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html + * Note that the code uses Little Endian byteorder, which is good for + * 386 etc, but we must add some conversion when used on a big endian box. + * + * + * Pseudo-code for RIPEMD-160 + * + * RIPEMD-160 is an iterative hash function that operates on 32-bit words. + * The round function takes as input a 5-word chaining variable and a 16-word + * message block and maps this to a new chaining variable. All operations are + * defined on 32-bit words. Padding is identical to that of MD4. + * + * + * RIPEMD-160: definitions + * + * + * nonlinear functions at bit level: exor, mux, -, mux, - + * + * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) + * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) + * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) + * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) + * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) + * + * + * added constants (hexadecimal) + * + * K(j) = 0x00000000 (0 <= j <= 15) + * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) + * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) + * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) + * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) + * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) + * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) + * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) + * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) + * K'(j) = 0x00000000 (64 <= j <= 79) + * + * + * selection of message word + * + * r(j) = j (0 <= j <= 15) + * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 + * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 + * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 + * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 + * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 + * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 + * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 + * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 + * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 + * + * + * amount for rotate left (rol) + * + * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 + * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 + * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 + * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 + * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 + * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 + * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 + * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 + * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 + * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 + * + * + * initial value (hexadecimal) + * + * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; + * h4 = 0xC3D2E1F0; + * + * + * RIPEMD-160: pseudo-code + * + * It is assumed that the message after padding consists of t 16-word blocks + * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. + * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left + * shift (rotate) over s positions. + * + * + * for i := 0 to t-1 { + * A := h0; B := h1; C := h2; D = h3; E = h4; + * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; + * for j := 0 to 79 { + * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; + * A := E; E := D; D := rol_10(C); C := B; B := T; + * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] + [+] K'(j)) [+] E'; + * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; + * } + * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; + * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; + * } + */ + +/* Some examples: + * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 + * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe + * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc + * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 + * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc + * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b + * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 + * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb + * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 + */ + + +void +_gcry_rmd160_init (void *context) +{ + RMD160_CONTEXT *hd = context; + + hd->h0 = 0x67452301; + hd->h1 = 0xEFCDAB89; + hd->h2 = 0x98BADCFE; + hd->h3 = 0x10325476; + hd->h4 = 0xC3D2E1F0; + hd->nblocks = 0; + hd->count = 0; +} + + + +/**************** + * Transform the message X which consists of 16 32-bit-words + */ +static void +transform ( RMD160_CONTEXT *hd, const unsigned char *data ) +{ + register u32 a,b,c,d,e; + u32 aa,bb,cc,dd,ee,t; +#ifdef WORDS_BIGENDIAN + u32 x[16]; + { + int i; + byte *p2; + const byte *p1; + for (i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) + { + p2[3] = *p1++; + p2[2] = *p1++; + p2[1] = *p1++; + p2[0] = *p1++; + } + } +#else + /* This version is better because it is always aligned; + * The performance penalty on a 586-100 is about 6% which + * is acceptable - because the data is more local it might + * also be possible that this is faster on some machines. + * This function (when compiled with -02 on gcc 2.7.2) + * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; + * [measured with a 4MB data and "gpgm --print-md rmd160"] */ + u32 x[16]; + memcpy( x, data, 64 ); +#endif + + +#define K0 0x00000000 +#define K1 0x5A827999 +#define K2 0x6ED9EBA1 +#define K3 0x8F1BBCDC +#define K4 0xA953FD4E +#define KK0 0x50A28BE6 +#define KK1 0x5C4DD124 +#define KK2 0x6D703EF3 +#define KK3 0x7A6D76E9 +#define KK4 0x00000000 +#define F0(x,y,z) ( (x) ^ (y) ^ (z) ) +#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) +#define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) +#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) +#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) +#define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ + a = rol(t,s) + e; \ + c = rol(c,10); \ + } while(0) + + /* left lane */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + R( a, b, c, d, e, F0, K0, 0, 11 ); + R( e, a, b, c, d, F0, K0, 1, 14 ); + R( d, e, a, b, c, F0, K0, 2, 15 ); + R( c, d, e, a, b, F0, K0, 3, 12 ); + R( b, c, d, e, a, F0, K0, 4, 5 ); + R( a, b, c, d, e, F0, K0, 5, 8 ); + R( e, a, b, c, d, F0, K0, 6, 7 ); + R( d, e, a, b, c, F0, K0, 7, 9 ); + R( c, d, e, a, b, F0, K0, 8, 11 ); + R( b, c, d, e, a, F0, K0, 9, 13 ); + R( a, b, c, d, e, F0, K0, 10, 14 ); + R( e, a, b, c, d, F0, K0, 11, 15 ); + R( d, e, a, b, c, F0, K0, 12, 6 ); + R( c, d, e, a, b, F0, K0, 13, 7 ); + R( b, c, d, e, a, F0, K0, 14, 9 ); + R( a, b, c, d, e, F0, K0, 15, 8 ); + R( e, a, b, c, d, F1, K1, 7, 7 ); + R( d, e, a, b, c, F1, K1, 4, 6 ); + R( c, d, e, a, b, F1, K1, 13, 8 ); + R( b, c, d, e, a, F1, K1, 1, 13 ); + R( a, b, c, d, e, F1, K1, 10, 11 ); + R( e, a, b, c, d, F1, K1, 6, 9 ); + R( d, e, a, b, c, F1, K1, 15, 7 ); + R( c, d, e, a, b, F1, K1, 3, 15 ); + R( b, c, d, e, a, F1, K1, 12, 7 ); + R( a, b, c, d, e, F1, K1, 0, 12 ); + R( e, a, b, c, d, F1, K1, 9, 15 ); + R( d, e, a, b, c, F1, K1, 5, 9 ); + R( c, d, e, a, b, F1, K1, 2, 11 ); + R( b, c, d, e, a, F1, K1, 14, 7 ); + R( a, b, c, d, e, F1, K1, 11, 13 ); + R( e, a, b, c, d, F1, K1, 8, 12 ); + R( d, e, a, b, c, F2, K2, 3, 11 ); + R( c, d, e, a, b, F2, K2, 10, 13 ); + R( b, c, d, e, a, F2, K2, 14, 6 ); + R( a, b, c, d, e, F2, K2, 4, 7 ); + R( e, a, b, c, d, F2, K2, 9, 14 ); + R( d, e, a, b, c, F2, K2, 15, 9 ); + R( c, d, e, a, b, F2, K2, 8, 13 ); + R( b, c, d, e, a, F2, K2, 1, 15 ); + R( a, b, c, d, e, F2, K2, 2, 14 ); + R( e, a, b, c, d, F2, K2, 7, 8 ); + R( d, e, a, b, c, F2, K2, 0, 13 ); + R( c, d, e, a, b, F2, K2, 6, 6 ); + R( b, c, d, e, a, F2, K2, 13, 5 ); + R( a, b, c, d, e, F2, K2, 11, 12 ); + R( e, a, b, c, d, F2, K2, 5, 7 ); + R( d, e, a, b, c, F2, K2, 12, 5 ); + R( c, d, e, a, b, F3, K3, 1, 11 ); + R( b, c, d, e, a, F3, K3, 9, 12 ); + R( a, b, c, d, e, F3, K3, 11, 14 ); + R( e, a, b, c, d, F3, K3, 10, 15 ); + R( d, e, a, b, c, F3, K3, 0, 14 ); + R( c, d, e, a, b, F3, K3, 8, 15 ); + R( b, c, d, e, a, F3, K3, 12, 9 ); + R( a, b, c, d, e, F3, K3, 4, 8 ); + R( e, a, b, c, d, F3, K3, 13, 9 ); + R( d, e, a, b, c, F3, K3, 3, 14 ); + R( c, d, e, a, b, F3, K3, 7, 5 ); + R( b, c, d, e, a, F3, K3, 15, 6 ); + R( a, b, c, d, e, F3, K3, 14, 8 ); + R( e, a, b, c, d, F3, K3, 5, 6 ); + R( d, e, a, b, c, F3, K3, 6, 5 ); + R( c, d, e, a, b, F3, K3, 2, 12 ); + R( b, c, d, e, a, F4, K4, 4, 9 ); + R( a, b, c, d, e, F4, K4, 0, 15 ); + R( e, a, b, c, d, F4, K4, 5, 5 ); + R( d, e, a, b, c, F4, K4, 9, 11 ); + R( c, d, e, a, b, F4, K4, 7, 6 ); + R( b, c, d, e, a, F4, K4, 12, 8 ); + R( a, b, c, d, e, F4, K4, 2, 13 ); + R( e, a, b, c, d, F4, K4, 10, 12 ); + R( d, e, a, b, c, F4, K4, 14, 5 ); + R( c, d, e, a, b, F4, K4, 1, 12 ); + R( b, c, d, e, a, F4, K4, 3, 13 ); + R( a, b, c, d, e, F4, K4, 8, 14 ); + R( e, a, b, c, d, F4, K4, 11, 11 ); + R( d, e, a, b, c, F4, K4, 6, 8 ); + R( c, d, e, a, b, F4, K4, 15, 5 ); + R( b, c, d, e, a, F4, K4, 13, 6 ); + + aa = a; bb = b; cc = c; dd = d; ee = e; + + /* right lane */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + R( a, b, c, d, e, F4, KK0, 5, 8); + R( e, a, b, c, d, F4, KK0, 14, 9); + R( d, e, a, b, c, F4, KK0, 7, 9); + R( c, d, e, a, b, F4, KK0, 0, 11); + R( b, c, d, e, a, F4, KK0, 9, 13); + R( a, b, c, d, e, F4, KK0, 2, 15); + R( e, a, b, c, d, F4, KK0, 11, 15); + R( d, e, a, b, c, F4, KK0, 4, 5); + R( c, d, e, a, b, F4, KK0, 13, 7); + R( b, c, d, e, a, F4, KK0, 6, 7); + R( a, b, c, d, e, F4, KK0, 15, 8); + R( e, a, b, c, d, F4, KK0, 8, 11); + R( d, e, a, b, c, F4, KK0, 1, 14); + R( c, d, e, a, b, F4, KK0, 10, 14); + R( b, c, d, e, a, F4, KK0, 3, 12); + R( a, b, c, d, e, F4, KK0, 12, 6); + R( e, a, b, c, d, F3, KK1, 6, 9); + R( d, e, a, b, c, F3, KK1, 11, 13); + R( c, d, e, a, b, F3, KK1, 3, 15); + R( b, c, d, e, a, F3, KK1, 7, 7); + R( a, b, c, d, e, F3, KK1, 0, 12); + R( e, a, b, c, d, F3, KK1, 13, 8); + R( d, e, a, b, c, F3, KK1, 5, 9); + R( c, d, e, a, b, F3, KK1, 10, 11); + R( b, c, d, e, a, F3, KK1, 14, 7); + R( a, b, c, d, e, F3, KK1, 15, 7); + R( e, a, b, c, d, F3, KK1, 8, 12); + R( d, e, a, b, c, F3, KK1, 12, 7); + R( c, d, e, a, b, F3, KK1, 4, 6); + R( b, c, d, e, a, F3, KK1, 9, 15); + R( a, b, c, d, e, F3, KK1, 1, 13); + R( e, a, b, c, d, F3, KK1, 2, 11); + R( d, e, a, b, c, F2, KK2, 15, 9); + R( c, d, e, a, b, F2, KK2, 5, 7); + R( b, c, d, e, a, F2, KK2, 1, 15); + R( a, b, c, d, e, F2, KK2, 3, 11); + R( e, a, b, c, d, F2, KK2, 7, 8); + R( d, e, a, b, c, F2, KK2, 14, 6); + R( c, d, e, a, b, F2, KK2, 6, 6); + R( b, c, d, e, a, F2, KK2, 9, 14); + R( a, b, c, d, e, F2, KK2, 11, 12); + R( e, a, b, c, d, F2, KK2, 8, 13); + R( d, e, a, b, c, F2, KK2, 12, 5); + R( c, d, e, a, b, F2, KK2, 2, 14); + R( b, c, d, e, a, F2, KK2, 10, 13); + R( a, b, c, d, e, F2, KK2, 0, 13); + R( e, a, b, c, d, F2, KK2, 4, 7); + R( d, e, a, b, c, F2, KK2, 13, 5); + R( c, d, e, a, b, F1, KK3, 8, 15); + R( b, c, d, e, a, F1, KK3, 6, 5); + R( a, b, c, d, e, F1, KK3, 4, 8); + R( e, a, b, c, d, F1, KK3, 1, 11); + R( d, e, a, b, c, F1, KK3, 3, 14); + R( c, d, e, a, b, F1, KK3, 11, 14); + R( b, c, d, e, a, F1, KK3, 15, 6); + R( a, b, c, d, e, F1, KK3, 0, 14); + R( e, a, b, c, d, F1, KK3, 5, 6); + R( d, e, a, b, c, F1, KK3, 12, 9); + R( c, d, e, a, b, F1, KK3, 2, 12); + R( b, c, d, e, a, F1, KK3, 13, 9); + R( a, b, c, d, e, F1, KK3, 9, 12); + R( e, a, b, c, d, F1, KK3, 7, 5); + R( d, e, a, b, c, F1, KK3, 10, 15); + R( c, d, e, a, b, F1, KK3, 14, 8); + R( b, c, d, e, a, F0, KK4, 12, 8); + R( a, b, c, d, e, F0, KK4, 15, 5); + R( e, a, b, c, d, F0, KK4, 10, 12); + R( d, e, a, b, c, F0, KK4, 4, 9); + R( c, d, e, a, b, F0, KK4, 1, 12); + R( b, c, d, e, a, F0, KK4, 5, 5); + R( a, b, c, d, e, F0, KK4, 8, 14); + R( e, a, b, c, d, F0, KK4, 7, 6); + R( d, e, a, b, c, F0, KK4, 6, 8); + R( c, d, e, a, b, F0, KK4, 2, 13); + R( b, c, d, e, a, F0, KK4, 13, 6); + R( a, b, c, d, e, F0, KK4, 14, 5); + R( e, a, b, c, d, F0, KK4, 0, 15); + R( d, e, a, b, c, F0, KK4, 3, 13); + R( c, d, e, a, b, F0, KK4, 9, 11); + R( b, c, d, e, a, F0, KK4, 11, 11); + + + t = hd->h1 + d + cc; + hd->h1 = hd->h2 + e + dd; + hd->h2 = hd->h3 + a + ee; + hd->h3 = hd->h4 + b + aa; + hd->h4 = hd->h0 + c + bb; + hd->h0 = t; +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +rmd160_write ( void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + RMD160_CONTEXT *hd = context; + + if( hd->count == 64 ) /* flush the buffer */ + { + transform( hd, hd->buf ); + _gcry_burn_stack (108+5*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + if( hd->count ) + { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + rmd160_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + + while( inlen >= 64 ) + { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + _gcry_burn_stack (108+5*sizeof(void*)); + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; +} + +/**************** + * Apply the rmd160 transform function on the buffer which must have + * a length 64 bytes. Do not use this function together with the + * other functions, use rmd160_init to initialize internal variables. + * Returns: 16 bytes in buffer with the mixed contentes of buffer. + */ + + +/* The routine terminates the computation + */ + +static void +rmd160_final( void *context ) +{ + RMD160_CONTEXT *hd = context; + u32 t, msb, lsb; + byte *p; + + rmd160_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) /* enough room */ + { + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else /* need one extra block */ + { + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + rmd160_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + _gcry_burn_stack (108+5*sizeof(void*)); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ + *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) +#else /* little endian */ +#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) +#endif + X(0); + X(1); + X(2); + X(3); + X(4); +#undef X +} + +static byte * +rmd160_read( void *context ) +{ + RMD160_CONTEXT *hd = context; + + return hd->buf; +} + + + +/**************** + * Shortcut functions which puts the hash value of the supplied buffer + * into outbuf which must have a size of 20 bytes. + */ + +static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; + +static gcry_md_oid_spec_t oid_spec_rmd160[] = + { + /* rsaSignatureWithripemd160 */ + { "1.3.36.3.3.1.2" }, + /* TeleTrust hash algorithm. */ + { "1.3.36.3.2.1" }, + { NULL } + }; + +gcry_md_spec_t _gcry_digest_spec_rmd160 = + { + "RIPEMD160", asn, DIM (asn), oid_spec_rmd160, 20, + _gcry_rmd160_init, rmd160_write, rmd160_final, rmd160_read, + sizeof (RMD160_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_rmd160", +#endif + .blocksize = 64 + }; + + +GRUB_MOD_INIT(gcry_rmd160) +{ + COMPILE_TIME_ASSERT(sizeof (RMD160_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + grub_md_register (&_gcry_digest_spec_rmd160); +} + +GRUB_MOD_FINI(gcry_rmd160) +{ + grub_md_unregister (&_gcry_digest_spec_rmd160); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/rsa.c b/grub-core/lib/libgcrypt-grub/cipher/rsa.c new file mode 100644 index 0000000..6e0187b --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/rsa.c @@ -0,0 +1,395 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* rsa.c - RSA implementation + * Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn) + * Copyright (C) 2000, 2001, 2002, 2003, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* This code uses an algorithm protected by U.S. Patent #4,405,829 + which expired on September 20, 2000. The patent holder placed that + patent into the public domain on Sep 6th, 2000. +*/ + + +#include "g10lib.h" +#include "mpi.h" +#include "cipher.h" + + +typedef struct +{ + gcry_mpi_t n; /* modulus */ + gcry_mpi_t e; /* exponent */ +} RSA_public_key; + + +typedef struct +{ + gcry_mpi_t n; /* public modulus */ + gcry_mpi_t e; /* public exponent */ + gcry_mpi_t d; /* exponent */ + gcry_mpi_t p; /* prime p. */ + gcry_mpi_t q; /* prime q. */ + gcry_mpi_t u; /* inverse of p mod q. */ +} RSA_secret_key; + + +/* A sample 1024 bit RSA key used for the selftests. */ +/* A sample 1024 bit RSA key used for the selftests (public only). */ + + + + +static int check_secret_key (RSA_secret_key *sk); +static void public (gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *skey); + + +/* Check that a freshly generated key actually works. Returns 0 on success. */ + + +/* Callback used by the prime generation to test whether the exponent + is suitable. Returns 0 if the test has been passed. */ + +/**************** + * Generate a key pair with a key of size NBITS. + * USE_E = 0 let Libcgrypt decide what exponent to use. + * = 1 request the use of a "secure" exponent; this is required by some + * specification to be 65537. + * > 2 Use this public exponent. If the given exponent + * is not odd one is internally added to it. + * TRANSIENT_KEY: If true, generate the primes using the standard RNG. + * Returns: 2 structures filled with all needed values + */ + + +/* Helper for generate_x931. */ + + +/* Helper for generate_x931. */ + + + +/* Variant of the standard key generation code using the algorithm + from X9.31. Using this algorithm has the advantage that the + generation can be made deterministic which is required for CAVS + testing. */ + + +/**************** + * Test whether the secret key is valid. + * Returns: true if this is a valid key. + */ +static int +check_secret_key( RSA_secret_key *sk ) +{ + int rc; + gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 ); + + mpi_mul(temp, sk->p, sk->q ); + rc = mpi_cmp( temp, sk->n ); + mpi_free(temp); + return !rc; +} + + + +/**************** + * Public key operation. Encrypt INPUT with PKEY and put result into OUTPUT. + * + * c = m^e mod n + * + * Where c is OUTPUT, m is INPUT and e,n are elements of PKEY. + */ +static void +public(gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *pkey ) +{ + if( output == input ) /* powm doesn't like output and input the same */ + { + gcry_mpi_t x = mpi_alloc( mpi_get_nlimbs(input)*2 ); + mpi_powm( x, input, pkey->e, pkey->n ); + mpi_set(output, x); + mpi_free(x); + } + else + mpi_powm( output, input, pkey->e, pkey->n ); +} + +#if 0 +static void +stronger_key_check ( RSA_secret_key *skey ) +{ + gcry_mpi_t t = mpi_alloc_secure ( 0 ); + gcry_mpi_t t1 = mpi_alloc_secure ( 0 ); + gcry_mpi_t t2 = mpi_alloc_secure ( 0 ); + gcry_mpi_t phi = mpi_alloc_secure ( 0 ); + + /* check that n == p * q */ + mpi_mul( t, skey->p, skey->q); + if (mpi_cmp( t, skey->n) ) + log_info ( "RSA Oops: n != p * q\n" ); + + /* check that p is less than q */ + if( mpi_cmp( skey->p, skey->q ) > 0 ) + { + log_info ("RSA Oops: p >= q - fixed\n"); + _gcry_mpi_swap ( skey->p, skey->q); + } + + /* check that e divides neither p-1 nor q-1 */ + mpi_sub_ui(t, skey->p, 1 ); + mpi_fdiv_r(t, t, skey->e ); + if ( !mpi_cmp_ui( t, 0) ) + log_info ( "RSA Oops: e divides p-1\n" ); + mpi_sub_ui(t, skey->q, 1 ); + mpi_fdiv_r(t, t, skey->e ); + if ( !mpi_cmp_ui( t, 0) ) + log_info ( "RSA Oops: e divides q-1\n" ); + + /* check that d is correct */ + mpi_sub_ui( t1, skey->p, 1 ); + mpi_sub_ui( t2, skey->q, 1 ); + mpi_mul( phi, t1, t2 ); + gcry_mpi_gcd(t, t1, t2); + mpi_fdiv_q(t, phi, t); + mpi_invm(t, skey->e, t ); + if ( mpi_cmp(t, skey->d ) ) + { + log_info ( "RSA Oops: d is wrong - fixed\n"); + mpi_set (skey->d, t); + _gcry_log_mpidump (" fixed d", skey->d); + } + + /* check for correctness of u */ + mpi_invm(t, skey->p, skey->q ); + if ( mpi_cmp(t, skey->u ) ) + { + log_info ( "RSA Oops: u is wrong - fixed\n"); + mpi_set (skey->u, t); + _gcry_log_mpidump (" fixed u", skey->u); + } + + log_info ( "RSA secret key check finished\n"); + + mpi_free (t); + mpi_free (t1); + mpi_free (t2); + mpi_free (phi); +} +#endif + + + +/**************** + * Secret key operation. Encrypt INPUT with SKEY and put result into OUTPUT. + * + * m = c^d mod n + * + * Or faster: + * + * m1 = c ^ (d mod (p-1)) mod p + * m2 = c ^ (d mod (q-1)) mod q + * h = u * (m2 - m1) mod q + * m = m1 + h * p + * + * Where m is OUTPUT, c is INPUT and d,n,p,q,u are elements of SKEY. + */ + + + +/* Perform RSA blinding. */ + +/* Undo RSA blinding. */ + +/********************************************* + ************** interface ****************** + *********************************************/ + + + +#define rsa_generate 0 + +static gcry_err_code_t +rsa_check_secret_key (int algo, gcry_mpi_t *skey) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + RSA_secret_key sk; + + (void)algo; + + sk.n = skey[0]; + sk.e = skey[1]; + sk.d = skey[2]; + sk.p = skey[3]; + sk.q = skey[4]; + sk.u = skey[5]; + + if (!sk.p || !sk.q || !sk.u) + err = GPG_ERR_NO_OBJ; /* To check the key we need the optional + parameters. */ + else if (!check_secret_key (&sk)) + err = GPG_ERR_BAD_SECKEY; + + return err; +} + + +static gcry_err_code_t +rsa_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, + gcry_mpi_t *pkey, int flags) +{ + RSA_public_key pk; + + (void)algo; + (void)flags; + + pk.n = pkey[0]; + pk.e = pkey[1]; + resarr[0] = mpi_alloc (mpi_get_nlimbs (pk.n)); + public (resarr[0], data, &pk); + + return GPG_ERR_NO_ERROR; +} + + +#define rsa_decrypt 0 + +#define rsa_sign 0 + +static gcry_err_code_t +rsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, + int (*cmp) (void *opaque, gcry_mpi_t tmp), + void *opaquev) +{ + RSA_public_key pk; + gcry_mpi_t result; + gcry_err_code_t rc; + + (void)algo; + (void)cmp; + (void)opaquev; + + pk.n = pkey[0]; + pk.e = pkey[1]; + result = gcry_mpi_new ( 160 ); + public( result, data[0], &pk ); +#ifdef IS_DEVELOPMENT_VERSION + if (DBG_CIPHER) + { + log_mpidump ("rsa verify result:", result ); + log_mpidump (" hash:", hash ); + } +#endif /*IS_DEVELOPMENT_VERSION*/ + if (cmp) + rc = (*cmp) (opaquev, result); + else + rc = mpi_cmp (result, hash) ? GPG_ERR_BAD_SIGNATURE : GPG_ERR_NO_ERROR; + gcry_mpi_release (result); + + return rc; +} + + +static unsigned int +rsa_get_nbits (int algo, gcry_mpi_t *pkey) +{ + (void)algo; + + return mpi_get_nbits (pkey[0]); +} + + +/* Compute a keygrip. MD is the hash context which we are going to + update. KEYPARAM is an S-expression with the key parameters, this + is usually a public key but may also be a secret key. An example + of such an S-expression is: + + (rsa + (n #00B...#) + (e #010001#)) + + PKCS-15 says that for RSA only the modulus should be hashed - + however, it is not clear whether this is meant to use the raw bytes + (assuming this is an unsigned integer) or whether the DER required + 0 should be prefixed. We hash the raw bytes. */ + + + + +/* + Self-test section. + */ + + + + +/* Given an S-expression ENCR_DATA of the form: + + (enc-val + (rsa + (a a-value))) + + as returned by gcry_pk_decrypt, return the the A-VALUE. On error, + return NULL. */ + + + + + + +/* Run a full self-test for ALGO and return 0 on success. */ + + + + +static const char *rsa_names[] = + { + "rsa", + "openpgp-rsa", + "oid.1.2.840.113549.1.1.1", + NULL, + }; + +gcry_pk_spec_t _gcry_pubkey_spec_rsa = + { + "RSA", rsa_names, + "ne", "nedpqu", "a", "s", "n", + GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR, + rsa_generate, + rsa_check_secret_key, + rsa_encrypt, + rsa_decrypt, + rsa_sign, + rsa_verify, + rsa_get_nbits, +#ifdef GRUB_UTIL + .modname = "gcry_rsa", +#endif + }; + + +GRUB_MOD_INIT(gcry_rsa) +{ + grub_crypto_pk_rsa = &_gcry_pubkey_spec_rsa; +} + +GRUB_MOD_FINI(gcry_rsa) +{ + grub_crypto_pk_rsa = 0; +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/seed.c b/grub-core/lib/libgcrypt-grub/cipher/seed.c new file mode 100644 index 0000000..087e27b --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/seed.c @@ -0,0 +1,461 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* SEED for libgcrypt + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -- + * This implementation was provided for libgcrypt in public domain + * by Hye-Shik Chang <perky@FreeBSD.org>, July 2006. + */ + + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + +#define NUMKC 16 + +#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ + ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) { (ct)[0] = (byte)((st) >> 24); \ + (ct)[1] = (byte)((st) >> 16); \ + (ct)[2] = (byte)((st) >> 8); \ + (ct)[3] = (byte)(st); } + +union wordbuf +{ + u32 w; + byte b[4]; +}; + +#ifdef WORDS_BIGENDIAN +#define b0 b[3] +#define b1 b[2] +#define b2 b[1] +#define b3 b[0] +#else +#define b0 b[0] +#define b1 b[1] +#define b2 b[2] +#define b3 b[3] +#endif + + +typedef struct +{ + u32 keyschedule[32]; +} SEED_context; + +static const u32 SS0[256] = { + 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, + 0x2c8ca0ac, 0x25052124, 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, + 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360, 0x28082028, 0x04444044, + 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314, + 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, + 0x12c2d2d0, 0x2ecee2ec, 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, + 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074, 0x2ccce0ec, 0x15859194, + 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100, + 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, + 0x32c2f2f0, 0x19c9d1d8, 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, + 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8, 0x20406060, 0x10405050, + 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c, + 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, + 0x2f8fa3ac, 0x15c5d1d4, 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, + 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008, 0x1f0f131c, 0x19899198, + 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0, + 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, + 0x0e0e020c, 0x2b8ba3a8, 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, + 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208, 0x3f8fb3bc, 0x2fcfe3ec, + 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064, + 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, + 0x2b4b6368, 0x26466264, 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, + 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0, 0x3a4a7278, 0x07474344, + 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc, + 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, + 0x22022220, 0x38083038, 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, + 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394, 0x35053134, 0x0bcbc3c8, + 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188, + 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, + 0x02828280, 0x04c4c0c4, 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, + 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8, 0x0f0f030c, 0x0e8e828c, + 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4, + 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, + 0x2d0d212c, 0x00404040, 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, + 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154, 0x3b0b3338, 0x1cccd0dc, + 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254, + 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, + 0x25456164, 0x3acaf2f8, 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, + 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0, 0x31013130, 0x2acae2e8, + 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088, + 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, + 0x07070304, 0x33033330, 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, + 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298, +}; + +static const u32 SS1[256] = { + 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, + 0xb03383b3, 0xb83888b0, 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, + 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53, 0xc003c3c3, 0x60224262, + 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3, + 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, + 0x34360632, 0x480b4b43, 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, + 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0, 0xc002c2c2, 0x44054541, + 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890, + 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, + 0x0c0d0d01, 0xdc1fcfd3, 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, + 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272, 0x40024242, 0xd414c4d0, + 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83, + 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, + 0xa82a8aa2, 0x34340430, 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, + 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0, 0x54174753, 0xac2e8ea2, + 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1, + 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, + 0x682a4a62, 0xb03181b1, 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, + 0x20220222, 0x04040400, 0x68284860, 0x70314171, 0x04070703, 0xd81bcbd3, + 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951, + 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, + 0xa82b8ba3, 0xd010c0d0, 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, + 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3, 0x94168692, 0x783b4b73, + 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41, + 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, + 0xb83a8ab2, 0x6c2e4e62, 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, + 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0, 0x14150511, 0xf83bcbf3, + 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303, + 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, + 0xe82acae2, 0x08090901, 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, + 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501, 0xf83acaf2, 0x00010101, + 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343, + 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, + 0x48084840, 0x78394971, 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, + 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53, 0x74374773, 0x54144450, + 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642, + 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, + 0xc809c9c1, 0xfc3dcdf1, 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, + 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70, 0x0c0e0e02, 0x50104050, + 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393, + 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, + 0x080a0a02, 0x84078783, 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, + 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3, +}; + +static const u32 SS2[256] = { + 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, + 0xa0ac2c8c, 0x21242505, 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, + 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343, 0x20282808, 0x40440444, + 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707, + 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, + 0xd2d012c2, 0xe2ec2ece, 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, + 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444, 0xe0ec2ccc, 0x91941585, + 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101, + 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, + 0xf2f032c2, 0xd1d819c9, 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, + 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9, 0x60602040, 0x50501040, + 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f, + 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, + 0xa3ac2f8f, 0xd1d415c5, 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, + 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808, 0x131c1f0f, 0x91981989, + 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1, + 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, + 0x020c0e0e, 0xa3a82b8b, 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, + 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a, 0xb3bc3f8f, 0xe3ec2fcf, + 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444, + 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, + 0x63682b4b, 0x62642646, 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, + 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0, 0x72783a4a, 0x43440747, + 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf, + 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, + 0x22202202, 0x30383808, 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, + 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787, 0x31343505, 0xc3c80bcb, + 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989, + 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, + 0x82800282, 0xc0c404c4, 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, + 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888, 0x030c0f0f, 0x828c0e8e, + 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484, + 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, + 0x212c2d0d, 0x40400040, 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, + 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545, 0x33383b0b, 0xd0dc1ccc, + 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646, + 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, + 0x61642545, 0xf2f83aca, 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, + 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282, 0x31303101, 0xe2e82aca, + 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888, + 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, + 0x03040707, 0x33303303, 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, + 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a, +}; + +static const u32 SS3[256] = { + 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, + 0x83b3b033, 0x88b0b838, 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, + 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b, 0xc3c3c003, 0x42626022, + 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427, + 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, + 0x06323436, 0x4b43480b, 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, + 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434, 0xc2c2c002, 0x45414405, + 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818, + 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, + 0x0d010c0d, 0xcfd3dc1f, 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, + 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032, 0x42424002, 0xc4d0d414, + 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b, + 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, + 0x8aa2a82a, 0x04303434, 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, + 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838, 0x47535417, 0x8ea2ac2e, + 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839, + 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, + 0x4a62682a, 0x81b1b031, 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, + 0x02222022, 0x04000404, 0x48606828, 0x41717031, 0x07030407, 0xcbd3d81b, + 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819, + 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, + 0x8ba3a82b, 0xc0d0d010, 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, + 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f, 0x86929416, 0x4b73783b, + 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d, + 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, + 0x8ab2b83a, 0x4e626c2e, 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, + 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c, 0x05111415, 0xcbf3f83b, + 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003, + 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, + 0xcae2e82a, 0x09010809, 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, + 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405, 0xcaf2f83a, 0x01010001, + 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003, + 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, + 0x48404808, 0x49717839, 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, + 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f, 0x47737437, 0x44505414, + 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406, + 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, + 0xc9c1c809, 0xcdf1fc3d, 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, + 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c, 0x0e020c0e, 0x40505010, + 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013, + 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, + 0x0a02080a, 0x87838407, 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, + 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437, +}; + +static const u32 KC[NUMKC] = { + 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc, + 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf, + 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1, + 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b, +}; + + + +/* Perform the key setup. + */ +static gcry_err_code_t +do_setkey (SEED_context *ctx, const byte *key, const unsigned keylen) +{ + static int initialized = 0; + static const char *selftest_failed=0; + u32 x1, x2, x3, x4; + union wordbuf t0, t1; + u32 *keyout = ctx->keyschedule; + int i; + + if (!initialized) + { + initialized = 1; + selftest_failed = selftest (); + if( selftest_failed ) + log_error ("%s\n", selftest_failed ); + } + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + if (keylen != 16) + return GPG_ERR_INV_KEYLEN; + + x1 = GETU32 (key); + x2 = GETU32 (key+4); + x3 = GETU32 (key+8); + x4 = GETU32 (key+12); + + for (i = 0; i < NUMKC; i++) + { + t0.w = x1 + x3 - KC[i]; + t1.w = x2 + KC[i] - x4; + *(keyout++) = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3]; + *(keyout++) = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; + + if (i % 2 == 0) + { + t0.w = x1; + x1 = (x1>>8) ^ (x2<<24); + x2 = (x2>>8) ^ (t0.w<<24); + } + else + { + t0.w = x3; + x3 = (x3<<8) ^ (x4>>24); + x4 = (x4<<8) ^ (t0.w>>24); + } + } + + return 0; +} + +static gcry_err_code_t +seed_setkey (void *context, const byte *key, const unsigned keylen) +{ + SEED_context *ctx = context; + + int rc = do_setkey (ctx, key, keylen); + _gcry_burn_stack (4*6 + sizeof(void*)*2 + sizeof(int)*2); + return rc; +} + + + +#define OP(X1, X2, X3, X4, rbase) \ + t0.w = X3 ^ ctx->keyschedule[rbase]; \ + t1.w = X4 ^ ctx->keyschedule[rbase+1]; \ + t1.w ^= t0.w; \ + t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; \ + t0.w += t1.w; \ + t0.w = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3]; \ + t1.w += t0.w; \ + t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; \ + t0.w += t1.w; \ + X1 ^= t0.w; \ + X2 ^= t1.w; + +/* Encrypt one block. inbuf and outbuf may be the same. */ +static void +do_encrypt (const SEED_context *ctx, byte *outbuf, const byte *inbuf) +{ + u32 x1, x2, x3, x4; + union wordbuf t0, t1; + + x1 = GETU32 (inbuf); + x2 = GETU32 (inbuf+4); + x3 = GETU32 (inbuf+8); + x4 = GETU32 (inbuf+12); + + OP (x1, x2, x3, x4, 0); + OP (x3, x4, x1, x2, 2); + OP (x1, x2, x3, x4, 4); + OP (x3, x4, x1, x2, 6); + OP (x1, x2, x3, x4, 8); + OP (x3, x4, x1, x2, 10); + OP (x1, x2, x3, x4, 12); + OP (x3, x4, x1, x2, 14); + OP (x1, x2, x3, x4, 16); + OP (x3, x4, x1, x2, 18); + OP (x1, x2, x3, x4, 20); + OP (x3, x4, x1, x2, 22); + OP (x1, x2, x3, x4, 24); + OP (x3, x4, x1, x2, 26); + OP (x1, x2, x3, x4, 28); + OP (x3, x4, x1, x2, 30); + + PUTU32 (outbuf, x3); + PUTU32 (outbuf+4, x4); + PUTU32 (outbuf+8, x1); + PUTU32 (outbuf+12, x2); +} + +static void +seed_encrypt (void *context, byte *outbuf, const byte *inbuf) +{ + SEED_context *ctx = context; + + do_encrypt (ctx, outbuf, inbuf); + _gcry_burn_stack (4*6); +} + + + +/* Decrypt one block. inbuf and outbuf may be the same. */ +static void +do_decrypt (SEED_context *ctx, byte *outbuf, const byte *inbuf) +{ + u32 x1, x2, x3, x4; + union wordbuf t0, t1; + + x1 = GETU32 (inbuf); + x2 = GETU32 (inbuf+4); + x3 = GETU32 (inbuf+8); + x4 = GETU32 (inbuf+12); + + OP (x1, x2, x3, x4, 30); + OP (x3, x4, x1, x2, 28); + OP (x1, x2, x3, x4, 26); + OP (x3, x4, x1, x2, 24); + OP (x1, x2, x3, x4, 22); + OP (x3, x4, x1, x2, 20); + OP (x1, x2, x3, x4, 18); + OP (x3, x4, x1, x2, 16); + OP (x1, x2, x3, x4, 14); + OP (x3, x4, x1, x2, 12); + OP (x1, x2, x3, x4, 10); + OP (x3, x4, x1, x2, 8); + OP (x1, x2, x3, x4, 6); + OP (x3, x4, x1, x2, 4); + OP (x1, x2, x3, x4, 2); + OP (x3, x4, x1, x2, 0); + + PUTU32 (outbuf, x3); + PUTU32 (outbuf+4, x4); + PUTU32 (outbuf+8, x1); + PUTU32 (outbuf+12, x2); +} + +static void +seed_decrypt (void *context, byte *outbuf, const byte *inbuf) +{ + SEED_context *ctx = context; + + do_decrypt (ctx, outbuf, inbuf); + _gcry_burn_stack (4*6); +} + + +/* Test a single encryption and decryption with each key size. */ + + + +static gcry_cipher_oid_spec_t seed_oids[] = + { + { "1.2.410.200004.1.3", GCRY_CIPHER_MODE_ECB }, + { "1.2.410.200004.1.4", GCRY_CIPHER_MODE_CBC }, + { "1.2.410.200004.1.5", GCRY_CIPHER_MODE_CFB }, + { "1.2.410.200004.1.6", GCRY_CIPHER_MODE_OFB }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_seed = + { + "SEED", NULL, seed_oids, 16, 128, sizeof (SEED_context), + seed_setkey, seed_encrypt, seed_decrypt, +#ifdef GRUB_UTIL + .modname = "gcry_seed", +#endif + }; + + +GRUB_MOD_INIT(gcry_seed) +{ + grub_cipher_register (&_gcry_cipher_spec_seed); +} + +GRUB_MOD_FINI(gcry_seed) +{ + grub_cipher_unregister (&_gcry_cipher_spec_seed); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/serpent.c b/grub-core/lib/libgcrypt-grub/cipher/serpent.c new file mode 100644 index 0000000..75be7b8 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/serpent.c @@ -0,0 +1,903 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* serpent.c - Implementation of the Serpent encryption algorithm. + * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + + + +#include "types.h" +#include "g10lib.h" +#include "cipher.h" +#include "bithelp.h" + +/* Number of rounds per Serpent encrypt/decrypt operation. */ +#define ROUNDS 32 + +/* Magic number, used during generating of the subkeys. */ +#define PHI 0x9E3779B9 + +/* Serpent works on 128 bit blocks. */ +typedef u32 serpent_block_t[4]; + +/* Serpent key, provided by the user. If the original key is shorter + than 256 bits, it is padded. */ +typedef u32 serpent_key_t[8]; + +/* The key schedule consists of 33 128 bit subkeys. */ +typedef u32 serpent_subkeys_t[ROUNDS + 1][4]; + +/* A Serpent context. */ +typedef struct serpent_context +{ + serpent_subkeys_t keys; /* Generated subkeys. */ +} serpent_context_t; + + +/* A prototype. */ +static const char *serpent_test (void); + + +#define byte_swap_32(x) \ + (0 \ + | (((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \ + | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +/* These are the S-Boxes of Serpent. They are copied from Serpents + reference implementation (the optimized one, contained in + `floppy2') and are therefore: + + Copyright (C) 1998 Ross Anderson, Eli Biham, Lars Knudsen. + + To quote the Serpent homepage + (http://www.cl.cam.ac.uk/~rja14/serpent.html): + + "Serpent is now completely in the public domain, and we impose no + restrictions on its use. This was announced on the 21st August at + the First AES Candidate Conference. The optimised implementations + in the submission package are now under the GNU PUBLIC LICENSE + (GPL), although some comments in the code still say otherwise. You + are welcome to use Serpent for any application." */ + +#define SBOX0(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t05, t06, t07, t08, t09; \ + u32 t11, t12, t13, t14, t15, t17, t01; \ + t01 = b ^ c ; \ + t02 = a | d ; \ + t03 = a ^ b ; \ + z = t02 ^ t01; \ + t05 = c | z ; \ + t06 = a ^ d ; \ + t07 = b | c ; \ + t08 = d & t05; \ + t09 = t03 & t07; \ + y = t09 ^ t08; \ + t11 = t09 & y ; \ + t12 = c ^ d ; \ + t13 = t07 ^ t11; \ + t14 = b & t06; \ + t15 = t06 ^ t13; \ + w = ~ t15; \ + t17 = w ^ t14; \ + x = t12 ^ t17; \ + } + +#define SBOX0_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t08, t09, t10; \ + u32 t12, t13, t14, t15, t17, t18, t01; \ + t01 = c ^ d ; \ + t02 = a | b ; \ + t03 = b | c ; \ + t04 = c & t01; \ + t05 = t02 ^ t01; \ + t06 = a | t04; \ + y = ~ t05; \ + t08 = b ^ d ; \ + t09 = t03 & t08; \ + t10 = d | y ; \ + x = t09 ^ t06; \ + t12 = a | t05; \ + t13 = x ^ t12; \ + t14 = t03 ^ t10; \ + t15 = a ^ c ; \ + z = t14 ^ t13; \ + t17 = t05 & t13; \ + t18 = t14 | t17; \ + w = t15 ^ t18; \ + } + +#define SBOX1(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t08; \ + u32 t10, t11, t12, t13, t16, t17, t01; \ + t01 = a | d ; \ + t02 = c ^ d ; \ + t03 = ~ b ; \ + t04 = a ^ c ; \ + t05 = a | t03; \ + t06 = d & t04; \ + t07 = t01 & t02; \ + t08 = b | t06; \ + y = t02 ^ t05; \ + t10 = t07 ^ t08; \ + t11 = t01 ^ t10; \ + t12 = y ^ t11; \ + t13 = b & d ; \ + z = ~ t10; \ + x = t13 ^ t12; \ + t16 = t10 | x ; \ + t17 = t05 & t16; \ + w = c ^ t17; \ + } + +#define SBOX1_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t08; \ + u32 t09, t10, t11, t14, t15, t17, t01; \ + t01 = a ^ b ; \ + t02 = b | d ; \ + t03 = a & c ; \ + t04 = c ^ t02; \ + t05 = a | t04; \ + t06 = t01 & t05; \ + t07 = d | t03; \ + t08 = b ^ t06; \ + t09 = t07 ^ t06; \ + t10 = t04 | t03; \ + t11 = d & t08; \ + y = ~ t09; \ + x = t10 ^ t11; \ + t14 = a | y ; \ + t15 = t06 ^ x ; \ + z = t01 ^ t04; \ + t17 = c ^ t15; \ + w = t14 ^ t17; \ + } + +#define SBOX2(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t05, t06, t07, t08; \ + u32 t09, t10, t12, t13, t14, t01; \ + t01 = a | c ; \ + t02 = a ^ b ; \ + t03 = d ^ t01; \ + w = t02 ^ t03; \ + t05 = c ^ w ; \ + t06 = b ^ t05; \ + t07 = b | t05; \ + t08 = t01 & t06; \ + t09 = t03 ^ t07; \ + t10 = t02 | t09; \ + x = t10 ^ t08; \ + t12 = a | d ; \ + t13 = t09 ^ x ; \ + t14 = b ^ t13; \ + z = ~ t09; \ + y = t12 ^ t14; \ + } + +#define SBOX2_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t06, t07, t08, t09; \ + u32 t10, t11, t12, t15, t16, t17, t01; \ + t01 = a ^ d ; \ + t02 = c ^ d ; \ + t03 = a & c ; \ + t04 = b | t02; \ + w = t01 ^ t04; \ + t06 = a | c ; \ + t07 = d | w ; \ + t08 = ~ d ; \ + t09 = b & t06; \ + t10 = t08 | t03; \ + t11 = b & t07; \ + t12 = t06 & t02; \ + z = t09 ^ t10; \ + x = t12 ^ t11; \ + t15 = c & z ; \ + t16 = w ^ x ; \ + t17 = t10 ^ t15; \ + y = t16 ^ t17; \ + } + +#define SBOX3(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t08; \ + u32 t09, t10, t11, t13, t14, t15, t01; \ + t01 = a ^ c ; \ + t02 = a | d ; \ + t03 = a & d ; \ + t04 = t01 & t02; \ + t05 = b | t03; \ + t06 = a & b ; \ + t07 = d ^ t04; \ + t08 = c | t06; \ + t09 = b ^ t07; \ + t10 = d & t05; \ + t11 = t02 ^ t10; \ + z = t08 ^ t09; \ + t13 = d | z ; \ + t14 = a | t07; \ + t15 = b & t13; \ + y = t08 ^ t11; \ + w = t14 ^ t15; \ + x = t05 ^ t04; \ + } + +#define SBOX3_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t09; \ + u32 t11, t12, t13, t14, t16, t01; \ + t01 = c | d ; \ + t02 = a | d ; \ + t03 = c ^ t02; \ + t04 = b ^ t02; \ + t05 = a ^ d ; \ + t06 = t04 & t03; \ + t07 = b & t01; \ + y = t05 ^ t06; \ + t09 = a ^ t03; \ + w = t07 ^ t03; \ + t11 = w | t05; \ + t12 = t09 & t11; \ + t13 = a & y ; \ + t14 = t01 ^ t05; \ + x = b ^ t12; \ + t16 = b | t13; \ + z = t14 ^ t16; \ + } + +#define SBOX4(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t08, t09; \ + u32 t10, t11, t12, t13, t14, t15, t16, t01; \ + t01 = a | b ; \ + t02 = b | c ; \ + t03 = a ^ t02; \ + t04 = b ^ d ; \ + t05 = d | t03; \ + t06 = d & t01; \ + z = t03 ^ t06; \ + t08 = z & t04; \ + t09 = t04 & t05; \ + t10 = c ^ t06; \ + t11 = b & c ; \ + t12 = t04 ^ t08; \ + t13 = t11 | t03; \ + t14 = t10 ^ t09; \ + t15 = a & t05; \ + t16 = t11 | t12; \ + y = t13 ^ t08; \ + x = t15 ^ t16; \ + w = ~ t14; \ + } + +#define SBOX4_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t09; \ + u32 t10, t11, t12, t13, t15, t01; \ + t01 = b | d ; \ + t02 = c | d ; \ + t03 = a & t01; \ + t04 = b ^ t02; \ + t05 = c ^ d ; \ + t06 = ~ t03; \ + t07 = a & t04; \ + x = t05 ^ t07; \ + t09 = x | t06; \ + t10 = a ^ t07; \ + t11 = t01 ^ t09; \ + t12 = d ^ t04; \ + t13 = c | t10; \ + z = t03 ^ t12; \ + t15 = a ^ t04; \ + y = t11 ^ t13; \ + w = t15 ^ t09; \ + } + +#define SBOX5(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t07, t08, t09; \ + u32 t10, t11, t12, t13, t14, t01; \ + t01 = b ^ d ; \ + t02 = b | d ; \ + t03 = a & t01; \ + t04 = c ^ t02; \ + t05 = t03 ^ t04; \ + w = ~ t05; \ + t07 = a ^ t01; \ + t08 = d | w ; \ + t09 = b | t05; \ + t10 = d ^ t08; \ + t11 = b | t07; \ + t12 = t03 | w ; \ + t13 = t07 | t10; \ + t14 = t01 ^ t11; \ + y = t09 ^ t13; \ + x = t07 ^ t08; \ + z = t12 ^ t14; \ + } + +#define SBOX5_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t07, t08, t09; \ + u32 t10, t12, t13, t15, t16, t01; \ + t01 = a & d ; \ + t02 = c ^ t01; \ + t03 = a ^ d ; \ + t04 = b & t02; \ + t05 = a & c ; \ + w = t03 ^ t04; \ + t07 = a & w ; \ + t08 = t01 ^ w ; \ + t09 = b | t05; \ + t10 = ~ b ; \ + x = t08 ^ t09; \ + t12 = t10 | t07; \ + t13 = w | x ; \ + z = t02 ^ t12; \ + t15 = t02 ^ t13; \ + t16 = b ^ d ; \ + y = t16 ^ t15; \ + } + +#define SBOX6(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t07, t08, t09, t10; \ + u32 t11, t12, t13, t15, t17, t18, t01; \ + t01 = a & d ; \ + t02 = b ^ c ; \ + t03 = a ^ d ; \ + t04 = t01 ^ t02; \ + t05 = b | c ; \ + x = ~ t04; \ + t07 = t03 & t05; \ + t08 = b & x ; \ + t09 = a | c ; \ + t10 = t07 ^ t08; \ + t11 = b | d ; \ + t12 = c ^ t11; \ + t13 = t09 ^ t10; \ + y = ~ t13; \ + t15 = x & t03; \ + z = t12 ^ t07; \ + t17 = a ^ b ; \ + t18 = y ^ t15; \ + w = t17 ^ t18; \ + } + +#define SBOX6_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t08, t09; \ + u32 t12, t13, t14, t15, t16, t17, t01; \ + t01 = a ^ c ; \ + t02 = ~ c ; \ + t03 = b & t01; \ + t04 = b | t02; \ + t05 = d | t03; \ + t06 = b ^ d ; \ + t07 = a & t04; \ + t08 = a | t02; \ + t09 = t07 ^ t05; \ + x = t06 ^ t08; \ + w = ~ t09; \ + t12 = b & w ; \ + t13 = t01 & t05; \ + t14 = t01 ^ t12; \ + t15 = t07 ^ t13; \ + t16 = d | t02; \ + t17 = a ^ x ; \ + z = t17 ^ t15; \ + y = t16 ^ t14; \ + } + +#define SBOX7(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t08, t09, t10; \ + u32 t11, t13, t14, t15, t16, t17, t01; \ + t01 = a & c ; \ + t02 = ~ d ; \ + t03 = a & t02; \ + t04 = b | t01; \ + t05 = a & b ; \ + t06 = c ^ t04; \ + z = t03 ^ t06; \ + t08 = c | z ; \ + t09 = d | t05; \ + t10 = a ^ t08; \ + t11 = t04 & z ; \ + x = t09 ^ t10; \ + t13 = b ^ x ; \ + t14 = t01 ^ x ; \ + t15 = c ^ t05; \ + t16 = t11 | t13; \ + t17 = t02 | t14; \ + w = t15 ^ t17; \ + y = a ^ t16; \ + } + +#define SBOX7_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t06, t07, t08, t09; \ + u32 t10, t11, t13, t14, t15, t16, t01; \ + t01 = a & b ; \ + t02 = a | b ; \ + t03 = c | t01; \ + t04 = d & t02; \ + z = t03 ^ t04; \ + t06 = b ^ t04; \ + t07 = d ^ z ; \ + t08 = ~ t07; \ + t09 = t06 | t08; \ + t10 = b ^ d ; \ + t11 = a | d ; \ + x = a ^ t09; \ + t13 = c ^ t06; \ + t14 = c & t11; \ + t15 = d | x ; \ + t16 = t01 | t10; \ + w = t13 ^ t15; \ + y = t14 ^ t16; \ + } + +/* XOR BLOCK1 into BLOCK0. */ +#define BLOCK_XOR(block0, block1) \ + { \ + block0[0] ^= block1[0]; \ + block0[1] ^= block1[1]; \ + block0[2] ^= block1[2]; \ + block0[3] ^= block1[3]; \ + } + +/* Copy BLOCK_SRC to BLOCK_DST. */ +#define BLOCK_COPY(block_dst, block_src) \ + { \ + block_dst[0] = block_src[0]; \ + block_dst[1] = block_src[1]; \ + block_dst[2] = block_src[2]; \ + block_dst[3] = block_src[3]; \ + } + +/* Apply SBOX number WHICH to to the block found in ARRAY0 at index + INDEX, writing the output to the block found in ARRAY1 at index + INDEX. */ +#define SBOX(which, array0, array1, index) \ + SBOX##which (array0[index + 0], array0[index + 1], \ + array0[index + 2], array0[index + 3], \ + array1[index + 0], array1[index + 1], \ + array1[index + 2], array1[index + 3]); + +/* Apply inverse SBOX number WHICH to to the block found in ARRAY0 at + index INDEX, writing the output to the block found in ARRAY1 at + index INDEX. */ +#define SBOX_INVERSE(which, array0, array1, index) \ + SBOX##which##_INVERSE (array0[index + 0], array0[index + 1], \ + array0[index + 2], array0[index + 3], \ + array1[index + 0], array1[index + 1], \ + array1[index + 2], array1[index + 3]); + +/* Apply the linear transformation to BLOCK. */ +#define LINEAR_TRANSFORMATION(block) \ + { \ + block[0] = rol (block[0], 13); \ + block[2] = rol (block[2], 3); \ + block[1] = block[1] ^ block[0] ^ block[2]; \ + block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ + block[1] = rol (block[1], 1); \ + block[3] = rol (block[3], 7); \ + block[0] = block[0] ^ block[1] ^ block[3]; \ + block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ + block[0] = rol (block[0], 5); \ + block[2] = rol (block[2], 22); \ + } + +/* Apply the inverse linear transformation to BLOCK. */ +#define LINEAR_TRANSFORMATION_INVERSE(block) \ + { \ + block[2] = ror (block[2], 22); \ + block[0] = ror (block[0] , 5); \ + block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ + block[0] = block[0] ^ block[1] ^ block[3]; \ + block[3] = ror (block[3], 7); \ + block[1] = ror (block[1], 1); \ + block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ + block[1] = block[1] ^ block[0] ^ block[2]; \ + block[2] = ror (block[2], 3); \ + block[0] = ror (block[0], 13); \ + } + +/* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the + subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. + This macro increments `round'. */ +#define ROUND(which, subkeys, block, block_tmp) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round++; \ + SBOX (which, block, block_tmp, 0); \ + LINEAR_TRANSFORMATION (block_tmp); \ + BLOCK_COPY (block, block_tmp); \ + } + +/* Apply the last Serpent round to BLOCK, using the SBOX number WHICH + and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary + storage. The result will be stored in BLOCK_TMP. This macro + increments `round'. */ +#define ROUND_LAST(which, subkeys, block, block_tmp) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round++; \ + SBOX (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkeys[round]); \ + round++; \ + } + +/* Apply an inverse Serpent round to BLOCK, using the SBOX number + WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as + temporary storage. This macro increments `round'. */ +#define ROUND_INVERSE(which, subkey, block, block_tmp) \ + { \ + LINEAR_TRANSFORMATION_INVERSE (block); \ + SBOX_INVERSE (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkey[round]); \ + round--; \ + BLOCK_COPY (block, block_tmp); \ + } + +/* Apply the first Serpent round to BLOCK, using the SBOX number WHICH + and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary + storage. The result will be stored in BLOCK_TMP. This macro + increments `round'. */ +#define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round--; \ + SBOX_INVERSE (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkeys[round]); \ + round--; \ + } + +/* Convert the user provided key KEY of KEY_LENGTH bytes into the + internally used format. */ +static void +serpent_key_prepare (const byte *key, unsigned int key_length, + serpent_key_t key_prepared) +{ + int i; + + /* Copy key. */ + memcpy (key_prepared, key, key_length); + key_length /= 4; +#ifdef WORDS_BIGENDIAN + for (i = 0; i < key_length; i++) + key_prepared[i] = byte_swap_32 (key_prepared[i]); +#else + i = key_length; +#endif + if (i < 8) + { + /* Key must be padded according to the Serpent + specification. */ + key_prepared[i] = 0x00000001; + + for (i++; i < 8; i++) + key_prepared[i] = 0; + } +} + +/* Derive the 33 subkeys from KEY and store them in SUBKEYS. */ +static void +serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys) +{ + u32 w_real[140]; /* The `prekey'. */ + u32 k[132]; + u32 *w = &w_real[8]; + int i, j; + + /* Initialize with key values. */ + for (i = 0; i < 8; i++) + w[i - 8] = key[i]; + + /* Expand to intermediate key using the affine recurrence. */ + for (i = 0; i < 132; i++) + w[i] = rol (w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11); + + /* Calculate subkeys via S-Boxes, in bitslice mode. */ + SBOX (3, w, k, 0); + SBOX (2, w, k, 4); + SBOX (1, w, k, 8); + SBOX (0, w, k, 12); + SBOX (7, w, k, 16); + SBOX (6, w, k, 20); + SBOX (5, w, k, 24); + SBOX (4, w, k, 28); + SBOX (3, w, k, 32); + SBOX (2, w, k, 36); + SBOX (1, w, k, 40); + SBOX (0, w, k, 44); + SBOX (7, w, k, 48); + SBOX (6, w, k, 52); + SBOX (5, w, k, 56); + SBOX (4, w, k, 60); + SBOX (3, w, k, 64); + SBOX (2, w, k, 68); + SBOX (1, w, k, 72); + SBOX (0, w, k, 76); + SBOX (7, w, k, 80); + SBOX (6, w, k, 84); + SBOX (5, w, k, 88); + SBOX (4, w, k, 92); + SBOX (3, w, k, 96); + SBOX (2, w, k, 100); + SBOX (1, w, k, 104); + SBOX (0, w, k, 108); + SBOX (7, w, k, 112); + SBOX (6, w, k, 116); + SBOX (5, w, k, 120); + SBOX (4, w, k, 124); + SBOX (3, w, k, 128); + + /* Renumber subkeys. */ + for (i = 0; i < ROUNDS + 1; i++) + for (j = 0; j < 4; j++) + subkeys[i][j] = k[4 * i + j]; +} + +/* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */ +static void +serpent_setkey_internal (serpent_context_t *context, + const byte *key, unsigned int key_length) +{ + serpent_key_t key_prepared; + + serpent_key_prepare (key, key_length, key_prepared); + serpent_subkeys_generate (key_prepared, context->keys); + _gcry_burn_stack (272 * sizeof (u32)); +} + +/* Initialize CTX with the key KEY of KEY_LENGTH bytes. */ +static gcry_err_code_t +serpent_setkey (void *ctx, + const byte *key, unsigned int key_length) +{ + serpent_context_t *context = ctx; + static const char *serpent_test_ret; + static int serpent_init_done; + gcry_err_code_t ret = GPG_ERR_NO_ERROR; + + if (! serpent_init_done) + { + /* Execute a self-test the first time, Serpent is used. */ + serpent_test_ret = serpent_test (); + if (serpent_test_ret) + log_error ("Serpent test failure: %s\n", serpent_test_ret); + serpent_init_done = 1; + } + + if (serpent_test_ret) + ret = GPG_ERR_SELFTEST_FAILED; + else + { + serpent_setkey_internal (context, key, key_length); + _gcry_burn_stack (sizeof (serpent_key_t)); + } + + return ret; +} + +static void +serpent_encrypt_internal (serpent_context_t *context, + const byte *input, byte *output) +{ + serpent_block_t b, b_next; + int round = 0; + + memcpy (b, input, sizeof (b)); +#ifdef WORDS_BIGENDIAN + b[0] = byte_swap_32 (b[0]); + b[1] = byte_swap_32 (b[1]); + b[2] = byte_swap_32 (b[2]); + b[3] = byte_swap_32 (b[3]); +#endif + + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + ROUND (7, context->keys, b, b_next); + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + ROUND (7, context->keys, b, b_next); + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + ROUND (7, context->keys, b, b_next); + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + + ROUND_LAST (7, context->keys, b, b_next); + +#ifdef WORDS_BIGENDIAN + b_next[0] = byte_swap_32 (b_next[0]); + b_next[1] = byte_swap_32 (b_next[1]); + b_next[2] = byte_swap_32 (b_next[2]); + b_next[3] = byte_swap_32 (b_next[3]); +#endif + memcpy (output, b_next, sizeof (b_next)); +} + +static void +serpent_decrypt_internal (serpent_context_t *context, + const byte *input, byte *output) +{ + serpent_block_t b, b_next; + int round = ROUNDS; + + memcpy (b_next, input, sizeof (b)); +#ifdef WORDS_BIGENDIAN + b_next[0] = byte_swap_32 (b_next[0]); + b_next[1] = byte_swap_32 (b_next[1]); + b_next[2] = byte_swap_32 (b_next[2]); + b_next[3] = byte_swap_32 (b_next[3]); +#endif + + ROUND_FIRST_INVERSE (7, context->keys, b_next, b); + + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + ROUND_INVERSE (7, context->keys, b, b_next); + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + ROUND_INVERSE (7, context->keys, b, b_next); + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + ROUND_INVERSE (7, context->keys, b, b_next); + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + +#ifdef WORDS_BIGENDIAN + b_next[0] = byte_swap_32 (b_next[0]); + b_next[1] = byte_swap_32 (b_next[1]); + b_next[2] = byte_swap_32 (b_next[2]); + b_next[3] = byte_swap_32 (b_next[3]); +#endif + memcpy (output, b_next, sizeof (b_next)); +} + +static void +serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in) +{ + serpent_context_t *context = ctx; + + serpent_encrypt_internal (context, buffer_in, buffer_out); + _gcry_burn_stack (2 * sizeof (serpent_block_t)); +} + +static void +serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in) +{ + serpent_context_t *context = ctx; + + serpent_decrypt_internal (context, buffer_in, buffer_out); + _gcry_burn_stack (2 * sizeof (serpent_block_t)); +} + + + +/* Serpent test. */ + +static const char *serpent_test (void) { return 0; } + + + +/* "SERPENT" is an alias for "SERPENT128". */ +static const char *cipher_spec_serpent128_aliases[] = + { + "SERPENT", + NULL + }; + +gcry_cipher_spec_t _gcry_cipher_spec_serpent128 = + { + "SERPENT128", cipher_spec_serpent128_aliases, NULL, 16, 128, + sizeof (serpent_context_t), + serpent_setkey, serpent_encrypt, serpent_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_serpent", +#endif + }; + +gcry_cipher_spec_t _gcry_cipher_spec_serpent192 = + { + "SERPENT192", NULL, NULL, 16, 192, + sizeof (serpent_context_t), + serpent_setkey, serpent_encrypt, serpent_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_serpent", +#endif + }; + +gcry_cipher_spec_t _gcry_cipher_spec_serpent256 = + { + "SERPENT256", NULL, NULL, 16, 256, + sizeof (serpent_context_t), + serpent_setkey, serpent_encrypt, serpent_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_serpent", +#endif + }; + + +GRUB_MOD_INIT(gcry_serpent) +{ + grub_cipher_register (&_gcry_cipher_spec_serpent128); + grub_cipher_register (&_gcry_cipher_spec_serpent192); + grub_cipher_register (&_gcry_cipher_spec_serpent256); +} + +GRUB_MOD_FINI(gcry_serpent) +{ + grub_cipher_unregister (&_gcry_cipher_spec_serpent128); + grub_cipher_unregister (&_gcry_cipher_spec_serpent192); + grub_cipher_unregister (&_gcry_cipher_spec_serpent256); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/sha1.c b/grub-core/lib/libgcrypt-grub/cipher/sha1.c new file mode 100644 index 0000000..581802d --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/sha1.c @@ -0,0 +1,419 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* sha1.c - SHA1 hash function + * Copyright (C) 1998, 2001, 2002, 2003, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + + +/* Test vectors: + * + * "abc" + * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D + * + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 + */ + + +#ifdef HAVE_STDINT_H +#endif + +#include "g10lib.h" +#include "bithelp.h" +#include "cipher.h" +#include "hash-common.h" + + +/* A macro to test whether P is properly aligned for an u32 type. + Note that config.h provides a suitable replacement for uintptr_t if + it does not exist in stdint.h. */ +/* #if __GNUC__ >= 2 */ +/* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % __alignof__ (u32))) */ +/* #else */ +/* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % sizeof (u32))) */ +/* #endif */ + +#define TRANSFORM(x,d,n) transform ((x), (d), (n)) + + +typedef struct +{ + u32 h0,h1,h2,h3,h4; + u32 nblocks; + unsigned char buf[64]; + int count; +} SHA1_CONTEXT; + + + +static void +sha1_init (void *context) +{ + SHA1_CONTEXT *hd = context; + + hd->h0 = 0x67452301; + hd->h1 = 0xefcdab89; + hd->h2 = 0x98badcfe; + hd->h3 = 0x10325476; + hd->h4 = 0xc3d2e1f0; + hd->nblocks = 0; + hd->count = 0; +} + + +/* Round function macros. */ +#define K1 0x5A827999L +#define K2 0x6ED9EBA1L +#define K3 0x8F1BBCDCL +#define K4 0xCA62C1D6L +#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) +#define F2(x,y,z) ( x ^ y ^ z ) +#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) +#define F4(x,y,z) ( x ^ y ^ z ) +#define M(i) ( tm = x[ i &0x0f] \ + ^ x[(i-14)&0x0f] \ + ^ x[(i-8) &0x0f] \ + ^ x[(i-3) &0x0f], \ + (x[i&0x0f] = rol(tm, 1))) +#define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \ + + f( b, c, d ) \ + + k \ + + m; \ + b = rol( b, 30 ); \ + } while(0) + + +/* + * Transform NBLOCKS of each 64 bytes (16 32-bit words) at DATA. + */ +static void +transform (SHA1_CONTEXT *hd, const unsigned char *data, size_t nblocks) +{ + register u32 a, b, c, d, e; /* Local copies of the chaining variables. */ + register u32 tm; /* Helper. */ + u32 x[16]; /* The array we work on. */ + + /* Loop over all blocks. */ + for ( ;nblocks; nblocks--) + { +#ifdef WORDS_BIGENDIAN + memcpy (x, data, 64); + data += 64; +#else + { + int i; + unsigned char *p; + + for(i=0, p=(unsigned char*)x; i < 16; i++, p += 4 ) + { + p[3] = *data++; + p[2] = *data++; + p[1] = *data++; + p[0] = *data++; + } + } +#endif + /* Get the values of the chaining variables. */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + + /* Transform. */ + R( a, b, c, d, e, F1, K1, x[ 0] ); + R( e, a, b, c, d, F1, K1, x[ 1] ); + R( d, e, a, b, c, F1, K1, x[ 2] ); + R( c, d, e, a, b, F1, K1, x[ 3] ); + R( b, c, d, e, a, F1, K1, x[ 4] ); + R( a, b, c, d, e, F1, K1, x[ 5] ); + R( e, a, b, c, d, F1, K1, x[ 6] ); + R( d, e, a, b, c, F1, K1, x[ 7] ); + R( c, d, e, a, b, F1, K1, x[ 8] ); + R( b, c, d, e, a, F1, K1, x[ 9] ); + R( a, b, c, d, e, F1, K1, x[10] ); + R( e, a, b, c, d, F1, K1, x[11] ); + R( d, e, a, b, c, F1, K1, x[12] ); + R( c, d, e, a, b, F1, K1, x[13] ); + R( b, c, d, e, a, F1, K1, x[14] ); + R( a, b, c, d, e, F1, K1, x[15] ); + R( e, a, b, c, d, F1, K1, M(16) ); + R( d, e, a, b, c, F1, K1, M(17) ); + R( c, d, e, a, b, F1, K1, M(18) ); + R( b, c, d, e, a, F1, K1, M(19) ); + R( a, b, c, d, e, F2, K2, M(20) ); + R( e, a, b, c, d, F2, K2, M(21) ); + R( d, e, a, b, c, F2, K2, M(22) ); + R( c, d, e, a, b, F2, K2, M(23) ); + R( b, c, d, e, a, F2, K2, M(24) ); + R( a, b, c, d, e, F2, K2, M(25) ); + R( e, a, b, c, d, F2, K2, M(26) ); + R( d, e, a, b, c, F2, K2, M(27) ); + R( c, d, e, a, b, F2, K2, M(28) ); + R( b, c, d, e, a, F2, K2, M(29) ); + R( a, b, c, d, e, F2, K2, M(30) ); + R( e, a, b, c, d, F2, K2, M(31) ); + R( d, e, a, b, c, F2, K2, M(32) ); + R( c, d, e, a, b, F2, K2, M(33) ); + R( b, c, d, e, a, F2, K2, M(34) ); + R( a, b, c, d, e, F2, K2, M(35) ); + R( e, a, b, c, d, F2, K2, M(36) ); + R( d, e, a, b, c, F2, K2, M(37) ); + R( c, d, e, a, b, F2, K2, M(38) ); + R( b, c, d, e, a, F2, K2, M(39) ); + R( a, b, c, d, e, F3, K3, M(40) ); + R( e, a, b, c, d, F3, K3, M(41) ); + R( d, e, a, b, c, F3, K3, M(42) ); + R( c, d, e, a, b, F3, K3, M(43) ); + R( b, c, d, e, a, F3, K3, M(44) ); + R( a, b, c, d, e, F3, K3, M(45) ); + R( e, a, b, c, d, F3, K3, M(46) ); + R( d, e, a, b, c, F3, K3, M(47) ); + R( c, d, e, a, b, F3, K3, M(48) ); + R( b, c, d, e, a, F3, K3, M(49) ); + R( a, b, c, d, e, F3, K3, M(50) ); + R( e, a, b, c, d, F3, K3, M(51) ); + R( d, e, a, b, c, F3, K3, M(52) ); + R( c, d, e, a, b, F3, K3, M(53) ); + R( b, c, d, e, a, F3, K3, M(54) ); + R( a, b, c, d, e, F3, K3, M(55) ); + R( e, a, b, c, d, F3, K3, M(56) ); + R( d, e, a, b, c, F3, K3, M(57) ); + R( c, d, e, a, b, F3, K3, M(58) ); + R( b, c, d, e, a, F3, K3, M(59) ); + R( a, b, c, d, e, F4, K4, M(60) ); + R( e, a, b, c, d, F4, K4, M(61) ); + R( d, e, a, b, c, F4, K4, M(62) ); + R( c, d, e, a, b, F4, K4, M(63) ); + R( b, c, d, e, a, F4, K4, M(64) ); + R( a, b, c, d, e, F4, K4, M(65) ); + R( e, a, b, c, d, F4, K4, M(66) ); + R( d, e, a, b, c, F4, K4, M(67) ); + R( c, d, e, a, b, F4, K4, M(68) ); + R( b, c, d, e, a, F4, K4, M(69) ); + R( a, b, c, d, e, F4, K4, M(70) ); + R( e, a, b, c, d, F4, K4, M(71) ); + R( d, e, a, b, c, F4, K4, M(72) ); + R( c, d, e, a, b, F4, K4, M(73) ); + R( b, c, d, e, a, F4, K4, M(74) ); + R( a, b, c, d, e, F4, K4, M(75) ); + R( e, a, b, c, d, F4, K4, M(76) ); + R( d, e, a, b, c, F4, K4, M(77) ); + R( c, d, e, a, b, F4, K4, M(78) ); + R( b, c, d, e, a, F4, K4, M(79) ); + + /* Update the chaining variables. */ + hd->h0 += a; + hd->h1 += b; + hd->h2 += c; + hd->h3 += d; + hd->h4 += e; + } +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +sha1_write( void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + SHA1_CONTEXT *hd = context; + size_t nblocks; + + if (hd->count == 64) /* Flush the buffer. */ + { + TRANSFORM( hd, hd->buf, 1 ); + _gcry_burn_stack (88+4*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if (!inbuf) + return; + + if (hd->count) + { + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; + sha1_write (hd, NULL, 0); + if (!inlen) + return; + } + + nblocks = inlen / 64; + if (nblocks) + { + TRANSFORM (hd, inbuf, nblocks); + hd->count = 0; + hd->nblocks += nblocks; + inlen -= nblocks * 64; + inbuf += nblocks * 64; + } + _gcry_burn_stack (88+4*sizeof(void*)); + + /* Save remaining bytes. */ + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; +} + + +/* The routine final terminates the computation and + * returns the digest. + * The handle is prepared for a new cycle, but adding bytes to the + * handle will the destroy the returned buffer. + * Returns: 20 bytes representing the digest. + */ + +static void +sha1_final(void *context) +{ + SHA1_CONTEXT *hd = context; + + u32 t, msb, lsb; + unsigned char *p; + + sha1_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) /* enough room */ + { + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else /* need one extra block */ + { + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + sha1_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = msb >> 24; + hd->buf[57] = msb >> 16; + hd->buf[58] = msb >> 8; + hd->buf[59] = msb ; + hd->buf[60] = lsb >> 24; + hd->buf[61] = lsb >> 16; + hd->buf[62] = lsb >> 8; + hd->buf[63] = lsb ; + TRANSFORM( hd, hd->buf, 1 ); + _gcry_burn_stack (88+4*sizeof(void*)); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) +#else /* little endian */ +#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ + *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) +#endif + X(0); + X(1); + X(2); + X(3); + X(4); +#undef X + +} + +static unsigned char * +sha1_read( void *context ) +{ + SHA1_CONTEXT *hd = context; + + return hd->buf; +} + +/**************** + * Shortcut functions which puts the hash value of the supplied buffer + * into outbuf which must have a size of 20 bytes. + */ + + + +/* + Self-test section. + */ + + + + +/* Run a full self-test for ALGO and return 0 on success. */ + + + + +static unsigned char asn[15] = /* Object ID is 1.3.14.3.2.26 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; + +static gcry_md_oid_spec_t oid_spec_sha1[] = + { + /* iso.member-body.us.rsadsi.pkcs.pkcs-1.5 (sha1WithRSAEncryption) */ + { "1.2.840.113549.1.1.5" }, + /* iso.member-body.us.x9-57.x9cm.3 (dsaWithSha1)*/ + { "1.2.840.10040.4.3" }, + /* from NIST's OIW (sha1) */ + { "1.3.14.3.2.26" }, + /* from NIST OIW (sha-1WithRSAEncryption) */ + { "1.3.14.3.2.29" }, + /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha1 */ + { "1.2.840.10045.4.1" }, + { NULL }, + }; + +gcry_md_spec_t _gcry_digest_spec_sha1 = + { + "SHA1", asn, DIM (asn), oid_spec_sha1, 20, + sha1_init, sha1_write, sha1_final, sha1_read, + sizeof (SHA1_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_sha1", +#endif + .blocksize = 64 + }; + + +GRUB_MOD_INIT(gcry_sha1) +{ + COMPILE_TIME_ASSERT(sizeof (SHA1_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + grub_md_register (&_gcry_digest_spec_sha1); +} + +GRUB_MOD_FINI(gcry_sha1) +{ + grub_md_unregister (&_gcry_digest_spec_sha1); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/sha256.c b/grub-core/lib/libgcrypt-grub/cipher/sha256.c new file mode 100644 index 0000000..0c9fd6b --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/sha256.c @@ -0,0 +1,463 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* sha256.c - SHA256 hash function + * Copyright (C) 2003, 2006, 2008, 2009 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + + +/* Test vectors: + + "abc" + SHA224: 23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7 + SHA256: ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad + + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + SHA224: 75388b16 512776cc 5dba5da1 fd890150 b0c6455c b4f58b19 52522525 + SHA256: 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1 + + "a" one million times + SHA224: 20794655 980c91d8 bbb4c1ea 97618a4b f03f4258 1948b2ee 4ee7ad67 + SHA256: cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0 + + */ + + + +#include "g10lib.h" +#include "bithelp.h" +#include "cipher.h" +#include "hash-common.h" + +typedef struct { + u32 h0,h1,h2,h3,h4,h5,h6,h7; + u32 nblocks; + byte buf[64]; + int count; +} SHA256_CONTEXT; + + +static void +sha256_init (void *context) +{ + SHA256_CONTEXT *hd = context; + + hd->h0 = 0x6a09e667; + hd->h1 = 0xbb67ae85; + hd->h2 = 0x3c6ef372; + hd->h3 = 0xa54ff53a; + hd->h4 = 0x510e527f; + hd->h5 = 0x9b05688c; + hd->h6 = 0x1f83d9ab; + hd->h7 = 0x5be0cd19; + + hd->nblocks = 0; + hd->count = 0; +} + + +static void +sha224_init (void *context) +{ + SHA256_CONTEXT *hd = context; + + hd->h0 = 0xc1059ed8; + hd->h1 = 0x367cd507; + hd->h2 = 0x3070dd17; + hd->h3 = 0xf70e5939; + hd->h4 = 0xffc00b31; + hd->h5 = 0x68581511; + hd->h6 = 0x64f98fa7; + hd->h7 = 0xbefa4fa4; + + hd->nblocks = 0; + hd->count = 0; +} + + +/* + Transform the message X which consists of 16 32-bit-words. See FIPS + 180-2 for details. */ +#define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */ +#define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */ +#define R(a,b,c,d,e,f,g,h,k,w) do \ + { \ + t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + (k) + (w); \ + t2 = Sum0((a)) + Maj((a),(b),(c)); \ + h = g; \ + g = f; \ + f = e; \ + e = d + t1; \ + d = c; \ + c = b; \ + b = a; \ + a = t1 + t2; \ + } while (0) + +/* (4.2) same as SHA-1's F1. */ +static inline u32 +Cho (u32 x, u32 y, u32 z) +{ + return (z ^ (x & (y ^ z))); +} + +/* (4.3) same as SHA-1's F3 */ +static inline u32 +Maj (u32 x, u32 y, u32 z) +{ + return ((x & y) | (z & (x|y))); +} + +/* (4.4) */ +static inline u32 +Sum0 (u32 x) +{ + return (ror (x, 2) ^ ror (x, 13) ^ ror (x, 22)); +} + +/* (4.5) */ +static inline u32 +Sum1 (u32 x) +{ + return (ror (x, 6) ^ ror (x, 11) ^ ror (x, 25)); +} + + +static void +transform (SHA256_CONTEXT *hd, const unsigned char *data) +{ + static const u32 K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + + u32 a,b,c,d,e,f,g,h,t1,t2; + u32 x[16]; + u32 w[64]; + int i; + + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + f = hd->h5; + g = hd->h6; + h = hd->h7; + +#ifdef WORDS_BIGENDIAN + memcpy (x, data, 64); +#else + { + byte *p2; + + for (i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) + { + p2[3] = *data++; + p2[2] = *data++; + p2[1] = *data++; + p2[0] = *data++; + } + } +#endif + + for (i=0; i < 16; i++) + w[i] = x[i]; + for (; i < 64; i++) + w[i] = S1(w[i-2]) + w[i-7] + S0(w[i-15]) + w[i-16]; + + for (i=0; i < 64;) + { +#if 0 + R(a,b,c,d,e,f,g,h,K[i],w[i]); + i++; +#else + t1 = h + Sum1 (e) + Cho (e, f, g) + K[i] + w[i]; + t2 = Sum0 (a) + Maj (a, b, c); + d += t1; + h = t1 + t2; + + t1 = g + Sum1 (d) + Cho (d, e, f) + K[i+1] + w[i+1]; + t2 = Sum0 (h) + Maj (h, a, b); + c += t1; + g = t1 + t2; + + t1 = f + Sum1 (c) + Cho (c, d, e) + K[i+2] + w[i+2]; + t2 = Sum0 (g) + Maj (g, h, a); + b += t1; + f = t1 + t2; + + t1 = e + Sum1 (b) + Cho (b, c, d) + K[i+3] + w[i+3]; + t2 = Sum0 (f) + Maj (f, g, h); + a += t1; + e = t1 + t2; + + t1 = d + Sum1 (a) + Cho (a, b, c) + K[i+4] + w[i+4]; + t2 = Sum0 (e) + Maj (e, f, g); + h += t1; + d = t1 + t2; + + t1 = c + Sum1 (h) + Cho (h, a, b) + K[i+5] + w[i+5]; + t2 = Sum0 (d) + Maj (d, e, f); + g += t1; + c = t1 + t2; + + t1 = b + Sum1 (g) + Cho (g, h, a) + K[i+6] + w[i+6]; + t2 = Sum0 (c) + Maj (c, d, e); + f += t1; + b = t1 + t2; + + t1 = a + Sum1 (f) + Cho (f, g, h) + K[i+7] + w[i+7]; + t2 = Sum0 (b) + Maj (b, c, d); + e += t1; + a = t1 + t2; + + i += 8; +#endif + } + + hd->h0 += a; + hd->h1 += b; + hd->h2 += c; + hd->h3 += d; + hd->h4 += e; + hd->h5 += f; + hd->h6 += g; + hd->h7 += h; +} +#undef S0 +#undef S1 +#undef R + + +/* Update the message digest with the contents of INBUF with length + INLEN. */ +static void +sha256_write (void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + SHA256_CONTEXT *hd = context; + + if (hd->count == 64) + { /* flush the buffer */ + transform (hd, hd->buf); + _gcry_burn_stack (74*4+32); + hd->count = 0; + hd->nblocks++; + } + if (!inbuf) + return; + if (hd->count) + { + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; + sha256_write (hd, NULL, 0); + if (!inlen) + return; + } + + while (inlen >= 64) + { + transform (hd, inbuf); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + _gcry_burn_stack (74*4+32); + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; +} + + +/* + The routine finally terminates the computation and returns the + digest. The handle is prepared for a new cycle, but adding bytes + to the handle will the destroy the returned buffer. Returns: 32 + bytes with the message the digest. */ +static void +sha256_final(void *context) +{ + SHA256_CONTEXT *hd = context; + u32 t, msb, lsb; + byte *p; + + sha256_write (hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if ((lsb += hd->count) < t) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if (hd->count < 56) + { /* enough room */ + hd->buf[hd->count++] = 0x80; /* pad */ + while (hd->count < 56) + hd->buf[hd->count++] = 0; /* pad */ + } + else + { /* need one extra block */ + hd->buf[hd->count++] = 0x80; /* pad character */ + while (hd->count < 64) + hd->buf[hd->count++] = 0; + sha256_write (hd, NULL, 0); /* flush */; + memset (hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = msb >> 24; + hd->buf[57] = msb >> 16; + hd->buf[58] = msb >> 8; + hd->buf[59] = msb; + hd->buf[60] = lsb >> 24; + hd->buf[61] = lsb >> 16; + hd->buf[62] = lsb >> 8; + hd->buf[63] = lsb; + transform (hd, hd->buf); + _gcry_burn_stack (74*4+32); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) +#else /* little endian */ +#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ + *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) +#endif + X(0); + X(1); + X(2); + X(3); + X(4); + X(5); + X(6); + X(7); +#undef X +} + +static byte * +sha256_read (void *context) +{ + SHA256_CONTEXT *hd = context; + + return hd->buf; +} + + + +/* + Self-test section. + */ + + + + + +/* Run a full self-test for ALGO and return 0 on success. */ + + + + +static byte asn224[19] = /* Object ID is 2.16.840.1.101.3.4.2.4 */ + { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, + 0x1C + }; + +static gcry_md_oid_spec_t oid_spec_sha224[] = + { + /* From RFC3874, Section 4 */ + { "2.16.840.1.101.3.4.2.4" }, + { NULL }, + }; + +static byte asn256[19] = /* Object ID is 2.16.840.1.101.3.4.2.1 */ + { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04, 0x20 }; + +static gcry_md_oid_spec_t oid_spec_sha256[] = + { + /* According to the OpenPGP draft rfc2440-bis06 */ + { "2.16.840.1.101.3.4.2.1" }, + /* PKCS#1 sha256WithRSAEncryption */ + { "1.2.840.113549.1.1.11" }, + + { NULL }, + }; + +gcry_md_spec_t _gcry_digest_spec_sha224 = + { + "SHA224", asn224, DIM (asn224), oid_spec_sha224, 28, + sha224_init, sha256_write, sha256_final, sha256_read, + sizeof (SHA256_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_sha256", +#endif + .blocksize = 64 + }; + +gcry_md_spec_t _gcry_digest_spec_sha256 = + { + "SHA256", asn256, DIM (asn256), oid_spec_sha256, 32, + sha256_init, sha256_write, sha256_final, sha256_read, + sizeof (SHA256_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_sha256", +#endif + .blocksize = 64 + }; + + +GRUB_MOD_INIT(gcry_sha256) +{ + COMPILE_TIME_ASSERT(sizeof (SHA256_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + COMPILE_TIME_ASSERT(sizeof (SHA256_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + grub_md_register (&_gcry_digest_spec_sha224); + grub_md_register (&_gcry_digest_spec_sha256); +} + +GRUB_MOD_FINI(gcry_sha256) +{ + grub_md_unregister (&_gcry_digest_spec_sha224); + grub_md_unregister (&_gcry_digest_spec_sha256); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/sha512.c b/grub-core/lib/libgcrypt-grub/cipher/sha512.c new file mode 100644 index 0000000..717551c --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/sha512.c @@ -0,0 +1,525 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* sha512.c - SHA384 and SHA512 hash functions + * Copyright (C) 2003, 2008, 2009 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + + +/* Test vectors from FIPS-180-2: + * + * "abc" + * 384: + * CB00753F 45A35E8B B5A03D69 9AC65007 272C32AB 0EDED163 + * 1A8B605A 43FF5BED 8086072B A1E7CC23 58BAECA1 34C825A7 + * 512: + * DDAF35A1 93617ABA CC417349 AE204131 12E6FA4E 89A97EA2 0A9EEEE6 4B55D39A + * 2192992A 274FC1A8 36BA3C23 A3FEEBBD 454D4423 643CE80E 2A9AC94F A54CA49F + * + * "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" + * 384: + * 09330C33 F71147E8 3D192FC7 82CD1B47 53111B17 3B3B05D2 + * 2FA08086 E3B0F712 FCC7C71A 557E2DB9 66C3E9FA 91746039 + * 512: + * 8E959B75 DAE313DA 8CF4F728 14FC143F 8F7779C6 EB9F7FA1 7299AEAD B6889018 + * 501D289E 4900F7E4 331B99DE C4B5433A C7D329EE B6DD2654 5E96E55B 874BE909 + * + * "a" x 1000000 + * 384: + * 9D0E1809 716474CB 086E834E 310A4A1C ED149E9C 00F24852 + * 7972CEC5 704C2A5B 07B8B3DC 38ECC4EB AE97DDD8 7F3D8985 + * 512: + * E718483D 0CE76964 4E2E42C7 BC15B463 8E1F98B1 3B204428 5632A803 AFA973EB + * DE0FF244 877EA60A 4CB0432C E577C31B EB009C5C 2C49AA2E 4EADB217 AD8CC09B + */ + + +#include "g10lib.h" +#include "bithelp.h" +#include "cipher.h" +#include "hash-common.h" + +typedef struct +{ + u64 h0, h1, h2, h3, h4, h5, h6, h7; + u64 nblocks; + byte buf[128]; + int count; +} SHA512_CONTEXT; + +static void +sha512_init (void *context) +{ + SHA512_CONTEXT *hd = context; + + hd->h0 = U64_C(0x6a09e667f3bcc908); + hd->h1 = U64_C(0xbb67ae8584caa73b); + hd->h2 = U64_C(0x3c6ef372fe94f82b); + hd->h3 = U64_C(0xa54ff53a5f1d36f1); + hd->h4 = U64_C(0x510e527fade682d1); + hd->h5 = U64_C(0x9b05688c2b3e6c1f); + hd->h6 = U64_C(0x1f83d9abfb41bd6b); + hd->h7 = U64_C(0x5be0cd19137e2179); + + hd->nblocks = 0; + hd->count = 0; +} + +static void +sha384_init (void *context) +{ + SHA512_CONTEXT *hd = context; + + hd->h0 = U64_C(0xcbbb9d5dc1059ed8); + hd->h1 = U64_C(0x629a292a367cd507); + hd->h2 = U64_C(0x9159015a3070dd17); + hd->h3 = U64_C(0x152fecd8f70e5939); + hd->h4 = U64_C(0x67332667ffc00b31); + hd->h5 = U64_C(0x8eb44a8768581511); + hd->h6 = U64_C(0xdb0c2e0d64f98fa7); + hd->h7 = U64_C(0x47b5481dbefa4fa4); + + hd->nblocks = 0; + hd->count = 0; +} + + +static inline u64 +ROTR (u64 x, u64 n) +{ + return ((x >> n) | (x << (64 - n))); +} + +static inline u64 +Ch (u64 x, u64 y, u64 z) +{ + return ((x & y) ^ ( ~x & z)); +} + +static inline u64 +Maj (u64 x, u64 y, u64 z) +{ + return ((x & y) ^ (x & z) ^ (y & z)); +} + +static inline u64 +Sum0 (u64 x) +{ + return (ROTR (x, 28) ^ ROTR (x, 34) ^ ROTR (x, 39)); +} + +static inline u64 +Sum1 (u64 x) +{ + return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41)); +} + +/**************** + * Transform the message W which consists of 16 64-bit-words + */ +static void +transform (SHA512_CONTEXT *hd, const unsigned char *data) +{ + u64 a, b, c, d, e, f, g, h; + u64 w[80]; + int t; + static const u64 k[] = + { + U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd), + U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc), + U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019), + U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118), + U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe), + U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2), + U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1), + U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694), + U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3), + U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65), + U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483), + U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5), + U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210), + U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4), + U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725), + U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70), + U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926), + U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df), + U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8), + U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b), + U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001), + U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30), + U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910), + U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8), + U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53), + U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8), + U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb), + U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3), + U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60), + U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec), + U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9), + U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b), + U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207), + U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178), + U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6), + U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b), + U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493), + U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c), + U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a), + U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817) + }; + + /* get values from the chaining vars */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + f = hd->h5; + g = hd->h6; + h = hd->h7; + +#ifdef WORDS_BIGENDIAN + memcpy (w, data, 128); +#else + { + int i; + byte *p2; + + for (i = 0, p2 = (byte *) w; i < 16; i++, p2 += 8) + { + p2[7] = *data++; + p2[6] = *data++; + p2[5] = *data++; + p2[4] = *data++; + p2[3] = *data++; + p2[2] = *data++; + p2[1] = *data++; + p2[0] = *data++; + } + } +#endif + +#define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) +#define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) + + for (t = 16; t < 80; t++) + w[t] = S1 (w[t - 2]) + w[t - 7] + S0 (w[t - 15]) + w[t - 16]; + + + for (t = 0; t < 80; ) + { + u64 t1, t2; + + /* Performance on a AMD Athlon(tm) Dual Core Processor 4050e + with gcc 4.3.3 using gcry_md_hash_buffer of each 10000 bytes + initialized to 0,1,2,3...255,0,... and 1000 iterations: + + Not unrolled with macros: 440ms + Unrolled with macros: 350ms + Unrolled with inline: 330ms + */ +#if 0 /* Not unrolled. */ + t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; + t2 = Sum0 (a) + Maj (a, b, c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + t++; +#else /* Unrolled to interweave the chain variables. */ + t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; + t2 = Sum0 (a) + Maj (a, b, c); + d += t1; + h = t1 + t2; + + t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[t+1]; + t2 = Sum0 (h) + Maj (h, a, b); + c += t1; + g = t1 + t2; + + t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[t+2]; + t2 = Sum0 (g) + Maj (g, h, a); + b += t1; + f = t1 + t2; + + t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[t+3]; + t2 = Sum0 (f) + Maj (f, g, h); + a += t1; + e = t1 + t2; + + t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[t+4]; + t2 = Sum0 (e) + Maj (e, f, g); + h += t1; + d = t1 + t2; + + t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[t+5]; + t2 = Sum0 (d) + Maj (d, e, f); + g += t1; + c = t1 + t2; + + t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[t+6]; + t2 = Sum0 (c) + Maj (c, d, e); + f += t1; + b = t1 + t2; + + t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[t+7]; + t2 = Sum0 (b) + Maj (b, c, d); + e += t1; + a = t1 + t2; + + t += 8; +#endif + } + + /* Update chaining vars. */ + hd->h0 += a; + hd->h1 += b; + hd->h2 += c; + hd->h3 += d; + hd->h4 += e; + hd->h5 += f; + hd->h6 += g; + hd->h7 += h; +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +sha512_write (void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + SHA512_CONTEXT *hd = context; + + if (hd->count == 128) + { /* flush the buffer */ + transform (hd, hd->buf); + _gcry_burn_stack (768); + hd->count = 0; + hd->nblocks++; + } + if (!inbuf) + return; + if (hd->count) + { + for (; inlen && hd->count < 128; inlen--) + hd->buf[hd->count++] = *inbuf++; + sha512_write (context, NULL, 0); + if (!inlen) + return; + } + + while (inlen >= 128) + { + transform (hd, inbuf); + hd->count = 0; + hd->nblocks++; + inlen -= 128; + inbuf += 128; + } + _gcry_burn_stack (768); + for (; inlen && hd->count < 128; inlen--) + hd->buf[hd->count++] = *inbuf++; +} + + +/* The routine final terminates the computation and + * returns the digest. + * The handle is prepared for a new cycle, but adding bytes to the + * handle will the destroy the returned buffer. + * Returns: 64 bytes representing the digest. When used for sha384, + * we take the leftmost 48 of those bytes. + */ + +static void +sha512_final (void *context) +{ + SHA512_CONTEXT *hd = context; + u64 t, msb, lsb; + byte *p; + + sha512_write (context, NULL, 0); /* flush */ ; + + t = hd->nblocks; + /* multiply by 128 to make a byte count */ + lsb = t << 7; + msb = t >> 57; + /* add the count */ + t = lsb; + if ((lsb += hd->count) < t) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 61; + + if (hd->count < 112) + { /* enough room */ + hd->buf[hd->count++] = 0x80; /* pad */ + while (hd->count < 112) + hd->buf[hd->count++] = 0; /* pad */ + } + else + { /* need one extra block */ + hd->buf[hd->count++] = 0x80; /* pad character */ + while (hd->count < 128) + hd->buf[hd->count++] = 0; + sha512_write (context, NULL, 0); /* flush */ ; + memset (hd->buf, 0, 112); /* fill next block with zeroes */ + } + /* append the 128 bit count */ + hd->buf[112] = msb >> 56; + hd->buf[113] = msb >> 48; + hd->buf[114] = msb >> 40; + hd->buf[115] = msb >> 32; + hd->buf[116] = msb >> 24; + hd->buf[117] = msb >> 16; + hd->buf[118] = msb >> 8; + hd->buf[119] = msb; + + hd->buf[120] = lsb >> 56; + hd->buf[121] = lsb >> 48; + hd->buf[122] = lsb >> 40; + hd->buf[123] = lsb >> 32; + hd->buf[124] = lsb >> 24; + hd->buf[125] = lsb >> 16; + hd->buf[126] = lsb >> 8; + hd->buf[127] = lsb; + transform (hd, hd->buf); + _gcry_burn_stack (768); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *(u64*)p = hd->h##a ; p += 8; } while (0) +#else /* little endian */ +#define X(a) do { *p++ = hd->h##a >> 56; *p++ = hd->h##a >> 48; \ + *p++ = hd->h##a >> 40; *p++ = hd->h##a >> 32; \ + *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ + *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0) +#endif + X (0); + X (1); + X (2); + X (3); + X (4); + X (5); + /* Note that these last two chunks are included even for SHA384. + We just ignore them. */ + X (6); + X (7); +#undef X +} + +static byte * +sha512_read (void *context) +{ + SHA512_CONTEXT *hd = (SHA512_CONTEXT *) context; + return hd->buf; +} + + + +/* + Self-test section. + */ + + + + + +/* Run a full self-test for ALGO and return 0 on success. */ + + + + +static byte sha512_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.3 */ + { + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40 + }; + +static gcry_md_oid_spec_t oid_spec_sha512[] = + { + { "2.16.840.1.101.3.4.2.3" }, + + /* PKCS#1 sha512WithRSAEncryption */ + { "1.2.840.113549.1.1.13" }, + + { NULL } + }; + +gcry_md_spec_t _gcry_digest_spec_sha512 = + { + "SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64, + sha512_init, sha512_write, sha512_final, sha512_read, + sizeof (SHA512_CONTEXT), +#ifdef GRUB_UTIL + .modname = "gcry_sha512", +#endif + .blocksize = 128 + }; + +static byte sha384_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.2 */ + { + 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, + 0x00, 0x04, 0x30 + }; + +static gcry_md_oid_spec_t oid_spec_sha384[] = + { + { "2.16.840.1.101.3.4.2.2" }, + + /* PKCS#1 sha384WithRSAEncryption */ + { "1.2.840.113549.1.1.12" }, + + { NULL }, + }; + +gcry_md_spec_t _gcry_digest_spec_sha384 = + { + "SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48, + sha384_init, sha512_write, sha512_final, sha512_read, + sizeof (SHA512_CONTEXT), +#ifdef GRUB_UTIL + .modname = "gcry_sha512", +#endif + .blocksize = 128 + }; + + +GRUB_MOD_INIT(gcry_sha512) +{ + COMPILE_TIME_ASSERT(sizeof (SHA512_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + COMPILE_TIME_ASSERT(sizeof (SHA512_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + grub_md_register (&_gcry_digest_spec_sha512); + grub_md_register (&_gcry_digest_spec_sha384); +} + +GRUB_MOD_FINI(gcry_sha512) +{ + grub_md_unregister (&_gcry_digest_spec_sha512); + grub_md_unregister (&_gcry_digest_spec_sha384); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/tiger.c b/grub-core/lib/libgcrypt-grub/cipher/tiger.c new file mode 100644 index 0000000..c277293 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/tiger.c @@ -0,0 +1,944 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* tiger.c - The TIGER hash function + * Copyright (C) 1998, 2001, 2002, 2003, 2010 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* See http://www.cs.technion.ac.il/~biham/Reports/Tiger/ */ + + +#include "g10lib.h" +#include "cipher.h" + +/* We really need a 64 bit type for this code. */ +#ifdef HAVE_U64_TYPEDEF + +typedef struct +{ + u64 a, b, c; + byte buf[64]; + int count; + u32 nblocks; + int variant; /* 0 = old code, 1 = fixed code, 2 - TIGER2. */ +} TIGER_CONTEXT; + + +/********************************* + * Okay, okay, this is not the fastest code - improvements are welcome. + * + */ + +/* Some test vectors: + * "" 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A + * "abc" F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951 + * "Tiger" 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF + * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" + * 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386 + * "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789" + * 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197 + * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham" + * 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303 + * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" + * "eedings of Fast Software Encryption 3, Cambridge." + * EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193 + * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" + * "eedings of Fast Software Encryption 3, Cambridge, 1996." + * 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC + * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEF" + * "GHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" + * 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4 + */ + +static u64 sbox1[256] = { + U64_C(0x02aab17cf7e90c5e) /* 0 */, U64_C(0xac424b03e243a8ec) /* 1 */, + U64_C(0x72cd5be30dd5fcd3) /* 2 */, U64_C(0x6d019b93f6f97f3a) /* 3 */, + U64_C(0xcd9978ffd21f9193) /* 4 */, U64_C(0x7573a1c9708029e2) /* 5 */, + U64_C(0xb164326b922a83c3) /* 6 */, U64_C(0x46883eee04915870) /* 7 */, + U64_C(0xeaace3057103ece6) /* 8 */, U64_C(0xc54169b808a3535c) /* 9 */, + U64_C(0x4ce754918ddec47c) /* 10 */, U64_C(0x0aa2f4dfdc0df40c) /* 11 */, + U64_C(0x10b76f18a74dbefa) /* 12 */, U64_C(0xc6ccb6235ad1ab6a) /* 13 */, + U64_C(0x13726121572fe2ff) /* 14 */, U64_C(0x1a488c6f199d921e) /* 15 */, + U64_C(0x4bc9f9f4da0007ca) /* 16 */, U64_C(0x26f5e6f6e85241c7) /* 17 */, + U64_C(0x859079dbea5947b6) /* 18 */, U64_C(0x4f1885c5c99e8c92) /* 19 */, + U64_C(0xd78e761ea96f864b) /* 20 */, U64_C(0x8e36428c52b5c17d) /* 21 */, + U64_C(0x69cf6827373063c1) /* 22 */, U64_C(0xb607c93d9bb4c56e) /* 23 */, + U64_C(0x7d820e760e76b5ea) /* 24 */, U64_C(0x645c9cc6f07fdc42) /* 25 */, + U64_C(0xbf38a078243342e0) /* 26 */, U64_C(0x5f6b343c9d2e7d04) /* 27 */, + U64_C(0xf2c28aeb600b0ec6) /* 28 */, U64_C(0x6c0ed85f7254bcac) /* 29 */, + U64_C(0x71592281a4db4fe5) /* 30 */, U64_C(0x1967fa69ce0fed9f) /* 31 */, + U64_C(0xfd5293f8b96545db) /* 32 */, U64_C(0xc879e9d7f2a7600b) /* 33 */, + U64_C(0x860248920193194e) /* 34 */, U64_C(0xa4f9533b2d9cc0b3) /* 35 */, + U64_C(0x9053836c15957613) /* 36 */, U64_C(0xdb6dcf8afc357bf1) /* 37 */, + U64_C(0x18beea7a7a370f57) /* 38 */, U64_C(0x037117ca50b99066) /* 39 */, + U64_C(0x6ab30a9774424a35) /* 40 */, U64_C(0xf4e92f02e325249b) /* 41 */, + U64_C(0x7739db07061ccae1) /* 42 */, U64_C(0xd8f3b49ceca42a05) /* 43 */, + U64_C(0xbd56be3f51382f73) /* 44 */, U64_C(0x45faed5843b0bb28) /* 45 */, + U64_C(0x1c813d5c11bf1f83) /* 46 */, U64_C(0x8af0e4b6d75fa169) /* 47 */, + U64_C(0x33ee18a487ad9999) /* 48 */, U64_C(0x3c26e8eab1c94410) /* 49 */, + U64_C(0xb510102bc0a822f9) /* 50 */, U64_C(0x141eef310ce6123b) /* 51 */, + U64_C(0xfc65b90059ddb154) /* 52 */, U64_C(0xe0158640c5e0e607) /* 53 */, + U64_C(0x884e079826c3a3cf) /* 54 */, U64_C(0x930d0d9523c535fd) /* 55 */, + U64_C(0x35638d754e9a2b00) /* 56 */, U64_C(0x4085fccf40469dd5) /* 57 */, + U64_C(0xc4b17ad28be23a4c) /* 58 */, U64_C(0xcab2f0fc6a3e6a2e) /* 59 */, + U64_C(0x2860971a6b943fcd) /* 60 */, U64_C(0x3dde6ee212e30446) /* 61 */, + U64_C(0x6222f32ae01765ae) /* 62 */, U64_C(0x5d550bb5478308fe) /* 63 */, + U64_C(0xa9efa98da0eda22a) /* 64 */, U64_C(0xc351a71686c40da7) /* 65 */, + U64_C(0x1105586d9c867c84) /* 66 */, U64_C(0xdcffee85fda22853) /* 67 */, + U64_C(0xccfbd0262c5eef76) /* 68 */, U64_C(0xbaf294cb8990d201) /* 69 */, + U64_C(0xe69464f52afad975) /* 70 */, U64_C(0x94b013afdf133e14) /* 71 */, + U64_C(0x06a7d1a32823c958) /* 72 */, U64_C(0x6f95fe5130f61119) /* 73 */, + U64_C(0xd92ab34e462c06c0) /* 74 */, U64_C(0xed7bde33887c71d2) /* 75 */, + U64_C(0x79746d6e6518393e) /* 76 */, U64_C(0x5ba419385d713329) /* 77 */, + U64_C(0x7c1ba6b948a97564) /* 78 */, U64_C(0x31987c197bfdac67) /* 79 */, + U64_C(0xde6c23c44b053d02) /* 80 */, U64_C(0x581c49fed002d64d) /* 81 */, + U64_C(0xdd474d6338261571) /* 82 */, U64_C(0xaa4546c3e473d062) /* 83 */, + U64_C(0x928fce349455f860) /* 84 */, U64_C(0x48161bbacaab94d9) /* 85 */, + U64_C(0x63912430770e6f68) /* 86 */, U64_C(0x6ec8a5e602c6641c) /* 87 */, + U64_C(0x87282515337ddd2b) /* 88 */, U64_C(0x2cda6b42034b701b) /* 89 */, + U64_C(0xb03d37c181cb096d) /* 90 */, U64_C(0xe108438266c71c6f) /* 91 */, + U64_C(0x2b3180c7eb51b255) /* 92 */, U64_C(0xdf92b82f96c08bbc) /* 93 */, + U64_C(0x5c68c8c0a632f3ba) /* 94 */, U64_C(0x5504cc861c3d0556) /* 95 */, + U64_C(0xabbfa4e55fb26b8f) /* 96 */, U64_C(0x41848b0ab3baceb4) /* 97 */, + U64_C(0xb334a273aa445d32) /* 98 */, U64_C(0xbca696f0a85ad881) /* 99 */, + U64_C(0x24f6ec65b528d56c) /* 100 */, U64_C(0x0ce1512e90f4524a) /* 101 */, + U64_C(0x4e9dd79d5506d35a) /* 102 */, U64_C(0x258905fac6ce9779) /* 103 */, + U64_C(0x2019295b3e109b33) /* 104 */, U64_C(0xf8a9478b73a054cc) /* 105 */, + U64_C(0x2924f2f934417eb0) /* 106 */, U64_C(0x3993357d536d1bc4) /* 107 */, + U64_C(0x38a81ac21db6ff8b) /* 108 */, U64_C(0x47c4fbf17d6016bf) /* 109 */, + U64_C(0x1e0faadd7667e3f5) /* 110 */, U64_C(0x7abcff62938beb96) /* 111 */, + U64_C(0xa78dad948fc179c9) /* 112 */, U64_C(0x8f1f98b72911e50d) /* 113 */, + U64_C(0x61e48eae27121a91) /* 114 */, U64_C(0x4d62f7ad31859808) /* 115 */, + U64_C(0xeceba345ef5ceaeb) /* 116 */, U64_C(0xf5ceb25ebc9684ce) /* 117 */, + U64_C(0xf633e20cb7f76221) /* 118 */, U64_C(0xa32cdf06ab8293e4) /* 119 */, + U64_C(0x985a202ca5ee2ca4) /* 120 */, U64_C(0xcf0b8447cc8a8fb1) /* 121 */, + U64_C(0x9f765244979859a3) /* 122 */, U64_C(0xa8d516b1a1240017) /* 123 */, + U64_C(0x0bd7ba3ebb5dc726) /* 124 */, U64_C(0xe54bca55b86adb39) /* 125 */, + U64_C(0x1d7a3afd6c478063) /* 126 */, U64_C(0x519ec608e7669edd) /* 127 */, + U64_C(0x0e5715a2d149aa23) /* 128 */, U64_C(0x177d4571848ff194) /* 129 */, + U64_C(0xeeb55f3241014c22) /* 130 */, U64_C(0x0f5e5ca13a6e2ec2) /* 131 */, + U64_C(0x8029927b75f5c361) /* 132 */, U64_C(0xad139fabc3d6e436) /* 133 */, + U64_C(0x0d5df1a94ccf402f) /* 134 */, U64_C(0x3e8bd948bea5dfc8) /* 135 */, + U64_C(0xa5a0d357bd3ff77e) /* 136 */, U64_C(0xa2d12e251f74f645) /* 137 */, + U64_C(0x66fd9e525e81a082) /* 138 */, U64_C(0x2e0c90ce7f687a49) /* 139 */, + U64_C(0xc2e8bcbeba973bc5) /* 140 */, U64_C(0x000001bce509745f) /* 141 */, + U64_C(0x423777bbe6dab3d6) /* 142 */, U64_C(0xd1661c7eaef06eb5) /* 143 */, + U64_C(0xa1781f354daacfd8) /* 144 */, U64_C(0x2d11284a2b16affc) /* 145 */, + U64_C(0xf1fc4f67fa891d1f) /* 146 */, U64_C(0x73ecc25dcb920ada) /* 147 */, + U64_C(0xae610c22c2a12651) /* 148 */, U64_C(0x96e0a810d356b78a) /* 149 */, + U64_C(0x5a9a381f2fe7870f) /* 150 */, U64_C(0xd5ad62ede94e5530) /* 151 */, + U64_C(0xd225e5e8368d1427) /* 152 */, U64_C(0x65977b70c7af4631) /* 153 */, + U64_C(0x99f889b2de39d74f) /* 154 */, U64_C(0x233f30bf54e1d143) /* 155 */, + U64_C(0x9a9675d3d9a63c97) /* 156 */, U64_C(0x5470554ff334f9a8) /* 157 */, + U64_C(0x166acb744a4f5688) /* 158 */, U64_C(0x70c74caab2e4aead) /* 159 */, + U64_C(0xf0d091646f294d12) /* 160 */, U64_C(0x57b82a89684031d1) /* 161 */, + U64_C(0xefd95a5a61be0b6b) /* 162 */, U64_C(0x2fbd12e969f2f29a) /* 163 */, + U64_C(0x9bd37013feff9fe8) /* 164 */, U64_C(0x3f9b0404d6085a06) /* 165 */, + U64_C(0x4940c1f3166cfe15) /* 166 */, U64_C(0x09542c4dcdf3defb) /* 167 */, + U64_C(0xb4c5218385cd5ce3) /* 168 */, U64_C(0xc935b7dc4462a641) /* 169 */, + U64_C(0x3417f8a68ed3b63f) /* 170 */, U64_C(0xb80959295b215b40) /* 171 */, + U64_C(0xf99cdaef3b8c8572) /* 172 */, U64_C(0x018c0614f8fcb95d) /* 173 */, + U64_C(0x1b14accd1a3acdf3) /* 174 */, U64_C(0x84d471f200bb732d) /* 175 */, + U64_C(0xc1a3110e95e8da16) /* 176 */, U64_C(0x430a7220bf1a82b8) /* 177 */, + U64_C(0xb77e090d39df210e) /* 178 */, U64_C(0x5ef4bd9f3cd05e9d) /* 179 */, + U64_C(0x9d4ff6da7e57a444) /* 180 */, U64_C(0xda1d60e183d4a5f8) /* 181 */, + U64_C(0xb287c38417998e47) /* 182 */, U64_C(0xfe3edc121bb31886) /* 183 */, + U64_C(0xc7fe3ccc980ccbef) /* 184 */, U64_C(0xe46fb590189bfd03) /* 185 */, + U64_C(0x3732fd469a4c57dc) /* 186 */, U64_C(0x7ef700a07cf1ad65) /* 187 */, + U64_C(0x59c64468a31d8859) /* 188 */, U64_C(0x762fb0b4d45b61f6) /* 189 */, + U64_C(0x155baed099047718) /* 190 */, U64_C(0x68755e4c3d50baa6) /* 191 */, + U64_C(0xe9214e7f22d8b4df) /* 192 */, U64_C(0x2addbf532eac95f4) /* 193 */, + U64_C(0x32ae3909b4bd0109) /* 194 */, U64_C(0x834df537b08e3450) /* 195 */, + U64_C(0xfa209da84220728d) /* 196 */, U64_C(0x9e691d9b9efe23f7) /* 197 */, + U64_C(0x0446d288c4ae8d7f) /* 198 */, U64_C(0x7b4cc524e169785b) /* 199 */, + U64_C(0x21d87f0135ca1385) /* 200 */, U64_C(0xcebb400f137b8aa5) /* 201 */, + U64_C(0x272e2b66580796be) /* 202 */, U64_C(0x3612264125c2b0de) /* 203 */, + U64_C(0x057702bdad1efbb2) /* 204 */, U64_C(0xd4babb8eacf84be9) /* 205 */, + U64_C(0x91583139641bc67b) /* 206 */, U64_C(0x8bdc2de08036e024) /* 207 */, + U64_C(0x603c8156f49f68ed) /* 208 */, U64_C(0xf7d236f7dbef5111) /* 209 */, + U64_C(0x9727c4598ad21e80) /* 210 */, U64_C(0xa08a0896670a5fd7) /* 211 */, + U64_C(0xcb4a8f4309eba9cb) /* 212 */, U64_C(0x81af564b0f7036a1) /* 213 */, + U64_C(0xc0b99aa778199abd) /* 214 */, U64_C(0x959f1ec83fc8e952) /* 215 */, + U64_C(0x8c505077794a81b9) /* 216 */, U64_C(0x3acaaf8f056338f0) /* 217 */, + U64_C(0x07b43f50627a6778) /* 218 */, U64_C(0x4a44ab49f5eccc77) /* 219 */, + U64_C(0x3bc3d6e4b679ee98) /* 220 */, U64_C(0x9cc0d4d1cf14108c) /* 221 */, + U64_C(0x4406c00b206bc8a0) /* 222 */, U64_C(0x82a18854c8d72d89) /* 223 */, + U64_C(0x67e366b35c3c432c) /* 224 */, U64_C(0xb923dd61102b37f2) /* 225 */, + U64_C(0x56ab2779d884271d) /* 226 */, U64_C(0xbe83e1b0ff1525af) /* 227 */, + U64_C(0xfb7c65d4217e49a9) /* 228 */, U64_C(0x6bdbe0e76d48e7d4) /* 229 */, + U64_C(0x08df828745d9179e) /* 230 */, U64_C(0x22ea6a9add53bd34) /* 231 */, + U64_C(0xe36e141c5622200a) /* 232 */, U64_C(0x7f805d1b8cb750ee) /* 233 */, + U64_C(0xafe5c7a59f58e837) /* 234 */, U64_C(0xe27f996a4fb1c23c) /* 235 */, + U64_C(0xd3867dfb0775f0d0) /* 236 */, U64_C(0xd0e673de6e88891a) /* 237 */, + U64_C(0x123aeb9eafb86c25) /* 238 */, U64_C(0x30f1d5d5c145b895) /* 239 */, + U64_C(0xbb434a2dee7269e7) /* 240 */, U64_C(0x78cb67ecf931fa38) /* 241 */, + U64_C(0xf33b0372323bbf9c) /* 242 */, U64_C(0x52d66336fb279c74) /* 243 */, + U64_C(0x505f33ac0afb4eaa) /* 244 */, U64_C(0xe8a5cd99a2cce187) /* 245 */, + U64_C(0x534974801e2d30bb) /* 246 */, U64_C(0x8d2d5711d5876d90) /* 247 */, + U64_C(0x1f1a412891bc038e) /* 248 */, U64_C(0xd6e2e71d82e56648) /* 249 */, + U64_C(0x74036c3a497732b7) /* 250 */, U64_C(0x89b67ed96361f5ab) /* 251 */, + U64_C(0xffed95d8f1ea02a2) /* 252 */, U64_C(0xe72b3bd61464d43d) /* 253 */, + U64_C(0xa6300f170bdc4820) /* 254 */, U64_C(0xebc18760ed78a77a) /* 255 */ +}; +static u64 sbox2[256] = { + U64_C(0xe6a6be5a05a12138) /* 256 */, U64_C(0xb5a122a5b4f87c98) /* 257 */, + U64_C(0x563c6089140b6990) /* 258 */, U64_C(0x4c46cb2e391f5dd5) /* 259 */, + U64_C(0xd932addbc9b79434) /* 260 */, U64_C(0x08ea70e42015aff5) /* 261 */, + U64_C(0xd765a6673e478cf1) /* 262 */, U64_C(0xc4fb757eab278d99) /* 263 */, + U64_C(0xdf11c6862d6e0692) /* 264 */, U64_C(0xddeb84f10d7f3b16) /* 265 */, + U64_C(0x6f2ef604a665ea04) /* 266 */, U64_C(0x4a8e0f0ff0e0dfb3) /* 267 */, + U64_C(0xa5edeef83dbcba51) /* 268 */, U64_C(0xfc4f0a2a0ea4371e) /* 269 */, + U64_C(0xe83e1da85cb38429) /* 270 */, U64_C(0xdc8ff882ba1b1ce2) /* 271 */, + U64_C(0xcd45505e8353e80d) /* 272 */, U64_C(0x18d19a00d4db0717) /* 273 */, + U64_C(0x34a0cfeda5f38101) /* 274 */, U64_C(0x0be77e518887caf2) /* 275 */, + U64_C(0x1e341438b3c45136) /* 276 */, U64_C(0xe05797f49089ccf9) /* 277 */, + U64_C(0xffd23f9df2591d14) /* 278 */, U64_C(0x543dda228595c5cd) /* 279 */, + U64_C(0x661f81fd99052a33) /* 280 */, U64_C(0x8736e641db0f7b76) /* 281 */, + U64_C(0x15227725418e5307) /* 282 */, U64_C(0xe25f7f46162eb2fa) /* 283 */, + U64_C(0x48a8b2126c13d9fe) /* 284 */, U64_C(0xafdc541792e76eea) /* 285 */, + U64_C(0x03d912bfc6d1898f) /* 286 */, U64_C(0x31b1aafa1b83f51b) /* 287 */, + U64_C(0xf1ac2796e42ab7d9) /* 288 */, U64_C(0x40a3a7d7fcd2ebac) /* 289 */, + U64_C(0x1056136d0afbbcc5) /* 290 */, U64_C(0x7889e1dd9a6d0c85) /* 291 */, + U64_C(0xd33525782a7974aa) /* 292 */, U64_C(0xa7e25d09078ac09b) /* 293 */, + U64_C(0xbd4138b3eac6edd0) /* 294 */, U64_C(0x920abfbe71eb9e70) /* 295 */, + U64_C(0xa2a5d0f54fc2625c) /* 296 */, U64_C(0xc054e36b0b1290a3) /* 297 */, + U64_C(0xf6dd59ff62fe932b) /* 298 */, U64_C(0x3537354511a8ac7d) /* 299 */, + U64_C(0xca845e9172fadcd4) /* 300 */, U64_C(0x84f82b60329d20dc) /* 301 */, + U64_C(0x79c62ce1cd672f18) /* 302 */, U64_C(0x8b09a2add124642c) /* 303 */, + U64_C(0xd0c1e96a19d9e726) /* 304 */, U64_C(0x5a786a9b4ba9500c) /* 305 */, + U64_C(0x0e020336634c43f3) /* 306 */, U64_C(0xc17b474aeb66d822) /* 307 */, + U64_C(0x6a731ae3ec9baac2) /* 308 */, U64_C(0x8226667ae0840258) /* 309 */, + U64_C(0x67d4567691caeca5) /* 310 */, U64_C(0x1d94155c4875adb5) /* 311 */, + U64_C(0x6d00fd985b813fdf) /* 312 */, U64_C(0x51286efcb774cd06) /* 313 */, + U64_C(0x5e8834471fa744af) /* 314 */, U64_C(0xf72ca0aee761ae2e) /* 315 */, + U64_C(0xbe40e4cdaee8e09a) /* 316 */, U64_C(0xe9970bbb5118f665) /* 317 */, + U64_C(0x726e4beb33df1964) /* 318 */, U64_C(0x703b000729199762) /* 319 */, + U64_C(0x4631d816f5ef30a7) /* 320 */, U64_C(0xb880b5b51504a6be) /* 321 */, + U64_C(0x641793c37ed84b6c) /* 322 */, U64_C(0x7b21ed77f6e97d96) /* 323 */, + U64_C(0x776306312ef96b73) /* 324 */, U64_C(0xae528948e86ff3f4) /* 325 */, + U64_C(0x53dbd7f286a3f8f8) /* 326 */, U64_C(0x16cadce74cfc1063) /* 327 */, + U64_C(0x005c19bdfa52c6dd) /* 328 */, U64_C(0x68868f5d64d46ad3) /* 329 */, + U64_C(0x3a9d512ccf1e186a) /* 330 */, U64_C(0x367e62c2385660ae) /* 331 */, + U64_C(0xe359e7ea77dcb1d7) /* 332 */, U64_C(0x526c0773749abe6e) /* 333 */, + U64_C(0x735ae5f9d09f734b) /* 334 */, U64_C(0x493fc7cc8a558ba8) /* 335 */, + U64_C(0xb0b9c1533041ab45) /* 336 */, U64_C(0x321958ba470a59bd) /* 337 */, + U64_C(0x852db00b5f46c393) /* 338 */, U64_C(0x91209b2bd336b0e5) /* 339 */, + U64_C(0x6e604f7d659ef19f) /* 340 */, U64_C(0xb99a8ae2782ccb24) /* 341 */, + U64_C(0xccf52ab6c814c4c7) /* 342 */, U64_C(0x4727d9afbe11727b) /* 343 */, + U64_C(0x7e950d0c0121b34d) /* 344 */, U64_C(0x756f435670ad471f) /* 345 */, + U64_C(0xf5add442615a6849) /* 346 */, U64_C(0x4e87e09980b9957a) /* 347 */, + U64_C(0x2acfa1df50aee355) /* 348 */, U64_C(0xd898263afd2fd556) /* 349 */, + U64_C(0xc8f4924dd80c8fd6) /* 350 */, U64_C(0xcf99ca3d754a173a) /* 351 */, + U64_C(0xfe477bacaf91bf3c) /* 352 */, U64_C(0xed5371f6d690c12d) /* 353 */, + U64_C(0x831a5c285e687094) /* 354 */, U64_C(0xc5d3c90a3708a0a4) /* 355 */, + U64_C(0x0f7f903717d06580) /* 356 */, U64_C(0x19f9bb13b8fdf27f) /* 357 */, + U64_C(0xb1bd6f1b4d502843) /* 358 */, U64_C(0x1c761ba38fff4012) /* 359 */, + U64_C(0x0d1530c4e2e21f3b) /* 360 */, U64_C(0x8943ce69a7372c8a) /* 361 */, + U64_C(0xe5184e11feb5ce66) /* 362 */, U64_C(0x618bdb80bd736621) /* 363 */, + U64_C(0x7d29bad68b574d0b) /* 364 */, U64_C(0x81bb613e25e6fe5b) /* 365 */, + U64_C(0x071c9c10bc07913f) /* 366 */, U64_C(0xc7beeb7909ac2d97) /* 367 */, + U64_C(0xc3e58d353bc5d757) /* 368 */, U64_C(0xeb017892f38f61e8) /* 369 */, + U64_C(0xd4effb9c9b1cc21a) /* 370 */, U64_C(0x99727d26f494f7ab) /* 371 */, + U64_C(0xa3e063a2956b3e03) /* 372 */, U64_C(0x9d4a8b9a4aa09c30) /* 373 */, + U64_C(0x3f6ab7d500090fb4) /* 374 */, U64_C(0x9cc0f2a057268ac0) /* 375 */, + U64_C(0x3dee9d2dedbf42d1) /* 376 */, U64_C(0x330f49c87960a972) /* 377 */, + U64_C(0xc6b2720287421b41) /* 378 */, U64_C(0x0ac59ec07c00369c) /* 379 */, + U64_C(0xef4eac49cb353425) /* 380 */, U64_C(0xf450244eef0129d8) /* 381 */, + U64_C(0x8acc46e5caf4deb6) /* 382 */, U64_C(0x2ffeab63989263f7) /* 383 */, + U64_C(0x8f7cb9fe5d7a4578) /* 384 */, U64_C(0x5bd8f7644e634635) /* 385 */, + U64_C(0x427a7315bf2dc900) /* 386 */, U64_C(0x17d0c4aa2125261c) /* 387 */, + U64_C(0x3992486c93518e50) /* 388 */, U64_C(0xb4cbfee0a2d7d4c3) /* 389 */, + U64_C(0x7c75d6202c5ddd8d) /* 390 */, U64_C(0xdbc295d8e35b6c61) /* 391 */, + U64_C(0x60b369d302032b19) /* 392 */, U64_C(0xce42685fdce44132) /* 393 */, + U64_C(0x06f3ddb9ddf65610) /* 394 */, U64_C(0x8ea4d21db5e148f0) /* 395 */, + U64_C(0x20b0fce62fcd496f) /* 396 */, U64_C(0x2c1b912358b0ee31) /* 397 */, + U64_C(0xb28317b818f5a308) /* 398 */, U64_C(0xa89c1e189ca6d2cf) /* 399 */, + U64_C(0x0c6b18576aaadbc8) /* 400 */, U64_C(0xb65deaa91299fae3) /* 401 */, + U64_C(0xfb2b794b7f1027e7) /* 402 */, U64_C(0x04e4317f443b5beb) /* 403 */, + U64_C(0x4b852d325939d0a6) /* 404 */, U64_C(0xd5ae6beefb207ffc) /* 405 */, + U64_C(0x309682b281c7d374) /* 406 */, U64_C(0xbae309a194c3b475) /* 407 */, + U64_C(0x8cc3f97b13b49f05) /* 408 */, U64_C(0x98a9422ff8293967) /* 409 */, + U64_C(0x244b16b01076ff7c) /* 410 */, U64_C(0xf8bf571c663d67ee) /* 411 */, + U64_C(0x1f0d6758eee30da1) /* 412 */, U64_C(0xc9b611d97adeb9b7) /* 413 */, + U64_C(0xb7afd5887b6c57a2) /* 414 */, U64_C(0x6290ae846b984fe1) /* 415 */, + U64_C(0x94df4cdeacc1a5fd) /* 416 */, U64_C(0x058a5bd1c5483aff) /* 417 */, + U64_C(0x63166cc142ba3c37) /* 418 */, U64_C(0x8db8526eb2f76f40) /* 419 */, + U64_C(0xe10880036f0d6d4e) /* 420 */, U64_C(0x9e0523c9971d311d) /* 421 */, + U64_C(0x45ec2824cc7cd691) /* 422 */, U64_C(0x575b8359e62382c9) /* 423 */, + U64_C(0xfa9e400dc4889995) /* 424 */, U64_C(0xd1823ecb45721568) /* 425 */, + U64_C(0xdafd983b8206082f) /* 426 */, U64_C(0xaa7d29082386a8cb) /* 427 */, + U64_C(0x269fcd4403b87588) /* 428 */, U64_C(0x1b91f5f728bdd1e0) /* 429 */, + U64_C(0xe4669f39040201f6) /* 430 */, U64_C(0x7a1d7c218cf04ade) /* 431 */, + U64_C(0x65623c29d79ce5ce) /* 432 */, U64_C(0x2368449096c00bb1) /* 433 */, + U64_C(0xab9bf1879da503ba) /* 434 */, U64_C(0xbc23ecb1a458058e) /* 435 */, + U64_C(0x9a58df01bb401ecc) /* 436 */, U64_C(0xa070e868a85f143d) /* 437 */, + U64_C(0x4ff188307df2239e) /* 438 */, U64_C(0x14d565b41a641183) /* 439 */, + U64_C(0xee13337452701602) /* 440 */, U64_C(0x950e3dcf3f285e09) /* 441 */, + U64_C(0x59930254b9c80953) /* 442 */, U64_C(0x3bf299408930da6d) /* 443 */, + U64_C(0xa955943f53691387) /* 444 */, U64_C(0xa15edecaa9cb8784) /* 445 */, + U64_C(0x29142127352be9a0) /* 446 */, U64_C(0x76f0371fff4e7afb) /* 447 */, + U64_C(0x0239f450274f2228) /* 448 */, U64_C(0xbb073af01d5e868b) /* 449 */, + U64_C(0xbfc80571c10e96c1) /* 450 */, U64_C(0xd267088568222e23) /* 451 */, + U64_C(0x9671a3d48e80b5b0) /* 452 */, U64_C(0x55b5d38ae193bb81) /* 453 */, + U64_C(0x693ae2d0a18b04b8) /* 454 */, U64_C(0x5c48b4ecadd5335f) /* 455 */, + U64_C(0xfd743b194916a1ca) /* 456 */, U64_C(0x2577018134be98c4) /* 457 */, + U64_C(0xe77987e83c54a4ad) /* 458 */, U64_C(0x28e11014da33e1b9) /* 459 */, + U64_C(0x270cc59e226aa213) /* 460 */, U64_C(0x71495f756d1a5f60) /* 461 */, + U64_C(0x9be853fb60afef77) /* 462 */, U64_C(0xadc786a7f7443dbf) /* 463 */, + U64_C(0x0904456173b29a82) /* 464 */, U64_C(0x58bc7a66c232bd5e) /* 465 */, + U64_C(0xf306558c673ac8b2) /* 466 */, U64_C(0x41f639c6b6c9772a) /* 467 */, + U64_C(0x216defe99fda35da) /* 468 */, U64_C(0x11640cc71c7be615) /* 469 */, + U64_C(0x93c43694565c5527) /* 470 */, U64_C(0xea038e6246777839) /* 471 */, + U64_C(0xf9abf3ce5a3e2469) /* 472 */, U64_C(0x741e768d0fd312d2) /* 473 */, + U64_C(0x0144b883ced652c6) /* 474 */, U64_C(0xc20b5a5ba33f8552) /* 475 */, + U64_C(0x1ae69633c3435a9d) /* 476 */, U64_C(0x97a28ca4088cfdec) /* 477 */, + U64_C(0x8824a43c1e96f420) /* 478 */, U64_C(0x37612fa66eeea746) /* 479 */, + U64_C(0x6b4cb165f9cf0e5a) /* 480 */, U64_C(0x43aa1c06a0abfb4a) /* 481 */, + U64_C(0x7f4dc26ff162796b) /* 482 */, U64_C(0x6cbacc8e54ed9b0f) /* 483 */, + U64_C(0xa6b7ffefd2bb253e) /* 484 */, U64_C(0x2e25bc95b0a29d4f) /* 485 */, + U64_C(0x86d6a58bdef1388c) /* 486 */, U64_C(0xded74ac576b6f054) /* 487 */, + U64_C(0x8030bdbc2b45805d) /* 488 */, U64_C(0x3c81af70e94d9289) /* 489 */, + U64_C(0x3eff6dda9e3100db) /* 490 */, U64_C(0xb38dc39fdfcc8847) /* 491 */, + U64_C(0x123885528d17b87e) /* 492 */, U64_C(0xf2da0ed240b1b642) /* 493 */, + U64_C(0x44cefadcd54bf9a9) /* 494 */, U64_C(0x1312200e433c7ee6) /* 495 */, + U64_C(0x9ffcc84f3a78c748) /* 496 */, U64_C(0xf0cd1f72248576bb) /* 497 */, + U64_C(0xec6974053638cfe4) /* 498 */, U64_C(0x2ba7b67c0cec4e4c) /* 499 */, + U64_C(0xac2f4df3e5ce32ed) /* 500 */, U64_C(0xcb33d14326ea4c11) /* 501 */, + U64_C(0xa4e9044cc77e58bc) /* 502 */, U64_C(0x5f513293d934fcef) /* 503 */, + U64_C(0x5dc9645506e55444) /* 504 */, U64_C(0x50de418f317de40a) /* 505 */, + U64_C(0x388cb31a69dde259) /* 506 */, U64_C(0x2db4a83455820a86) /* 507 */, + U64_C(0x9010a91e84711ae9) /* 508 */, U64_C(0x4df7f0b7b1498371) /* 509 */, + U64_C(0xd62a2eabc0977179) /* 510 */, U64_C(0x22fac097aa8d5c0e) /* 511 */ +}; +static u64 sbox3[256] = { + U64_C(0xf49fcc2ff1daf39b) /* 512 */, U64_C(0x487fd5c66ff29281) /* 513 */, + U64_C(0xe8a30667fcdca83f) /* 514 */, U64_C(0x2c9b4be3d2fcce63) /* 515 */, + U64_C(0xda3ff74b93fbbbc2) /* 516 */, U64_C(0x2fa165d2fe70ba66) /* 517 */, + U64_C(0xa103e279970e93d4) /* 518 */, U64_C(0xbecdec77b0e45e71) /* 519 */, + U64_C(0xcfb41e723985e497) /* 520 */, U64_C(0xb70aaa025ef75017) /* 521 */, + U64_C(0xd42309f03840b8e0) /* 522 */, U64_C(0x8efc1ad035898579) /* 523 */, + U64_C(0x96c6920be2b2abc5) /* 524 */, U64_C(0x66af4163375a9172) /* 525 */, + U64_C(0x2174abdcca7127fb) /* 526 */, U64_C(0xb33ccea64a72ff41) /* 527 */, + U64_C(0xf04a4933083066a5) /* 528 */, U64_C(0x8d970acdd7289af5) /* 529 */, + U64_C(0x8f96e8e031c8c25e) /* 530 */, U64_C(0xf3fec02276875d47) /* 531 */, + U64_C(0xec7bf310056190dd) /* 532 */, U64_C(0xf5adb0aebb0f1491) /* 533 */, + U64_C(0x9b50f8850fd58892) /* 534 */, U64_C(0x4975488358b74de8) /* 535 */, + U64_C(0xa3354ff691531c61) /* 536 */, U64_C(0x0702bbe481d2c6ee) /* 537 */, + U64_C(0x89fb24057deded98) /* 538 */, U64_C(0xac3075138596e902) /* 539 */, + U64_C(0x1d2d3580172772ed) /* 540 */, U64_C(0xeb738fc28e6bc30d) /* 541 */, + U64_C(0x5854ef8f63044326) /* 542 */, U64_C(0x9e5c52325add3bbe) /* 543 */, + U64_C(0x90aa53cf325c4623) /* 544 */, U64_C(0xc1d24d51349dd067) /* 545 */, + U64_C(0x2051cfeea69ea624) /* 546 */, U64_C(0x13220f0a862e7e4f) /* 547 */, + U64_C(0xce39399404e04864) /* 548 */, U64_C(0xd9c42ca47086fcb7) /* 549 */, + U64_C(0x685ad2238a03e7cc) /* 550 */, U64_C(0x066484b2ab2ff1db) /* 551 */, + U64_C(0xfe9d5d70efbf79ec) /* 552 */, U64_C(0x5b13b9dd9c481854) /* 553 */, + U64_C(0x15f0d475ed1509ad) /* 554 */, U64_C(0x0bebcd060ec79851) /* 555 */, + U64_C(0xd58c6791183ab7f8) /* 556 */, U64_C(0xd1187c5052f3eee4) /* 557 */, + U64_C(0xc95d1192e54e82ff) /* 558 */, U64_C(0x86eea14cb9ac6ca2) /* 559 */, + U64_C(0x3485beb153677d5d) /* 560 */, U64_C(0xdd191d781f8c492a) /* 561 */, + U64_C(0xf60866baa784ebf9) /* 562 */, U64_C(0x518f643ba2d08c74) /* 563 */, + U64_C(0x8852e956e1087c22) /* 564 */, U64_C(0xa768cb8dc410ae8d) /* 565 */, + U64_C(0x38047726bfec8e1a) /* 566 */, U64_C(0xa67738b4cd3b45aa) /* 567 */, + U64_C(0xad16691cec0dde19) /* 568 */, U64_C(0xc6d4319380462e07) /* 569 */, + U64_C(0xc5a5876d0ba61938) /* 570 */, U64_C(0x16b9fa1fa58fd840) /* 571 */, + U64_C(0x188ab1173ca74f18) /* 572 */, U64_C(0xabda2f98c99c021f) /* 573 */, + U64_C(0x3e0580ab134ae816) /* 574 */, U64_C(0x5f3b05b773645abb) /* 575 */, + U64_C(0x2501a2be5575f2f6) /* 576 */, U64_C(0x1b2f74004e7e8ba9) /* 577 */, + U64_C(0x1cd7580371e8d953) /* 578 */, U64_C(0x7f6ed89562764e30) /* 579 */, + U64_C(0xb15926ff596f003d) /* 580 */, U64_C(0x9f65293da8c5d6b9) /* 581 */, + U64_C(0x6ecef04dd690f84c) /* 582 */, U64_C(0x4782275fff33af88) /* 583 */, + U64_C(0xe41433083f820801) /* 584 */, U64_C(0xfd0dfe409a1af9b5) /* 585 */, + U64_C(0x4325a3342cdb396b) /* 586 */, U64_C(0x8ae77e62b301b252) /* 587 */, + U64_C(0xc36f9e9f6655615a) /* 588 */, U64_C(0x85455a2d92d32c09) /* 589 */, + U64_C(0xf2c7dea949477485) /* 590 */, U64_C(0x63cfb4c133a39eba) /* 591 */, + U64_C(0x83b040cc6ebc5462) /* 592 */, U64_C(0x3b9454c8fdb326b0) /* 593 */, + U64_C(0x56f56a9e87ffd78c) /* 594 */, U64_C(0x2dc2940d99f42bc6) /* 595 */, + U64_C(0x98f7df096b096e2d) /* 596 */, U64_C(0x19a6e01e3ad852bf) /* 597 */, + U64_C(0x42a99ccbdbd4b40b) /* 598 */, U64_C(0xa59998af45e9c559) /* 599 */, + U64_C(0x366295e807d93186) /* 600 */, U64_C(0x6b48181bfaa1f773) /* 601 */, + U64_C(0x1fec57e2157a0a1d) /* 602 */, U64_C(0x4667446af6201ad5) /* 603 */, + U64_C(0xe615ebcacfb0f075) /* 604 */, U64_C(0xb8f31f4f68290778) /* 605 */, + U64_C(0x22713ed6ce22d11e) /* 606 */, U64_C(0x3057c1a72ec3c93b) /* 607 */, + U64_C(0xcb46acc37c3f1f2f) /* 608 */, U64_C(0xdbb893fd02aaf50e) /* 609 */, + U64_C(0x331fd92e600b9fcf) /* 610 */, U64_C(0xa498f96148ea3ad6) /* 611 */, + U64_C(0xa8d8426e8b6a83ea) /* 612 */, U64_C(0xa089b274b7735cdc) /* 613 */, + U64_C(0x87f6b3731e524a11) /* 614 */, U64_C(0x118808e5cbc96749) /* 615 */, + U64_C(0x9906e4c7b19bd394) /* 616 */, U64_C(0xafed7f7e9b24a20c) /* 617 */, + U64_C(0x6509eadeeb3644a7) /* 618 */, U64_C(0x6c1ef1d3e8ef0ede) /* 619 */, + U64_C(0xb9c97d43e9798fb4) /* 620 */, U64_C(0xa2f2d784740c28a3) /* 621 */, + U64_C(0x7b8496476197566f) /* 622 */, U64_C(0x7a5be3e6b65f069d) /* 623 */, + U64_C(0xf96330ed78be6f10) /* 624 */, U64_C(0xeee60de77a076a15) /* 625 */, + U64_C(0x2b4bee4aa08b9bd0) /* 626 */, U64_C(0x6a56a63ec7b8894e) /* 627 */, + U64_C(0x02121359ba34fef4) /* 628 */, U64_C(0x4cbf99f8283703fc) /* 629 */, + U64_C(0x398071350caf30c8) /* 630 */, U64_C(0xd0a77a89f017687a) /* 631 */, + U64_C(0xf1c1a9eb9e423569) /* 632 */, U64_C(0x8c7976282dee8199) /* 633 */, + U64_C(0x5d1737a5dd1f7abd) /* 634 */, U64_C(0x4f53433c09a9fa80) /* 635 */, + U64_C(0xfa8b0c53df7ca1d9) /* 636 */, U64_C(0x3fd9dcbc886ccb77) /* 637 */, + U64_C(0xc040917ca91b4720) /* 638 */, U64_C(0x7dd00142f9d1dcdf) /* 639 */, + U64_C(0x8476fc1d4f387b58) /* 640 */, U64_C(0x23f8e7c5f3316503) /* 641 */, + U64_C(0x032a2244e7e37339) /* 642 */, U64_C(0x5c87a5d750f5a74b) /* 643 */, + U64_C(0x082b4cc43698992e) /* 644 */, U64_C(0xdf917becb858f63c) /* 645 */, + U64_C(0x3270b8fc5bf86dda) /* 646 */, U64_C(0x10ae72bb29b5dd76) /* 647 */, + U64_C(0x576ac94e7700362b) /* 648 */, U64_C(0x1ad112dac61efb8f) /* 649 */, + U64_C(0x691bc30ec5faa427) /* 650 */, U64_C(0xff246311cc327143) /* 651 */, + U64_C(0x3142368e30e53206) /* 652 */, U64_C(0x71380e31e02ca396) /* 653 */, + U64_C(0x958d5c960aad76f1) /* 654 */, U64_C(0xf8d6f430c16da536) /* 655 */, + U64_C(0xc8ffd13f1be7e1d2) /* 656 */, U64_C(0x7578ae66004ddbe1) /* 657 */, + U64_C(0x05833f01067be646) /* 658 */, U64_C(0xbb34b5ad3bfe586d) /* 659 */, + U64_C(0x095f34c9a12b97f0) /* 660 */, U64_C(0x247ab64525d60ca8) /* 661 */, + U64_C(0xdcdbc6f3017477d1) /* 662 */, U64_C(0x4a2e14d4decad24d) /* 663 */, + U64_C(0xbdb5e6d9be0a1eeb) /* 664 */, U64_C(0x2a7e70f7794301ab) /* 665 */, + U64_C(0xdef42d8a270540fd) /* 666 */, U64_C(0x01078ec0a34c22c1) /* 667 */, + U64_C(0xe5de511af4c16387) /* 668 */, U64_C(0x7ebb3a52bd9a330a) /* 669 */, + U64_C(0x77697857aa7d6435) /* 670 */, U64_C(0x004e831603ae4c32) /* 671 */, + U64_C(0xe7a21020ad78e312) /* 672 */, U64_C(0x9d41a70c6ab420f2) /* 673 */, + U64_C(0x28e06c18ea1141e6) /* 674 */, U64_C(0xd2b28cbd984f6b28) /* 675 */, + U64_C(0x26b75f6c446e9d83) /* 676 */, U64_C(0xba47568c4d418d7f) /* 677 */, + U64_C(0xd80badbfe6183d8e) /* 678 */, U64_C(0x0e206d7f5f166044) /* 679 */, + U64_C(0xe258a43911cbca3e) /* 680 */, U64_C(0x723a1746b21dc0bc) /* 681 */, + U64_C(0xc7caa854f5d7cdd3) /* 682 */, U64_C(0x7cac32883d261d9c) /* 683 */, + U64_C(0x7690c26423ba942c) /* 684 */, U64_C(0x17e55524478042b8) /* 685 */, + U64_C(0xe0be477656a2389f) /* 686 */, U64_C(0x4d289b5e67ab2da0) /* 687 */, + U64_C(0x44862b9c8fbbfd31) /* 688 */, U64_C(0xb47cc8049d141365) /* 689 */, + U64_C(0x822c1b362b91c793) /* 690 */, U64_C(0x4eb14655fb13dfd8) /* 691 */, + U64_C(0x1ecbba0714e2a97b) /* 692 */, U64_C(0x6143459d5cde5f14) /* 693 */, + U64_C(0x53a8fbf1d5f0ac89) /* 694 */, U64_C(0x97ea04d81c5e5b00) /* 695 */, + U64_C(0x622181a8d4fdb3f3) /* 696 */, U64_C(0xe9bcd341572a1208) /* 697 */, + U64_C(0x1411258643cce58a) /* 698 */, U64_C(0x9144c5fea4c6e0a4) /* 699 */, + U64_C(0x0d33d06565cf620f) /* 700 */, U64_C(0x54a48d489f219ca1) /* 701 */, + U64_C(0xc43e5eac6d63c821) /* 702 */, U64_C(0xa9728b3a72770daf) /* 703 */, + U64_C(0xd7934e7b20df87ef) /* 704 */, U64_C(0xe35503b61a3e86e5) /* 705 */, + U64_C(0xcae321fbc819d504) /* 706 */, U64_C(0x129a50b3ac60bfa6) /* 707 */, + U64_C(0xcd5e68ea7e9fb6c3) /* 708 */, U64_C(0xb01c90199483b1c7) /* 709 */, + U64_C(0x3de93cd5c295376c) /* 710 */, U64_C(0xaed52edf2ab9ad13) /* 711 */, + U64_C(0x2e60f512c0a07884) /* 712 */, U64_C(0xbc3d86a3e36210c9) /* 713 */, + U64_C(0x35269d9b163951ce) /* 714 */, U64_C(0x0c7d6e2ad0cdb5fa) /* 715 */, + U64_C(0x59e86297d87f5733) /* 716 */, U64_C(0x298ef221898db0e7) /* 717 */, + U64_C(0x55000029d1a5aa7e) /* 718 */, U64_C(0x8bc08ae1b5061b45) /* 719 */, + U64_C(0xc2c31c2b6c92703a) /* 720 */, U64_C(0x94cc596baf25ef42) /* 721 */, + U64_C(0x0a1d73db22540456) /* 722 */, U64_C(0x04b6a0f9d9c4179a) /* 723 */, + U64_C(0xeffdafa2ae3d3c60) /* 724 */, U64_C(0xf7c8075bb49496c4) /* 725 */, + U64_C(0x9cc5c7141d1cd4e3) /* 726 */, U64_C(0x78bd1638218e5534) /* 727 */, + U64_C(0xb2f11568f850246a) /* 728 */, U64_C(0xedfabcfa9502bc29) /* 729 */, + U64_C(0x796ce5f2da23051b) /* 730 */, U64_C(0xaae128b0dc93537c) /* 731 */, + U64_C(0x3a493da0ee4b29ae) /* 732 */, U64_C(0xb5df6b2c416895d7) /* 733 */, + U64_C(0xfcabbd25122d7f37) /* 734 */, U64_C(0x70810b58105dc4b1) /* 735 */, + U64_C(0xe10fdd37f7882a90) /* 736 */, U64_C(0x524dcab5518a3f5c) /* 737 */, + U64_C(0x3c9e85878451255b) /* 738 */, U64_C(0x4029828119bd34e2) /* 739 */, + U64_C(0x74a05b6f5d3ceccb) /* 740 */, U64_C(0xb610021542e13eca) /* 741 */, + U64_C(0x0ff979d12f59e2ac) /* 742 */, U64_C(0x6037da27e4f9cc50) /* 743 */, + U64_C(0x5e92975a0df1847d) /* 744 */, U64_C(0xd66de190d3e623fe) /* 745 */, + U64_C(0x5032d6b87b568048) /* 746 */, U64_C(0x9a36b7ce8235216e) /* 747 */, + U64_C(0x80272a7a24f64b4a) /* 748 */, U64_C(0x93efed8b8c6916f7) /* 749 */, + U64_C(0x37ddbff44cce1555) /* 750 */, U64_C(0x4b95db5d4b99bd25) /* 751 */, + U64_C(0x92d3fda169812fc0) /* 752 */, U64_C(0xfb1a4a9a90660bb6) /* 753 */, + U64_C(0x730c196946a4b9b2) /* 754 */, U64_C(0x81e289aa7f49da68) /* 755 */, + U64_C(0x64669a0f83b1a05f) /* 756 */, U64_C(0x27b3ff7d9644f48b) /* 757 */, + U64_C(0xcc6b615c8db675b3) /* 758 */, U64_C(0x674f20b9bcebbe95) /* 759 */, + U64_C(0x6f31238275655982) /* 760 */, U64_C(0x5ae488713e45cf05) /* 761 */, + U64_C(0xbf619f9954c21157) /* 762 */, U64_C(0xeabac46040a8eae9) /* 763 */, + U64_C(0x454c6fe9f2c0c1cd) /* 764 */, U64_C(0x419cf6496412691c) /* 765 */, + U64_C(0xd3dc3bef265b0f70) /* 766 */, U64_C(0x6d0e60f5c3578a9e) /* 767 */ +}; +static u64 sbox4[256] = { + U64_C(0x5b0e608526323c55) /* 768 */, U64_C(0x1a46c1a9fa1b59f5) /* 769 */, + U64_C(0xa9e245a17c4c8ffa) /* 770 */, U64_C(0x65ca5159db2955d7) /* 771 */, + U64_C(0x05db0a76ce35afc2) /* 772 */, U64_C(0x81eac77ea9113d45) /* 773 */, + U64_C(0x528ef88ab6ac0a0d) /* 774 */, U64_C(0xa09ea253597be3ff) /* 775 */, + U64_C(0x430ddfb3ac48cd56) /* 776 */, U64_C(0xc4b3a67af45ce46f) /* 777 */, + U64_C(0x4ececfd8fbe2d05e) /* 778 */, U64_C(0x3ef56f10b39935f0) /* 779 */, + U64_C(0x0b22d6829cd619c6) /* 780 */, U64_C(0x17fd460a74df2069) /* 781 */, + U64_C(0x6cf8cc8e8510ed40) /* 782 */, U64_C(0xd6c824bf3a6ecaa7) /* 783 */, + U64_C(0x61243d581a817049) /* 784 */, U64_C(0x048bacb6bbc163a2) /* 785 */, + U64_C(0xd9a38ac27d44cc32) /* 786 */, U64_C(0x7fddff5baaf410ab) /* 787 */, + U64_C(0xad6d495aa804824b) /* 788 */, U64_C(0xe1a6a74f2d8c9f94) /* 789 */, + U64_C(0xd4f7851235dee8e3) /* 790 */, U64_C(0xfd4b7f886540d893) /* 791 */, + U64_C(0x247c20042aa4bfda) /* 792 */, U64_C(0x096ea1c517d1327c) /* 793 */, + U64_C(0xd56966b4361a6685) /* 794 */, U64_C(0x277da5c31221057d) /* 795 */, + U64_C(0x94d59893a43acff7) /* 796 */, U64_C(0x64f0c51ccdc02281) /* 797 */, + U64_C(0x3d33bcc4ff6189db) /* 798 */, U64_C(0xe005cb184ce66af1) /* 799 */, + U64_C(0xff5ccd1d1db99bea) /* 800 */, U64_C(0xb0b854a7fe42980f) /* 801 */, + U64_C(0x7bd46a6a718d4b9f) /* 802 */, U64_C(0xd10fa8cc22a5fd8c) /* 803 */, + U64_C(0xd31484952be4bd31) /* 804 */, U64_C(0xc7fa975fcb243847) /* 805 */, + U64_C(0x4886ed1e5846c407) /* 806 */, U64_C(0x28cddb791eb70b04) /* 807 */, + U64_C(0xc2b00be2f573417f) /* 808 */, U64_C(0x5c9590452180f877) /* 809 */, + U64_C(0x7a6bddfff370eb00) /* 810 */, U64_C(0xce509e38d6d9d6a4) /* 811 */, + U64_C(0xebeb0f00647fa702) /* 812 */, U64_C(0x1dcc06cf76606f06) /* 813 */, + U64_C(0xe4d9f28ba286ff0a) /* 814 */, U64_C(0xd85a305dc918c262) /* 815 */, + U64_C(0x475b1d8732225f54) /* 816 */, U64_C(0x2d4fb51668ccb5fe) /* 817 */, + U64_C(0xa679b9d9d72bba20) /* 818 */, U64_C(0x53841c0d912d43a5) /* 819 */, + U64_C(0x3b7eaa48bf12a4e8) /* 820 */, U64_C(0x781e0e47f22f1ddf) /* 821 */, + U64_C(0xeff20ce60ab50973) /* 822 */, U64_C(0x20d261d19dffb742) /* 823 */, + U64_C(0x16a12b03062a2e39) /* 824 */, U64_C(0x1960eb2239650495) /* 825 */, + U64_C(0x251c16fed50eb8b8) /* 826 */, U64_C(0x9ac0c330f826016e) /* 827 */, + U64_C(0xed152665953e7671) /* 828 */, U64_C(0x02d63194a6369570) /* 829 */, + U64_C(0x5074f08394b1c987) /* 830 */, U64_C(0x70ba598c90b25ce1) /* 831 */, + U64_C(0x794a15810b9742f6) /* 832 */, U64_C(0x0d5925e9fcaf8c6c) /* 833 */, + U64_C(0x3067716cd868744e) /* 834 */, U64_C(0x910ab077e8d7731b) /* 835 */, + U64_C(0x6a61bbdb5ac42f61) /* 836 */, U64_C(0x93513efbf0851567) /* 837 */, + U64_C(0xf494724b9e83e9d5) /* 838 */, U64_C(0xe887e1985c09648d) /* 839 */, + U64_C(0x34b1d3c675370cfd) /* 840 */, U64_C(0xdc35e433bc0d255d) /* 841 */, + U64_C(0xd0aab84234131be0) /* 842 */, U64_C(0x08042a50b48b7eaf) /* 843 */, + U64_C(0x9997c4ee44a3ab35) /* 844 */, U64_C(0x829a7b49201799d0) /* 845 */, + U64_C(0x263b8307b7c54441) /* 846 */, U64_C(0x752f95f4fd6a6ca6) /* 847 */, + U64_C(0x927217402c08c6e5) /* 848 */, U64_C(0x2a8ab754a795d9ee) /* 849 */, + U64_C(0xa442f7552f72943d) /* 850 */, U64_C(0x2c31334e19781208) /* 851 */, + U64_C(0x4fa98d7ceaee6291) /* 852 */, U64_C(0x55c3862f665db309) /* 853 */, + U64_C(0xbd0610175d53b1f3) /* 854 */, U64_C(0x46fe6cb840413f27) /* 855 */, + U64_C(0x3fe03792df0cfa59) /* 856 */, U64_C(0xcfe700372eb85e8f) /* 857 */, + U64_C(0xa7be29e7adbce118) /* 858 */, U64_C(0xe544ee5cde8431dd) /* 859 */, + U64_C(0x8a781b1b41f1873e) /* 860 */, U64_C(0xa5c94c78a0d2f0e7) /* 861 */, + U64_C(0x39412e2877b60728) /* 862 */, U64_C(0xa1265ef3afc9a62c) /* 863 */, + U64_C(0xbcc2770c6a2506c5) /* 864 */, U64_C(0x3ab66dd5dce1ce12) /* 865 */, + U64_C(0xe65499d04a675b37) /* 866 */, U64_C(0x7d8f523481bfd216) /* 867 */, + U64_C(0x0f6f64fcec15f389) /* 868 */, U64_C(0x74efbe618b5b13c8) /* 869 */, + U64_C(0xacdc82b714273e1d) /* 870 */, U64_C(0xdd40bfe003199d17) /* 871 */, + U64_C(0x37e99257e7e061f8) /* 872 */, U64_C(0xfa52626904775aaa) /* 873 */, + U64_C(0x8bbbf63a463d56f9) /* 874 */, U64_C(0xf0013f1543a26e64) /* 875 */, + U64_C(0xa8307e9f879ec898) /* 876 */, U64_C(0xcc4c27a4150177cc) /* 877 */, + U64_C(0x1b432f2cca1d3348) /* 878 */, U64_C(0xde1d1f8f9f6fa013) /* 879 */, + U64_C(0x606602a047a7ddd6) /* 880 */, U64_C(0xd237ab64cc1cb2c7) /* 881 */, + U64_C(0x9b938e7225fcd1d3) /* 882 */, U64_C(0xec4e03708e0ff476) /* 883 */, + U64_C(0xfeb2fbda3d03c12d) /* 884 */, U64_C(0xae0bced2ee43889a) /* 885 */, + U64_C(0x22cb8923ebfb4f43) /* 886 */, U64_C(0x69360d013cf7396d) /* 887 */, + U64_C(0x855e3602d2d4e022) /* 888 */, U64_C(0x073805bad01f784c) /* 889 */, + U64_C(0x33e17a133852f546) /* 890 */, U64_C(0xdf4874058ac7b638) /* 891 */, + U64_C(0xba92b29c678aa14a) /* 892 */, U64_C(0x0ce89fc76cfaadcd) /* 893 */, + U64_C(0x5f9d4e0908339e34) /* 894 */, U64_C(0xf1afe9291f5923b9) /* 895 */, + U64_C(0x6e3480f60f4a265f) /* 896 */, U64_C(0xeebf3a2ab29b841c) /* 897 */, + U64_C(0xe21938a88f91b4ad) /* 898 */, U64_C(0x57dfeff845c6d3c3) /* 899 */, + U64_C(0x2f006b0bf62caaf2) /* 900 */, U64_C(0x62f479ef6f75ee78) /* 901 */, + U64_C(0x11a55ad41c8916a9) /* 902 */, U64_C(0xf229d29084fed453) /* 903 */, + U64_C(0x42f1c27b16b000e6) /* 904 */, U64_C(0x2b1f76749823c074) /* 905 */, + U64_C(0x4b76eca3c2745360) /* 906 */, U64_C(0x8c98f463b91691bd) /* 907 */, + U64_C(0x14bcc93cf1ade66a) /* 908 */, U64_C(0x8885213e6d458397) /* 909 */, + U64_C(0x8e177df0274d4711) /* 910 */, U64_C(0xb49b73b5503f2951) /* 911 */, + U64_C(0x10168168c3f96b6b) /* 912 */, U64_C(0x0e3d963b63cab0ae) /* 913 */, + U64_C(0x8dfc4b5655a1db14) /* 914 */, U64_C(0xf789f1356e14de5c) /* 915 */, + U64_C(0x683e68af4e51dac1) /* 916 */, U64_C(0xc9a84f9d8d4b0fd9) /* 917 */, + U64_C(0x3691e03f52a0f9d1) /* 918 */, U64_C(0x5ed86e46e1878e80) /* 919 */, + U64_C(0x3c711a0e99d07150) /* 920 */, U64_C(0x5a0865b20c4e9310) /* 921 */, + U64_C(0x56fbfc1fe4f0682e) /* 922 */, U64_C(0xea8d5de3105edf9b) /* 923 */, + U64_C(0x71abfdb12379187a) /* 924 */, U64_C(0x2eb99de1bee77b9c) /* 925 */, + U64_C(0x21ecc0ea33cf4523) /* 926 */, U64_C(0x59a4d7521805c7a1) /* 927 */, + U64_C(0x3896f5eb56ae7c72) /* 928 */, U64_C(0xaa638f3db18f75dc) /* 929 */, + U64_C(0x9f39358dabe9808e) /* 930 */, U64_C(0xb7defa91c00b72ac) /* 931 */, + U64_C(0x6b5541fd62492d92) /* 932 */, U64_C(0x6dc6dee8f92e4d5b) /* 933 */, + U64_C(0x353f57abc4beea7e) /* 934 */, U64_C(0x735769d6da5690ce) /* 935 */, + U64_C(0x0a234aa642391484) /* 936 */, U64_C(0xf6f9508028f80d9d) /* 937 */, + U64_C(0xb8e319a27ab3f215) /* 938 */, U64_C(0x31ad9c1151341a4d) /* 939 */, + U64_C(0x773c22a57bef5805) /* 940 */, U64_C(0x45c7561a07968633) /* 941 */, + U64_C(0xf913da9e249dbe36) /* 942 */, U64_C(0xda652d9b78a64c68) /* 943 */, + U64_C(0x4c27a97f3bc334ef) /* 944 */, U64_C(0x76621220e66b17f4) /* 945 */, + U64_C(0x967743899acd7d0b) /* 946 */, U64_C(0xf3ee5bcae0ed6782) /* 947 */, + U64_C(0x409f753600c879fc) /* 948 */, U64_C(0x06d09a39b5926db6) /* 949 */, + U64_C(0x6f83aeb0317ac588) /* 950 */, U64_C(0x01e6ca4a86381f21) /* 951 */, + U64_C(0x66ff3462d19f3025) /* 952 */, U64_C(0x72207c24ddfd3bfb) /* 953 */, + U64_C(0x4af6b6d3e2ece2eb) /* 954 */, U64_C(0x9c994dbec7ea08de) /* 955 */, + U64_C(0x49ace597b09a8bc4) /* 956 */, U64_C(0xb38c4766cf0797ba) /* 957 */, + U64_C(0x131b9373c57c2a75) /* 958 */, U64_C(0xb1822cce61931e58) /* 959 */, + U64_C(0x9d7555b909ba1c0c) /* 960 */, U64_C(0x127fafdd937d11d2) /* 961 */, + U64_C(0x29da3badc66d92e4) /* 962 */, U64_C(0xa2c1d57154c2ecbc) /* 963 */, + U64_C(0x58c5134d82f6fe24) /* 964 */, U64_C(0x1c3ae3515b62274f) /* 965 */, + U64_C(0xe907c82e01cb8126) /* 966 */, U64_C(0xf8ed091913e37fcb) /* 967 */, + U64_C(0x3249d8f9c80046c9) /* 968 */, U64_C(0x80cf9bede388fb63) /* 969 */, + U64_C(0x1881539a116cf19e) /* 970 */, U64_C(0x5103f3f76bd52457) /* 971 */, + U64_C(0x15b7e6f5ae47f7a8) /* 972 */, U64_C(0xdbd7c6ded47e9ccf) /* 973 */, + U64_C(0x44e55c410228bb1a) /* 974 */, U64_C(0xb647d4255edb4e99) /* 975 */, + U64_C(0x5d11882bb8aafc30) /* 976 */, U64_C(0xf5098bbb29d3212a) /* 977 */, + U64_C(0x8fb5ea14e90296b3) /* 978 */, U64_C(0x677b942157dd025a) /* 979 */, + U64_C(0xfb58e7c0a390acb5) /* 980 */, U64_C(0x89d3674c83bd4a01) /* 981 */, + U64_C(0x9e2da4df4bf3b93b) /* 982 */, U64_C(0xfcc41e328cab4829) /* 983 */, + U64_C(0x03f38c96ba582c52) /* 984 */, U64_C(0xcad1bdbd7fd85db2) /* 985 */, + U64_C(0xbbb442c16082ae83) /* 986 */, U64_C(0xb95fe86ba5da9ab0) /* 987 */, + U64_C(0xb22e04673771a93f) /* 988 */, U64_C(0x845358c9493152d8) /* 989 */, + U64_C(0xbe2a488697b4541e) /* 990 */, U64_C(0x95a2dc2dd38e6966) /* 991 */, + U64_C(0xc02c11ac923c852b) /* 992 */, U64_C(0x2388b1990df2a87b) /* 993 */, + U64_C(0x7c8008fa1b4f37be) /* 994 */, U64_C(0x1f70d0c84d54e503) /* 995 */, + U64_C(0x5490adec7ece57d4) /* 996 */, U64_C(0x002b3c27d9063a3a) /* 997 */, + U64_C(0x7eaea3848030a2bf) /* 998 */, U64_C(0xc602326ded2003c0) /* 999 */, + U64_C(0x83a7287d69a94086) /* 1000 */, U64_C(0xc57a5fcb30f57a8a) /* 1001 */, + U64_C(0xb56844e479ebe779) /* 1002 */, U64_C(0xa373b40f05dcbce9) /* 1003 */, + U64_C(0xd71a786e88570ee2) /* 1004 */, U64_C(0x879cbacdbde8f6a0) /* 1005 */, + U64_C(0x976ad1bcc164a32f) /* 1006 */, U64_C(0xab21e25e9666d78b) /* 1007 */, + U64_C(0x901063aae5e5c33c) /* 1008 */, U64_C(0x9818b34448698d90) /* 1009 */, + U64_C(0xe36487ae3e1e8abb) /* 1010 */, U64_C(0xafbdf931893bdcb4) /* 1011 */, + U64_C(0x6345a0dc5fbbd519) /* 1012 */, U64_C(0x8628fe269b9465ca) /* 1013 */, + U64_C(0x1e5d01603f9c51ec) /* 1014 */, U64_C(0x4de44006a15049b7) /* 1015 */, + U64_C(0xbf6c70e5f776cbb1) /* 1016 */, U64_C(0x411218f2ef552bed) /* 1017 */, + U64_C(0xcb0c0708705a36a3) /* 1018 */, U64_C(0xe74d14754f986044) /* 1019 */, + U64_C(0xcd56d9430ea8280e) /* 1020 */, U64_C(0xc12591d7535f5065) /* 1021 */, + U64_C(0xc83223f1720aef96) /* 1022 */, U64_C(0xc3a0396f7363a51f) /* 1023 */ +}; + +static void +do_init (void *context, int variant) +{ + TIGER_CONTEXT *hd = context; + + hd->a = 0x0123456789abcdefLL; + hd->b = 0xfedcba9876543210LL; + hd->c = 0xf096a5b4c3b2e187LL; + hd->nblocks = 0; + hd->count = 0; + hd->variant = variant; +} + +static void +tiger_init (void *context) +{ + do_init (context, 0); +} + +static void +tiger1_init (void *context) +{ + do_init (context, 1); +} + +static void +tiger2_init (void *context) +{ + do_init (context, 2); +} + +static void +tiger_round( u64 *ra, u64 *rb, u64 *rc, u64 x, int mul ) +{ + u64 a = *ra; + u64 b = *rb; + u64 c = *rc; + + c ^= x; + a -= ( sbox1[ c & 0xff ] ^ sbox2[ (c >> 16) & 0xff ] + ^ sbox3[ (c >> 32) & 0xff ] ^ sbox4[ (c >> 48) & 0xff ]); + b += ( sbox4[ (c >> 8) & 0xff ] ^ sbox3[ (c >> 24) & 0xff ] + ^ sbox2[ (c >> 40) & 0xff ] ^ sbox1[ (c >> 56) & 0xff ]); + b *= mul; + + *ra = a; + *rb = b; + *rc = c; +} + + +static void +pass( u64 *ra, u64 *rb, u64 *rc, u64 *x, int mul ) +{ + u64 a = *ra; + u64 b = *rb; + u64 c = *rc; + + tiger_round( &a, &b, &c, x[0], mul ); + tiger_round( &b, &c, &a, x[1], mul ); + tiger_round( &c, &a, &b, x[2], mul ); + tiger_round( &a, &b, &c, x[3], mul ); + tiger_round( &b, &c, &a, x[4], mul ); + tiger_round( &c, &a, &b, x[5], mul ); + tiger_round( &a, &b, &c, x[6], mul ); + tiger_round( &b, &c, &a, x[7], mul ); + + *ra = a; + *rb = b; + *rc = c; +} + + +static void +key_schedule( u64 *x ) +{ + x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5LL; + x[1] ^= x[0]; + x[2] += x[1]; + x[3] -= x[2] ^ ((~x[1]) << 19 ); + x[4] ^= x[3]; + x[5] += x[4]; + x[6] -= x[5] ^ ((~x[4]) >> 23 ); + x[7] ^= x[6]; + x[0] += x[7]; + x[1] -= x[0] ^ ((~x[7]) << 19 ); + x[2] ^= x[1]; + x[3] += x[2]; + x[4] -= x[3] ^ ((~x[2]) >> 23 ); + x[5] ^= x[4]; + x[6] += x[5]; + x[7] -= x[6] ^ 0x0123456789abcdefLL; +} + + +/**************** + * Transform the message DATA which consists of 512 bytes (8 words) + */ +static void +transform ( TIGER_CONTEXT *hd, const unsigned char *data ) +{ + u64 a,b,c,aa,bb,cc; + u64 x[8]; +#ifdef WORDS_BIGENDIAN +#define MKWORD(d,n) \ + ( ((u64)(d)[8*(n)+7]) << 56 | ((u64)(d)[8*(n)+6]) << 48 \ + | ((u64)(d)[8*(n)+5]) << 40 | ((u64)(d)[8*(n)+4]) << 32 \ + | ((u64)(d)[8*(n)+3]) << 24 | ((u64)(d)[8*(n)+2]) << 16 \ + | ((u64)(d)[8*(n)+1]) << 8 | ((u64)(d)[8*(n) ]) ) + x[0] = MKWORD(data, 0); + x[1] = MKWORD(data, 1); + x[2] = MKWORD(data, 2); + x[3] = MKWORD(data, 3); + x[4] = MKWORD(data, 4); + x[5] = MKWORD(data, 5); + x[6] = MKWORD(data, 6); + x[7] = MKWORD(data, 7); +#undef MKWORD +#else + memcpy( &x[0], data, 64 ); +#endif + + /* save */ + a = aa = hd->a; + b = bb = hd->b; + c = cc = hd->c; + + pass( &a, &b, &c, x, 5); + key_schedule( x ); + pass( &c, &a, &b, x, 7); + key_schedule( x ); + pass( &b, &c, &a, x, 9); + + /* feedforward */ + a ^= aa; + b -= bb; + c += cc; + /* store */ + hd->a = a; + hd->b = b; + hd->c = c; +} + + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +tiger_write ( void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + TIGER_CONTEXT *hd = context; + + if( hd->count == 64 ) /* flush the buffer */ + { + transform( hd, hd->buf ); + _gcry_burn_stack (21*8+11*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + if( hd->count ) + { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + tiger_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + + while( inlen >= 64 ) + { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + _gcry_burn_stack (21*8+11*sizeof(void*)); + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; +} + + + +/* The routine terminates the computation + */ +static void +tiger_final( void *context ) +{ + TIGER_CONTEXT *hd = context; + u32 t, msb, lsb; + byte *p; + byte pad = hd->variant == 2? 0x80 : 0x01; + + tiger_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) /* enough room */ + { + hd->buf[hd->count++] = pad; + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else /* need one extra block */ + { + hd->buf[hd->count++] = pad; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + tiger_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + _gcry_burn_stack (21*8+11*sizeof(void*)); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *(u64*)p = hd->a ; p += 8; } while(0) +#else /* little endian */ +#define X(a) do { *p++ = hd->a >> 56; *p++ = hd->a >> 48; \ + *p++ = hd->a >> 40; *p++ = hd->a >> 32; \ + *p++ = hd->a >> 24; *p++ = hd->a >> 16; \ + *p++ = hd->a >> 8; *p++ = hd->a; } while(0) +#endif +#define Y(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ + *p++ = hd->a >> 16; *p++ = hd->a >> 24; \ + *p++ = hd->a >> 32; *p++ = hd->a >> 40; \ + *p++ = hd->a >> 48; *p++ = hd->a >> 56; } while(0) + if (hd->variant == 0) + { + X(a); + X(b); + X(c); + } + else + { + Y(a); + Y(b); + Y(c); + } +#undef X +#undef Y +} + +static byte * +tiger_read( void *context ) +{ + TIGER_CONTEXT *hd = context; + + return hd->buf; +} + + + +/* This is the old TIGER variant based on the unfixed reference + implementation. IT was used in GnupG up to 1.3.2. We don't provide + an OID anymore because that would not be correct. */ +gcry_md_spec_t _gcry_digest_spec_tiger = + { + "TIGER192", NULL, 0, NULL, 24, + tiger_init, tiger_write, tiger_final, tiger_read, + sizeof (TIGER_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_tiger", +#endif + .blocksize = 64 + }; + + + +/* This is the fixed TIGER implementation. */ +static byte asn1[19] = /* Object ID is 1.3.6.1.4.1.11591.12.2 */ + { 0x30, 0x29, 0x30, 0x0d, 0x06, 0x09, 0x2b, 0x06, + 0x01, 0x04, 0x01, 0xda, 0x47, 0x0c, 0x02, + 0x05, 0x00, 0x04, 0x18 }; + +static gcry_md_oid_spec_t oid_spec_tiger1[] = + { + /* GNU.digestAlgorithm TIGER */ + { "1.3.6.1.4.1.11591.12.2" }, + { NULL } + }; + +gcry_md_spec_t _gcry_digest_spec_tiger1 = + { + "TIGER", asn1, DIM (asn1), oid_spec_tiger1, 24, + tiger1_init, tiger_write, tiger_final, tiger_read, + sizeof (TIGER_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_tiger", +#endif + .blocksize = 64 + }; + + + +/* This is TIGER2 which usues a changed padding algorithm. */ +gcry_md_spec_t _gcry_digest_spec_tiger2 = + { + "TIGER2", NULL, 0, NULL, 24, + tiger2_init, tiger_write, tiger_final, tiger_read, + sizeof (TIGER_CONTEXT) + , +#ifdef GRUB_UTIL + .modname = "gcry_tiger", +#endif + .blocksize = 64 + }; + +#endif /* HAVE_U64_TYPEDEF */ + + +GRUB_MOD_INIT(gcry_tiger) +{ + COMPILE_TIME_ASSERT(sizeof (TIGER_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + COMPILE_TIME_ASSERT(sizeof (TIGER_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + COMPILE_TIME_ASSERT(sizeof (TIGER_CONTEXT) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + grub_md_register (&_gcry_digest_spec_tiger); + grub_md_register (&_gcry_digest_spec_tiger1); + grub_md_register (&_gcry_digest_spec_tiger2); +} + +GRUB_MOD_FINI(gcry_tiger) +{ + grub_md_unregister (&_gcry_digest_spec_tiger); + grub_md_unregister (&_gcry_digest_spec_tiger1); + grub_md_unregister (&_gcry_digest_spec_tiger2); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/twofish.c b/grub-core/lib/libgcrypt-grub/cipher/twofish.c new file mode 100644 index 0000000..0a65ac1 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/twofish.c @@ -0,0 +1,1001 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* Twofish for GPG + * Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc. + * Written by Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998 + * 256-bit key length added March 20, 1999 + * Some modifications to reduce the text size by Werner Koch, April, 1998 + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + ******************************************************************** + * + * This code is a "clean room" implementation, written from the paper + * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey, + * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available + * through http://www.counterpane.com/twofish.html + * + * For background information on multiplication in finite fields, used for + * the matrix operations in the key schedule, see the book _Contemporary + * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the + * Third Edition. + * + * Only the 128- and 256-bit key sizes are supported. This code is intended + * for GNU C on a 32-bit system, but it should work almost anywhere. Loops + * are unrolled, precomputation tables are used, etc., for maximum speed at + * some cost in memory consumption. */ + + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + +/* Prototype for the self-test function. */ + +/* Structure for an expanded Twofish key. s contains the key-dependent + * S-boxes composed with the MDS matrix; w contains the eight "whitening" + * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note + * that k[i] corresponds to what the Twofish paper calls K[i+8]. */ +typedef struct { + u32 s[4][256], w[8], k[32]; +} TWOFISH_context; + +/* These two tables are the q0 and q1 permutations, exactly as described in + * the Twofish paper. */ + +static const byte q0[256] = { + 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, + 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, + 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, + 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, + 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, + 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, + 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, + 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, + 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, + 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, + 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, + 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, + 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, + 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, + 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, + 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, + 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, + 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, + 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, + 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, + 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, + 0x4A, 0x5E, 0xC1, 0xE0 +}; + +static const byte q1[256] = { + 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, + 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, + 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, + 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, + 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, + 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, + 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, + 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, + 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, + 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, + 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, + 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, + 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, + 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, + 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, + 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, + 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, + 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, + 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, + 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, + 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, + 0x55, 0x09, 0xBE, 0x91 +}; + +/* These MDS tables are actually tables of MDS composed with q0 and q1, + * because it is only ever used that way and we can save some time by + * precomputing. Of course the main saving comes from precomputing the + * GF(2^8) multiplication involved in the MDS matrix multiply; by looking + * things up in these tables we reduce the matrix multiply to four lookups + * and three XORs. Semi-formally, the definition of these tables is: + * mds[0][i] = MDS (q1[i] 0 0 0)^T mds[1][i] = MDS (0 q0[i] 0 0)^T + * mds[2][i] = MDS (0 0 q1[i] 0)^T mds[3][i] = MDS (0 0 0 q0[i])^T + * where ^T means "transpose", the matrix multiply is performed in GF(2^8) + * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described + * by Schneier et al, and I'm casually glossing over the byte/word + * conversion issues. */ + +static const u32 mds[4][256] = { + {0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, + 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, + 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, + 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, + 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, + 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, + 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, + 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, + 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, + 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, + 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, + 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, + 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, + 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, + 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, + 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, + 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, + 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, + 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, + 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, + 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, + 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, + 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, + 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, + 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, + 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, + 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, + 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, + 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, + 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, + 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, + 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, + 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, + 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, + 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, + 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, + 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, + 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, + 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, + 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, + 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, + 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, + 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91}, + + {0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, + 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, + 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, + 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, + 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, + 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, + 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, + 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, + 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, + 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, + 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, + 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, + 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, + 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, + 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, + 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, + 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, + 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, + 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, + 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, + 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, + 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, + 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, + 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, + 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, + 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, + 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, + 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, + 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, + 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, + 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, + 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, + 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, + 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, + 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, + 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, + 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, + 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, + 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, + 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, + 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, + 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, + 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8}, + + {0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, + 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, + 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, + 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, + 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, + 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, + 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, + 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, + 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, + 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, + 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, + 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, + 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, + 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, + 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, + 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, + 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, + 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, + 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, + 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, + 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, + 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, + 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, + 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, + 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, + 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, + 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, + 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, + 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, + 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, + 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, + 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, + 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, + 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, + 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, + 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, + 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, + 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, + 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, + 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, + 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, + 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, + 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF}, + + {0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, + 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, + 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, + 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, + 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, + 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, + 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, + 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, + 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, + 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, + 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, + 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, + 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, + 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, + 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, + 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, + 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, + 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, + 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, + 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, + 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, + 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, + 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, + 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, + 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, + 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, + 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, + 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, + 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, + 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, + 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, + 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, + 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, + 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, + 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, + 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, + 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, + 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, + 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, + 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, + 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, + 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, + 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8} +}; + +/* The exp_to_poly and poly_to_exp tables are used to perform efficient + * operations in GF(2^8) represented as GF(2)[x]/w(x) where + * w(x)=x^8+x^6+x^3+x^2+1. We care about doing that because it's part of the + * definition of the RS matrix in the key schedule. Elements of that field + * are polynomials of degree not greater than 7 and all coefficients 0 or 1, + * which can be represented naturally by bytes (just substitute x=2). In that + * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8) + * multiplication is inefficient without hardware support. To multiply + * faster, I make use of the fact x is a generator for the nonzero elements, + * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for + * some n in 0..254. Note that that caret is exponentiation in GF(2^8), + * *not* polynomial notation. So if I want to compute pq where p and q are + * in GF(2^8), I can just say: + * 1. if p=0 or q=0 then pq=0 + * 2. otherwise, find m and n such that p=x^m and q=x^n + * 3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq + * The translations in steps 2 and 3 are looked up in the tables + * poly_to_exp (for step 2) and exp_to_poly (for step 3). To see this + * in action, look at the CALC_S macro. As additional wrinkles, note that + * one of my operands is always a constant, so the poly_to_exp lookup on it + * is done in advance; I included the original values in the comments so + * readers can have some chance of recognizing that this *is* the RS matrix + * from the Twofish paper. I've only included the table entries I actually + * need; I never do a lookup on a variable input of zero and the biggest + * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll + * never sum to more than 491. I'm repeating part of the exp_to_poly table + * so that I don't have to do mod-255 reduction in the exponent arithmetic. + * Since I know my constant operands are never zero, I only have to worry + * about zero values in the variable operand, and I do it with a simple + * conditional branch. I know conditionals are expensive, but I couldn't + * see a non-horrible way of avoiding them, and I did manage to group the + * statements so that each if covers four group multiplications. */ + +static const byte poly_to_exp[255] = { + 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, + 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, + 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, + 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, + 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, + 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, + 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, + 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, + 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, + 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, + 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, + 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, + 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, + 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, + 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, + 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, + 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, + 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, + 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, + 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, + 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, + 0x85, 0xC8, 0xA1 +}; + +static const byte exp_to_poly[492] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, + 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, + 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, + 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, + 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, + 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, + 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, + 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, + 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, + 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, + 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, + 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, + 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, + 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, + 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, + 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, + 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, + 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, + 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, + 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, + 0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, + 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, + 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, + 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, + 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, + 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, + 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, + 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, + 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, + 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, + 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, + 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, + 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, + 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, + 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, + 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, + 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, + 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, + 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, + 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB +}; + + +/* The table constants are indices of + * S-box entries, preprocessed through q0 and q1. */ +static byte calc_sb_tbl[512] = { + 0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4, + 0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8, + 0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B, + 0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B, + 0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD, + 0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1, + 0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B, + 0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F, + 0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B, + 0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D, + 0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E, + 0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5, + 0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14, + 0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3, + 0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54, + 0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51, + 0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A, + 0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96, + 0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10, + 0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C, + 0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7, + 0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70, + 0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB, + 0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8, + 0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF, + 0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC, + 0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF, + 0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2, + 0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82, + 0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9, + 0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97, + 0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17, + 0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D, + 0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3, + 0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C, + 0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E, + 0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F, + 0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49, + 0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21, + 0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9, + 0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD, + 0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01, + 0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F, + 0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48, + 0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E, + 0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19, + 0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57, + 0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64, + 0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE, + 0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5, + 0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44, + 0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69, + 0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15, + 0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E, + 0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34, + 0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC, + 0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B, + 0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB, + 0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52, + 0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9, + 0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4, + 0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2, + 0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56, + 0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91 +}; +/* Macro to perform one column of the RS matrix multiplication. The + * parameters a, b, c, and d are the four bytes of output; i is the index + * of the key bytes, and w, x, y, and z, are the column of constants from + * the RS matrix, preprocessed through the poly_to_exp table. */ + +#define CALC_S(a, b, c, d, i, w, x, y, z) \ + if (key[i]) { \ + tmp = poly_to_exp[key[i] - 1]; \ + (a) ^= exp_to_poly[tmp + (w)]; \ + (b) ^= exp_to_poly[tmp + (x)]; \ + (c) ^= exp_to_poly[tmp + (y)]; \ + (d) ^= exp_to_poly[tmp + (z)]; \ + } + +/* Macros to calculate the key-dependent S-boxes for a 128-bit key using + * the S vector from CALC_S. CALC_SB_2 computes a single entry in all + * four S-boxes, where i is the index of the entry to compute, and a and b + * are the index numbers preprocessed through the q0 and q1 tables + * respectively. CALC_SB is simply a convenience to make the code shorter; + * it calls CALC_SB_2 four times with consecutive indices from i to i+3, + * using the remaining parameters two by two. */ + +#define CALC_SB_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \ + ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \ + ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \ + ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh] + +#define CALC_SB(i, a, b, c, d, e, f, g, h) \ + CALC_SB_2 (i, a, b); CALC_SB_2 ((i)+1, c, d); \ + CALC_SB_2 ((i)+2, e, f); CALC_SB_2 ((i)+3, g, h) + +/* Macros exactly like CALC_SB and CALC_SB_2, but for 256-bit keys. */ + +#define CALC_SB256_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \ + ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \ + ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \ + ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp]; + +#define CALC_SB256(i, a, b, c, d, e, f, g, h) \ + CALC_SB256_2 (i, a, b); CALC_SB256_2 ((i)+1, c, d); \ + CALC_SB256_2 ((i)+2, e, f); CALC_SB256_2 ((i)+3, g, h) + +/* Macros to calculate the whitening and round subkeys. CALC_K_2 computes the + * last two stages of the h() function for a given index (either 2i or 2i+1). + * a, b, c, and d are the four bytes going into the last two stages. For + * 128-bit keys, this is the entire h() function and a and c are the index + * preprocessed through q0 and q1 respectively; for longer keys they are the + * output of previous stages. j is the index of the first key byte to use. + * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 + * twice, doing the Pseudo-Hadamard Transform, and doing the necessary + * rotations. Its parameters are: a, the array to write the results into, + * j, the index of the first output entry, k and l, the preprocessed indices + * for index 2i, and m and n, the preprocessed indices for index 2i+1. + * CALC_K256_2 expands CALC_K_2 to handle 256-bit keys, by doing two + * additional lookup-and-XOR stages. The parameters a and b are the index + * preprocessed through q0 and q1 respectively; j is the index of the first + * key byte to use. CALC_K256 is identical to CALC_K but for using the + * CALC_K256_2 macro instead of CALC_K_2. */ + +#define CALC_K_2(a, b, c, d, j) \ + mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \ + ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \ + ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \ + ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]] + +#define CALC_K(a, j, k, l, m, n) \ + x = CALC_K_2 (k, l, k, l, 0); \ + y = CALC_K_2 (m, n, m, n, 4); \ + y = (y << 8) + (y >> 24); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = (y << 9) + (y >> 23) + +#define CALC_K256_2(a, b, j) \ + CALC_K_2 (q0[q1[b ^ key[(j) + 24]] ^ key[(j) + 16]], \ + q1[q1[a ^ key[(j) + 25]] ^ key[(j) + 17]], \ + q0[q0[a ^ key[(j) + 26]] ^ key[(j) + 18]], \ + q1[q0[b ^ key[(j) + 27]] ^ key[(j) + 19]], j) + +#define CALC_K256(a, j, k, l, m, n) \ + x = CALC_K256_2 (k, l, 0); \ + y = CALC_K256_2 (m, n, 4); \ + y = (y << 8) + (y >> 24); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = (y << 9) + (y >> 23) + + + +/* Perform the key setup. Note that this works only with 128- and 256-bit + * keys, despite the API that looks like it might support other sizes. */ + +static gcry_err_code_t +do_twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen) +{ + int i, j, k; + + /* Temporaries for CALC_K. */ + u32 x, y; + + /* The S vector used to key the S-boxes, split up into individual bytes. + * 128-bit keys use only sa through sh; 256-bit use all of them. */ + byte sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0; + byte si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0; + + /* Temporary for CALC_S. */ + byte tmp; + + /* Flags for self-test. */ + static int initialized = 0; + static const char *selftest_failed=0; + + /* Check key length. */ + if( ( ( keylen - 16 ) | 16 ) != 16 ) + return GPG_ERR_INV_KEYLEN; + + /* Do self-test if necessary. */ + if (!initialized) + { + initialized = 1; + selftest_failed = selftest (); + if( selftest_failed ) + log_error("%s\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + /* Compute the first two words of the S vector. The magic numbers are + * the entries of the RS matrix, preprocessed through poly_to_exp. The + * numbers in the comments are the original (polynomial form) matrix + * entries. */ + CALC_S (sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + CALC_S (se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + + if (keylen == 32) /* 256-bit key */ + { + /* Calculate the remaining two words of the S vector */ + CALC_S (si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + CALC_S (sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + + /* Compute the S-boxes. */ + for(i=j=0,k=1; i < 256; i++, j += 2, k += 2 ) + { + CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } + else + { + /* Compute the S-boxes. */ + for(i=j=0,k=1; i < 256; i++, j += 2, k += 2 ) + { + CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } + + return 0; +} + +static gcry_err_code_t +twofish_setkey (void *context, const byte *key, unsigned int keylen) +{ + TWOFISH_context *ctx = context; + int rc = do_twofish_setkey (ctx, key, keylen); + _gcry_burn_stack (23+6*sizeof(void*)); + return rc; +} + + + +/* Macros to compute the g() function in the encryption and decryption + * rounds. G1 is the straight g() function; G2 includes the 8-bit + * rotation for the high 32-bit word. */ + +#define G1(a) \ + (ctx->s[0][(a) & 0xFF]) ^ (ctx->s[1][((a) >> 8) & 0xFF]) \ + ^ (ctx->s[2][((a) >> 16) & 0xFF]) ^ (ctx->s[3][(a) >> 24]) + +#define G2(b) \ + (ctx->s[1][(b) & 0xFF]) ^ (ctx->s[2][((b) >> 8) & 0xFF]) \ + ^ (ctx->s[3][((b) >> 16) & 0xFF]) ^ (ctx->s[0][(b) >> 24]) + +/* Encryption and decryption Feistel rounds. Each one calls the two g() + * macros, does the PHT, and performs the XOR and the appropriate bit + * rotations. The parameters are the round number (used to select subkeys), + * and the four 32-bit chunks of the text. */ + +#define ENCROUND(n, a, b, c, d) \ + x = G1 (a); y = G2 (b); \ + x += y; y += x + ctx->k[2 * (n) + 1]; \ + (c) ^= x + ctx->k[2 * (n)]; \ + (c) = ((c) >> 1) + ((c) << 31); \ + (d) = (((d) << 1)+((d) >> 31)) ^ y + +#define DECROUND(n, a, b, c, d) \ + x = G1 (a); y = G2 (b); \ + x += y; y += x; \ + (d) ^= y + ctx->k[2 * (n) + 1]; \ + (d) = ((d) >> 1) + ((d) << 31); \ + (c) = (((c) << 1)+((c) >> 31)); \ + (c) ^= (x + ctx->k[2 * (n)]) + +/* Encryption and decryption cycles; each one is simply two Feistel rounds + * with the 32-bit chunks re-ordered to simulate the "swap" */ + +#define ENCCYCLE(n) \ + ENCROUND (2 * (n), a, b, c, d); \ + ENCROUND (2 * (n) + 1, c, d, a, b) + +#define DECCYCLE(n) \ + DECROUND (2 * (n) + 1, c, d, a, b); \ + DECROUND (2 * (n), a, b, c, d) + +/* Macros to convert the input and output bytes into 32-bit words, + * and simultaneously perform the whitening step. INPACK packs word + * number n into the variable named by x, using whitening subkey number m. + * OUTUNPACK unpacks word number n from the variable named by x, using + * whitening subkey number m. */ + +#define INPACK(n, x, m) \ + x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ + ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] + +#define OUTUNPACK(n, x, m) \ + x ^= ctx->w[m]; \ + out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ + out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 + +/* Encrypt one block. in and out may be the same. */ + +static void +do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) +{ + /* The four 32-bit chunks of the text. */ + u32 a, b, c, d; + + /* Temporaries used by the round function. */ + u32 x, y; + + /* Input whitening and packing. */ + INPACK (0, a, 0); + INPACK (1, b, 1); + INPACK (2, c, 2); + INPACK (3, d, 3); + + /* Encryption Feistel cycles. */ + ENCCYCLE (0); + ENCCYCLE (1); + ENCCYCLE (2); + ENCCYCLE (3); + ENCCYCLE (4); + ENCCYCLE (5); + ENCCYCLE (6); + ENCCYCLE (7); + + /* Output whitening and unpacking. */ + OUTUNPACK (0, c, 4); + OUTUNPACK (1, d, 5); + OUTUNPACK (2, a, 6); + OUTUNPACK (3, b, 7); +} + +static void +twofish_encrypt (void *context, byte *out, const byte *in) +{ + TWOFISH_context *ctx = context; + do_twofish_encrypt (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + + +/* Decrypt one block. in and out may be the same. */ + +static void +do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) +{ + /* The four 32-bit chunks of the text. */ + u32 a, b, c, d; + + /* Temporaries used by the round function. */ + u32 x, y; + + /* Input whitening and packing. */ + INPACK (0, c, 4); + INPACK (1, d, 5); + INPACK (2, a, 6); + INPACK (3, b, 7); + + /* Encryption Feistel cycles. */ + DECCYCLE (7); + DECCYCLE (6); + DECCYCLE (5); + DECCYCLE (4); + DECCYCLE (3); + DECCYCLE (2); + DECCYCLE (1); + DECCYCLE (0); + + /* Output whitening and unpacking. */ + OUTUNPACK (0, a, 0); + OUTUNPACK (1, b, 1); + OUTUNPACK (2, c, 2); + OUTUNPACK (3, d, 3); +} + +static void +twofish_decrypt (void *context, byte *out, const byte *in) +{ + TWOFISH_context *ctx = context; + + do_twofish_decrypt (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + + +/* Test a single encryption and decryption with each key size. */ + + +/* More complete test program. This does 1000 encryptions and decryptions + * with each of 250 128-bit keys and 2000 encryptions and decryptions with + * each of 125 256-bit keys, using a feedback scheme similar to a Feistel + * cipher, so as to be sure of testing all the table entries pretty + * thoroughly. We keep changing the keys so as to get a more meaningful + * performance number, since the key setup is non-trivial for Twofish. */ + +#ifdef TEST + + +int +main() +{ + TWOFISH_context ctx; /* Expanded key. */ + int i, j; /* Loop counters. */ + + const char *encrypt_msg; /* Message to print regarding encryption test; + * the printf is done outside the loop to avoid + * stuffing up the timing. */ + clock_t timer; /* For computing elapsed time. */ + + /* Test buffer. */ + byte buffer[4][16] = { + {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, + {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, + 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, + {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, + 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} + }; + + /* Expected outputs for the million-operation test */ + static const byte test_encrypt[4][16] = { + {0xC8, 0x23, 0xB8, 0xB7, 0x6B, 0xFE, 0x91, 0x13, + 0x2F, 0xA7, 0x5E, 0xE6, 0x94, 0x77, 0x6F, 0x6B}, + {0x90, 0x36, 0xD8, 0x29, 0xD5, 0x96, 0xC2, 0x8E, + 0xE4, 0xFF, 0x76, 0xBC, 0xE5, 0x77, 0x88, 0x27}, + {0xB8, 0x78, 0x69, 0xAF, 0x42, 0x8B, 0x48, 0x64, + 0xF7, 0xE9, 0xF3, 0x9C, 0x42, 0x18, 0x7B, 0x73}, + {0x7A, 0x88, 0xFB, 0xEB, 0x90, 0xA4, 0xB4, 0xA8, + 0x43, 0xA3, 0x1D, 0xF1, 0x26, 0xC4, 0x53, 0x57} + }; + static const byte test_decrypt[4][16] = { + {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, + {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, + 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, + {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, + 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} + }; + + /* Start the timer ticking. */ + timer = clock (); + + /* Encryption test. */ + for (i = 0; i < 125; i++) + { + twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); + for (j = 0; j < 1000; j++) + twofish_encrypt (&ctx, buffer[2], buffer[2]); + twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); + for (j = 0; j < 1000; j++) + twofish_encrypt (&ctx, buffer[3], buffer[3]); + twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); + for (j = 0; j < 1000; j++) { + twofish_encrypt (&ctx, buffer[0], buffer[0]); + twofish_encrypt (&ctx, buffer[1], buffer[1]); + } + } + encrypt_msg = memcmp (buffer, test_encrypt, sizeof (test_encrypt)) ? + "encryption failure!\n" : "encryption OK!\n"; + + /* Decryption test. */ + for (i = 0; i < 125; i++) + { + twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); + for (j = 0; j < 1000; j++) { + twofish_decrypt (&ctx, buffer[0], buffer[0]); + twofish_decrypt (&ctx, buffer[1], buffer[1]); + } + twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); + for (j = 0; j < 1000; j++) + twofish_decrypt (&ctx, buffer[3], buffer[3]); + twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); + for (j = 0; j < 1000; j++) + twofish_decrypt (&ctx, buffer[2], buffer[2]); + } + + /* Stop the timer, and print results. */ + timer = clock () - timer; + printf (encrypt_msg); + printf (memcmp (buffer, test_decrypt, sizeof (test_decrypt)) ? + "decryption failure!\n" : "decryption OK!\n"); + printf ("elapsed time: %.1f s.\n", (float) timer / CLOCKS_PER_SEC); + + return 0; +} + +#endif /* TEST */ + + + +gcry_cipher_spec_t _gcry_cipher_spec_twofish = + { + "TWOFISH", NULL, NULL, 16, 256, sizeof (TWOFISH_context), + twofish_setkey, twofish_encrypt, twofish_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_twofish", +#endif + }; + +gcry_cipher_spec_t _gcry_cipher_spec_twofish128 = + { + "TWOFISH128", NULL, NULL, 16, 128, sizeof (TWOFISH_context), + twofish_setkey, twofish_encrypt, twofish_decrypt + , +#ifdef GRUB_UTIL + .modname = "gcry_twofish", +#endif + }; + + +GRUB_MOD_INIT(gcry_twofish) +{ + grub_cipher_register (&_gcry_cipher_spec_twofish); + grub_cipher_register (&_gcry_cipher_spec_twofish128); +} + +GRUB_MOD_FINI(gcry_twofish) +{ + grub_cipher_unregister (&_gcry_cipher_spec_twofish); + grub_cipher_unregister (&_gcry_cipher_spec_twofish128); +} diff --git a/grub-core/lib/libgcrypt-grub/cipher/types.h b/grub-core/lib/libgcrypt-grub/cipher/types.h new file mode 100644 index 0000000..2ec78b6 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/types.h @@ -0,0 +1,2 @@ +#include <grub/types.h> +#include <cipher_wrap.h> diff --git a/grub-core/lib/libgcrypt-grub/cipher/whirlpool.c b/grub-core/lib/libgcrypt-grub/cipher/whirlpool.c new file mode 100644 index 0000000..f2a463d --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/cipher/whirlpool.c @@ -0,0 +1,1422 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +#include <grub/dl.h> +GRUB_MOD_LICENSE ("GPLv3+"); +/* whirlpool.c - Whirlpool hashing algorithm + * Copyright (C) 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + +/* This is an implementation of the Whirlpool hashing algorithm, which + has been developed by Vincent Rijmen and Paulo S. L. M. Barreto; + it's homepage is located at: + http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html. + + The S-Boxes and the structure of the main transformation function, + which implements an optimized version of the algorithm, is taken + from the reference implementation available from + http://planeta.terra.com.br/informatica/paulobarreto/whirlpool.zip. */ + + +#include "types.h" +#include "g10lib.h" +#include "cipher.h" + +#include "bithelp.h" + +/* Size of a whirlpool block (in bytes). */ +#define BLOCK_SIZE 64 + +/* Number of rounds. */ +#define R 10 + + + +/* Types. */ +typedef u64 whirlpool_block_t[BLOCK_SIZE / 8]; + +typedef struct { + whirlpool_block_t hash_state; + unsigned char buffer[BLOCK_SIZE]; + size_t count; + unsigned char length[32]; +} whirlpool_context_t; + + + +/* Macros. */ + +/* Convert the the buffer BUFFER into a block BLOCK, using I as + counter. */ +#define buffer_to_block(buffer, block, i) \ + for (i = 0; i < 8; i++) \ + (block)[i] = ((u64) (0 \ + | (((u64) (buffer)[i * 8 + 0]) << 56) \ + | (((u64) (buffer)[i * 8 + 1]) << 48) \ + | (((u64) (buffer)[i * 8 + 2]) << 40) \ + | (((u64) (buffer)[i * 8 + 3]) << 32) \ + | (((u64) (buffer)[i * 8 + 4]) << 24) \ + | (((u64) (buffer)[i * 8 + 5]) << 16) \ + | (((u64) (buffer)[i * 8 + 6]) << 8) \ + | (((u64) (buffer)[i * 8 + 7]) << 0))); + +/* Convert the block BLOCK into a buffer BUFFER, using I as + counter. */ +#define block_to_buffer(buffer, block, i) \ + for (i = 0; i < 8; i++) \ + { \ + (buffer)[i * 8 + 0] = (block[i] >> 56) & 0xFF; \ + (buffer)[i * 8 + 1] = (block[i] >> 48) & 0xFF; \ + (buffer)[i * 8 + 2] = (block[i] >> 40) & 0xFF; \ + (buffer)[i * 8 + 3] = (block[i] >> 32) & 0xFF; \ + (buffer)[i * 8 + 4] = (block[i] >> 24) & 0xFF; \ + (buffer)[i * 8 + 5] = (block[i] >> 16) & 0xFF; \ + (buffer)[i * 8 + 6] = (block[i] >> 8) & 0xFF; \ + (buffer)[i * 8 + 7] = (block[i] >> 0) & 0xFF; \ + } + +/* Copy the block BLOCK_SRC to BLOCK_DST, using I as counter. */ +#define block_copy(block_dst, block_src, i) \ + for (i = 0; i < 8; i++) \ + block_dst[i] = block_src[i]; + +/* XOR the block BLOCK_SRC into BLOCK_DST, using I as counter. */ +#define block_xor(block_dst, block_src, i) \ + for (i = 0; i < 8; i++) \ + block_dst[i] ^= block_src[i]; + + + +/* Round constants. */ +static const u64 rc[R] = + { + U64_C (0x1823c6e887b8014f), + U64_C (0x36a6d2f5796f9152), + U64_C (0x60bc9b8ea30c7b35), + U64_C (0x1de0d7c22e4bfe57), + U64_C (0x157737e59ff04ada), + U64_C (0x58c9290ab1a06b85), + U64_C (0xbd5d10f4cb3e0567), + U64_C (0xe427418ba77d95d8), + U64_C (0xfbee7c66dd17479e), + U64_C (0xca2dbf07ad5a8333), + }; + + + +/* Main lookup boxes. */ +static const u64 C0[256] = + { + U64_C (0x18186018c07830d8), U64_C (0x23238c2305af4626), + U64_C (0xc6c63fc67ef991b8), U64_C (0xe8e887e8136fcdfb), + U64_C (0x878726874ca113cb), U64_C (0xb8b8dab8a9626d11), + U64_C (0x0101040108050209), U64_C (0x4f4f214f426e9e0d), + U64_C (0x3636d836adee6c9b), U64_C (0xa6a6a2a6590451ff), + U64_C (0xd2d26fd2debdb90c), U64_C (0xf5f5f3f5fb06f70e), + U64_C (0x7979f979ef80f296), U64_C (0x6f6fa16f5fcede30), + U64_C (0x91917e91fcef3f6d), U64_C (0x52525552aa07a4f8), + U64_C (0x60609d6027fdc047), U64_C (0xbcbccabc89766535), + U64_C (0x9b9b569baccd2b37), U64_C (0x8e8e028e048c018a), + U64_C (0xa3a3b6a371155bd2), U64_C (0x0c0c300c603c186c), + U64_C (0x7b7bf17bff8af684), U64_C (0x3535d435b5e16a80), + U64_C (0x1d1d741de8693af5), U64_C (0xe0e0a7e05347ddb3), + U64_C (0xd7d77bd7f6acb321), U64_C (0xc2c22fc25eed999c), + U64_C (0x2e2eb82e6d965c43), U64_C (0x4b4b314b627a9629), + U64_C (0xfefedffea321e15d), U64_C (0x575741578216aed5), + U64_C (0x15155415a8412abd), U64_C (0x7777c1779fb6eee8), + U64_C (0x3737dc37a5eb6e92), U64_C (0xe5e5b3e57b56d79e), + U64_C (0x9f9f469f8cd92313), U64_C (0xf0f0e7f0d317fd23), + U64_C (0x4a4a354a6a7f9420), U64_C (0xdada4fda9e95a944), + U64_C (0x58587d58fa25b0a2), U64_C (0xc9c903c906ca8fcf), + U64_C (0x2929a429558d527c), U64_C (0x0a0a280a5022145a), + U64_C (0xb1b1feb1e14f7f50), U64_C (0xa0a0baa0691a5dc9), + U64_C (0x6b6bb16b7fdad614), U64_C (0x85852e855cab17d9), + U64_C (0xbdbdcebd8173673c), U64_C (0x5d5d695dd234ba8f), + U64_C (0x1010401080502090), U64_C (0xf4f4f7f4f303f507), + U64_C (0xcbcb0bcb16c08bdd), U64_C (0x3e3ef83eedc67cd3), + U64_C (0x0505140528110a2d), U64_C (0x676781671fe6ce78), + U64_C (0xe4e4b7e47353d597), U64_C (0x27279c2725bb4e02), + U64_C (0x4141194132588273), U64_C (0x8b8b168b2c9d0ba7), + U64_C (0xa7a7a6a7510153f6), U64_C (0x7d7de97dcf94fab2), + U64_C (0x95956e95dcfb3749), U64_C (0xd8d847d88e9fad56), + U64_C (0xfbfbcbfb8b30eb70), U64_C (0xeeee9fee2371c1cd), + U64_C (0x7c7ced7cc791f8bb), U64_C (0x6666856617e3cc71), + U64_C (0xdddd53dda68ea77b), U64_C (0x17175c17b84b2eaf), + U64_C (0x4747014702468e45), U64_C (0x9e9e429e84dc211a), + U64_C (0xcaca0fca1ec589d4), U64_C (0x2d2db42d75995a58), + U64_C (0xbfbfc6bf9179632e), U64_C (0x07071c07381b0e3f), + U64_C (0xadad8ead012347ac), U64_C (0x5a5a755aea2fb4b0), + U64_C (0x838336836cb51bef), U64_C (0x3333cc3385ff66b6), + U64_C (0x636391633ff2c65c), U64_C (0x02020802100a0412), + U64_C (0xaaaa92aa39384993), U64_C (0x7171d971afa8e2de), + U64_C (0xc8c807c80ecf8dc6), U64_C (0x19196419c87d32d1), + U64_C (0x494939497270923b), U64_C (0xd9d943d9869aaf5f), + U64_C (0xf2f2eff2c31df931), U64_C (0xe3e3abe34b48dba8), + U64_C (0x5b5b715be22ab6b9), U64_C (0x88881a8834920dbc), + U64_C (0x9a9a529aa4c8293e), U64_C (0x262698262dbe4c0b), + U64_C (0x3232c8328dfa64bf), U64_C (0xb0b0fab0e94a7d59), + U64_C (0xe9e983e91b6acff2), U64_C (0x0f0f3c0f78331e77), + U64_C (0xd5d573d5e6a6b733), U64_C (0x80803a8074ba1df4), + U64_C (0xbebec2be997c6127), U64_C (0xcdcd13cd26de87eb), + U64_C (0x3434d034bde46889), U64_C (0x48483d487a759032), + U64_C (0xffffdbffab24e354), U64_C (0x7a7af57af78ff48d), + U64_C (0x90907a90f4ea3d64), U64_C (0x5f5f615fc23ebe9d), + U64_C (0x202080201da0403d), U64_C (0x6868bd6867d5d00f), + U64_C (0x1a1a681ad07234ca), U64_C (0xaeae82ae192c41b7), + U64_C (0xb4b4eab4c95e757d), U64_C (0x54544d549a19a8ce), + U64_C (0x93937693ece53b7f), U64_C (0x222288220daa442f), + U64_C (0x64648d6407e9c863), U64_C (0xf1f1e3f1db12ff2a), + U64_C (0x7373d173bfa2e6cc), U64_C (0x12124812905a2482), + U64_C (0x40401d403a5d807a), U64_C (0x0808200840281048), + U64_C (0xc3c32bc356e89b95), U64_C (0xecec97ec337bc5df), + U64_C (0xdbdb4bdb9690ab4d), U64_C (0xa1a1bea1611f5fc0), + U64_C (0x8d8d0e8d1c830791), U64_C (0x3d3df43df5c97ac8), + U64_C (0x97976697ccf1335b), U64_C (0x0000000000000000), + U64_C (0xcfcf1bcf36d483f9), U64_C (0x2b2bac2b4587566e), + U64_C (0x7676c57697b3ece1), U64_C (0x8282328264b019e6), + U64_C (0xd6d67fd6fea9b128), U64_C (0x1b1b6c1bd87736c3), + U64_C (0xb5b5eeb5c15b7774), U64_C (0xafaf86af112943be), + U64_C (0x6a6ab56a77dfd41d), U64_C (0x50505d50ba0da0ea), + U64_C (0x45450945124c8a57), U64_C (0xf3f3ebf3cb18fb38), + U64_C (0x3030c0309df060ad), U64_C (0xefef9bef2b74c3c4), + U64_C (0x3f3ffc3fe5c37eda), U64_C (0x55554955921caac7), + U64_C (0xa2a2b2a2791059db), U64_C (0xeaea8fea0365c9e9), + U64_C (0x656589650fecca6a), U64_C (0xbabad2bab9686903), + U64_C (0x2f2fbc2f65935e4a), U64_C (0xc0c027c04ee79d8e), + U64_C (0xdede5fdebe81a160), U64_C (0x1c1c701ce06c38fc), + U64_C (0xfdfdd3fdbb2ee746), U64_C (0x4d4d294d52649a1f), + U64_C (0x92927292e4e03976), U64_C (0x7575c9758fbceafa), + U64_C (0x06061806301e0c36), U64_C (0x8a8a128a249809ae), + U64_C (0xb2b2f2b2f940794b), U64_C (0xe6e6bfe66359d185), + U64_C (0x0e0e380e70361c7e), U64_C (0x1f1f7c1ff8633ee7), + U64_C (0x6262956237f7c455), U64_C (0xd4d477d4eea3b53a), + U64_C (0xa8a89aa829324d81), U64_C (0x96966296c4f43152), + U64_C (0xf9f9c3f99b3aef62), U64_C (0xc5c533c566f697a3), + U64_C (0x2525942535b14a10), U64_C (0x59597959f220b2ab), + U64_C (0x84842a8454ae15d0), U64_C (0x7272d572b7a7e4c5), + U64_C (0x3939e439d5dd72ec), U64_C (0x4c4c2d4c5a619816), + U64_C (0x5e5e655eca3bbc94), U64_C (0x7878fd78e785f09f), + U64_C (0x3838e038ddd870e5), U64_C (0x8c8c0a8c14860598), + U64_C (0xd1d163d1c6b2bf17), U64_C (0xa5a5aea5410b57e4), + U64_C (0xe2e2afe2434dd9a1), U64_C (0x616199612ff8c24e), + U64_C (0xb3b3f6b3f1457b42), U64_C (0x2121842115a54234), + U64_C (0x9c9c4a9c94d62508), U64_C (0x1e1e781ef0663cee), + U64_C (0x4343114322528661), U64_C (0xc7c73bc776fc93b1), + U64_C (0xfcfcd7fcb32be54f), U64_C (0x0404100420140824), + U64_C (0x51515951b208a2e3), U64_C (0x99995e99bcc72f25), + U64_C (0x6d6da96d4fc4da22), U64_C (0x0d0d340d68391a65), + U64_C (0xfafacffa8335e979), U64_C (0xdfdf5bdfb684a369), + U64_C (0x7e7ee57ed79bfca9), U64_C (0x242490243db44819), + U64_C (0x3b3bec3bc5d776fe), U64_C (0xabab96ab313d4b9a), + U64_C (0xcece1fce3ed181f0), U64_C (0x1111441188552299), + U64_C (0x8f8f068f0c890383), U64_C (0x4e4e254e4a6b9c04), + U64_C (0xb7b7e6b7d1517366), U64_C (0xebeb8beb0b60cbe0), + U64_C (0x3c3cf03cfdcc78c1), U64_C (0x81813e817cbf1ffd), + U64_C (0x94946a94d4fe3540), U64_C (0xf7f7fbf7eb0cf31c), + U64_C (0xb9b9deb9a1676f18), U64_C (0x13134c13985f268b), + U64_C (0x2c2cb02c7d9c5851), U64_C (0xd3d36bd3d6b8bb05), + U64_C (0xe7e7bbe76b5cd38c), U64_C (0x6e6ea56e57cbdc39), + U64_C (0xc4c437c46ef395aa), U64_C (0x03030c03180f061b), + U64_C (0x565645568a13acdc), U64_C (0x44440d441a49885e), + U64_C (0x7f7fe17fdf9efea0), U64_C (0xa9a99ea921374f88), + U64_C (0x2a2aa82a4d825467), U64_C (0xbbbbd6bbb16d6b0a), + U64_C (0xc1c123c146e29f87), U64_C (0x53535153a202a6f1), + U64_C (0xdcdc57dcae8ba572), U64_C (0x0b0b2c0b58271653), + U64_C (0x9d9d4e9d9cd32701), U64_C (0x6c6cad6c47c1d82b), + U64_C (0x3131c43195f562a4), U64_C (0x7474cd7487b9e8f3), + U64_C (0xf6f6fff6e309f115), U64_C (0x464605460a438c4c), + U64_C (0xacac8aac092645a5), U64_C (0x89891e893c970fb5), + U64_C (0x14145014a04428b4), U64_C (0xe1e1a3e15b42dfba), + U64_C (0x16165816b04e2ca6), U64_C (0x3a3ae83acdd274f7), + U64_C (0x6969b9696fd0d206), U64_C (0x09092409482d1241), + U64_C (0x7070dd70a7ade0d7), U64_C (0xb6b6e2b6d954716f), + U64_C (0xd0d067d0ceb7bd1e), U64_C (0xeded93ed3b7ec7d6), + U64_C (0xcccc17cc2edb85e2), U64_C (0x424215422a578468), + U64_C (0x98985a98b4c22d2c), U64_C (0xa4a4aaa4490e55ed), + U64_C (0x2828a0285d885075), U64_C (0x5c5c6d5cda31b886), + U64_C (0xf8f8c7f8933fed6b), U64_C (0x8686228644a411c2), + }; + +static const u64 C1[256] = + { + U64_C (0xd818186018c07830), U64_C (0x2623238c2305af46), + U64_C (0xb8c6c63fc67ef991), U64_C (0xfbe8e887e8136fcd), + U64_C (0xcb878726874ca113), U64_C (0x11b8b8dab8a9626d), + U64_C (0x0901010401080502), U64_C (0x0d4f4f214f426e9e), + U64_C (0x9b3636d836adee6c), U64_C (0xffa6a6a2a6590451), + U64_C (0x0cd2d26fd2debdb9), U64_C (0x0ef5f5f3f5fb06f7), + U64_C (0x967979f979ef80f2), U64_C (0x306f6fa16f5fcede), + U64_C (0x6d91917e91fcef3f), U64_C (0xf852525552aa07a4), + U64_C (0x4760609d6027fdc0), U64_C (0x35bcbccabc897665), + U64_C (0x379b9b569baccd2b), U64_C (0x8a8e8e028e048c01), + U64_C (0xd2a3a3b6a371155b), U64_C (0x6c0c0c300c603c18), + U64_C (0x847b7bf17bff8af6), U64_C (0x803535d435b5e16a), + U64_C (0xf51d1d741de8693a), U64_C (0xb3e0e0a7e05347dd), + U64_C (0x21d7d77bd7f6acb3), U64_C (0x9cc2c22fc25eed99), + U64_C (0x432e2eb82e6d965c), U64_C (0x294b4b314b627a96), + U64_C (0x5dfefedffea321e1), U64_C (0xd5575741578216ae), + U64_C (0xbd15155415a8412a), U64_C (0xe87777c1779fb6ee), + U64_C (0x923737dc37a5eb6e), U64_C (0x9ee5e5b3e57b56d7), + U64_C (0x139f9f469f8cd923), U64_C (0x23f0f0e7f0d317fd), + U64_C (0x204a4a354a6a7f94), U64_C (0x44dada4fda9e95a9), + U64_C (0xa258587d58fa25b0), U64_C (0xcfc9c903c906ca8f), + U64_C (0x7c2929a429558d52), U64_C (0x5a0a0a280a502214), + U64_C (0x50b1b1feb1e14f7f), U64_C (0xc9a0a0baa0691a5d), + U64_C (0x146b6bb16b7fdad6), U64_C (0xd985852e855cab17), + U64_C (0x3cbdbdcebd817367), U64_C (0x8f5d5d695dd234ba), + U64_C (0x9010104010805020), U64_C (0x07f4f4f7f4f303f5), + U64_C (0xddcbcb0bcb16c08b), U64_C (0xd33e3ef83eedc67c), + U64_C (0x2d0505140528110a), U64_C (0x78676781671fe6ce), + U64_C (0x97e4e4b7e47353d5), U64_C (0x0227279c2725bb4e), + U64_C (0x7341411941325882), U64_C (0xa78b8b168b2c9d0b), + U64_C (0xf6a7a7a6a7510153), U64_C (0xb27d7de97dcf94fa), + U64_C (0x4995956e95dcfb37), U64_C (0x56d8d847d88e9fad), + U64_C (0x70fbfbcbfb8b30eb), U64_C (0xcdeeee9fee2371c1), + U64_C (0xbb7c7ced7cc791f8), U64_C (0x716666856617e3cc), + U64_C (0x7bdddd53dda68ea7), U64_C (0xaf17175c17b84b2e), + U64_C (0x454747014702468e), U64_C (0x1a9e9e429e84dc21), + U64_C (0xd4caca0fca1ec589), U64_C (0x582d2db42d75995a), + U64_C (0x2ebfbfc6bf917963), U64_C (0x3f07071c07381b0e), + U64_C (0xacadad8ead012347), U64_C (0xb05a5a755aea2fb4), + U64_C (0xef838336836cb51b), U64_C (0xb63333cc3385ff66), + U64_C (0x5c636391633ff2c6), U64_C (0x1202020802100a04), + U64_C (0x93aaaa92aa393849), U64_C (0xde7171d971afa8e2), + U64_C (0xc6c8c807c80ecf8d), U64_C (0xd119196419c87d32), + U64_C (0x3b49493949727092), U64_C (0x5fd9d943d9869aaf), + U64_C (0x31f2f2eff2c31df9), U64_C (0xa8e3e3abe34b48db), + U64_C (0xb95b5b715be22ab6), U64_C (0xbc88881a8834920d), + U64_C (0x3e9a9a529aa4c829), U64_C (0x0b262698262dbe4c), + U64_C (0xbf3232c8328dfa64), U64_C (0x59b0b0fab0e94a7d), + U64_C (0xf2e9e983e91b6acf), U64_C (0x770f0f3c0f78331e), + U64_C (0x33d5d573d5e6a6b7), U64_C (0xf480803a8074ba1d), + U64_C (0x27bebec2be997c61), U64_C (0xebcdcd13cd26de87), + U64_C (0x893434d034bde468), U64_C (0x3248483d487a7590), + U64_C (0x54ffffdbffab24e3), U64_C (0x8d7a7af57af78ff4), + U64_C (0x6490907a90f4ea3d), U64_C (0x9d5f5f615fc23ebe), + U64_C (0x3d202080201da040), U64_C (0x0f6868bd6867d5d0), + U64_C (0xca1a1a681ad07234), U64_C (0xb7aeae82ae192c41), + U64_C (0x7db4b4eab4c95e75), U64_C (0xce54544d549a19a8), + U64_C (0x7f93937693ece53b), U64_C (0x2f222288220daa44), + U64_C (0x6364648d6407e9c8), U64_C (0x2af1f1e3f1db12ff), + U64_C (0xcc7373d173bfa2e6), U64_C (0x8212124812905a24), + U64_C (0x7a40401d403a5d80), U64_C (0x4808082008402810), + U64_C (0x95c3c32bc356e89b), U64_C (0xdfecec97ec337bc5), + U64_C (0x4ddbdb4bdb9690ab), U64_C (0xc0a1a1bea1611f5f), + U64_C (0x918d8d0e8d1c8307), U64_C (0xc83d3df43df5c97a), + U64_C (0x5b97976697ccf133), U64_C (0x0000000000000000), + U64_C (0xf9cfcf1bcf36d483), U64_C (0x6e2b2bac2b458756), + U64_C (0xe17676c57697b3ec), U64_C (0xe68282328264b019), + U64_C (0x28d6d67fd6fea9b1), U64_C (0xc31b1b6c1bd87736), + U64_C (0x74b5b5eeb5c15b77), U64_C (0xbeafaf86af112943), + U64_C (0x1d6a6ab56a77dfd4), U64_C (0xea50505d50ba0da0), + U64_C (0x5745450945124c8a), U64_C (0x38f3f3ebf3cb18fb), + U64_C (0xad3030c0309df060), U64_C (0xc4efef9bef2b74c3), + U64_C (0xda3f3ffc3fe5c37e), U64_C (0xc755554955921caa), + U64_C (0xdba2a2b2a2791059), U64_C (0xe9eaea8fea0365c9), + U64_C (0x6a656589650fecca), U64_C (0x03babad2bab96869), + U64_C (0x4a2f2fbc2f65935e), U64_C (0x8ec0c027c04ee79d), + U64_C (0x60dede5fdebe81a1), U64_C (0xfc1c1c701ce06c38), + U64_C (0x46fdfdd3fdbb2ee7), U64_C (0x1f4d4d294d52649a), + U64_C (0x7692927292e4e039), U64_C (0xfa7575c9758fbcea), + U64_C (0x3606061806301e0c), U64_C (0xae8a8a128a249809), + U64_C (0x4bb2b2f2b2f94079), U64_C (0x85e6e6bfe66359d1), + U64_C (0x7e0e0e380e70361c), U64_C (0xe71f1f7c1ff8633e), + U64_C (0x556262956237f7c4), U64_C (0x3ad4d477d4eea3b5), + U64_C (0x81a8a89aa829324d), U64_C (0x5296966296c4f431), + U64_C (0x62f9f9c3f99b3aef), U64_C (0xa3c5c533c566f697), + U64_C (0x102525942535b14a), U64_C (0xab59597959f220b2), + U64_C (0xd084842a8454ae15), U64_C (0xc57272d572b7a7e4), + U64_C (0xec3939e439d5dd72), U64_C (0x164c4c2d4c5a6198), + U64_C (0x945e5e655eca3bbc), U64_C (0x9f7878fd78e785f0), + U64_C (0xe53838e038ddd870), U64_C (0x988c8c0a8c148605), + U64_C (0x17d1d163d1c6b2bf), U64_C (0xe4a5a5aea5410b57), + U64_C (0xa1e2e2afe2434dd9), U64_C (0x4e616199612ff8c2), + U64_C (0x42b3b3f6b3f1457b), U64_C (0x342121842115a542), + U64_C (0x089c9c4a9c94d625), U64_C (0xee1e1e781ef0663c), + U64_C (0x6143431143225286), U64_C (0xb1c7c73bc776fc93), + U64_C (0x4ffcfcd7fcb32be5), U64_C (0x2404041004201408), + U64_C (0xe351515951b208a2), U64_C (0x2599995e99bcc72f), + U64_C (0x226d6da96d4fc4da), U64_C (0x650d0d340d68391a), + U64_C (0x79fafacffa8335e9), U64_C (0x69dfdf5bdfb684a3), + U64_C (0xa97e7ee57ed79bfc), U64_C (0x19242490243db448), + U64_C (0xfe3b3bec3bc5d776), U64_C (0x9aabab96ab313d4b), + U64_C (0xf0cece1fce3ed181), U64_C (0x9911114411885522), + U64_C (0x838f8f068f0c8903), U64_C (0x044e4e254e4a6b9c), + U64_C (0x66b7b7e6b7d15173), U64_C (0xe0ebeb8beb0b60cb), + U64_C (0xc13c3cf03cfdcc78), U64_C (0xfd81813e817cbf1f), + U64_C (0x4094946a94d4fe35), U64_C (0x1cf7f7fbf7eb0cf3), + U64_C (0x18b9b9deb9a1676f), U64_C (0x8b13134c13985f26), + U64_C (0x512c2cb02c7d9c58), U64_C (0x05d3d36bd3d6b8bb), + U64_C (0x8ce7e7bbe76b5cd3), U64_C (0x396e6ea56e57cbdc), + U64_C (0xaac4c437c46ef395), U64_C (0x1b03030c03180f06), + U64_C (0xdc565645568a13ac), U64_C (0x5e44440d441a4988), + U64_C (0xa07f7fe17fdf9efe), U64_C (0x88a9a99ea921374f), + U64_C (0x672a2aa82a4d8254), U64_C (0x0abbbbd6bbb16d6b), + U64_C (0x87c1c123c146e29f), U64_C (0xf153535153a202a6), + U64_C (0x72dcdc57dcae8ba5), U64_C (0x530b0b2c0b582716), + U64_C (0x019d9d4e9d9cd327), U64_C (0x2b6c6cad6c47c1d8), + U64_C (0xa43131c43195f562), U64_C (0xf37474cd7487b9e8), + U64_C (0x15f6f6fff6e309f1), U64_C (0x4c464605460a438c), + U64_C (0xa5acac8aac092645), U64_C (0xb589891e893c970f), + U64_C (0xb414145014a04428), U64_C (0xbae1e1a3e15b42df), + U64_C (0xa616165816b04e2c), U64_C (0xf73a3ae83acdd274), + U64_C (0x066969b9696fd0d2), U64_C (0x4109092409482d12), + U64_C (0xd77070dd70a7ade0), U64_C (0x6fb6b6e2b6d95471), + U64_C (0x1ed0d067d0ceb7bd), U64_C (0xd6eded93ed3b7ec7), + U64_C (0xe2cccc17cc2edb85), U64_C (0x68424215422a5784), + U64_C (0x2c98985a98b4c22d), U64_C (0xeda4a4aaa4490e55), + U64_C (0x752828a0285d8850), U64_C (0x865c5c6d5cda31b8), + U64_C (0x6bf8f8c7f8933fed), U64_C (0xc28686228644a411), + }; + +static const u64 C2[256] = + { + U64_C (0x30d818186018c078), U64_C (0x462623238c2305af), + U64_C (0x91b8c6c63fc67ef9), U64_C (0xcdfbe8e887e8136f), + U64_C (0x13cb878726874ca1), U64_C (0x6d11b8b8dab8a962), + U64_C (0x0209010104010805), U64_C (0x9e0d4f4f214f426e), + U64_C (0x6c9b3636d836adee), U64_C (0x51ffa6a6a2a65904), + U64_C (0xb90cd2d26fd2debd), U64_C (0xf70ef5f5f3f5fb06), + U64_C (0xf2967979f979ef80), U64_C (0xde306f6fa16f5fce), + U64_C (0x3f6d91917e91fcef), U64_C (0xa4f852525552aa07), + U64_C (0xc04760609d6027fd), U64_C (0x6535bcbccabc8976), + U64_C (0x2b379b9b569baccd), U64_C (0x018a8e8e028e048c), + U64_C (0x5bd2a3a3b6a37115), U64_C (0x186c0c0c300c603c), + U64_C (0xf6847b7bf17bff8a), U64_C (0x6a803535d435b5e1), + U64_C (0x3af51d1d741de869), U64_C (0xddb3e0e0a7e05347), + U64_C (0xb321d7d77bd7f6ac), U64_C (0x999cc2c22fc25eed), + U64_C (0x5c432e2eb82e6d96), U64_C (0x96294b4b314b627a), + U64_C (0xe15dfefedffea321), U64_C (0xaed5575741578216), + U64_C (0x2abd15155415a841), U64_C (0xeee87777c1779fb6), + U64_C (0x6e923737dc37a5eb), U64_C (0xd79ee5e5b3e57b56), + U64_C (0x23139f9f469f8cd9), U64_C (0xfd23f0f0e7f0d317), + U64_C (0x94204a4a354a6a7f), U64_C (0xa944dada4fda9e95), + U64_C (0xb0a258587d58fa25), U64_C (0x8fcfc9c903c906ca), + U64_C (0x527c2929a429558d), U64_C (0x145a0a0a280a5022), + U64_C (0x7f50b1b1feb1e14f), U64_C (0x5dc9a0a0baa0691a), + U64_C (0xd6146b6bb16b7fda), U64_C (0x17d985852e855cab), + U64_C (0x673cbdbdcebd8173), U64_C (0xba8f5d5d695dd234), + U64_C (0x2090101040108050), U64_C (0xf507f4f4f7f4f303), + U64_C (0x8bddcbcb0bcb16c0), U64_C (0x7cd33e3ef83eedc6), + U64_C (0x0a2d050514052811), U64_C (0xce78676781671fe6), + U64_C (0xd597e4e4b7e47353), U64_C (0x4e0227279c2725bb), + U64_C (0x8273414119413258), U64_C (0x0ba78b8b168b2c9d), + U64_C (0x53f6a7a7a6a75101), U64_C (0xfab27d7de97dcf94), + U64_C (0x374995956e95dcfb), U64_C (0xad56d8d847d88e9f), + U64_C (0xeb70fbfbcbfb8b30), U64_C (0xc1cdeeee9fee2371), + U64_C (0xf8bb7c7ced7cc791), U64_C (0xcc716666856617e3), + U64_C (0xa77bdddd53dda68e), U64_C (0x2eaf17175c17b84b), + U64_C (0x8e45474701470246), U64_C (0x211a9e9e429e84dc), + U64_C (0x89d4caca0fca1ec5), U64_C (0x5a582d2db42d7599), + U64_C (0x632ebfbfc6bf9179), U64_C (0x0e3f07071c07381b), + U64_C (0x47acadad8ead0123), U64_C (0xb4b05a5a755aea2f), + U64_C (0x1bef838336836cb5), U64_C (0x66b63333cc3385ff), + U64_C (0xc65c636391633ff2), U64_C (0x041202020802100a), + U64_C (0x4993aaaa92aa3938), U64_C (0xe2de7171d971afa8), + U64_C (0x8dc6c8c807c80ecf), U64_C (0x32d119196419c87d), + U64_C (0x923b494939497270), U64_C (0xaf5fd9d943d9869a), + U64_C (0xf931f2f2eff2c31d), U64_C (0xdba8e3e3abe34b48), + U64_C (0xb6b95b5b715be22a), U64_C (0x0dbc88881a883492), + U64_C (0x293e9a9a529aa4c8), U64_C (0x4c0b262698262dbe), + U64_C (0x64bf3232c8328dfa), U64_C (0x7d59b0b0fab0e94a), + U64_C (0xcff2e9e983e91b6a), U64_C (0x1e770f0f3c0f7833), + U64_C (0xb733d5d573d5e6a6), U64_C (0x1df480803a8074ba), + U64_C (0x6127bebec2be997c), U64_C (0x87ebcdcd13cd26de), + U64_C (0x68893434d034bde4), U64_C (0x903248483d487a75), + U64_C (0xe354ffffdbffab24), U64_C (0xf48d7a7af57af78f), + U64_C (0x3d6490907a90f4ea), U64_C (0xbe9d5f5f615fc23e), + U64_C (0x403d202080201da0), U64_C (0xd00f6868bd6867d5), + U64_C (0x34ca1a1a681ad072), U64_C (0x41b7aeae82ae192c), + U64_C (0x757db4b4eab4c95e), U64_C (0xa8ce54544d549a19), + U64_C (0x3b7f93937693ece5), U64_C (0x442f222288220daa), + U64_C (0xc86364648d6407e9), U64_C (0xff2af1f1e3f1db12), + U64_C (0xe6cc7373d173bfa2), U64_C (0x248212124812905a), + U64_C (0x807a40401d403a5d), U64_C (0x1048080820084028), + U64_C (0x9b95c3c32bc356e8), U64_C (0xc5dfecec97ec337b), + U64_C (0xab4ddbdb4bdb9690), U64_C (0x5fc0a1a1bea1611f), + U64_C (0x07918d8d0e8d1c83), U64_C (0x7ac83d3df43df5c9), + U64_C (0x335b97976697ccf1), U64_C (0x0000000000000000), + U64_C (0x83f9cfcf1bcf36d4), U64_C (0x566e2b2bac2b4587), + U64_C (0xece17676c57697b3), U64_C (0x19e68282328264b0), + U64_C (0xb128d6d67fd6fea9), U64_C (0x36c31b1b6c1bd877), + U64_C (0x7774b5b5eeb5c15b), U64_C (0x43beafaf86af1129), + U64_C (0xd41d6a6ab56a77df), U64_C (0xa0ea50505d50ba0d), + U64_C (0x8a5745450945124c), U64_C (0xfb38f3f3ebf3cb18), + U64_C (0x60ad3030c0309df0), U64_C (0xc3c4efef9bef2b74), + U64_C (0x7eda3f3ffc3fe5c3), U64_C (0xaac755554955921c), + U64_C (0x59dba2a2b2a27910), U64_C (0xc9e9eaea8fea0365), + U64_C (0xca6a656589650fec), U64_C (0x6903babad2bab968), + U64_C (0x5e4a2f2fbc2f6593), U64_C (0x9d8ec0c027c04ee7), + U64_C (0xa160dede5fdebe81), U64_C (0x38fc1c1c701ce06c), + U64_C (0xe746fdfdd3fdbb2e), U64_C (0x9a1f4d4d294d5264), + U64_C (0x397692927292e4e0), U64_C (0xeafa7575c9758fbc), + U64_C (0x0c3606061806301e), U64_C (0x09ae8a8a128a2498), + U64_C (0x794bb2b2f2b2f940), U64_C (0xd185e6e6bfe66359), + U64_C (0x1c7e0e0e380e7036), U64_C (0x3ee71f1f7c1ff863), + U64_C (0xc4556262956237f7), U64_C (0xb53ad4d477d4eea3), + U64_C (0x4d81a8a89aa82932), U64_C (0x315296966296c4f4), + U64_C (0xef62f9f9c3f99b3a), U64_C (0x97a3c5c533c566f6), + U64_C (0x4a102525942535b1), U64_C (0xb2ab59597959f220), + U64_C (0x15d084842a8454ae), U64_C (0xe4c57272d572b7a7), + U64_C (0x72ec3939e439d5dd), U64_C (0x98164c4c2d4c5a61), + U64_C (0xbc945e5e655eca3b), U64_C (0xf09f7878fd78e785), + U64_C (0x70e53838e038ddd8), U64_C (0x05988c8c0a8c1486), + U64_C (0xbf17d1d163d1c6b2), U64_C (0x57e4a5a5aea5410b), + U64_C (0xd9a1e2e2afe2434d), U64_C (0xc24e616199612ff8), + U64_C (0x7b42b3b3f6b3f145), U64_C (0x42342121842115a5), + U64_C (0x25089c9c4a9c94d6), U64_C (0x3cee1e1e781ef066), + U64_C (0x8661434311432252), U64_C (0x93b1c7c73bc776fc), + U64_C (0xe54ffcfcd7fcb32b), U64_C (0x0824040410042014), + U64_C (0xa2e351515951b208), U64_C (0x2f2599995e99bcc7), + U64_C (0xda226d6da96d4fc4), U64_C (0x1a650d0d340d6839), + U64_C (0xe979fafacffa8335), U64_C (0xa369dfdf5bdfb684), + U64_C (0xfca97e7ee57ed79b), U64_C (0x4819242490243db4), + U64_C (0x76fe3b3bec3bc5d7), U64_C (0x4b9aabab96ab313d), + U64_C (0x81f0cece1fce3ed1), U64_C (0x2299111144118855), + U64_C (0x03838f8f068f0c89), U64_C (0x9c044e4e254e4a6b), + U64_C (0x7366b7b7e6b7d151), U64_C (0xcbe0ebeb8beb0b60), + U64_C (0x78c13c3cf03cfdcc), U64_C (0x1ffd81813e817cbf), + U64_C (0x354094946a94d4fe), U64_C (0xf31cf7f7fbf7eb0c), + U64_C (0x6f18b9b9deb9a167), U64_C (0x268b13134c13985f), + U64_C (0x58512c2cb02c7d9c), U64_C (0xbb05d3d36bd3d6b8), + U64_C (0xd38ce7e7bbe76b5c), U64_C (0xdc396e6ea56e57cb), + U64_C (0x95aac4c437c46ef3), U64_C (0x061b03030c03180f), + U64_C (0xacdc565645568a13), U64_C (0x885e44440d441a49), + U64_C (0xfea07f7fe17fdf9e), U64_C (0x4f88a9a99ea92137), + U64_C (0x54672a2aa82a4d82), U64_C (0x6b0abbbbd6bbb16d), + U64_C (0x9f87c1c123c146e2), U64_C (0xa6f153535153a202), + U64_C (0xa572dcdc57dcae8b), U64_C (0x16530b0b2c0b5827), + U64_C (0x27019d9d4e9d9cd3), U64_C (0xd82b6c6cad6c47c1), + U64_C (0x62a43131c43195f5), U64_C (0xe8f37474cd7487b9), + U64_C (0xf115f6f6fff6e309), U64_C (0x8c4c464605460a43), + U64_C (0x45a5acac8aac0926), U64_C (0x0fb589891e893c97), + U64_C (0x28b414145014a044), U64_C (0xdfbae1e1a3e15b42), + U64_C (0x2ca616165816b04e), U64_C (0x74f73a3ae83acdd2), + U64_C (0xd2066969b9696fd0), U64_C (0x124109092409482d), + U64_C (0xe0d77070dd70a7ad), U64_C (0x716fb6b6e2b6d954), + U64_C (0xbd1ed0d067d0ceb7), U64_C (0xc7d6eded93ed3b7e), + U64_C (0x85e2cccc17cc2edb), U64_C (0x8468424215422a57), + U64_C (0x2d2c98985a98b4c2), U64_C (0x55eda4a4aaa4490e), + U64_C (0x50752828a0285d88), U64_C (0xb8865c5c6d5cda31), + U64_C (0xed6bf8f8c7f8933f), U64_C (0x11c28686228644a4), + }; + +static const u64 C3[256] = + { + U64_C (0x7830d818186018c0), U64_C (0xaf462623238c2305), + U64_C (0xf991b8c6c63fc67e), U64_C (0x6fcdfbe8e887e813), + U64_C (0xa113cb878726874c), U64_C (0x626d11b8b8dab8a9), + U64_C (0x0502090101040108), U64_C (0x6e9e0d4f4f214f42), + U64_C (0xee6c9b3636d836ad), U64_C (0x0451ffa6a6a2a659), + U64_C (0xbdb90cd2d26fd2de), U64_C (0x06f70ef5f5f3f5fb), + U64_C (0x80f2967979f979ef), U64_C (0xcede306f6fa16f5f), + U64_C (0xef3f6d91917e91fc), U64_C (0x07a4f852525552aa), + U64_C (0xfdc04760609d6027), U64_C (0x766535bcbccabc89), + U64_C (0xcd2b379b9b569bac), U64_C (0x8c018a8e8e028e04), + U64_C (0x155bd2a3a3b6a371), U64_C (0x3c186c0c0c300c60), + U64_C (0x8af6847b7bf17bff), U64_C (0xe16a803535d435b5), + U64_C (0x693af51d1d741de8), U64_C (0x47ddb3e0e0a7e053), + U64_C (0xacb321d7d77bd7f6), U64_C (0xed999cc2c22fc25e), + U64_C (0x965c432e2eb82e6d), U64_C (0x7a96294b4b314b62), + U64_C (0x21e15dfefedffea3), U64_C (0x16aed55757415782), + U64_C (0x412abd15155415a8), U64_C (0xb6eee87777c1779f), + U64_C (0xeb6e923737dc37a5), U64_C (0x56d79ee5e5b3e57b), + U64_C (0xd923139f9f469f8c), U64_C (0x17fd23f0f0e7f0d3), + U64_C (0x7f94204a4a354a6a), U64_C (0x95a944dada4fda9e), + U64_C (0x25b0a258587d58fa), U64_C (0xca8fcfc9c903c906), + U64_C (0x8d527c2929a42955), U64_C (0x22145a0a0a280a50), + U64_C (0x4f7f50b1b1feb1e1), U64_C (0x1a5dc9a0a0baa069), + U64_C (0xdad6146b6bb16b7f), U64_C (0xab17d985852e855c), + U64_C (0x73673cbdbdcebd81), U64_C (0x34ba8f5d5d695dd2), + U64_C (0x5020901010401080), U64_C (0x03f507f4f4f7f4f3), + U64_C (0xc08bddcbcb0bcb16), U64_C (0xc67cd33e3ef83eed), + U64_C (0x110a2d0505140528), U64_C (0xe6ce78676781671f), + U64_C (0x53d597e4e4b7e473), U64_C (0xbb4e0227279c2725), + U64_C (0x5882734141194132), U64_C (0x9d0ba78b8b168b2c), + U64_C (0x0153f6a7a7a6a751), U64_C (0x94fab27d7de97dcf), + U64_C (0xfb374995956e95dc), U64_C (0x9fad56d8d847d88e), + U64_C (0x30eb70fbfbcbfb8b), U64_C (0x71c1cdeeee9fee23), + U64_C (0x91f8bb7c7ced7cc7), U64_C (0xe3cc716666856617), + U64_C (0x8ea77bdddd53dda6), U64_C (0x4b2eaf17175c17b8), + U64_C (0x468e454747014702), U64_C (0xdc211a9e9e429e84), + U64_C (0xc589d4caca0fca1e), U64_C (0x995a582d2db42d75), + U64_C (0x79632ebfbfc6bf91), U64_C (0x1b0e3f07071c0738), + U64_C (0x2347acadad8ead01), U64_C (0x2fb4b05a5a755aea), + U64_C (0xb51bef838336836c), U64_C (0xff66b63333cc3385), + U64_C (0xf2c65c636391633f), U64_C (0x0a04120202080210), + U64_C (0x384993aaaa92aa39), U64_C (0xa8e2de7171d971af), + U64_C (0xcf8dc6c8c807c80e), U64_C (0x7d32d119196419c8), + U64_C (0x70923b4949394972), U64_C (0x9aaf5fd9d943d986), + U64_C (0x1df931f2f2eff2c3), U64_C (0x48dba8e3e3abe34b), + U64_C (0x2ab6b95b5b715be2), U64_C (0x920dbc88881a8834), + U64_C (0xc8293e9a9a529aa4), U64_C (0xbe4c0b262698262d), + U64_C (0xfa64bf3232c8328d), U64_C (0x4a7d59b0b0fab0e9), + U64_C (0x6acff2e9e983e91b), U64_C (0x331e770f0f3c0f78), + U64_C (0xa6b733d5d573d5e6), U64_C (0xba1df480803a8074), + U64_C (0x7c6127bebec2be99), U64_C (0xde87ebcdcd13cd26), + U64_C (0xe468893434d034bd), U64_C (0x75903248483d487a), + U64_C (0x24e354ffffdbffab), U64_C (0x8ff48d7a7af57af7), + U64_C (0xea3d6490907a90f4), U64_C (0x3ebe9d5f5f615fc2), + U64_C (0xa0403d202080201d), U64_C (0xd5d00f6868bd6867), + U64_C (0x7234ca1a1a681ad0), U64_C (0x2c41b7aeae82ae19), + U64_C (0x5e757db4b4eab4c9), U64_C (0x19a8ce54544d549a), + U64_C (0xe53b7f93937693ec), U64_C (0xaa442f222288220d), + U64_C (0xe9c86364648d6407), U64_C (0x12ff2af1f1e3f1db), + U64_C (0xa2e6cc7373d173bf), U64_C (0x5a24821212481290), + U64_C (0x5d807a40401d403a), U64_C (0x2810480808200840), + U64_C (0xe89b95c3c32bc356), U64_C (0x7bc5dfecec97ec33), + U64_C (0x90ab4ddbdb4bdb96), U64_C (0x1f5fc0a1a1bea161), + U64_C (0x8307918d8d0e8d1c), U64_C (0xc97ac83d3df43df5), + U64_C (0xf1335b97976697cc), U64_C (0x0000000000000000), + U64_C (0xd483f9cfcf1bcf36), U64_C (0x87566e2b2bac2b45), + U64_C (0xb3ece17676c57697), U64_C (0xb019e68282328264), + U64_C (0xa9b128d6d67fd6fe), U64_C (0x7736c31b1b6c1bd8), + U64_C (0x5b7774b5b5eeb5c1), U64_C (0x2943beafaf86af11), + U64_C (0xdfd41d6a6ab56a77), U64_C (0x0da0ea50505d50ba), + U64_C (0x4c8a574545094512), U64_C (0x18fb38f3f3ebf3cb), + U64_C (0xf060ad3030c0309d), U64_C (0x74c3c4efef9bef2b), + U64_C (0xc37eda3f3ffc3fe5), U64_C (0x1caac75555495592), + U64_C (0x1059dba2a2b2a279), U64_C (0x65c9e9eaea8fea03), + U64_C (0xecca6a656589650f), U64_C (0x686903babad2bab9), + U64_C (0x935e4a2f2fbc2f65), U64_C (0xe79d8ec0c027c04e), + U64_C (0x81a160dede5fdebe), U64_C (0x6c38fc1c1c701ce0), + U64_C (0x2ee746fdfdd3fdbb), U64_C (0x649a1f4d4d294d52), + U64_C (0xe0397692927292e4), U64_C (0xbceafa7575c9758f), + U64_C (0x1e0c360606180630), U64_C (0x9809ae8a8a128a24), + U64_C (0x40794bb2b2f2b2f9), U64_C (0x59d185e6e6bfe663), + U64_C (0x361c7e0e0e380e70), U64_C (0x633ee71f1f7c1ff8), + U64_C (0xf7c4556262956237), U64_C (0xa3b53ad4d477d4ee), + U64_C (0x324d81a8a89aa829), U64_C (0xf4315296966296c4), + U64_C (0x3aef62f9f9c3f99b), U64_C (0xf697a3c5c533c566), + U64_C (0xb14a102525942535), U64_C (0x20b2ab59597959f2), + U64_C (0xae15d084842a8454), U64_C (0xa7e4c57272d572b7), + U64_C (0xdd72ec3939e439d5), U64_C (0x6198164c4c2d4c5a), + U64_C (0x3bbc945e5e655eca), U64_C (0x85f09f7878fd78e7), + U64_C (0xd870e53838e038dd), U64_C (0x8605988c8c0a8c14), + U64_C (0xb2bf17d1d163d1c6), U64_C (0x0b57e4a5a5aea541), + U64_C (0x4dd9a1e2e2afe243), U64_C (0xf8c24e616199612f), + U64_C (0x457b42b3b3f6b3f1), U64_C (0xa542342121842115), + U64_C (0xd625089c9c4a9c94), U64_C (0x663cee1e1e781ef0), + U64_C (0x5286614343114322), U64_C (0xfc93b1c7c73bc776), + U64_C (0x2be54ffcfcd7fcb3), U64_C (0x1408240404100420), + U64_C (0x08a2e351515951b2), U64_C (0xc72f2599995e99bc), + U64_C (0xc4da226d6da96d4f), U64_C (0x391a650d0d340d68), + U64_C (0x35e979fafacffa83), U64_C (0x84a369dfdf5bdfb6), + U64_C (0x9bfca97e7ee57ed7), U64_C (0xb44819242490243d), + U64_C (0xd776fe3b3bec3bc5), U64_C (0x3d4b9aabab96ab31), + U64_C (0xd181f0cece1fce3e), U64_C (0x5522991111441188), + U64_C (0x8903838f8f068f0c), U64_C (0x6b9c044e4e254e4a), + U64_C (0x517366b7b7e6b7d1), U64_C (0x60cbe0ebeb8beb0b), + U64_C (0xcc78c13c3cf03cfd), U64_C (0xbf1ffd81813e817c), + U64_C (0xfe354094946a94d4), U64_C (0x0cf31cf7f7fbf7eb), + U64_C (0x676f18b9b9deb9a1), U64_C (0x5f268b13134c1398), + U64_C (0x9c58512c2cb02c7d), U64_C (0xb8bb05d3d36bd3d6), + U64_C (0x5cd38ce7e7bbe76b), U64_C (0xcbdc396e6ea56e57), + U64_C (0xf395aac4c437c46e), U64_C (0x0f061b03030c0318), + U64_C (0x13acdc565645568a), U64_C (0x49885e44440d441a), + U64_C (0x9efea07f7fe17fdf), U64_C (0x374f88a9a99ea921), + U64_C (0x8254672a2aa82a4d), U64_C (0x6d6b0abbbbd6bbb1), + U64_C (0xe29f87c1c123c146), U64_C (0x02a6f153535153a2), + U64_C (0x8ba572dcdc57dcae), U64_C (0x2716530b0b2c0b58), + U64_C (0xd327019d9d4e9d9c), U64_C (0xc1d82b6c6cad6c47), + U64_C (0xf562a43131c43195), U64_C (0xb9e8f37474cd7487), + U64_C (0x09f115f6f6fff6e3), U64_C (0x438c4c464605460a), + U64_C (0x2645a5acac8aac09), U64_C (0x970fb589891e893c), + U64_C (0x4428b414145014a0), U64_C (0x42dfbae1e1a3e15b), + U64_C (0x4e2ca616165816b0), U64_C (0xd274f73a3ae83acd), + U64_C (0xd0d2066969b9696f), U64_C (0x2d12410909240948), + U64_C (0xade0d77070dd70a7), U64_C (0x54716fb6b6e2b6d9), + U64_C (0xb7bd1ed0d067d0ce), U64_C (0x7ec7d6eded93ed3b), + U64_C (0xdb85e2cccc17cc2e), U64_C (0x578468424215422a), + U64_C (0xc22d2c98985a98b4), U64_C (0x0e55eda4a4aaa449), + U64_C (0x8850752828a0285d), U64_C (0x31b8865c5c6d5cda), + U64_C (0x3fed6bf8f8c7f893), U64_C (0xa411c28686228644), + }; + +static const u64 C4[256] = + { + U64_C (0xc07830d818186018), U64_C (0x05af462623238c23), + U64_C (0x7ef991b8c6c63fc6), U64_C (0x136fcdfbe8e887e8), + U64_C (0x4ca113cb87872687), U64_C (0xa9626d11b8b8dab8), + U64_C (0x0805020901010401), U64_C (0x426e9e0d4f4f214f), + U64_C (0xadee6c9b3636d836), U64_C (0x590451ffa6a6a2a6), + U64_C (0xdebdb90cd2d26fd2), U64_C (0xfb06f70ef5f5f3f5), + U64_C (0xef80f2967979f979), U64_C (0x5fcede306f6fa16f), + U64_C (0xfcef3f6d91917e91), U64_C (0xaa07a4f852525552), + U64_C (0x27fdc04760609d60), U64_C (0x89766535bcbccabc), + U64_C (0xaccd2b379b9b569b), U64_C (0x048c018a8e8e028e), + U64_C (0x71155bd2a3a3b6a3), U64_C (0x603c186c0c0c300c), + U64_C (0xff8af6847b7bf17b), U64_C (0xb5e16a803535d435), + U64_C (0xe8693af51d1d741d), U64_C (0x5347ddb3e0e0a7e0), + U64_C (0xf6acb321d7d77bd7), U64_C (0x5eed999cc2c22fc2), + U64_C (0x6d965c432e2eb82e), U64_C (0x627a96294b4b314b), + U64_C (0xa321e15dfefedffe), U64_C (0x8216aed557574157), + U64_C (0xa8412abd15155415), U64_C (0x9fb6eee87777c177), + U64_C (0xa5eb6e923737dc37), U64_C (0x7b56d79ee5e5b3e5), + U64_C (0x8cd923139f9f469f), U64_C (0xd317fd23f0f0e7f0), + U64_C (0x6a7f94204a4a354a), U64_C (0x9e95a944dada4fda), + U64_C (0xfa25b0a258587d58), U64_C (0x06ca8fcfc9c903c9), + U64_C (0x558d527c2929a429), U64_C (0x5022145a0a0a280a), + U64_C (0xe14f7f50b1b1feb1), U64_C (0x691a5dc9a0a0baa0), + U64_C (0x7fdad6146b6bb16b), U64_C (0x5cab17d985852e85), + U64_C (0x8173673cbdbdcebd), U64_C (0xd234ba8f5d5d695d), + U64_C (0x8050209010104010), U64_C (0xf303f507f4f4f7f4), + U64_C (0x16c08bddcbcb0bcb), U64_C (0xedc67cd33e3ef83e), + U64_C (0x28110a2d05051405), U64_C (0x1fe6ce7867678167), + U64_C (0x7353d597e4e4b7e4), U64_C (0x25bb4e0227279c27), + U64_C (0x3258827341411941), U64_C (0x2c9d0ba78b8b168b), + U64_C (0x510153f6a7a7a6a7), U64_C (0xcf94fab27d7de97d), + U64_C (0xdcfb374995956e95), U64_C (0x8e9fad56d8d847d8), + U64_C (0x8b30eb70fbfbcbfb), U64_C (0x2371c1cdeeee9fee), + U64_C (0xc791f8bb7c7ced7c), U64_C (0x17e3cc7166668566), + U64_C (0xa68ea77bdddd53dd), U64_C (0xb84b2eaf17175c17), + U64_C (0x02468e4547470147), U64_C (0x84dc211a9e9e429e), + U64_C (0x1ec589d4caca0fca), U64_C (0x75995a582d2db42d), + U64_C (0x9179632ebfbfc6bf), U64_C (0x381b0e3f07071c07), + U64_C (0x012347acadad8ead), U64_C (0xea2fb4b05a5a755a), + U64_C (0x6cb51bef83833683), U64_C (0x85ff66b63333cc33), + U64_C (0x3ff2c65c63639163), U64_C (0x100a041202020802), + U64_C (0x39384993aaaa92aa), U64_C (0xafa8e2de7171d971), + U64_C (0x0ecf8dc6c8c807c8), U64_C (0xc87d32d119196419), + U64_C (0x7270923b49493949), U64_C (0x869aaf5fd9d943d9), + U64_C (0xc31df931f2f2eff2), U64_C (0x4b48dba8e3e3abe3), + U64_C (0xe22ab6b95b5b715b), U64_C (0x34920dbc88881a88), + U64_C (0xa4c8293e9a9a529a), U64_C (0x2dbe4c0b26269826), + U64_C (0x8dfa64bf3232c832), U64_C (0xe94a7d59b0b0fab0), + U64_C (0x1b6acff2e9e983e9), U64_C (0x78331e770f0f3c0f), + U64_C (0xe6a6b733d5d573d5), U64_C (0x74ba1df480803a80), + U64_C (0x997c6127bebec2be), U64_C (0x26de87ebcdcd13cd), + U64_C (0xbde468893434d034), U64_C (0x7a75903248483d48), + U64_C (0xab24e354ffffdbff), U64_C (0xf78ff48d7a7af57a), + U64_C (0xf4ea3d6490907a90), U64_C (0xc23ebe9d5f5f615f), + U64_C (0x1da0403d20208020), U64_C (0x67d5d00f6868bd68), + U64_C (0xd07234ca1a1a681a), U64_C (0x192c41b7aeae82ae), + U64_C (0xc95e757db4b4eab4), U64_C (0x9a19a8ce54544d54), + U64_C (0xece53b7f93937693), U64_C (0x0daa442f22228822), + U64_C (0x07e9c86364648d64), U64_C (0xdb12ff2af1f1e3f1), + U64_C (0xbfa2e6cc7373d173), U64_C (0x905a248212124812), + U64_C (0x3a5d807a40401d40), U64_C (0x4028104808082008), + U64_C (0x56e89b95c3c32bc3), U64_C (0x337bc5dfecec97ec), + U64_C (0x9690ab4ddbdb4bdb), U64_C (0x611f5fc0a1a1bea1), + U64_C (0x1c8307918d8d0e8d), U64_C (0xf5c97ac83d3df43d), + U64_C (0xccf1335b97976697), U64_C (0x0000000000000000), + U64_C (0x36d483f9cfcf1bcf), U64_C (0x4587566e2b2bac2b), + U64_C (0x97b3ece17676c576), U64_C (0x64b019e682823282), + U64_C (0xfea9b128d6d67fd6), U64_C (0xd87736c31b1b6c1b), + U64_C (0xc15b7774b5b5eeb5), U64_C (0x112943beafaf86af), + U64_C (0x77dfd41d6a6ab56a), U64_C (0xba0da0ea50505d50), + U64_C (0x124c8a5745450945), U64_C (0xcb18fb38f3f3ebf3), + U64_C (0x9df060ad3030c030), U64_C (0x2b74c3c4efef9bef), + U64_C (0xe5c37eda3f3ffc3f), U64_C (0x921caac755554955), + U64_C (0x791059dba2a2b2a2), U64_C (0x0365c9e9eaea8fea), + U64_C (0x0fecca6a65658965), U64_C (0xb9686903babad2ba), + U64_C (0x65935e4a2f2fbc2f), U64_C (0x4ee79d8ec0c027c0), + U64_C (0xbe81a160dede5fde), U64_C (0xe06c38fc1c1c701c), + U64_C (0xbb2ee746fdfdd3fd), U64_C (0x52649a1f4d4d294d), + U64_C (0xe4e0397692927292), U64_C (0x8fbceafa7575c975), + U64_C (0x301e0c3606061806), U64_C (0x249809ae8a8a128a), + U64_C (0xf940794bb2b2f2b2), U64_C (0x6359d185e6e6bfe6), + U64_C (0x70361c7e0e0e380e), U64_C (0xf8633ee71f1f7c1f), + U64_C (0x37f7c45562629562), U64_C (0xeea3b53ad4d477d4), + U64_C (0x29324d81a8a89aa8), U64_C (0xc4f4315296966296), + U64_C (0x9b3aef62f9f9c3f9), U64_C (0x66f697a3c5c533c5), + U64_C (0x35b14a1025259425), U64_C (0xf220b2ab59597959), + U64_C (0x54ae15d084842a84), U64_C (0xb7a7e4c57272d572), + U64_C (0xd5dd72ec3939e439), U64_C (0x5a6198164c4c2d4c), + U64_C (0xca3bbc945e5e655e), U64_C (0xe785f09f7878fd78), + U64_C (0xddd870e53838e038), U64_C (0x148605988c8c0a8c), + U64_C (0xc6b2bf17d1d163d1), U64_C (0x410b57e4a5a5aea5), + U64_C (0x434dd9a1e2e2afe2), U64_C (0x2ff8c24e61619961), + U64_C (0xf1457b42b3b3f6b3), U64_C (0x15a5423421218421), + U64_C (0x94d625089c9c4a9c), U64_C (0xf0663cee1e1e781e), + U64_C (0x2252866143431143), U64_C (0x76fc93b1c7c73bc7), + U64_C (0xb32be54ffcfcd7fc), U64_C (0x2014082404041004), + U64_C (0xb208a2e351515951), U64_C (0xbcc72f2599995e99), + U64_C (0x4fc4da226d6da96d), U64_C (0x68391a650d0d340d), + U64_C (0x8335e979fafacffa), U64_C (0xb684a369dfdf5bdf), + U64_C (0xd79bfca97e7ee57e), U64_C (0x3db4481924249024), + U64_C (0xc5d776fe3b3bec3b), U64_C (0x313d4b9aabab96ab), + U64_C (0x3ed181f0cece1fce), U64_C (0x8855229911114411), + U64_C (0x0c8903838f8f068f), U64_C (0x4a6b9c044e4e254e), + U64_C (0xd1517366b7b7e6b7), U64_C (0x0b60cbe0ebeb8beb), + U64_C (0xfdcc78c13c3cf03c), U64_C (0x7cbf1ffd81813e81), + U64_C (0xd4fe354094946a94), U64_C (0xeb0cf31cf7f7fbf7), + U64_C (0xa1676f18b9b9deb9), U64_C (0x985f268b13134c13), + U64_C (0x7d9c58512c2cb02c), U64_C (0xd6b8bb05d3d36bd3), + U64_C (0x6b5cd38ce7e7bbe7), U64_C (0x57cbdc396e6ea56e), + U64_C (0x6ef395aac4c437c4), U64_C (0x180f061b03030c03), + U64_C (0x8a13acdc56564556), U64_C (0x1a49885e44440d44), + U64_C (0xdf9efea07f7fe17f), U64_C (0x21374f88a9a99ea9), + U64_C (0x4d8254672a2aa82a), U64_C (0xb16d6b0abbbbd6bb), + U64_C (0x46e29f87c1c123c1), U64_C (0xa202a6f153535153), + U64_C (0xae8ba572dcdc57dc), U64_C (0x582716530b0b2c0b), + U64_C (0x9cd327019d9d4e9d), U64_C (0x47c1d82b6c6cad6c), + U64_C (0x95f562a43131c431), U64_C (0x87b9e8f37474cd74), + U64_C (0xe309f115f6f6fff6), U64_C (0x0a438c4c46460546), + U64_C (0x092645a5acac8aac), U64_C (0x3c970fb589891e89), + U64_C (0xa04428b414145014), U64_C (0x5b42dfbae1e1a3e1), + U64_C (0xb04e2ca616165816), U64_C (0xcdd274f73a3ae83a), + U64_C (0x6fd0d2066969b969), U64_C (0x482d124109092409), + U64_C (0xa7ade0d77070dd70), U64_C (0xd954716fb6b6e2b6), + U64_C (0xceb7bd1ed0d067d0), U64_C (0x3b7ec7d6eded93ed), + U64_C (0x2edb85e2cccc17cc), U64_C (0x2a57846842421542), + U64_C (0xb4c22d2c98985a98), U64_C (0x490e55eda4a4aaa4), + U64_C (0x5d8850752828a028), U64_C (0xda31b8865c5c6d5c), + U64_C (0x933fed6bf8f8c7f8), U64_C (0x44a411c286862286), + }; + +static const u64 C5[256] = + { + U64_C (0x18c07830d8181860), U64_C (0x2305af462623238c), + U64_C (0xc67ef991b8c6c63f), U64_C (0xe8136fcdfbe8e887), + U64_C (0x874ca113cb878726), U64_C (0xb8a9626d11b8b8da), + U64_C (0x0108050209010104), U64_C (0x4f426e9e0d4f4f21), + U64_C (0x36adee6c9b3636d8), U64_C (0xa6590451ffa6a6a2), + U64_C (0xd2debdb90cd2d26f), U64_C (0xf5fb06f70ef5f5f3), + U64_C (0x79ef80f2967979f9), U64_C (0x6f5fcede306f6fa1), + U64_C (0x91fcef3f6d91917e), U64_C (0x52aa07a4f8525255), + U64_C (0x6027fdc04760609d), U64_C (0xbc89766535bcbcca), + U64_C (0x9baccd2b379b9b56), U64_C (0x8e048c018a8e8e02), + U64_C (0xa371155bd2a3a3b6), U64_C (0x0c603c186c0c0c30), + U64_C (0x7bff8af6847b7bf1), U64_C (0x35b5e16a803535d4), + U64_C (0x1de8693af51d1d74), U64_C (0xe05347ddb3e0e0a7), + U64_C (0xd7f6acb321d7d77b), U64_C (0xc25eed999cc2c22f), + U64_C (0x2e6d965c432e2eb8), U64_C (0x4b627a96294b4b31), + U64_C (0xfea321e15dfefedf), U64_C (0x578216aed5575741), + U64_C (0x15a8412abd151554), U64_C (0x779fb6eee87777c1), + U64_C (0x37a5eb6e923737dc), U64_C (0xe57b56d79ee5e5b3), + U64_C (0x9f8cd923139f9f46), U64_C (0xf0d317fd23f0f0e7), + U64_C (0x4a6a7f94204a4a35), U64_C (0xda9e95a944dada4f), + U64_C (0x58fa25b0a258587d), U64_C (0xc906ca8fcfc9c903), + U64_C (0x29558d527c2929a4), U64_C (0x0a5022145a0a0a28), + U64_C (0xb1e14f7f50b1b1fe), U64_C (0xa0691a5dc9a0a0ba), + U64_C (0x6b7fdad6146b6bb1), U64_C (0x855cab17d985852e), + U64_C (0xbd8173673cbdbdce), U64_C (0x5dd234ba8f5d5d69), + U64_C (0x1080502090101040), U64_C (0xf4f303f507f4f4f7), + U64_C (0xcb16c08bddcbcb0b), U64_C (0x3eedc67cd33e3ef8), + U64_C (0x0528110a2d050514), U64_C (0x671fe6ce78676781), + U64_C (0xe47353d597e4e4b7), U64_C (0x2725bb4e0227279c), + U64_C (0x4132588273414119), U64_C (0x8b2c9d0ba78b8b16), + U64_C (0xa7510153f6a7a7a6), U64_C (0x7dcf94fab27d7de9), + U64_C (0x95dcfb374995956e), U64_C (0xd88e9fad56d8d847), + U64_C (0xfb8b30eb70fbfbcb), U64_C (0xee2371c1cdeeee9f), + U64_C (0x7cc791f8bb7c7ced), U64_C (0x6617e3cc71666685), + U64_C (0xdda68ea77bdddd53), U64_C (0x17b84b2eaf17175c), + U64_C (0x4702468e45474701), U64_C (0x9e84dc211a9e9e42), + U64_C (0xca1ec589d4caca0f), U64_C (0x2d75995a582d2db4), + U64_C (0xbf9179632ebfbfc6), U64_C (0x07381b0e3f07071c), + U64_C (0xad012347acadad8e), U64_C (0x5aea2fb4b05a5a75), + U64_C (0x836cb51bef838336), U64_C (0x3385ff66b63333cc), + U64_C (0x633ff2c65c636391), U64_C (0x02100a0412020208), + U64_C (0xaa39384993aaaa92), U64_C (0x71afa8e2de7171d9), + U64_C (0xc80ecf8dc6c8c807), U64_C (0x19c87d32d1191964), + U64_C (0x497270923b494939), U64_C (0xd9869aaf5fd9d943), + U64_C (0xf2c31df931f2f2ef), U64_C (0xe34b48dba8e3e3ab), + U64_C (0x5be22ab6b95b5b71), U64_C (0x8834920dbc88881a), + U64_C (0x9aa4c8293e9a9a52), U64_C (0x262dbe4c0b262698), + U64_C (0x328dfa64bf3232c8), U64_C (0xb0e94a7d59b0b0fa), + U64_C (0xe91b6acff2e9e983), U64_C (0x0f78331e770f0f3c), + U64_C (0xd5e6a6b733d5d573), U64_C (0x8074ba1df480803a), + U64_C (0xbe997c6127bebec2), U64_C (0xcd26de87ebcdcd13), + U64_C (0x34bde468893434d0), U64_C (0x487a75903248483d), + U64_C (0xffab24e354ffffdb), U64_C (0x7af78ff48d7a7af5), + U64_C (0x90f4ea3d6490907a), U64_C (0x5fc23ebe9d5f5f61), + U64_C (0x201da0403d202080), U64_C (0x6867d5d00f6868bd), + U64_C (0x1ad07234ca1a1a68), U64_C (0xae192c41b7aeae82), + U64_C (0xb4c95e757db4b4ea), U64_C (0x549a19a8ce54544d), + U64_C (0x93ece53b7f939376), U64_C (0x220daa442f222288), + U64_C (0x6407e9c86364648d), U64_C (0xf1db12ff2af1f1e3), + U64_C (0x73bfa2e6cc7373d1), U64_C (0x12905a2482121248), + U64_C (0x403a5d807a40401d), U64_C (0x0840281048080820), + U64_C (0xc356e89b95c3c32b), U64_C (0xec337bc5dfecec97), + U64_C (0xdb9690ab4ddbdb4b), U64_C (0xa1611f5fc0a1a1be), + U64_C (0x8d1c8307918d8d0e), U64_C (0x3df5c97ac83d3df4), + U64_C (0x97ccf1335b979766), U64_C (0x0000000000000000), + U64_C (0xcf36d483f9cfcf1b), U64_C (0x2b4587566e2b2bac), + U64_C (0x7697b3ece17676c5), U64_C (0x8264b019e6828232), + U64_C (0xd6fea9b128d6d67f), U64_C (0x1bd87736c31b1b6c), + U64_C (0xb5c15b7774b5b5ee), U64_C (0xaf112943beafaf86), + U64_C (0x6a77dfd41d6a6ab5), U64_C (0x50ba0da0ea50505d), + U64_C (0x45124c8a57454509), U64_C (0xf3cb18fb38f3f3eb), + U64_C (0x309df060ad3030c0), U64_C (0xef2b74c3c4efef9b), + U64_C (0x3fe5c37eda3f3ffc), U64_C (0x55921caac7555549), + U64_C (0xa2791059dba2a2b2), U64_C (0xea0365c9e9eaea8f), + U64_C (0x650fecca6a656589), U64_C (0xbab9686903babad2), + U64_C (0x2f65935e4a2f2fbc), U64_C (0xc04ee79d8ec0c027), + U64_C (0xdebe81a160dede5f), U64_C (0x1ce06c38fc1c1c70), + U64_C (0xfdbb2ee746fdfdd3), U64_C (0x4d52649a1f4d4d29), + U64_C (0x92e4e03976929272), U64_C (0x758fbceafa7575c9), + U64_C (0x06301e0c36060618), U64_C (0x8a249809ae8a8a12), + U64_C (0xb2f940794bb2b2f2), U64_C (0xe66359d185e6e6bf), + U64_C (0x0e70361c7e0e0e38), U64_C (0x1ff8633ee71f1f7c), + U64_C (0x6237f7c455626295), U64_C (0xd4eea3b53ad4d477), + U64_C (0xa829324d81a8a89a), U64_C (0x96c4f43152969662), + U64_C (0xf99b3aef62f9f9c3), U64_C (0xc566f697a3c5c533), + U64_C (0x2535b14a10252594), U64_C (0x59f220b2ab595979), + U64_C (0x8454ae15d084842a), U64_C (0x72b7a7e4c57272d5), + U64_C (0x39d5dd72ec3939e4), U64_C (0x4c5a6198164c4c2d), + U64_C (0x5eca3bbc945e5e65), U64_C (0x78e785f09f7878fd), + U64_C (0x38ddd870e53838e0), U64_C (0x8c148605988c8c0a), + U64_C (0xd1c6b2bf17d1d163), U64_C (0xa5410b57e4a5a5ae), + U64_C (0xe2434dd9a1e2e2af), U64_C (0x612ff8c24e616199), + U64_C (0xb3f1457b42b3b3f6), U64_C (0x2115a54234212184), + U64_C (0x9c94d625089c9c4a), U64_C (0x1ef0663cee1e1e78), + U64_C (0x4322528661434311), U64_C (0xc776fc93b1c7c73b), + U64_C (0xfcb32be54ffcfcd7), U64_C (0x0420140824040410), + U64_C (0x51b208a2e3515159), U64_C (0x99bcc72f2599995e), + U64_C (0x6d4fc4da226d6da9), U64_C (0x0d68391a650d0d34), + U64_C (0xfa8335e979fafacf), U64_C (0xdfb684a369dfdf5b), + U64_C (0x7ed79bfca97e7ee5), U64_C (0x243db44819242490), + U64_C (0x3bc5d776fe3b3bec), U64_C (0xab313d4b9aabab96), + U64_C (0xce3ed181f0cece1f), U64_C (0x1188552299111144), + U64_C (0x8f0c8903838f8f06), U64_C (0x4e4a6b9c044e4e25), + U64_C (0xb7d1517366b7b7e6), U64_C (0xeb0b60cbe0ebeb8b), + U64_C (0x3cfdcc78c13c3cf0), U64_C (0x817cbf1ffd81813e), + U64_C (0x94d4fe354094946a), U64_C (0xf7eb0cf31cf7f7fb), + U64_C (0xb9a1676f18b9b9de), U64_C (0x13985f268b13134c), + U64_C (0x2c7d9c58512c2cb0), U64_C (0xd3d6b8bb05d3d36b), + U64_C (0xe76b5cd38ce7e7bb), U64_C (0x6e57cbdc396e6ea5), + U64_C (0xc46ef395aac4c437), U64_C (0x03180f061b03030c), + U64_C (0x568a13acdc565645), U64_C (0x441a49885e44440d), + U64_C (0x7fdf9efea07f7fe1), U64_C (0xa921374f88a9a99e), + U64_C (0x2a4d8254672a2aa8), U64_C (0xbbb16d6b0abbbbd6), + U64_C (0xc146e29f87c1c123), U64_C (0x53a202a6f1535351), + U64_C (0xdcae8ba572dcdc57), U64_C (0x0b582716530b0b2c), + U64_C (0x9d9cd327019d9d4e), U64_C (0x6c47c1d82b6c6cad), + U64_C (0x3195f562a43131c4), U64_C (0x7487b9e8f37474cd), + U64_C (0xf6e309f115f6f6ff), U64_C (0x460a438c4c464605), + U64_C (0xac092645a5acac8a), U64_C (0x893c970fb589891e), + U64_C (0x14a04428b4141450), U64_C (0xe15b42dfbae1e1a3), + U64_C (0x16b04e2ca6161658), U64_C (0x3acdd274f73a3ae8), + U64_C (0x696fd0d2066969b9), U64_C (0x09482d1241090924), + U64_C (0x70a7ade0d77070dd), U64_C (0xb6d954716fb6b6e2), + U64_C (0xd0ceb7bd1ed0d067), U64_C (0xed3b7ec7d6eded93), + U64_C (0xcc2edb85e2cccc17), U64_C (0x422a578468424215), + U64_C (0x98b4c22d2c98985a), U64_C (0xa4490e55eda4a4aa), + U64_C (0x285d8850752828a0), U64_C (0x5cda31b8865c5c6d), + U64_C (0xf8933fed6bf8f8c7), U64_C (0x8644a411c2868622), + }; + +static const u64 C6[256] = + { + U64_C (0x6018c07830d81818), U64_C (0x8c2305af46262323), + U64_C (0x3fc67ef991b8c6c6), U64_C (0x87e8136fcdfbe8e8), + U64_C (0x26874ca113cb8787), U64_C (0xdab8a9626d11b8b8), + U64_C (0x0401080502090101), U64_C (0x214f426e9e0d4f4f), + U64_C (0xd836adee6c9b3636), U64_C (0xa2a6590451ffa6a6), + U64_C (0x6fd2debdb90cd2d2), U64_C (0xf3f5fb06f70ef5f5), + U64_C (0xf979ef80f2967979), U64_C (0xa16f5fcede306f6f), + U64_C (0x7e91fcef3f6d9191), U64_C (0x5552aa07a4f85252), + U64_C (0x9d6027fdc0476060), U64_C (0xcabc89766535bcbc), + U64_C (0x569baccd2b379b9b), U64_C (0x028e048c018a8e8e), + U64_C (0xb6a371155bd2a3a3), U64_C (0x300c603c186c0c0c), + U64_C (0xf17bff8af6847b7b), U64_C (0xd435b5e16a803535), + U64_C (0x741de8693af51d1d), U64_C (0xa7e05347ddb3e0e0), + U64_C (0x7bd7f6acb321d7d7), U64_C (0x2fc25eed999cc2c2), + U64_C (0xb82e6d965c432e2e), U64_C (0x314b627a96294b4b), + U64_C (0xdffea321e15dfefe), U64_C (0x41578216aed55757), + U64_C (0x5415a8412abd1515), U64_C (0xc1779fb6eee87777), + U64_C (0xdc37a5eb6e923737), U64_C (0xb3e57b56d79ee5e5), + U64_C (0x469f8cd923139f9f), U64_C (0xe7f0d317fd23f0f0), + U64_C (0x354a6a7f94204a4a), U64_C (0x4fda9e95a944dada), + U64_C (0x7d58fa25b0a25858), U64_C (0x03c906ca8fcfc9c9), + U64_C (0xa429558d527c2929), U64_C (0x280a5022145a0a0a), + U64_C (0xfeb1e14f7f50b1b1), U64_C (0xbaa0691a5dc9a0a0), + U64_C (0xb16b7fdad6146b6b), U64_C (0x2e855cab17d98585), + U64_C (0xcebd8173673cbdbd), U64_C (0x695dd234ba8f5d5d), + U64_C (0x4010805020901010), U64_C (0xf7f4f303f507f4f4), + U64_C (0x0bcb16c08bddcbcb), U64_C (0xf83eedc67cd33e3e), + U64_C (0x140528110a2d0505), U64_C (0x81671fe6ce786767), + U64_C (0xb7e47353d597e4e4), U64_C (0x9c2725bb4e022727), + U64_C (0x1941325882734141), U64_C (0x168b2c9d0ba78b8b), + U64_C (0xa6a7510153f6a7a7), U64_C (0xe97dcf94fab27d7d), + U64_C (0x6e95dcfb37499595), U64_C (0x47d88e9fad56d8d8), + U64_C (0xcbfb8b30eb70fbfb), U64_C (0x9fee2371c1cdeeee), + U64_C (0xed7cc791f8bb7c7c), U64_C (0x856617e3cc716666), + U64_C (0x53dda68ea77bdddd), U64_C (0x5c17b84b2eaf1717), + U64_C (0x014702468e454747), U64_C (0x429e84dc211a9e9e), + U64_C (0x0fca1ec589d4caca), U64_C (0xb42d75995a582d2d), + U64_C (0xc6bf9179632ebfbf), U64_C (0x1c07381b0e3f0707), + U64_C (0x8ead012347acadad), U64_C (0x755aea2fb4b05a5a), + U64_C (0x36836cb51bef8383), U64_C (0xcc3385ff66b63333), + U64_C (0x91633ff2c65c6363), U64_C (0x0802100a04120202), + U64_C (0x92aa39384993aaaa), U64_C (0xd971afa8e2de7171), + U64_C (0x07c80ecf8dc6c8c8), U64_C (0x6419c87d32d11919), + U64_C (0x39497270923b4949), U64_C (0x43d9869aaf5fd9d9), + U64_C (0xeff2c31df931f2f2), U64_C (0xabe34b48dba8e3e3), + U64_C (0x715be22ab6b95b5b), U64_C (0x1a8834920dbc8888), + U64_C (0x529aa4c8293e9a9a), U64_C (0x98262dbe4c0b2626), + U64_C (0xc8328dfa64bf3232), U64_C (0xfab0e94a7d59b0b0), + U64_C (0x83e91b6acff2e9e9), U64_C (0x3c0f78331e770f0f), + U64_C (0x73d5e6a6b733d5d5), U64_C (0x3a8074ba1df48080), + U64_C (0xc2be997c6127bebe), U64_C (0x13cd26de87ebcdcd), + U64_C (0xd034bde468893434), U64_C (0x3d487a7590324848), + U64_C (0xdbffab24e354ffff), U64_C (0xf57af78ff48d7a7a), + U64_C (0x7a90f4ea3d649090), U64_C (0x615fc23ebe9d5f5f), + U64_C (0x80201da0403d2020), U64_C (0xbd6867d5d00f6868), + U64_C (0x681ad07234ca1a1a), U64_C (0x82ae192c41b7aeae), + U64_C (0xeab4c95e757db4b4), U64_C (0x4d549a19a8ce5454), + U64_C (0x7693ece53b7f9393), U64_C (0x88220daa442f2222), + U64_C (0x8d6407e9c8636464), U64_C (0xe3f1db12ff2af1f1), + U64_C (0xd173bfa2e6cc7373), U64_C (0x4812905a24821212), + U64_C (0x1d403a5d807a4040), U64_C (0x2008402810480808), + U64_C (0x2bc356e89b95c3c3), U64_C (0x97ec337bc5dfecec), + U64_C (0x4bdb9690ab4ddbdb), U64_C (0xbea1611f5fc0a1a1), + U64_C (0x0e8d1c8307918d8d), U64_C (0xf43df5c97ac83d3d), + U64_C (0x6697ccf1335b9797), U64_C (0x0000000000000000), + U64_C (0x1bcf36d483f9cfcf), U64_C (0xac2b4587566e2b2b), + U64_C (0xc57697b3ece17676), U64_C (0x328264b019e68282), + U64_C (0x7fd6fea9b128d6d6), U64_C (0x6c1bd87736c31b1b), + U64_C (0xeeb5c15b7774b5b5), U64_C (0x86af112943beafaf), + U64_C (0xb56a77dfd41d6a6a), U64_C (0x5d50ba0da0ea5050), + U64_C (0x0945124c8a574545), U64_C (0xebf3cb18fb38f3f3), + U64_C (0xc0309df060ad3030), U64_C (0x9bef2b74c3c4efef), + U64_C (0xfc3fe5c37eda3f3f), U64_C (0x4955921caac75555), + U64_C (0xb2a2791059dba2a2), U64_C (0x8fea0365c9e9eaea), + U64_C (0x89650fecca6a6565), U64_C (0xd2bab9686903baba), + U64_C (0xbc2f65935e4a2f2f), U64_C (0x27c04ee79d8ec0c0), + U64_C (0x5fdebe81a160dede), U64_C (0x701ce06c38fc1c1c), + U64_C (0xd3fdbb2ee746fdfd), U64_C (0x294d52649a1f4d4d), + U64_C (0x7292e4e039769292), U64_C (0xc9758fbceafa7575), + U64_C (0x1806301e0c360606), U64_C (0x128a249809ae8a8a), + U64_C (0xf2b2f940794bb2b2), U64_C (0xbfe66359d185e6e6), + U64_C (0x380e70361c7e0e0e), U64_C (0x7c1ff8633ee71f1f), + U64_C (0x956237f7c4556262), U64_C (0x77d4eea3b53ad4d4), + U64_C (0x9aa829324d81a8a8), U64_C (0x6296c4f431529696), + U64_C (0xc3f99b3aef62f9f9), U64_C (0x33c566f697a3c5c5), + U64_C (0x942535b14a102525), U64_C (0x7959f220b2ab5959), + U64_C (0x2a8454ae15d08484), U64_C (0xd572b7a7e4c57272), + U64_C (0xe439d5dd72ec3939), U64_C (0x2d4c5a6198164c4c), + U64_C (0x655eca3bbc945e5e), U64_C (0xfd78e785f09f7878), + U64_C (0xe038ddd870e53838), U64_C (0x0a8c148605988c8c), + U64_C (0x63d1c6b2bf17d1d1), U64_C (0xaea5410b57e4a5a5), + U64_C (0xafe2434dd9a1e2e2), U64_C (0x99612ff8c24e6161), + U64_C (0xf6b3f1457b42b3b3), U64_C (0x842115a542342121), + U64_C (0x4a9c94d625089c9c), U64_C (0x781ef0663cee1e1e), + U64_C (0x1143225286614343), U64_C (0x3bc776fc93b1c7c7), + U64_C (0xd7fcb32be54ffcfc), U64_C (0x1004201408240404), + U64_C (0x5951b208a2e35151), U64_C (0x5e99bcc72f259999), + U64_C (0xa96d4fc4da226d6d), U64_C (0x340d68391a650d0d), + U64_C (0xcffa8335e979fafa), U64_C (0x5bdfb684a369dfdf), + U64_C (0xe57ed79bfca97e7e), U64_C (0x90243db448192424), + U64_C (0xec3bc5d776fe3b3b), U64_C (0x96ab313d4b9aabab), + U64_C (0x1fce3ed181f0cece), U64_C (0x4411885522991111), + U64_C (0x068f0c8903838f8f), U64_C (0x254e4a6b9c044e4e), + U64_C (0xe6b7d1517366b7b7), U64_C (0x8beb0b60cbe0ebeb), + U64_C (0xf03cfdcc78c13c3c), U64_C (0x3e817cbf1ffd8181), + U64_C (0x6a94d4fe35409494), U64_C (0xfbf7eb0cf31cf7f7), + U64_C (0xdeb9a1676f18b9b9), U64_C (0x4c13985f268b1313), + U64_C (0xb02c7d9c58512c2c), U64_C (0x6bd3d6b8bb05d3d3), + U64_C (0xbbe76b5cd38ce7e7), U64_C (0xa56e57cbdc396e6e), + U64_C (0x37c46ef395aac4c4), U64_C (0x0c03180f061b0303), + U64_C (0x45568a13acdc5656), U64_C (0x0d441a49885e4444), + U64_C (0xe17fdf9efea07f7f), U64_C (0x9ea921374f88a9a9), + U64_C (0xa82a4d8254672a2a), U64_C (0xd6bbb16d6b0abbbb), + U64_C (0x23c146e29f87c1c1), U64_C (0x5153a202a6f15353), + U64_C (0x57dcae8ba572dcdc), U64_C (0x2c0b582716530b0b), + U64_C (0x4e9d9cd327019d9d), U64_C (0xad6c47c1d82b6c6c), + U64_C (0xc43195f562a43131), U64_C (0xcd7487b9e8f37474), + U64_C (0xfff6e309f115f6f6), U64_C (0x05460a438c4c4646), + U64_C (0x8aac092645a5acac), U64_C (0x1e893c970fb58989), + U64_C (0x5014a04428b41414), U64_C (0xa3e15b42dfbae1e1), + U64_C (0x5816b04e2ca61616), U64_C (0xe83acdd274f73a3a), + U64_C (0xb9696fd0d2066969), U64_C (0x2409482d12410909), + U64_C (0xdd70a7ade0d77070), U64_C (0xe2b6d954716fb6b6), + U64_C (0x67d0ceb7bd1ed0d0), U64_C (0x93ed3b7ec7d6eded), + U64_C (0x17cc2edb85e2cccc), U64_C (0x15422a5784684242), + U64_C (0x5a98b4c22d2c9898), U64_C (0xaaa4490e55eda4a4), + U64_C (0xa0285d8850752828), U64_C (0x6d5cda31b8865c5c), + U64_C (0xc7f8933fed6bf8f8), U64_C (0x228644a411c28686), + }; + +static const u64 C7[256] = + { + U64_C (0x186018c07830d818), U64_C (0x238c2305af462623), + U64_C (0xc63fc67ef991b8c6), U64_C (0xe887e8136fcdfbe8), + U64_C (0x8726874ca113cb87), U64_C (0xb8dab8a9626d11b8), + U64_C (0x0104010805020901), U64_C (0x4f214f426e9e0d4f), + U64_C (0x36d836adee6c9b36), U64_C (0xa6a2a6590451ffa6), + U64_C (0xd26fd2debdb90cd2), U64_C (0xf5f3f5fb06f70ef5), + U64_C (0x79f979ef80f29679), U64_C (0x6fa16f5fcede306f), + U64_C (0x917e91fcef3f6d91), U64_C (0x525552aa07a4f852), + U64_C (0x609d6027fdc04760), U64_C (0xbccabc89766535bc), + U64_C (0x9b569baccd2b379b), U64_C (0x8e028e048c018a8e), + U64_C (0xa3b6a371155bd2a3), U64_C (0x0c300c603c186c0c), + U64_C (0x7bf17bff8af6847b), U64_C (0x35d435b5e16a8035), + U64_C (0x1d741de8693af51d), U64_C (0xe0a7e05347ddb3e0), + U64_C (0xd77bd7f6acb321d7), U64_C (0xc22fc25eed999cc2), + U64_C (0x2eb82e6d965c432e), U64_C (0x4b314b627a96294b), + U64_C (0xfedffea321e15dfe), U64_C (0x5741578216aed557), + U64_C (0x155415a8412abd15), U64_C (0x77c1779fb6eee877), + U64_C (0x37dc37a5eb6e9237), U64_C (0xe5b3e57b56d79ee5), + U64_C (0x9f469f8cd923139f), U64_C (0xf0e7f0d317fd23f0), + U64_C (0x4a354a6a7f94204a), U64_C (0xda4fda9e95a944da), + U64_C (0x587d58fa25b0a258), U64_C (0xc903c906ca8fcfc9), + U64_C (0x29a429558d527c29), U64_C (0x0a280a5022145a0a), + U64_C (0xb1feb1e14f7f50b1), U64_C (0xa0baa0691a5dc9a0), + U64_C (0x6bb16b7fdad6146b), U64_C (0x852e855cab17d985), + U64_C (0xbdcebd8173673cbd), U64_C (0x5d695dd234ba8f5d), + U64_C (0x1040108050209010), U64_C (0xf4f7f4f303f507f4), + U64_C (0xcb0bcb16c08bddcb), U64_C (0x3ef83eedc67cd33e), + U64_C (0x05140528110a2d05), U64_C (0x6781671fe6ce7867), + U64_C (0xe4b7e47353d597e4), U64_C (0x279c2725bb4e0227), + U64_C (0x4119413258827341), U64_C (0x8b168b2c9d0ba78b), + U64_C (0xa7a6a7510153f6a7), U64_C (0x7de97dcf94fab27d), + U64_C (0x956e95dcfb374995), U64_C (0xd847d88e9fad56d8), + U64_C (0xfbcbfb8b30eb70fb), U64_C (0xee9fee2371c1cdee), + U64_C (0x7ced7cc791f8bb7c), U64_C (0x66856617e3cc7166), + U64_C (0xdd53dda68ea77bdd), U64_C (0x175c17b84b2eaf17), + U64_C (0x47014702468e4547), U64_C (0x9e429e84dc211a9e), + U64_C (0xca0fca1ec589d4ca), U64_C (0x2db42d75995a582d), + U64_C (0xbfc6bf9179632ebf), U64_C (0x071c07381b0e3f07), + U64_C (0xad8ead012347acad), U64_C (0x5a755aea2fb4b05a), + U64_C (0x8336836cb51bef83), U64_C (0x33cc3385ff66b633), + U64_C (0x6391633ff2c65c63), U64_C (0x020802100a041202), + U64_C (0xaa92aa39384993aa), U64_C (0x71d971afa8e2de71), + U64_C (0xc807c80ecf8dc6c8), U64_C (0x196419c87d32d119), + U64_C (0x4939497270923b49), U64_C (0xd943d9869aaf5fd9), + U64_C (0xf2eff2c31df931f2), U64_C (0xe3abe34b48dba8e3), + U64_C (0x5b715be22ab6b95b), U64_C (0x881a8834920dbc88), + U64_C (0x9a529aa4c8293e9a), U64_C (0x2698262dbe4c0b26), + U64_C (0x32c8328dfa64bf32), U64_C (0xb0fab0e94a7d59b0), + U64_C (0xe983e91b6acff2e9), U64_C (0x0f3c0f78331e770f), + U64_C (0xd573d5e6a6b733d5), U64_C (0x803a8074ba1df480), + U64_C (0xbec2be997c6127be), U64_C (0xcd13cd26de87ebcd), + U64_C (0x34d034bde4688934), U64_C (0x483d487a75903248), + U64_C (0xffdbffab24e354ff), U64_C (0x7af57af78ff48d7a), + U64_C (0x907a90f4ea3d6490), U64_C (0x5f615fc23ebe9d5f), + U64_C (0x2080201da0403d20), U64_C (0x68bd6867d5d00f68), + U64_C (0x1a681ad07234ca1a), U64_C (0xae82ae192c41b7ae), + U64_C (0xb4eab4c95e757db4), U64_C (0x544d549a19a8ce54), + U64_C (0x937693ece53b7f93), U64_C (0x2288220daa442f22), + U64_C (0x648d6407e9c86364), U64_C (0xf1e3f1db12ff2af1), + U64_C (0x73d173bfa2e6cc73), U64_C (0x124812905a248212), + U64_C (0x401d403a5d807a40), U64_C (0x0820084028104808), + U64_C (0xc32bc356e89b95c3), U64_C (0xec97ec337bc5dfec), + U64_C (0xdb4bdb9690ab4ddb), U64_C (0xa1bea1611f5fc0a1), + U64_C (0x8d0e8d1c8307918d), U64_C (0x3df43df5c97ac83d), + U64_C (0x976697ccf1335b97), U64_C (0x0000000000000000), + U64_C (0xcf1bcf36d483f9cf), U64_C (0x2bac2b4587566e2b), + U64_C (0x76c57697b3ece176), U64_C (0x82328264b019e682), + U64_C (0xd67fd6fea9b128d6), U64_C (0x1b6c1bd87736c31b), + U64_C (0xb5eeb5c15b7774b5), U64_C (0xaf86af112943beaf), + U64_C (0x6ab56a77dfd41d6a), U64_C (0x505d50ba0da0ea50), + U64_C (0x450945124c8a5745), U64_C (0xf3ebf3cb18fb38f3), + U64_C (0x30c0309df060ad30), U64_C (0xef9bef2b74c3c4ef), + U64_C (0x3ffc3fe5c37eda3f), U64_C (0x554955921caac755), + U64_C (0xa2b2a2791059dba2), U64_C (0xea8fea0365c9e9ea), + U64_C (0x6589650fecca6a65), U64_C (0xbad2bab9686903ba), + U64_C (0x2fbc2f65935e4a2f), U64_C (0xc027c04ee79d8ec0), + U64_C (0xde5fdebe81a160de), U64_C (0x1c701ce06c38fc1c), + U64_C (0xfdd3fdbb2ee746fd), U64_C (0x4d294d52649a1f4d), + U64_C (0x927292e4e0397692), U64_C (0x75c9758fbceafa75), + U64_C (0x061806301e0c3606), U64_C (0x8a128a249809ae8a), + U64_C (0xb2f2b2f940794bb2), U64_C (0xe6bfe66359d185e6), + U64_C (0x0e380e70361c7e0e), U64_C (0x1f7c1ff8633ee71f), + U64_C (0x62956237f7c45562), U64_C (0xd477d4eea3b53ad4), + U64_C (0xa89aa829324d81a8), U64_C (0x966296c4f4315296), + U64_C (0xf9c3f99b3aef62f9), U64_C (0xc533c566f697a3c5), + U64_C (0x25942535b14a1025), U64_C (0x597959f220b2ab59), + U64_C (0x842a8454ae15d084), U64_C (0x72d572b7a7e4c572), + U64_C (0x39e439d5dd72ec39), U64_C (0x4c2d4c5a6198164c), + U64_C (0x5e655eca3bbc945e), U64_C (0x78fd78e785f09f78), + U64_C (0x38e038ddd870e538), U64_C (0x8c0a8c148605988c), + U64_C (0xd163d1c6b2bf17d1), U64_C (0xa5aea5410b57e4a5), + U64_C (0xe2afe2434dd9a1e2), U64_C (0x6199612ff8c24e61), + U64_C (0xb3f6b3f1457b42b3), U64_C (0x21842115a5423421), + U64_C (0x9c4a9c94d625089c), U64_C (0x1e781ef0663cee1e), + U64_C (0x4311432252866143), U64_C (0xc73bc776fc93b1c7), + U64_C (0xfcd7fcb32be54ffc), U64_C (0x0410042014082404), + U64_C (0x515951b208a2e351), U64_C (0x995e99bcc72f2599), + U64_C (0x6da96d4fc4da226d), U64_C (0x0d340d68391a650d), + U64_C (0xfacffa8335e979fa), U64_C (0xdf5bdfb684a369df), + U64_C (0x7ee57ed79bfca97e), U64_C (0x2490243db4481924), + U64_C (0x3bec3bc5d776fe3b), U64_C (0xab96ab313d4b9aab), + U64_C (0xce1fce3ed181f0ce), U64_C (0x1144118855229911), + U64_C (0x8f068f0c8903838f), U64_C (0x4e254e4a6b9c044e), + U64_C (0xb7e6b7d1517366b7), U64_C (0xeb8beb0b60cbe0eb), + U64_C (0x3cf03cfdcc78c13c), U64_C (0x813e817cbf1ffd81), + U64_C (0x946a94d4fe354094), U64_C (0xf7fbf7eb0cf31cf7), + U64_C (0xb9deb9a1676f18b9), U64_C (0x134c13985f268b13), + U64_C (0x2cb02c7d9c58512c), U64_C (0xd36bd3d6b8bb05d3), + U64_C (0xe7bbe76b5cd38ce7), U64_C (0x6ea56e57cbdc396e), + U64_C (0xc437c46ef395aac4), U64_C (0x030c03180f061b03), + U64_C (0x5645568a13acdc56), U64_C (0x440d441a49885e44), + U64_C (0x7fe17fdf9efea07f), U64_C (0xa99ea921374f88a9), + U64_C (0x2aa82a4d8254672a), U64_C (0xbbd6bbb16d6b0abb), + U64_C (0xc123c146e29f87c1), U64_C (0x535153a202a6f153), + U64_C (0xdc57dcae8ba572dc), U64_C (0x0b2c0b582716530b), + U64_C (0x9d4e9d9cd327019d), U64_C (0x6cad6c47c1d82b6c), + U64_C (0x31c43195f562a431), U64_C (0x74cd7487b9e8f374), + U64_C (0xf6fff6e309f115f6), U64_C (0x4605460a438c4c46), + U64_C (0xac8aac092645a5ac), U64_C (0x891e893c970fb589), + U64_C (0x145014a04428b414), U64_C (0xe1a3e15b42dfbae1), + U64_C (0x165816b04e2ca616), U64_C (0x3ae83acdd274f73a), + U64_C (0x69b9696fd0d20669), U64_C (0x092409482d124109), + U64_C (0x70dd70a7ade0d770), U64_C (0xb6e2b6d954716fb6), + U64_C (0xd067d0ceb7bd1ed0), U64_C (0xed93ed3b7ec7d6ed), + U64_C (0xcc17cc2edb85e2cc), U64_C (0x4215422a57846842), + U64_C (0x985a98b4c22d2c98), U64_C (0xa4aaa4490e55eda4), + U64_C (0x28a0285d88507528), U64_C (0x5c6d5cda31b8865c), + U64_C (0xf8c7f8933fed6bf8), U64_C (0x86228644a411c286), + }; + + + +static void +whirlpool_init (void *ctx) +{ + whirlpool_context_t *context = ctx; + + memset (context, 0, sizeof (*context)); +} + + +/* + * Transform block. + */ +static void +whirlpool_transform (whirlpool_context_t *context, const unsigned char *data) +{ + whirlpool_block_t data_block; + whirlpool_block_t key; + whirlpool_block_t state; + whirlpool_block_t block; + unsigned int r; + unsigned int i; + + buffer_to_block (data, data_block, i); + block_copy (key, context->hash_state, i); + block_copy (state, context->hash_state, i); + block_xor (state, data_block, i); + + for (r = 0; r < R; r++) + { + /* Compute round key K^r. */ + + block[0] = (C0[(key[0] >> 56) & 0xFF] ^ C1[(key[7] >> 48) & 0xFF] ^ + C2[(key[6] >> 40) & 0xFF] ^ C3[(key[5] >> 32) & 0xFF] ^ + C4[(key[4] >> 24) & 0xFF] ^ C5[(key[3] >> 16) & 0xFF] ^ + C6[(key[2] >> 8) & 0xFF] ^ C7[(key[1] >> 0) & 0xFF] ^ rc[r]); + block[1] = (C0[(key[1] >> 56) & 0xFF] ^ C1[(key[0] >> 48) & 0xFF] ^ + C2[(key[7] >> 40) & 0xFF] ^ C3[(key[6] >> 32) & 0xFF] ^ + C4[(key[5] >> 24) & 0xFF] ^ C5[(key[4] >> 16) & 0xFF] ^ + C6[(key[3] >> 8) & 0xFF] ^ C7[(key[2] >> 0) & 0xFF]); + block[2] = (C0[(key[2] >> 56) & 0xFF] ^ C1[(key[1] >> 48) & 0xFF] ^ + C2[(key[0] >> 40) & 0xFF] ^ C3[(key[7] >> 32) & 0xFF] ^ + C4[(key[6] >> 24) & 0xFF] ^ C5[(key[5] >> 16) & 0xFF] ^ + C6[(key[4] >> 8) & 0xFF] ^ C7[(key[3] >> 0) & 0xFF]); + block[3] = (C0[(key[3] >> 56) & 0xFF] ^ C1[(key[2] >> 48) & 0xFF] ^ + C2[(key[1] >> 40) & 0xFF] ^ C3[(key[0] >> 32) & 0xFF] ^ + C4[(key[7] >> 24) & 0xFF] ^ C5[(key[6] >> 16) & 0xFF] ^ + C6[(key[5] >> 8) & 0xFF] ^ C7[(key[4] >> 0) & 0xFF]); + block[4] = (C0[(key[4] >> 56) & 0xFF] ^ C1[(key[3] >> 48) & 0xFF] ^ + C2[(key[2] >> 40) & 0xFF] ^ C3[(key[1] >> 32) & 0xFF] ^ + C4[(key[0] >> 24) & 0xFF] ^ C5[(key[7] >> 16) & 0xFF] ^ + C6[(key[6] >> 8) & 0xFF] ^ C7[(key[5] >> 0) & 0xFF]); + block[5] = (C0[(key[5] >> 56) & 0xFF] ^ C1[(key[4] >> 48) & 0xFF] ^ + C2[(key[3] >> 40) & 0xFF] ^ C3[(key[2] >> 32) & 0xFF] ^ + C4[(key[1] >> 24) & 0xFF] ^ C5[(key[0] >> 16) & 0xFF] ^ + C6[(key[7] >> 8) & 0xFF] ^ C7[(key[6] >> 0) & 0xFF]); + block[6] = (C0[(key[6] >> 56) & 0xFF] ^ C1[(key[5] >> 48) & 0xFF] ^ + C2[(key[4] >> 40) & 0xFF] ^ C3[(key[3] >> 32) & 0xFF] ^ + C4[(key[2] >> 24) & 0xFF] ^ C5[(key[1] >> 16) & 0xFF] ^ + C6[(key[0] >> 8) & 0xFF] ^ C7[(key[7] >> 0) & 0xFF]); + block[7] = (C0[(key[7] >> 56) & 0xFF] ^ C1[(key[6] >> 48) & 0xFF] ^ + C2[(key[5] >> 40) & 0xFF] ^ C3[(key[4] >> 32) & 0xFF] ^ + C4[(key[3] >> 24) & 0xFF] ^ C5[(key[2] >> 16) & 0xFF] ^ + C6[(key[1] >> 8) & 0xFF] ^ C7[(key[0] >> 0) & 0xFF]); + block_copy (key, block, i); + + /* Apply r-th round transformation. */ + + block[0] = (C0[(state[0] >> 56) & 0xFF] ^ C1[(state[7] >> 48) & 0xFF] ^ + C2[(state[6] >> 40) & 0xFF] ^ C3[(state[5] >> 32) & 0xFF] ^ + C4[(state[4] >> 24) & 0xFF] ^ C5[(state[3] >> 16) & 0xFF] ^ + C6[(state[2] >> 8) & 0xFF] ^ C7[(state[1] >> 0) & 0xFF] ^ key[0]); + block[1] = (C0[(state[1] >> 56) & 0xFF] ^ C1[(state[0] >> 48) & 0xFF] ^ + C2[(state[7] >> 40) & 0xFF] ^ C3[(state[6] >> 32) & 0xFF] ^ + C4[(state[5] >> 24) & 0xFF] ^ C5[(state[4] >> 16) & 0xFF] ^ + C6[(state[3] >> 8) & 0xFF] ^ C7[(state[2] >> 0) & 0xFF] ^ key[1]); + block[2] = (C0[(state[2] >> 56) & 0xFF] ^ C1[(state[1] >> 48) & 0xFF] ^ + C2[(state[0] >> 40) & 0xFF] ^ C3[(state[7] >> 32) & 0xFF] ^ + C4[(state[6] >> 24) & 0xFF] ^ C5[(state[5] >> 16) & 0xFF] ^ + C6[(state[4] >> 8) & 0xFF] ^ C7[(state[3] >> 0) & 0xFF] ^ key[2]); + block[3] = (C0[(state[3] >> 56) & 0xFF] ^ C1[(state[2] >> 48) & 0xFF] ^ + C2[(state[1] >> 40) & 0xFF] ^ C3[(state[0] >> 32) & 0xFF] ^ + C4[(state[7] >> 24) & 0xFF] ^ C5[(state[6] >> 16) & 0xFF] ^ + C6[(state[5] >> 8) & 0xFF] ^ C7[(state[4] >> 0) & 0xFF] ^ key[3]); + block[4] = (C0[(state[4] >> 56) & 0xFF] ^ C1[(state[3] >> 48) & 0xFF] ^ + C2[(state[2] >> 40) & 0xFF] ^ C3[(state[1] >> 32) & 0xFF] ^ + C4[(state[0] >> 24) & 0xFF] ^ C5[(state[7] >> 16) & 0xFF] ^ + C6[(state[6] >> 8) & 0xFF] ^ C7[(state[5] >> 0) & 0xFF] ^ key[4]); + block[5] = (C0[(state[5] >> 56) & 0xFF] ^ C1[(state[4] >> 48) & 0xFF] ^ + C2[(state[3] >> 40) & 0xFF] ^ C3[(state[2] >> 32) & 0xFF] ^ + C4[(state[1] >> 24) & 0xFF] ^ C5[(state[0] >> 16) & 0xFF] ^ + C6[(state[7] >> 8) & 0xFF] ^ C7[(state[6] >> 0) & 0xFF] ^ key[5]); + block[6] = (C0[(state[6] >> 56) & 0xFF] ^ C1[(state[5] >> 48) & 0xFF] ^ + C2[(state[4] >> 40) & 0xFF] ^ C3[(state[3] >> 32) & 0xFF] ^ + C4[(state[2] >> 24) & 0xFF] ^ C5[(state[1] >> 16) & 0xFF] ^ + C6[(state[0] >> 8) & 0xFF] ^ C7[(state[7] >> 0) & 0xFF] ^ key[6]); + block[7] = (C0[(state[7] >> 56) & 0xFF] ^ C1[(state[6] >> 48) & 0xFF] ^ + C2[(state[5] >> 40) & 0xFF] ^ C3[(state[4] >> 32) & 0xFF] ^ + C4[(state[3] >> 24) & 0xFF] ^ C5[(state[2] >> 16) & 0xFF] ^ + C6[(state[1] >> 8) & 0xFF] ^ C7[(state[0] >> 0) & 0xFF] ^ key[7]); + block_copy (state, block, i); + } + + /* Compression. */ + + block_xor (context->hash_state, data_block, i); + block_xor (context->hash_state, state, i); +} + +static void +whirlpool_add (whirlpool_context_t *context, + const void *buffer_arg, size_t buffer_n) +{ + const unsigned char *buffer = buffer_arg; + u64 buffer_size; + unsigned int carry; + unsigned int i; + + buffer_size = buffer_n; + + if (context->count == BLOCK_SIZE) + { + /* Flush the buffer. */ + whirlpool_transform (context, context->buffer); + /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ + context->count = 0; + } + if (! buffer) + return; /* Nothing to add. */ + + if (context->count) + { + while (buffer_n && (context->count < BLOCK_SIZE)) + { + context->buffer[context->count++] = *buffer++; + buffer_n--; + } + whirlpool_add (context, NULL, 0); + if (!buffer_n) + /* Done. */ + return; + } + /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ + + while (buffer_n >= BLOCK_SIZE) + { + whirlpool_transform (context, buffer); + context->count = 0; + buffer_n -= BLOCK_SIZE; + buffer += BLOCK_SIZE; + } + while (buffer_n && (context->count < BLOCK_SIZE)) + { + context->buffer[context->count++] = *buffer++; + buffer_n--; + } + + /* Update bit counter. */ + carry = 0; + buffer_size <<= 3; + for (i = 1; i <= 32; i++) + { + if (! (buffer_size || carry)) + break; + + carry += context->length[32 - i] + (buffer_size & 0xFF); + context->length[32 - i] = carry; + buffer_size >>= 8; + carry >>= 8; + } + gcry_assert (! (buffer_size || carry)); +} + +static void +whirlpool_write (void *ctx, const void *buffer, size_t buffer_n) +{ + whirlpool_context_t *context = ctx; + + whirlpool_add (context, buffer, buffer_n); +} + +static void +whirlpool_final (void *ctx) +{ + whirlpool_context_t *context = ctx; + unsigned int i; + + /* Flush. */ + whirlpool_add (context, NULL, 0); + + /* Pad. */ + context->buffer[context->count++] = 0x80; + + if (context->count > 32) + { + /* An extra block is necessary. */ + while (context->count < 64) + context->buffer[context->count++] = 0; + whirlpool_add (context, NULL, 0); + } + while (context->count < 32) + context->buffer[context->count++] = 0; + + /* Add length of message. */ + memcpy (context->buffer + context->count, context->length, 32); + context->count += 32; + whirlpool_add (context, NULL, 0); + + block_to_buffer (context->buffer, context->hash_state, i); +} + +static byte * +whirlpool_read (void *ctx) +{ + whirlpool_context_t *context = ctx; + + return context->buffer; +} + +gcry_md_spec_t _gcry_digest_spec_whirlpool = + { + "WHIRLPOOL", NULL, 0, NULL, 64, + whirlpool_init, whirlpool_write, whirlpool_final, whirlpool_read, + sizeof (whirlpool_context_t) + , +#ifdef GRUB_UTIL + .modname = "gcry_whirlpool", +#endif + .blocksize = 64 + }; + + +GRUB_MOD_INIT(gcry_whirlpool) +{ + COMPILE_TIME_ASSERT(sizeof (whirlpool_context_t) <= GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + grub_md_register (&_gcry_digest_spec_whirlpool); +} + +GRUB_MOD_FINI(gcry_whirlpool) +{ + grub_md_unregister (&_gcry_digest_spec_whirlpool); +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/generic/Manifest b/grub-core/lib/libgcrypt-grub/mpi/generic/Manifest new file mode 100644 index 0000000..c429fde --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/generic/Manifest @@ -0,0 +1,29 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +mpih-add1.c iQCVAwUAP+Lj2DEAnp832S/7AQKn/AQAwQLWggl6zNQ5EZ+lE+jKV8W3FsogW3/6tp9T5rrSR5JnlWyoHQ9/Pu4knOcLjS6nIfVOiAEifu3nuIysQr9jDSSSJA2LylSUBSXKLKDamPsOCwXOLxiZODslJT3CCGAUtLvXJrWDbTZQrkEuwnLnjQFDzuA7iY9JLrG9kAoXD6Q==WoWm +mpih-mul1.c iQCVAwUAP+LkCTEAnp832S/7AQKFVQP+MhBNjcY73JtnsHZfnaVZq3TiKwN151cWV51nDc1RnTaMhSIFeuNlj3vNML2W0Gn8n+GnyiWE2XXdQEaik6BL02eekUn9aq7I/rdpnTHuOjQPK1uwjuNl8RuJ9YrERBAxq4oB71f+iwMab8dsMSUlVC+NdeAocRqLLgnR/efkdLc==2Tkb +mpih-mul2.c iQCVAwUAP+LkMjEAnp832S/7AQLPeAQAqmRzxFe/mDqTdZr/pTXT8RVyB1vKB0Ei2THV05BxmI4OPv39uysfFpLMt/INsX7AGqdOlj4jOZ/qNaFXR1ceMrlSXvo8u/epk6rCXFp82kM7Qs983LjoP//PrMCkYkXwblaVrgUGiBUCbuPMliWTK6qKkxxXtEfqZ7nVbEWdBx8==Kwhl +mpih-mul3.c iQCVAwUAP+LkVDEAnp832S/7AQL91gP/Qd5iZWxRiN5DdEIVHAedoNvl23NPrT2UUdXvnSK49DpplTxkLiMBj0WqCayG/YIET2NpMRCeLvAZNcSt6lOm0bSZDYo1Hv/N+UoqD3V1McjY16REBv/nnPaMWMZcx7rl5yKTVZiX2PgV6oQOL7Yfrt5ZIOlrHBRs9S2/zcCaVz0==9BQe +mpih-lshift.c iQCVAwUAP+LlATEAnp832S/7AQIACAQAhMrpx0SRXE/LN1NkjMO9n74nMrvmzYJyru0gw2O4BYrUPvD/LWGju2FZaggKV0IBjmi0cDoCrNeK9EGjKOO1lfgODbX2IZ1LUhr9jDuMj0QRqj6T9YkAFYTNUk4GfpwIf7T6Ybo7c78Jx93PidCJt7d39eMMEalooC7LZ4IU3NM==nZ4k +mpih-rshift.c iQCVAwUAP+LlIjEAnp832S/7AQKiuAP/eYC2ZScd+taBx/kNzRvGjA0eAXvORMkMLV6Ot+OXVzVUi04eoP2yXdxSNFKwUj12p8GWXkdoMG3aOGBKg2a7bY5Q5RUho3hUWb9UsVYVUfXLf7IOTt/3a6MLh2CmV5dFPWJmSlbCyQRcn6n/fLDeJ3A2bWTS/BhqGfpOXUIU1ws==jCf8 +mpih-sub1.c iQCVAwUAP+LlZzEAnp832S/7AQIEPgP/dLHTDRbPrYJhsLp9SjGstU1M8/IC5XytcDtO3NQeu4mx6vaXjpujtsTvKIbX4QL5IahNntVVKv1xFLEm2yFg7L2ns0uD/mfwGgOhCG1j2o/SaTAWP5KxP7ae5UDcZl2w6NWvEuMj9t32zmziAZjP8W73A37FUspeRDYiL9sQzkI==QQzk +udiv-w-sdiv.c iQCVAwUAP+Lk0TEAnp832S/7AQICXAQAsxe1SQD4+xZaZTqBC0V9Cyuo0mrdccnRFzthOtm0ARwKFXU2cuLW/ZBOkmeWOVmOFhBp22/I8dEGYnMA3gcfmOMCpNu9i9zk/XHfptdunA1MnOe3GsoWgfHL0rhpAyPhp/X043ICB41NElnnuxADuQQlD4Z1fca5ygYxMr2crJg==EI/6 +mpi-asm-defs.h iQCVAwUAP+LkgDEAnp832S/7AQK0FgQAxJZ7xvXhoZa33GWe23LRb3asrno/loZSyAIXrntqtVH8M3pEsCY0OyW4ry4hX2RnxpuhRCM/PdRNLG3xXyMSVIhkHU8WVRLqzF2LLjEkyU3cAmHnnTQ9aO/XpUWtJGTZ8q2bv7ZsAEi4aPl0p6KhPXcPgM9vQ2XcyOPn3Dl0d6Q==xpjI +$names$ iQCVAwUAP+LmNDEAnp832S/7AQJa+gP+KQNJpbNOgc+s2UX+Ya2gDaOFcAROImIllhg3ej8EaBF8xxdHmWT1zaKwTwi3moEEleykMR104YAGWyQeMbFYiuPPBW+ohrT6KxRBVJpIA9auOOqqJMyglZyoR3Hv7gduVYUW1h/DebnqiKXKEfzQDFqYuT0ayuteoOR4B5NICbE==nLSh diff --git a/grub-core/lib/libgcrypt-grub/mpi/generic/distfiles b/grub-core/lib/libgcrypt-grub/mpi/generic/distfiles new file mode 100644 index 0000000..9810eef --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/generic/distfiles @@ -0,0 +1,11 @@ +Manifest +mpih-add1.c +mpih-mul1.c +mpih-mul2.c +mpih-mul3.c +mpih-lshift.c +mpih-rshift.c +mpih-sub1.c +udiv-w-sdiv.c +mpi-asm-defs.h + diff --git a/grub-core/lib/libgcrypt-grub/mpi/generic/mpi-asm-defs.h b/grub-core/lib/libgcrypt-grub/mpi/generic/mpi-asm-defs.h new file mode 100644 index 0000000..13424e2 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/generic/mpi-asm-defs.h @@ -0,0 +1,10 @@ +/* This file defines some basic constants for the MPI machinery. We + * need to define the types on a per-CPU basis, so it is done with + * this file here. */ +#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG) + + + + + + diff --git a/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-add1.c b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-add1.c new file mode 100644 index 0000000..4a84df6 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-add1.c @@ -0,0 +1,65 @@ +/* mpihelp-add_1.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, + * 2000, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +_gcry_mpih_add_n (mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size) +{ + mpi_limb_t x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to one addend */ + cy = y < cy; /* get out carry from that addition */ + y += x; /* add other addend */ + cy += y < x; /* get out carry from that add, combine */ + res_ptr[j] = y; + } + while ( ++j ); + + return cy; +} + diff --git a/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-lshift.c b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-lshift.c new file mode 100644 index 0000000..f48c12c --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-lshift.c @@ -0,0 +1,68 @@ +/* mpi-lshift.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + +/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left + * and store the USIZE least significant digits of the result at WP. + * Return the bits shifted out from the most significant digit. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be >= UP. + */ + +mpi_limb_t +_gcry_mpih_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned int cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp += 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + i = usize - 1; + low_limb = up[i]; + retval = low_limb >> sh_2; + high_limb = low_limb; + while ( --i >= 0 ) + { + low_limb = up[i]; + wp[i] = (high_limb << sh_1) | (low_limb >> sh_2); + high_limb = low_limb; + } + wp[i] = high_limb << sh_1; + + return retval; +} + + diff --git a/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-mul1.c b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-mul1.c new file mode 100644 index 0000000..0e8197d --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-mul1.c @@ -0,0 +1,62 @@ +/* mpihelp-mul_1.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +_gcry_mpih_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + + /* The loop counter and index J goes from -S1_SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + res_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + res_ptr[j] = prod_low; + } + while( ++j ); + + return cy_limb; +} + diff --git a/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-mul2.c b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-mul2.c new file mode 100644 index 0000000..3b75496 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-mul2.c @@ -0,0 +1,68 @@ +/* mpih-mul2.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +mpi_limb_t +_gcry_mpih_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x + prod_low; + cy_limb += prod_low < x?1:0; + res_ptr[j] = prod_low; + } + while ( ++j ); + + return cy_limb; +} + + diff --git a/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-mul3.c b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-mul3.c new file mode 100644 index 0000000..5e84f94 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-mul3.c @@ -0,0 +1,68 @@ +/* mpih-mul3.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +mpi_limb_t +_gcry_mpih_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x - prod_low; + cy_limb += prod_low > x?1:0; + res_ptr[j] = prod_low; + } + while( ++j ); + + return cy_limb; +} + + diff --git a/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-rshift.c b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-rshift.c new file mode 100644 index 0000000..e40794f --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-rshift.c @@ -0,0 +1,67 @@ +/* mpih-rshift.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 1999, + * 2000, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + + +/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right + * and store the USIZE least significant limbs of the result at WP. + * The bits shifted out to the right are returned. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be <= UP. + */ + +mpi_limb_t +_gcry_mpih_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp -= 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + high_limb = up[0]; + retval = high_limb << sh_2; + low_limb = high_limb; + for (i=1; i < usize; i++) + { + high_limb = up[i]; + wp[i] = (low_limb >> sh_1) | (high_limb << sh_2); + low_limb = high_limb; + } + wp[i] = low_limb >> sh_1; + + return retval; +} + diff --git a/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-sub1.c b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-sub1.c new file mode 100644 index 0000000..e88821b --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/generic/mpih-sub1.c @@ -0,0 +1,66 @@ +/* mpihelp-add_2.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +_gcry_mpih_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size) +{ + mpi_limb_t x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to subtrahend */ + cy = y < cy; /* get out carry from that addition */ + y = x - y; /* main subtract */ + cy += y > x; /* get out carry from the subtract, combine */ + res_ptr[j] = y; + } + while( ++j ); + + return cy; +} + + diff --git a/grub-core/lib/libgcrypt-grub/mpi/generic/udiv-w-sdiv.c b/grub-core/lib/libgcrypt-grub/mpi/generic/udiv-w-sdiv.c new file mode 100644 index 0000000..e80d98b --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/generic/udiv-w-sdiv.c @@ -0,0 +1,133 @@ +/* mpih-w-sdiv -- implement udiv_qrnnd on machines with only signed + * division. + * Copyright (C) 1992, 1994, 1996, 1998, 2002 Free Software Foundation, Inc. + * Contributed by Peter L. Montgomery. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +#if 0 /* not yet ported to MPI */ + +mpi_limb_t +mpihelp_udiv_w_sdiv( mpi_limp_t *rp, + mpi_limp_t *a1, + mpi_limp_t *a0, + mpi_limp_t *d ) +{ + mp_limb_t q, r; + mp_limb_t c0, c1, b1; + + if ((mpi_limb_signed_t) d >= 0) + { + if (a1 < d - a1 - (a0 >> (BITS_PER_MP_LIMB - 1))) + { + /* dividend, divisor, and quotient are nonnegative */ + sdiv_qrnnd (q, r, a1, a0, d); + } + else + { + /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ + sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (BITS_PER_MP_LIMB - 1)); + /* Divide (c1*2^32 + c0) by d */ + sdiv_qrnnd (q, r, c1, c0, d); + /* Add 2^31 to quotient */ + q += (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1); + } + } + else + { + b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */ + c1 = a1 >> 1; /* A/2 */ + c0 = (a1 << (BITS_PER_MP_LIMB - 1)) + (a0 >> 1); + + if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */ + { + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */ + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */ + { + c1 = (b1 - 1) - c1; + c0 = ~c0; /* logical NOT */ + + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + q = ~q; /* (A/2)/b1 */ + r = (b1 - 1) - r; + + r = 2*r + (a0 & 1); /* A/(2*b1) */ + + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else /* Implies c1 = b1 */ + { /* Hence a1 = d - 1 = 2*b1 - 1 */ + if (a0 >= -d) + { + q = -1; + r = a0 + d; + } + else + { + q = -2; + r = a0 + 2*d; + } + } + } + + *rp = r; + return q; +} + +#endif + diff --git a/grub-core/lib/libgcrypt-grub/mpi/longlong.h b/grub-core/lib/libgcrypt-grub/mpi/longlong.h new file mode 100644 index 0000000..37a9b9a --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/longlong.h @@ -0,0 +1,1615 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Note: I added some stuff for use with gnupg + +Copyright (C) 1991, 1992, 1993, 1994, 1996, 1998, + 2000, 2001, 2002, 2003, 2004, 2011 Free Software Foundation, Inc. + +This file is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with this file; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. +*/ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +/* This is used to make sure no undesirable sharing between different libraries + that use this file takes place. */ +#ifndef __MPN +#define __MPN(x) __##x +#endif + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two + UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first non-zero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! */ + +#ifdef __riscos__ +#pragma continue_after_hash_error +#else /* !__riscos__ */ +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + + +/*************************************** + ************** A29K ***************** + ***************************************/ +#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %1,%4,%5\n" \ + "addc %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %1,%4,%5\n" \ + "subc %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("multiplu %0,%1,%2" \ + : "=r" ((USItype)(xl)) \ + : "r" (__m0), \ + "r" (__m1)); \ + __asm__ ("multmu %0,%1,%2" \ + : "=r" ((USItype)(xh)) \ + : "r" (__m0), \ + "r" (__m1)); \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("dividu %0,%3,%4" \ + : "=r" ((USItype)(q)), \ + "=q" ((USItype)(r)) \ + : "1" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))) +#define COUNT_LEADING_ZEROS_0 32 +#endif /* __a29k__ */ + + +#if defined (__alpha) && W_TYPE_SIZE == 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("umulh %r1,%2,%0" \ + : "=r" ((UDItype) ph) \ + : "%rJ" (__m0), \ + "rI" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 46 +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UDItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UDItype __udiv_qrnnd (); +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ +#endif /* __alpha */ + +/*************************************** + ************** ARM ****************** + ***************************************/ +#if defined (__arm__) && W_TYPE_SIZE == 32 && \ + (!defined (__thumb__) || defined (__thumb2__)) +/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */ +#ifndef __ARM_ARCH +# ifdef __ARM_ARCH_2__ +# define __ARM_ARCH 2 +# elif defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__) +# define __ARM_ARCH 3 +# elif defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__) +# define __ARM_ARCH 4 +# elif defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5E__) \ + || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) +# define __ARM_ARCH 5 +# elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ + || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) +# define __ARM_ARCH 6 +# elif defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7EM__) +# define __ARM_ARCH 7 +# else + /* could not detect? */ +# endif +#endif +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds %1, %4, %5\n" \ + "adc %0, %2, %3" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "%r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl)) __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs %1, %4, %5\n" \ + "sbc %0, %2, %3" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "r" ((USItype)(al)), \ + "rI" ((USItype)(bl)) __CLOBBER_CC) +#if (defined __ARM_ARCH && __ARM_ARCH <= 3) +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("@ Inlined umul_ppmm\n" \ + "mov %|r0, %2, lsr #16 @ AAAA\n" \ + "mov %|r2, %3, lsr #16 @ BBBB\n" \ + "bic %|r1, %2, %|r0, lsl #16 @ aaaa\n" \ + "bic %0, %3, %|r2, lsl #16 @ bbbb\n" \ + "mul %1, %|r1, %|r2 @ aaaa * BBBB\n" \ + "mul %|r2, %|r0, %|r2 @ AAAA * BBBB\n" \ + "mul %|r1, %0, %|r1 @ aaaa * bbbb\n" \ + "mul %0, %|r0, %0 @ AAAA * bbbb\n" \ + "adds %|r0, %1, %0 @ central sum\n" \ + "addcs %|r2, %|r2, #65536\n" \ + "adds %1, %|r1, %|r0, lsl #16\n" \ + "adc %0, %|r2, %|r0, lsr #16" \ + : "=&r" ((xh)), \ + "=r" ((xl)) \ + : "r" ((USItype)(a)), \ + "r" ((USItype)(b)) \ + : "r0", "r1", "r2" __AND_CLOBBER_CC) +#else /* __ARM_ARCH >= 4 */ +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("@ Inlined umul_ppmm\n" \ + "umull %1, %0, %2, %3" \ + : "=&r" ((xh)), \ + "=r" ((xl)) \ + : "r" ((USItype)(a)), \ + "r" ((USItype)(b))) +#endif /* __ARM_ARCH >= 4 */ +#define UMUL_TIME 20 +#define UDIV_TIME 100 +#if (defined __ARM_ARCH && __ARM_ARCH >= 5) +#define count_leading_zeros(count, x) \ + __asm__ ("clz %0, %1" \ + : "=r" ((count)) \ + : "r" ((USItype)(x))) +#endif /* __ARM_ARCH >= 5 */ +#endif /* __arm__ */ + +/*************************************** + ************** CLIPPER ************** + ***************************************/ +#if defined (__clipper__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__xx.__ll) \ + : "%0" ((USItype)(u)), \ + "r" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define smul_ppmm(w1, w0, u, v) \ + ({union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("mulwx %2,%0" \ + : "=r" (__xx.__ll) \ + : "%0" ((SItype)(u)), \ + "r" ((SItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__w) \ + : "%0" ((USItype)(u)), \ + "r" ((USItype)(v))); \ + __w; }) +#endif /* __clipper__ */ + + +/*************************************** + ************** GMICRO *************** + ***************************************/ +#if defined (__gmicro__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.w %5,%1\n" \ + "addx %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.w %5,%1\n" \ + "subx %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + __asm__ ("mulx %3,%0,%1" \ + : "=g" ((USItype)(ph)), \ + "=r" ((USItype)(pl)) \ + : "%0" ((USItype)(m0)), \ + "g" ((USItype)(m1))) +#define udiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("divx %4,%0,%1" \ + : "=g" ((USItype)(q)), \ + "=r" ((USItype)(r)) \ + : "1" ((USItype)(nh)), \ + "0" ((USItype)(nl)), \ + "g" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("bsch/1 %1,%0" \ + : "=g" (count) \ + : "g" ((USItype)(x)), \ + "0" ((USItype)0)) +#endif + + +/*************************************** + ************** HPPA ***************** + ***************************************/ +#if defined (__hppa) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ (" add %4,%5,%1\n" \ + " addc %2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rM" ((USItype)(ah)), \ + "rM" ((USItype)(bh)), \ + "%rM" ((USItype)(al)), \ + "rM" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ (" sub %4,%5,%1\n" \ + " subb %2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rM" ((USItype)(ah)), \ + "rM" ((USItype)(bh)), \ + "rM" ((USItype)(al)), \ + "rM" ((USItype)(bl))) +#if defined (_PA_RISC1_1) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ (" xmpyu %1,%2,%0" \ + : "=*f" (__xx.__ll) \ + : "*f" ((USItype)(u)), \ + "*f" ((USItype)(v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define UMUL_TIME 8 +#define UDIV_TIME 60 +#else +#define UMUL_TIME 40 +#define UDIV_TIME 80 +#endif +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { USItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern USItype __udiv_qrnnd (); +#endif /* LONGLONG_STANDALONE */ +#define count_leading_zeros(count, x) \ + do { \ + USItype __tmp; \ + __asm__ ( \ + " ldi 1,%0 \n" \ + " extru,= %1,15,16,%%r0 ; Bits 31..16 zero? \n" \ + " extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ + " ldo 16(%0),%0 ; Yes. Perform add. \n" \ + " extru,= %1,23,8,%%r0 ; Bits 15..8 zero? \n" \ + " extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ + " ldo 8(%0),%0 ; Yes. Perform add. \n" \ + " extru,= %1,27,4,%%r0 ; Bits 7..4 zero? \n" \ + " extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ + " ldo 4(%0),%0 ; Yes. Perform add. \n" \ + " extru,= %1,29,2,%%r0 ; Bits 3..2 zero? \n" \ + " extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ + " ldo 2(%0),%0 ; Yes. Perform add. \n" \ + " extru %1,30,1,%1 ; Extract bit 1. \n" \ + " sub %0,%1,%0 ; Subtract it. " \ + : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif /* hppa */ + + +/*************************************** + ************** I370 ***************** + ***************************************/ +#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32 +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "r" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (m0), \ + "r" (m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("dr %0,%2" \ + : "=r" (__xx.__ll) \ + : "0" (__xx.__ll), "r" (d)); \ + (q) = __xx.__i.__l; (r) = __xx.__i.__h; \ + } while (0) +#endif + + +/*************************************** + ************** I386 ***************** + ***************************************/ +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl %5,%1\n" \ + "adcl %3,%0" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%1\n" \ + "sbbl %3,%0" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl)) \ + __CLOBBER_CC) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mull %3" \ + : "=a" ((w0)), \ + "=d" ((w1)) \ + : "%0" ((USItype)(u)), \ + "rm" ((USItype)(v)) \ + __CLOBBER_CC) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divl %4" \ + : "=a" ((q)), \ + "=d" ((r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "rm" ((USItype)(d)) \ + __CLOBBER_CC) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("bsrl %1,%0" \ + : "=r" (__cbtmp) : "rm" ((USItype)(x)) \ + __CLOBBER_CC); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define count_trailing_zeros(count, x) \ + __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)) __CLOBBER_CC) +#ifndef UMUL_TIME +#define UMUL_TIME 40 +#endif +#ifndef UDIV_TIME +#define UDIV_TIME 40 +#endif +#endif /* 80x86 */ + + +/*************************************** + ************** I860 ***************** + ***************************************/ +#if defined (__i860__) && W_TYPE_SIZE == 32 +#define rshift_rhlc(r,h,l,c) \ + __asm__ ("shr %3,r0,r0\n" \ + "shrd %1,%2,%0" \ + "=r" (r) : "r" (h), "r" (l), "rn" (c)) +#endif /* i860 */ + +/*************************************** + ************** I960 ***************** + ***************************************/ +#if defined (__i960__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 1,0\n" \ + "addc %5,%4,%1\n" \ + "addc %3,%2,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%dI" ((USItype)(ah)), \ + "dI" ((USItype)(bh)), \ + "%dI" ((USItype)(al)), \ + "dI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 0,0\n" \ + "subc %5,%4,%1\n" \ + "subc %3,%2,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "dI" ((USItype)(ah)), \ + "dI" ((USItype)(bh)), \ + "dI" ((USItype)(al)), \ + "dI" ((USItype)(bl))) +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__xx.__ll) \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__w) \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (nh); __nn.__i.__l = (nl); \ + __asm__ ("ediv %d,%n,%0" \ + : "=d" (__rq.__ll) \ + : "dI" (__nn.__ll), \ + "dI" ((USItype)(d))); \ + (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ + } while (0) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("scanbit %1,%0" \ + : "=r" (__cbtmp) \ + : "r" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ +#if defined (__i960mx) /* what is the proper symbol to test??? */ +#define rshift_rhlc(r,h,l,c) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (h); __nn.__i.__l = (l); \ + __asm__ ("shre %2,%1,%0" \ + : "=d" (r) : "dI" (__nn.__ll), "dI" (c)); \ + } +#endif /* i960mx */ +#endif /* i960 */ + + +/*************************************** + ************** 68000 **************** + ***************************************/ +#if (defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%.l %5,%1\n" \ + "addx%.l %3,%0" \ + : "=d" ((USItype)(sh)), \ + "=&d" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "d" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%.l %5,%1\n" \ + "subx%.l %3,%0" \ + : "=d" ((USItype)(sh)), \ + "=&d" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "d" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "dmi" ((USItype)(v))) +#define UMUL_TIME 45 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divu%.l %4,%1:%0" \ + : "=d" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +#define UDIV_TIME 90 +#define sdiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divs%.l %4,%1:%0" \ + : "=d" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" ((USItype)(count)) \ + : "od" ((USItype)(x)), "n" (0)) +#define COUNT_LEADING_ZEROS_0 32 +#else /* not mc68020 */ +#define umul_ppmm(xh, xl, a, b) \ + do { USItype __umul_tmp1, __umul_tmp2; \ + __asm__ ("| Inlined umul_ppmm \n" \ + " move%.l %5,%3 \n" \ + " move%.l %2,%0 \n" \ + " move%.w %3,%1 \n" \ + " swap %3 \n" \ + " swap %0 \n" \ + " mulu %2,%1 \n" \ + " mulu %3,%0 \n" \ + " mulu %2,%3 \n" \ + " swap %2 \n" \ + " mulu %5,%2 \n" \ + " add%.l %3,%2 \n" \ + " jcc 1f \n" \ + " add%.l %#0x10000,%0 \n" \ + "1: move%.l %2,%3 \n" \ + " clr%.w %2 \n" \ + " swap %2 \n" \ + " swap %3 \n" \ + " clr%.w %3 \n" \ + " add%.l %3,%1 \n" \ + " addx%.l %2,%0 \n" \ + " | End inlined umul_ppmm" \ + : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)), \ + "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \ + : "%2" ((USItype)(a)), "d" ((USItype)(b))); \ + } while (0) +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#endif /* not mc68020 */ +#endif /* mc68000 */ + + +/*************************************** + ************** 88000 **************** + ***************************************/ +#if defined (__m88000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addu.co %1,%r4,%r5\n" \ + "addu.ci %0,%r2,%r3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rJ" ((USItype)(ah)), \ + "rJ" ((USItype)(bh)), \ + "%rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subu.co %1,%r4,%r5\n" \ + "subu.ci %0,%r2,%r3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rJ" ((USItype)(ah)), \ + "rJ" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("ff1 %0,%1" \ + : "=r" (__cbtmp) \ + : "r" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__m88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("mulu.d %0,%1,%2" : "=r" (__x.__ll) : "r" (u), "r" (v)); \ + (wh) = __x.__i.__h; \ + (wl) = __x.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x, __q; \ + __x.__i.__h = (n1); __x.__i.__l = (n0); \ + __asm__ ("divu.d %0,%1,%2" \ + : "=r" (__q.__ll) : "r" (__x.__ll), "r" (d)); \ + (r) = (n0) - __q.__l * (d); (q) = __q.__l; }) +#define UMUL_TIME 5 +#define UDIV_TIME 25 +#else +#define UMUL_TIME 17 +#define UDIV_TIME 150 +#endif /* __m88110__ */ +#endif /* __m88000__ */ + +/*************************************** + ************** MIPS ***************** + ***************************************/ +#if defined (__mips__) && W_TYPE_SIZE == 32 +#if defined (__clang__) || (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UDItype _r; \ + _r = (UDItype) u * v; \ + (w1) = _r >> 32; \ + (w0) = (USItype) _r; \ + } while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3" \ + : "=l" ((USItype)(w0)), \ + "=h" ((USItype)(w1)) \ + : "d" ((USItype)(u)), \ + "d" ((USItype)(v))) +#else +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3 \n" \ + "mflo %0 \n" \ + "mfhi %1" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "d" ((USItype)(u)), \ + "d" ((USItype)(v))) +#endif +#define UMUL_TIME 10 +#define UDIV_TIME 100 +#endif /* __mips__ */ + +/*************************************** + ************** MIPS/64 ************** + ***************************************/ +#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64 +#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +typedef unsigned int UTItype __attribute__ ((mode (TI))); +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UTItype _r; \ + _r = (UTItype) u * v; \ + (w1) = _r >> 64; \ + (w0) = (UDItype) _r; \ + } while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3" \ + : "=l" ((UDItype)(w0)), \ + "=h" ((UDItype)(w1)) \ + : "d" ((UDItype)(u)), \ + "d" ((UDItype)(v))) +#else +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3 \n" \ + "mflo %0 \n" \ + "mfhi %1" \ + : "=d" ((UDItype)(w0)), \ + "=d" ((UDItype)(w1)) \ + : "d" ((UDItype)(u)), \ + "d" ((UDItype)(v))) +#endif +#define UMUL_TIME 20 +#define UDIV_TIME 140 +#endif /* __mips__ */ + + +/*************************************** + ************** 32000 **************** + ***************************************/ +#if defined (__ns32000__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("meid %2,%0" \ + : "=g" (__xx.__ll) \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("deid %2,%0" \ + : "=g" (__xx.__ll) \ + : "0" (__xx.__ll), \ + "g" ((USItype)(d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +#define count_trailing_zeros(count,x) \ + do { + __asm__ ("ffsd %2,%0" \ + : "=r" ((USItype) (count)) \ + : "0" ((USItype) 0), \ + "r" ((USItype) (x))); \ + } while (0) +#endif /* __ns32000__ */ + + +/*************************************** + ************** PPC ****************** + ***************************************/ +#if (defined (_ARCH_PPC) || defined (_IBMR2)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "%r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("{cntlz|cntlzw} %0,%1" \ + : "=r" ((count)) \ + : "r" ((USItype)(x))) +#define COUNT_LEADING_ZEROS_0 32 +#if defined (_ARCH_PPC) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" \ + : "=r" (ph) \ + : "%r" (__m0), \ + "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + SItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhw %0,%1,%2" \ + : "=r" ((SItype) ph) \ + : "%r" (__m0), \ + "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 +#define UDIV_TIME 120 +#else +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mul %0,%2,%3" \ + : "=r" ((xh)), \ + "=q" ((xl)) \ + : "r" (__m0), \ + "r" (__m1)); \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 8 +#define smul_ppmm(xh, xl, m0, m1) \ + __asm__ ("mul %0,%2,%3" \ + : "=r" ((SItype)(xh)), \ + "=q" ((SItype)(xl)) \ + : "r" (m0), \ + "r" (m1)) +#define SMUL_TIME 4 +#define sdiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("div %0,%2,%4" \ + : "=r" ((SItype)(q)), "=q" ((SItype)(r)) \ + : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d))) +#define UDIV_TIME 100 +#endif +#endif /* Power architecture variants. */ + +/* Powerpc 64 bit support taken from gmp-4.1.2. */ +/* We should test _IBMR2 here when we add assembly support for the system + vendor compilers. */ +#if 0 /* Not yet enabled because we don't have hardware for a test. */ +#if (defined (_ARCH_PPC) || defined (__powerpc__)) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + DItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 /* ??? */ +#define UDIV_TIME 120 /* ??? */ +#endif /* 64-bit PowerPC. */ +#endif /* if 0 */ + +/*************************************** + ************** PYR ****************** + ***************************************/ +#if defined (__pyr__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addw %5,%1 \n" \ + "addwc %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subw %5,%1 \n" \ + "subwb %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */ +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("movw %1,%R0 \n" \ + "uemul %2,%0" \ + : "=&r" (__xx.__ll) \ + : "g" ((USItype) (u)), \ + "g" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#endif /* __pyr__ */ + + +/*************************************** + ************** RT/ROMP ************** + ***************************************/ +#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("a %1,%5 \n" \ + "ae %0,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "r" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("s %1,%5\n" \ + "se %0,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "r" ((USItype)(bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ( \ + "s r2,r2 \n" \ + "mts r10,%2 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "cas %0,r2,r0 \n" \ + "mfs r10,%1" \ + : "=r" ((USItype)(ph)), \ + "=r" ((USItype)(pl)) \ + : "%r" (__m0), \ + "r" (__m1) \ + : "r2"); \ + (ph) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))); \ + (count) += 16; \ + } \ + } while (0) +#endif /* RT/ROMP */ + + +/*************************************** + ************** SH2 ****************** + ***************************************/ +#if (defined (__sh2__) || defined(__sh3__) || defined(__SH4__) ) \ + && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ( \ + "dmulu.l %2,%3\n" \ + "sts macl,%1\n" \ + "sts mach,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "macl", "mach") +#define UMUL_TIME 5 +#endif + +/*************************************** + ************** SPARC **************** + ***************************************/ +#if defined (__sparc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n" \ + "addx %r2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rJ" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%rJ" ((USItype)(al)), \ + "rI" ((USItype)(bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n" \ + "subx %r2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rJ" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rI" ((USItype)(bl)) \ + __CLOBBER_CC) +#if defined (__sparc_v8__) +/* Don't match immediate range because, 1) it is not often useful, + 2) the 'I' flag thinks of the range as a 13 bit signed interval, + while we want to match a 13 bit interval, sign extended to 32 bits, + but INTERPRETED AS UNSIGNED. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))) +#define UMUL_TIME 5 +#ifndef SUPERSPARC /* SuperSPARC's udiv only handles 53 bit dividends */ +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + USItype __q; \ + __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ + : "=r" ((USItype)(__q)) \ + : "r" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))); \ + (r) = (n0) - __q * (d); \ + (q) = __q; \ + } while (0) +#define UDIV_TIME 25 +#endif /* SUPERSPARC */ +#else /* ! __sparc_v8__ */ +#if defined (__sparclite__) +/* This has hardware multiply but not divide. It also has two additional + instructions scan (ffs from high bit) and divscc. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))) +#define UMUL_TIME 5 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("! Inlined udiv_qrnnd \n" \ + " wr %%g0,%2,%%y ! Not a delayed write for sparclite \n" \ + " tst %%g0 \n" \ + " divscc %3,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%0 \n" \ + " rd %%y,%1 \n" \ + " bl,a 1f \n" \ + " add %1,%4,%1 \n" \ + "1: ! End of inline udiv_qrnnd" \ + : "=r" ((USItype)(q)), \ + "=r" ((USItype)(r)) \ + : "r" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "rI" ((USItype)(d)) \ + : "%g1" __AND_CLOBBER_CC) +#define UDIV_TIME 37 +#define count_leading_zeros(count, x) \ + __asm__ ("scan %1,0,%0" \ + : "=r" ((USItype)(x)) \ + : "r" ((USItype)(count))) +/* Early sparclites return 63 for an argument of 0, but they warn that future + implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 + undefined. */ +#endif /* __sparclite__ */ +#endif /* __sparc_v8__ */ +/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ +#ifndef umul_ppmm +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm \n" \ + " wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr \n" \ + " sra %3,31,%%g2 ! Don't move this insn \n" \ + " and %2,%%g2,%%g2 ! Don't move this insn \n" \ + " andcc %%g0,0,%%g1 ! Don't move this insn \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,0,%%g1 \n" \ + " add %%g1,%%g2,%0 \n" \ + " rd %%y,%1" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "%rI" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "%g1", "%g2" __AND_CLOBBER_CC) +#define UMUL_TIME 39 /* 39 instructions */ +#endif +#ifndef udiv_qrnnd +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { USItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern USItype __udiv_qrnnd (); +#define UDIV_TIME 140 +#endif /* LONGLONG_STANDALONE */ +#endif /* udiv_qrnnd */ +#endif /* __sparc__ */ + + +/*************************************** + ************** VAX ****************** + ***************************************/ +#if defined (__vax__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl2 %5,%1\n" \ + "adwc %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl2 %5,%1\n" \ + "sbwc %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("emul %1,%2,$0,%0" \ + : "=g" (__xx.__ll) \ + : "g" (__m0), \ + "g" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("ediv %3,%2,%0,%1" \ + : "=g" (q), "=g" (r) \ + : "g" (__xx.__ll), "g" (d)); \ + } while (0) +#endif /* __vax__ */ + + +/*************************************** + ************** Z8000 **************** + ***************************************/ +#if defined (__z8000__) && W_TYPE_SIZE == 16 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "%0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "%1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long int __ll; \ + struct {unsigned int __h, __l;} __i; \ + } __xx; \ + unsigned int __m0 = (m0), __m1 = (m1); \ + __asm__ ("mult %S0,%H3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "rQR" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((signed int) __m0 >> 15) & __m1) \ + + (((signed int) __m1 >> 15) & __m0)); \ + } while (0) +#endif /* __z8000__ */ + +#endif /* __GNUC__ */ +#endif /* !__riscos__ */ + + +/*************************************** + *********** Generic Versions ******** + ***************************************/ +#if !defined (umul_ppmm) && defined (__umulsidi3) +#define umul_ppmm(ph, pl, m0, m1) \ + { \ + UDWtype __ll = __umulsidi3 (m0, m1); \ + ph = (UWtype) (__ll >> W_TYPE_SIZE); \ + pl = (UWtype) __ll; \ + } +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({UWtype __hi, __lo; \ + umul_ppmm (__hi, __lo, u, v); \ + ((UDWtype) __hi << W_TYPE_SIZE) | __lo; }) +#endif + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + UWtype __u = (u), __v = (v); \ + \ + __ul = __ll_lowpart (__u); \ + __uh = __ll_highpart (__u); \ + __vl = __ll_lowpart (__v); \ + __vh = __ll_highpart (__v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define smul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __w1; \ + UWtype __m0 = (u), __m1 = (v); \ + umul_ppmm (__w1, w0, __m0, __m1); \ + (w1) = __w1 - (-(__m0 >> (W_TYPE_SIZE - 1)) & __m1) \ + - (-(__m1 >> (W_TYPE_SIZE - 1)) & __m0); \ + } while (0) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + UWtype __r; \ + (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +extern +#ifdef __STDC__ +const +#endif +unsigned char _gcry_clz_tab[]; +#define MPI_INTERNAL_NEED_CLZ_TAB 1 +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype) 1 << 2*__BITS4) \ + ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4);\ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (_gcry_clz_tab[__xr >> __a] + __a); \ + } while (0) +/* This version gives a well-defined value for zero. */ +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-add.c b/grub-core/lib/libgcrypt-grub/mpi/mpi-add.c new file mode 100644 index 0000000..f8f6094 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-add.c @@ -0,0 +1,237 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-add.c - MPI functions + * Copyright (C) 1994, 1996, 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "mpi-internal.h" + + +/**************** + * Add the unsigned integer V to the mpi-integer U and store the + * result in W. U and V may be the same. + */ +void +gcry_mpi_add_ui(gcry_mpi_t w, gcry_mpi_t u, unsigned long v ) +{ + mpi_ptr_t wp, up; + mpi_size_t usize, wsize; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + wsign = 0; + + /* If not space for W (and possible carry), increase space. */ + wsize = usize + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->d; + wp = w->d; + + if( !usize ) { /* simple */ + wp[0] = v; + wsize = v? 1:0; + } + else if( !usign ) { /* mpi is not negative */ + mpi_limb_t cy; + cy = _gcry_mpih_add_1(wp, up, usize, v); + wp[usize] = cy; + wsize = usize + cy; + } + else { /* The signs are different. Need exact comparison to determine + * which operand to subtract from which. */ + if( usize == 1 && up[0] < v ) { + wp[0] = v - up[0]; + wsize = 1; + } + else { + _gcry_mpih_sub_1(wp, up, usize, v); + /* Size can decrease with at most one limb. */ + wsize = usize - (wp[usize-1]==0); + wsign = 1; + } + } + + w->nlimbs = wsize; + w->sign = wsign; +} + + +void +gcry_mpi_add(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v) +{ + mpi_ptr_t wp, up, vp; + mpi_size_t usize, vsize, wsize; + int usign, vsign, wsign; + + if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ + usize = v->nlimbs; + usign = v->sign; + vsize = u->nlimbs; + vsign = u->sign; + wsize = usize + 1; + RESIZE_IF_NEEDED(w, wsize); + /* These must be after realloc (u or v may be the same as w). */ + up = v->d; + vp = u->d; + } + else { + usize = u->nlimbs; + usign = u->sign; + vsize = v->nlimbs; + vsign = v->sign; + wsize = usize + 1; + RESIZE_IF_NEEDED(w, wsize); + /* These must be after realloc (u or v may be the same as w). */ + up = u->d; + vp = v->d; + } + wp = w->d; + wsign = 0; + + if( !vsize ) { /* simple */ + MPN_COPY(wp, up, usize ); + wsize = usize; + wsign = usign; + } + else if( usign != vsign ) { /* different sign */ + /* This test is right since USIZE >= VSIZE */ + if( usize != vsize ) { + _gcry_mpih_sub(wp, up, usize, vp, vsize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + wsign = usign; + } + else if( _gcry_mpih_cmp(up, vp, usize) < 0 ) { + _gcry_mpih_sub_n(wp, vp, up, usize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + if( !usign ) + wsign = 1; + } + else { + _gcry_mpih_sub_n(wp, up, vp, usize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + if( usign ) + wsign = 1; + } + } + else { /* U and V have same sign. Add them. */ + mpi_limb_t cy = _gcry_mpih_add(wp, up, usize, vp, vsize); + wp[usize] = cy; + wsize = usize + cy; + if( usign ) + wsign = 1; + } + + w->nlimbs = wsize; + w->sign = wsign; +} + + +/**************** + * Subtract the unsigned integer V from the mpi-integer U and store the + * result in W. + */ +void +gcry_mpi_sub_ui(gcry_mpi_t w, gcry_mpi_t u, unsigned long v ) +{ + mpi_ptr_t wp, up; + mpi_size_t usize, wsize; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + wsign = 0; + + /* If not space for W (and possible carry), increase space. */ + wsize = usize + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->d; + wp = w->d; + + if( !usize ) { /* simple */ + wp[0] = v; + wsize = v? 1:0; + wsign = 1; + } + else if( usign ) { /* mpi and v are negative */ + mpi_limb_t cy; + cy = _gcry_mpih_add_1(wp, up, usize, v); + wp[usize] = cy; + wsize = usize + cy; + } + else { /* The signs are different. Need exact comparison to determine + * which operand to subtract from which. */ + if( usize == 1 && up[0] < v ) { + wp[0] = v - up[0]; + wsize = 1; + wsign = 1; + } + else { + _gcry_mpih_sub_1(wp, up, usize, v); + /* Size can decrease with at most one limb. */ + wsize = usize - (wp[usize-1]==0); + } + } + + w->nlimbs = wsize; + w->sign = wsign; +} + +void +gcry_mpi_sub(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v) +{ + gcry_mpi_t vv = mpi_copy (v); + vv->sign = ! vv->sign; + gcry_mpi_add (w, u, vv); + mpi_free (vv); +} + + +void +gcry_mpi_addm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) +{ + gcry_mpi_add(w, u, v); + _gcry_mpi_fdiv_r( w, w, m ); +} + +void +gcry_mpi_subm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) +{ + gcry_mpi_sub(w, u, v); + _gcry_mpi_fdiv_r( w, w, m ); +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-asm-defs.h b/grub-core/lib/libgcrypt-grub/mpi/mpi-asm-defs.h new file mode 100644 index 0000000..13424e2 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-asm-defs.h @@ -0,0 +1,10 @@ +/* This file defines some basic constants for the MPI machinery. We + * need to define the types on a per-CPU basis, so it is done with + * this file here. */ +#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG) + + + + + + diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-bit.c b/grub-core/lib/libgcrypt-grub/mpi/mpi-bit.c new file mode 100644 index 0000000..05b9f12 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-bit.c @@ -0,0 +1,366 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-bit.c - MPI bit level functions + * Copyright (C) 1998, 1999, 2001, 2002, 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +#ifdef MPI_INTERNAL_NEED_CLZ_TAB +#ifdef __STDC__ +const +#endif +unsigned char +_gcry_clz_tab[] = +{ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +}; +#endif + + +#define A_LIMB_1 ((mpi_limb_t)1) + + +/**************** + * Sometimes we have MSL (most significant limbs) which are 0; + * this is for some reasons not good, so this function removes them. + */ +void +_gcry_mpi_normalize( gcry_mpi_t a ) +{ + if( mpi_is_opaque(a) ) + return; + + for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- ) + ; +} + + + +/**************** + * Return the number of bits in A. + */ +unsigned int +gcry_mpi_get_nbits( gcry_mpi_t a ) +{ + unsigned n; + + if( mpi_is_opaque(a) ) { + return a->sign; /* which holds the number of bits */ + } + + _gcry_mpi_normalize( a ); + if( a->nlimbs ) { + mpi_limb_t alimb = a->d[a->nlimbs-1]; + if( alimb ) + count_leading_zeros( n, alimb ); + else + n = BITS_PER_MPI_LIMB; + n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB; + } + else + n = 0; + return n; +} + + +/**************** + * Test whether bit N is set. + */ +int +gcry_mpi_test_bit( gcry_mpi_t a, unsigned int n ) +{ + unsigned int limbno, bitno; + mpi_limb_t limb; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return 0; /* too far left: this is a 0 */ + limb = a->d[limbno]; + return (limb & (A_LIMB_1 << bitno))? 1: 0; +} + + +/**************** + * Set bit N of A. + */ +void +gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n ) +{ + unsigned int limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if ( limbno >= a->nlimbs ) + { + mpi_resize (a, limbno+1 ); + a->nlimbs = limbno+1; + } + a->d[limbno] |= (A_LIMB_1<<bitno); +} + +/**************** + * Set bit N of A. and clear all bits above + */ +void +gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n ) +{ + unsigned int limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if ( limbno >= a->nlimbs ) + { + mpi_resize (a, limbno+1 ); + a->nlimbs = limbno+1; + } + a->d[limbno] |= (A_LIMB_1<<bitno); + for ( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ ) + a->d[limbno] &= ~(A_LIMB_1 << bitno); + a->nlimbs = limbno+1; +} + +/**************** + * clear bit N of A and all bits above + */ +void +gcry_mpi_clear_highbit( gcry_mpi_t a, unsigned int n ) +{ + unsigned int limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return; /* not allocated, therefore no need to clear bits + :-) */ + + for( ; bitno < BITS_PER_MPI_LIMB; bitno++ ) + a->d[limbno] &= ~(A_LIMB_1 << bitno); + a->nlimbs = limbno+1; +} + +/**************** + * Clear bit N of A. + */ +void +gcry_mpi_clear_bit( gcry_mpi_t a, unsigned int n ) +{ + unsigned int limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return; /* don't need to clear this bit, it's to far to left */ + a->d[limbno] &= ~(A_LIMB_1 << bitno); +} + + +/**************** + * Shift A by COUNT limbs to the right + * This is used only within the MPI library + */ +void +_gcry_mpi_rshift_limbs( gcry_mpi_t a, unsigned int count ) +{ + mpi_ptr_t ap = a->d; + mpi_size_t n = a->nlimbs; + unsigned int i; + + if( count >= n ) { + a->nlimbs = 0; + return; + } + + for( i = 0; i < n - count; i++ ) + ap[i] = ap[i+count]; + ap[i] = 0; + a->nlimbs -= count; +} + + +/* + * Shift A by N bits to the right. + */ +void +gcry_mpi_rshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n ) +{ + mpi_size_t xsize; + unsigned int i; + unsigned int nlimbs = (n/BITS_PER_MPI_LIMB); + unsigned int nbits = (n%BITS_PER_MPI_LIMB); + + if ( x == a ) + { + /* In-place operation. */ + if ( nlimbs >= x->nlimbs ) + { + x->nlimbs = 0; + return; + } + + if (nlimbs) + { + for (i=0; i < x->nlimbs - nlimbs; i++ ) + x->d[i] = x->d[i+nlimbs]; + x->d[i] = 0; + x->nlimbs -= nlimbs; + + } + if ( x->nlimbs && nbits ) + _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits ); + } + else if ( nlimbs ) + { + /* Copy and shift by more or equal bits than in a limb. */ + xsize = a->nlimbs; + x->sign = a->sign; + RESIZE_IF_NEEDED (x, xsize); + x->nlimbs = xsize; + for (i=0; i < a->nlimbs; i++ ) + x->d[i] = a->d[i]; + x->nlimbs = i; + + if ( nlimbs >= x->nlimbs ) + { + x->nlimbs = 0; + return; + } + + if (nlimbs) + { + for (i=0; i < x->nlimbs - nlimbs; i++ ) + x->d[i] = x->d[i+nlimbs]; + x->d[i] = 0; + x->nlimbs -= nlimbs; + } + + if ( x->nlimbs && nbits ) + _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits ); + } + else + { + /* Copy and shift by less than bits in a limb. */ + xsize = a->nlimbs; + x->sign = a->sign; + RESIZE_IF_NEEDED (x, xsize); + x->nlimbs = xsize; + + if ( xsize ) + { + if (nbits ) + _gcry_mpih_rshift (x->d, a->d, x->nlimbs, nbits ); + else + { + /* The rshift helper function is not specified for + NBITS==0, thus we do a plain copy here. */ + for (i=0; i < x->nlimbs; i++ ) + x->d[i] = a->d[i]; + } + } + } + MPN_NORMALIZE (x->d, x->nlimbs); +} + + +/**************** + * Shift A by COUNT limbs to the left + * This is used only within the MPI library + */ +void +_gcry_mpi_lshift_limbs (gcry_mpi_t a, unsigned int count) +{ + mpi_ptr_t ap; + int n = a->nlimbs; + int i; + + if (!count || !n) + return; + + RESIZE_IF_NEEDED (a, n+count); + + ap = a->d; + for (i = n-1; i >= 0; i--) + ap[i+count] = ap[i]; + for (i=0; i < count; i++ ) + ap[i] = 0; + a->nlimbs += count; +} + + +/* + * Shift A by N bits to the left. + */ +void +gcry_mpi_lshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n ) +{ + unsigned int nlimbs = (n/BITS_PER_MPI_LIMB); + unsigned int nbits = (n%BITS_PER_MPI_LIMB); + + if (x == a && !n) + return; /* In-place shift with an amount of zero. */ + + if ( x != a ) + { + /* Copy A to X. */ + unsigned int alimbs = a->nlimbs; + int asign = a->sign; + mpi_ptr_t xp, ap; + + RESIZE_IF_NEEDED (x, alimbs+nlimbs+1); + xp = x->d; + ap = a->d; + MPN_COPY (xp, ap, alimbs); + x->nlimbs = alimbs; + x->flags = a->flags; + x->sign = asign; + } + + if (nlimbs && !nbits) + { + /* Shift a full number of limbs. */ + _gcry_mpi_lshift_limbs (x, nlimbs); + } + else if (n) + { + /* We use a very dump approach: Shift left by the number of + limbs plus one and than fix it up by an rshift. */ + _gcry_mpi_lshift_limbs (x, nlimbs+1); + gcry_mpi_rshift (x, x, BITS_PER_MPI_LIMB - nbits); + } + + MPN_NORMALIZE (x->d, x->nlimbs); +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-cmp.c b/grub-core/lib/libgcrypt-grub/mpi/mpi-cmp.c new file mode 100644 index 0000000..b0ebbc1 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-cmp.c @@ -0,0 +1,109 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-cmp.c - MPI functions + * Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + +int +gcry_mpi_cmp_ui (gcry_mpi_t u, unsigned long v) +{ + mpi_limb_t limb = v; + + _gcry_mpi_normalize (u); + + /* Handle the case that U contains no limb. */ + if (u->nlimbs == 0) + return -(limb != 0); + + /* Handle the case that U is negative. */ + if (u->sign) + return -1; + + if (u->nlimbs == 1) + { + /* Handle the case that U contains exactly one limb. */ + + if (u->d[0] > limb) + return 1; + if (u->d[0] < limb) + return -1; + return 0; + } + else + /* Handle the case that U contains more than one limb. */ + return 1; +} + + +int +gcry_mpi_cmp (gcry_mpi_t u, gcry_mpi_t v) +{ + mpi_size_t usize; + mpi_size_t vsize; + int cmp; + + if (mpi_is_opaque (u) || mpi_is_opaque (v)) + { + if (mpi_is_opaque (u) && !mpi_is_opaque (v)) + return -1; + if (!mpi_is_opaque (u) && mpi_is_opaque (v)) + return 1; + if (!u->sign && !v->sign) + return 0; /* Empty buffers are identical. */ + if (u->sign < v->sign) + return -1; + if (u->sign > v->sign) + return 1; + return memcmp (u->d, v->d, (u->sign+7)/8); + } + else + { + _gcry_mpi_normalize (u); + _gcry_mpi_normalize (v); + + usize = u->nlimbs; + vsize = v->nlimbs; + + /* Compare sign bits. */ + + if (!u->sign && v->sign) + return 1; + if (u->sign && !v->sign) + return -1; + + /* U and V are either both positive or both negative. */ + + if (usize != vsize && !u->sign && !v->sign) + return usize - vsize; + if (usize != vsize && u->sign && v->sign) + return vsize + usize; + if (!usize ) + return 0; + if (!(cmp = _gcry_mpih_cmp (u->d, v->d, usize))) + return 0; + if ((cmp < 0?1:0) == (u->sign?1:0)) + return 1; + } + return -1; +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-div.c b/grub-core/lib/libgcrypt-grub/mpi/mpi-div.c new file mode 100644 index 0000000..5218caa --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-div.c @@ -0,0 +1,357 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-div.c - MPI functions + * Copyright (C) 1994, 1996, 1998, 2001, 2002, + * 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" +#include "g10lib.h" + + +void +_gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor ) +{ + int divisor_sign = divisor->sign; + gcry_mpi_t temp_divisor = NULL; + + /* We need the original value of the divisor after the remainder has been + * preliminary calculated. We have to copy it to temporary space if it's + * the same variable as REM. */ + if( rem == divisor ) { + temp_divisor = mpi_copy( divisor ); + divisor = temp_divisor; + } + + _gcry_mpi_tdiv_r( rem, dividend, divisor ); + + if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs ) + gcry_mpi_add( rem, rem, divisor); + + if( temp_divisor ) + mpi_free(temp_divisor); +} + + + +/**************** + * Division rounding the quotient towards -infinity. + * The remainder gets the same sign as the denominator. + * rem is optional + */ + +ulong +_gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor ) +{ + mpi_limb_t rlimb; + + rlimb = _gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor ); + if( rlimb && dividend->sign ) + rlimb = divisor - rlimb; + + if( rem ) { + rem->d[0] = rlimb; + rem->nlimbs = rlimb? 1:0; + } + return rlimb; +} + + +void +_gcry_mpi_fdiv_q( gcry_mpi_t quot, gcry_mpi_t dividend, gcry_mpi_t divisor ) +{ + gcry_mpi_t tmp = mpi_alloc( mpi_get_nlimbs(quot) ); + _gcry_mpi_fdiv_qr( quot, tmp, dividend, divisor); + mpi_free(tmp); +} + +void +_gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor ) +{ + int divisor_sign = divisor->sign; + gcry_mpi_t temp_divisor = NULL; + + if( quot == divisor || rem == divisor ) { + temp_divisor = mpi_copy( divisor ); + divisor = temp_divisor; + } + + _gcry_mpi_tdiv_qr( quot, rem, dividend, divisor ); + + if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) { + gcry_mpi_sub_ui( quot, quot, 1 ); + gcry_mpi_add( rem, rem, divisor); + } + + if( temp_divisor ) + mpi_free(temp_divisor); +} + + +/* If den == quot, den needs temporary storage. + * If den == rem, den needs temporary storage. + * If num == quot, num needs temporary storage. + * If den has temporary storage, it can be normalized while being copied, + * i.e no extra storage should be allocated. + */ + +void +_gcry_mpi_tdiv_r( gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den) +{ + _gcry_mpi_tdiv_qr(NULL, rem, num, den ); +} + +void +_gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den) +{ + mpi_ptr_t np, dp; + mpi_ptr_t qp, rp; + mpi_size_t nsize = num->nlimbs; + mpi_size_t dsize = den->nlimbs; + mpi_size_t qsize, rsize; + mpi_size_t sign_remainder = num->sign; + mpi_size_t sign_quotient = num->sign ^ den->sign; + unsigned normalization_steps; + mpi_limb_t q_limb; + mpi_ptr_t marker[5]; + unsigned int marker_nlimbs[5]; + int markidx=0; + + /* Ensure space is enough for quotient and remainder. + * We need space for an extra limb in the remainder, because it's + * up-shifted (normalized) below. */ + rsize = nsize + 1; + mpi_resize( rem, rsize); + + qsize = rsize - dsize; /* qsize cannot be bigger than this. */ + if( qsize <= 0 ) { + if( num != rem ) { + rem->nlimbs = num->nlimbs; + rem->sign = num->sign; + MPN_COPY(rem->d, num->d, nsize); + } + if( quot ) { + /* This needs to follow the assignment to rem, in case the + * numerator and quotient are the same. */ + quot->nlimbs = 0; + quot->sign = 0; + } + return; + } + + if( quot ) + mpi_resize( quot, qsize); + + /* Read pointers here, when reallocation is finished. */ + np = num->d; + dp = den->d; + rp = rem->d; + + /* Optimize division by a single-limb divisor. */ + if( dsize == 1 ) { + mpi_limb_t rlimb; + if( quot ) { + qp = quot->d; + rlimb = _gcry_mpih_divmod_1( qp, np, nsize, dp[0] ); + qsize -= qp[qsize - 1] == 0; + quot->nlimbs = qsize; + quot->sign = sign_quotient; + } + else + rlimb = _gcry_mpih_mod_1( np, nsize, dp[0] ); + rp[0] = rlimb; + rsize = rlimb != 0?1:0; + rem->nlimbs = rsize; + rem->sign = sign_remainder; + return; + } + + + if( quot ) { + qp = quot->d; + /* Make sure QP and NP point to different objects. Otherwise the + * numerator would be gradually overwritten by the quotient limbs. */ + if(qp == np) { /* Copy NP object to temporary space. */ + marker_nlimbs[markidx] = nsize; + np = marker[markidx++] = mpi_alloc_limb_space(nsize, + mpi_is_secure(quot)); + MPN_COPY(np, qp, nsize); + } + } + else /* Put quotient at top of remainder. */ + qp = rp + dsize; + + count_leading_zeros( normalization_steps, dp[dsize - 1] ); + + /* Normalize the denominator, i.e. make its most significant bit set by + * shifting it NORMALIZATION_STEPS bits to the left. Also shift the + * numerator the same number of steps (to keep the quotient the same!). + */ + if( normalization_steps ) { + mpi_ptr_t tp; + mpi_limb_t nlimb; + + /* Shift up the denominator setting the most significant bit of + * the most significant word. Use temporary storage not to clobber + * the original contents of the denominator. */ + marker_nlimbs[markidx] = dsize; + tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den)); + _gcry_mpih_lshift( tp, dp, dsize, normalization_steps ); + dp = tp; + + /* Shift up the numerator, possibly introducing a new most + * significant word. Move the shifted numerator in the remainder + * meanwhile. */ + nlimb = _gcry_mpih_lshift(rp, np, nsize, normalization_steps); + if( nlimb ) { + rp[nsize] = nlimb; + rsize = nsize + 1; + } + else + rsize = nsize; + } + else { + /* The denominator is already normalized, as required. Copy it to + * temporary space if it overlaps with the quotient or remainder. */ + if( dp == rp || (quot && (dp == qp))) { + mpi_ptr_t tp; + + marker_nlimbs[markidx] = dsize; + tp = marker[markidx++] = mpi_alloc_limb_space(dsize, + mpi_is_secure(den)); + MPN_COPY( tp, dp, dsize ); + dp = tp; + } + + /* Move the numerator to the remainder. */ + if( rp != np ) + MPN_COPY(rp, np, nsize); + + rsize = nsize; + } + + q_limb = _gcry_mpih_divrem( qp, 0, rp, rsize, dp, dsize ); + + if( quot ) { + qsize = rsize - dsize; + if(q_limb) { + qp[qsize] = q_limb; + qsize += 1; + } + + quot->nlimbs = qsize; + quot->sign = sign_quotient; + } + + rsize = dsize; + MPN_NORMALIZE (rp, rsize); + + if( normalization_steps && rsize ) { + _gcry_mpih_rshift(rp, rp, rsize, normalization_steps); + rsize -= rp[rsize - 1] == 0?1:0; + } + + rem->nlimbs = rsize; + rem->sign = sign_remainder; + while( markidx ) + { + markidx--; + _gcry_mpi_free_limb_space (marker[markidx], marker_nlimbs[markidx]); + } +} + +void +_gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned int count ) +{ + mpi_size_t usize, wsize; + mpi_size_t limb_cnt; + + usize = u->nlimbs; + limb_cnt = count / BITS_PER_MPI_LIMB; + wsize = usize - limb_cnt; + if( limb_cnt >= usize ) + w->nlimbs = 0; + else { + mpi_ptr_t wp; + mpi_ptr_t up; + + RESIZE_IF_NEEDED( w, wsize ); + wp = w->d; + up = u->d; + + count %= BITS_PER_MPI_LIMB; + if( count ) { + _gcry_mpih_rshift( wp, up + limb_cnt, wsize, count ); + wsize -= !wp[wsize - 1]; + } + else { + MPN_COPY_INCR( wp, up + limb_cnt, wsize); + } + + w->nlimbs = wsize; + } +} + +/**************** + * Check whether dividend is divisible by divisor + * (note: divisor must fit into a limb) + */ +int +_gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor ) +{ + return !_gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor ); +} + + +void +gcry_mpi_div (gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor, int round) +{ + if (!round) + { + if (!rem) + { + gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs(quot)); + _gcry_mpi_tdiv_qr (quot, tmp, dividend, divisor); + mpi_free (tmp); + } + else + _gcry_mpi_tdiv_qr (quot, rem, dividend, divisor); + } + else if (round < 0) + { + if (!rem) + _gcry_mpi_fdiv_q (quot, dividend, divisor); + else if (!quot) + _gcry_mpi_fdiv_r (rem, dividend, divisor); + else + _gcry_mpi_fdiv_qr (quot, rem, dividend, divisor); + } + else + log_bug ("mpi rounding to ceiling not yet implemented\n"); +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-gcd.c b/grub-core/lib/libgcrypt-grub/mpi/mpi-gcd.c new file mode 100644 index 0000000..34bd249 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-gcd.c @@ -0,0 +1,53 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-gcd.c - MPI functions + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + +/**************** + * Find the greatest common divisor G of A and B. + * Return: true if this 1, false in all other cases + */ +int +gcry_mpi_gcd( gcry_mpi_t g, gcry_mpi_t xa, gcry_mpi_t xb ) +{ + gcry_mpi_t a, b; + + a = mpi_copy(xa); + b = mpi_copy(xb); + + /* TAOCP Vol II, 4.5.2, Algorithm A */ + a->sign = 0; + b->sign = 0; + while( gcry_mpi_cmp_ui( b, 0 ) ) { + _gcry_mpi_fdiv_r( g, a, b ); /* g used as temorary variable */ + mpi_set(a,b); + mpi_set(b,g); + } + mpi_set(g, a); + + mpi_free(a); + mpi_free(b); + return !gcry_mpi_cmp_ui( g, 1); +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-inline.c b/grub-core/lib/libgcrypt-grub/mpi/mpi-inline.c new file mode 100644 index 0000000..4e3e8f3 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-inline.c @@ -0,0 +1,37 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-inline.c + * Copyright (C) 1999, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +/* put the inline functions as real functions into the lib */ +#define G10_MPI_INLINE_DECL + +#include "mpi-internal.h" + +/* always include the header because it is only + * included by mpi-internal if __GCC__ is defined but we + * need it here in all cases and the above definition of + * of the macro allows us to do so + */ +#include "mpi-inline.h" diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-inline.h b/grub-core/lib/libgcrypt-grub/mpi/mpi-inline.h new file mode 100644 index 0000000..0818d20 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-inline.h @@ -0,0 +1,163 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-inline.h - Internal to the Multi Precision Integers + * Copyright (C) 1994, 1996, 1998, 1999, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#ifndef G10_MPI_INLINE_H +#define G10_MPI_INLINE_H + +/* Starting with gcc 4.3 "extern inline" conforms in c99 mode to the + c99 semantics. To keep the useful old semantics we use an + attribute. */ +#ifndef G10_MPI_INLINE_DECL +# ifdef __GNUC_STDC_INLINE__ +# define G10_MPI_INLINE_DECL extern inline __attribute__ ((__gnu_inline__)) +# else +# define G10_MPI_INLINE_DECL extern __inline__ +# endif +#endif + +G10_MPI_INLINE_DECL mpi_limb_t +_gcry_mpih_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t x; + + x = *s1_ptr++; + s2_limb += x; + *res_ptr++ = s2_limb; + if( s2_limb < x ) { /* sum is less than the left operand: handle carry */ + while( --s1_size ) { + x = *s1_ptr++ + 1; /* add carry */ + *res_ptr++ = x; /* and store */ + if( x ) /* not 0 (no overflow): we can stop */ + goto leave; + } + return 1; /* return carry (size of s1 to small) */ + } + + leave: + if( res_ptr != s1_ptr ) { /* not the same variable */ + mpi_size_t i; /* copy the rest */ + for( i=0; i < s1_size-1; i++ ) + res_ptr[i] = s1_ptr[i]; + } + return 0; /* no carry */ +} + + + +G10_MPI_INLINE_DECL mpi_limb_t +_gcry_mpih_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size) +{ + mpi_limb_t cy = 0; + + if( s2_size ) + cy = _gcry_mpih_add_n( res_ptr, s1_ptr, s2_ptr, s2_size ); + + if( s1_size - s2_size ) + cy = _gcry_mpih_add_1( res_ptr + s2_size, s1_ptr + s2_size, + s1_size - s2_size, cy); + return cy; +} + + +G10_MPI_INLINE_DECL mpi_limb_t +_gcry_mpih_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ) +{ + mpi_limb_t x; + + x = *s1_ptr++; + s2_limb = x - s2_limb; + *res_ptr++ = s2_limb; + if( s2_limb > x ) { + while( --s1_size ) { + x = *s1_ptr++; + *res_ptr++ = x - 1; + if( x ) + goto leave; + } + return 1; + } + + leave: + if( res_ptr != s1_ptr ) { + mpi_size_t i; + for( i=0; i < s1_size-1; i++ ) + res_ptr[i] = s1_ptr[i]; + } + return 0; +} + + + +G10_MPI_INLINE_DECL mpi_limb_t +_gcry_mpih_sub( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size) +{ + mpi_limb_t cy = 0; + + if( s2_size ) + cy = _gcry_mpih_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size); + + if( s1_size - s2_size ) + cy = _gcry_mpih_sub_1(res_ptr + s2_size, s1_ptr + s2_size, + s1_size - s2_size, cy); + return cy; +} + +/**************** + * Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE. + * There are no restrictions on the relative sizes of + * the two arguments. + * Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2. + */ +G10_MPI_INLINE_DECL int +_gcry_mpih_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ) +{ + mpi_size_t i; + mpi_limb_t op1_word, op2_word; + + for( i = size - 1; i >= 0 ; i--) { + op1_word = op1_ptr[i]; + op2_word = op2_ptr[i]; + if( op1_word != op2_word ) + goto diff; + } + return 0; + + diff: + /* This can *not* be simplified to + * op2_word - op2_word + * since that expression might give signed overflow. */ + return (op1_word > op2_word) ? 1 : -1; +} + + +#endif /*G10_MPI_INLINE_H*/ diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-internal.h b/grub-core/lib/libgcrypt-grub/mpi/mpi-internal.h new file mode 100644 index 0000000..c9684f2 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-internal.h @@ -0,0 +1,279 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-internal.h - Internal to the Multi Precision Integers + * Copyright (C) 1994, 1996, 1998, 2000, 2002, + * 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#ifndef G10_MPI_INTERNAL_H +#define G10_MPI_INTERNAL_H + +#include "mpi-asm-defs.h" + +#ifndef BITS_PER_MPI_LIMB +#if BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_INT + typedef unsigned int mpi_limb_t; + typedef signed int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG + typedef unsigned long int mpi_limb_t; + typedef signed long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG_LONG + typedef unsigned long long int mpi_limb_t; + typedef signed long long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_SHORT + typedef unsigned short int mpi_limb_t; + typedef signed short int mpi_limb_signed_t; +#else +#error BYTES_PER_MPI_LIMB does not match any C type +#endif +#define BITS_PER_MPI_LIMB (8*BYTES_PER_MPI_LIMB) +#endif /*BITS_PER_MPI_LIMB*/ + +#include "mpi.h" + +/* If KARATSUBA_THRESHOLD is not already defined, define it to a + * value which is good on most machines. */ + +/* tested 4, 16, 32 and 64, where 16 gave the best performance when + * checking a 768 and a 1024 bit ElGamal signature. + * (wk 22.12.97) */ +#ifndef KARATSUBA_THRESHOLD +#define KARATSUBA_THRESHOLD 16 +#endif + +/* The code can't handle KARATSUBA_THRESHOLD smaller than 2. */ +#if KARATSUBA_THRESHOLD < 2 +#undef KARATSUBA_THRESHOLD +#define KARATSUBA_THRESHOLD 2 +#endif + + +typedef mpi_limb_t *mpi_ptr_t; /* pointer to a limb */ +typedef int mpi_size_t; /* (must be a signed type) */ + +#define ABS(x) (x >= 0 ? x : -x) +#define MIN(l,o) ((l) < (o) ? (l) : (o)) +#define MAX(h,i) ((h) > (i) ? (h) : (i)) +#define RESIZE_IF_NEEDED(a,b) \ + do { \ + if( (a)->alloced < (b) ) \ + mpi_resize((a), (b)); \ + } while(0) + +/* Copy N limbs from S to D. */ +#define MPN_COPY( d, s, n) \ + do { \ + mpi_size_t _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = (s)[_i]; \ + } while(0) + +#define MPN_COPY_INCR( d, s, n) \ + do { \ + mpi_size_t _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = (d)[_i]; \ + } while (0) + +#define MPN_COPY_DECR( d, s, n ) \ + do { \ + mpi_size_t _i; \ + for( _i = (n)-1; _i >= 0; _i--) \ + (d)[_i] = (s)[_i]; \ + } while(0) + +/* Zero N limbs at D */ +#define MPN_ZERO(d, n) \ + do { \ + int _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = 0; \ + } while (0) + +#define MPN_NORMALIZE(d, n) \ + do { \ + while( (n) > 0 ) { \ + if( (d)[(n)-1] ) \ + break; \ + (n)--; \ + } \ + } while(0) + +#define MPN_NORMALIZE_NOT_ZERO(d, n) \ + do { \ + for(;;) { \ + if( (d)[(n)-1] ) \ + break; \ + (n)--; \ + } \ + } while(0) + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if( (size) < KARATSUBA_THRESHOLD ) \ + mul_n_basecase (prodp, up, vp, size); \ + else \ + mul_n (prodp, up, vp, size, tspace); \ + } while (0); + + +/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest + * limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB). + * If this would yield overflow, DI should be the largest possible number + * (i.e., only ones). For correct operation, the most significant bit of D + * has to be set. Put the quotient in Q and the remainder in R. + */ +#define UDIV_QRNND_PREINV(q, r, nh, nl, d, di) \ + do { \ + mpi_limb_t _q, _ql, _r; \ + mpi_limb_t _xh, _xl; \ + umul_ppmm (_q, _ql, (nh), (di)); \ + _q += (nh); /* DI is 2**BITS_PER_MPI_LIMB too small */ \ + umul_ppmm (_xh, _xl, _q, (d)); \ + sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl); \ + if( _xh ) { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q++; \ + if( _xh) { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q++; \ + } \ + } \ + if( _r >= (d) ) { \ + _r -= (d); \ + _q++; \ + } \ + (r) = _r; \ + (q) = _q; \ + } while (0) + + +/*-- mpiutil.c --*/ +#define mpi_alloc_limb_space(n,f) _gcry_mpi_alloc_limb_space((n),(f)) +mpi_ptr_t _gcry_mpi_alloc_limb_space( unsigned nlimbs, int sec ); +void _gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs ); +void _gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned nlimbs ); + +/*-- mpi-bit.c --*/ +#define mpi_rshift_limbs(a,n) _gcry_mpi_rshift_limbs ((a), (n)) +#define mpi_lshift_limbs(a,n) _gcry_mpi_lshift_limbs ((a), (n)) + +void _gcry_mpi_rshift_limbs( gcry_mpi_t a, unsigned int count ); +void _gcry_mpi_lshift_limbs( gcry_mpi_t a, unsigned int count ); + + +/*-- mpih-add.c --*/ +mpi_limb_t _gcry_mpih_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ); +mpi_limb_t _gcry_mpih_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size); +mpi_limb_t _gcry_mpih_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size); + +/*-- mpih-sub.c --*/ +mpi_limb_t _gcry_mpih_sub_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ); +mpi_limb_t _gcry_mpih_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size); +mpi_limb_t _gcry_mpih_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size); + +/*-- mpih-cmp.c --*/ +int _gcry_mpih_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ); + +/*-- mpih-mul.c --*/ + +struct karatsuba_ctx { + struct karatsuba_ctx *next; + mpi_ptr_t tspace; + unsigned int tspace_nlimbs; + mpi_size_t tspace_size; + mpi_ptr_t tp; + unsigned int tp_nlimbs; + mpi_size_t tp_size; +}; + +void _gcry_mpih_release_karatsuba_ctx( struct karatsuba_ctx *ctx ); + +mpi_limb_t _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); +mpi_limb_t _gcry_mpih_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); +void _gcry_mpih_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, + mpi_size_t size); +mpi_limb_t _gcry_mpih_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize); +void _gcry_mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ); +void _gcry_mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, + mpi_ptr_t tspace); + +void _gcry_mpih_mul_karatsuba_case( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize, + struct karatsuba_ctx *ctx ); + + +/*-- mpih-mul_1.c (or xxx/cpu/ *.S) --*/ +mpi_limb_t _gcry_mpih_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); + +/*-- mpih-div.c --*/ +mpi_limb_t _gcry_mpih_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb); +mpi_limb_t _gcry_mpih_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, + mpi_ptr_t np, mpi_size_t nsize, + mpi_ptr_t dp, mpi_size_t dsize); +mpi_limb_t _gcry_mpih_divmod_1( mpi_ptr_t quot_ptr, + mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb); + +/*-- mpih-shift.c --*/ +mpi_limb_t _gcry_mpih_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned cnt); +mpi_limb_t _gcry_mpih_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned cnt); + + +/* Define stuff for longlong.h. */ +#define W_TYPE_SIZE BITS_PER_MPI_LIMB + typedef mpi_limb_t UWtype; + typedef unsigned int UHWtype; +#if defined (__GNUC__) + typedef unsigned int UQItype __attribute__ ((mode (QI))); + typedef int SItype __attribute__ ((mode (SI))); + typedef unsigned int USItype __attribute__ ((mode (SI))); + typedef int DItype __attribute__ ((mode (DI))); + typedef unsigned int UDItype __attribute__ ((mode (DI))); +#else + typedef unsigned char UQItype; + typedef long SItype; + typedef unsigned long USItype; +#endif + +#ifdef __GNUC__ +#include "mpi-inline.h" +#endif + +#endif /*G10_MPI_INTERNAL_H*/ diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-inv.c b/grub-core/lib/libgcrypt-grub/mpi/mpi-inv.c new file mode 100644 index 0000000..684384f --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-inv.c @@ -0,0 +1,269 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-inv.c - MPI functions + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "g10lib.h" + +/**************** + * Calculate the multiplicative inverse X of A mod N + * That is: Find the solution x for + * 1 = (a*x) mod n + */ +int +gcry_mpi_invm( gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n ) +{ +#if 0 + gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3; + gcry_mpi_t ta, tb, tc; + + u = mpi_copy(a); + v = mpi_copy(n); + u1 = mpi_alloc_set_ui(1); + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_alloc_set_ui(0); + v2 = mpi_alloc_set_ui(1); + v3 = mpi_copy(v); + q = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t1 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t2 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t3 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + while( mpi_cmp_ui( v3, 0 ) ) { + mpi_fdiv_q( q, u3, v3 ); + mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q); + mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3); + mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3); + mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3); + } + /* log_debug("result:\n"); + log_mpidump("q =", q ); + log_mpidump("u1=", u1); + log_mpidump("u2=", u2); + log_mpidump("u3=", u3); + log_mpidump("v1=", v1); + log_mpidump("v2=", v2); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(u2); + mpi_free(u3); + mpi_free(v1); + mpi_free(v2); + mpi_free(v3); + mpi_free(q); + mpi_free(t1); + mpi_free(t2); + mpi_free(t3); + mpi_free(u); + mpi_free(v); +#elif 0 + /* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X) + * modified according to Michael Penk's solution for Exercise 35 */ + + /* FIXME: we can simplify this in most cases (see Knuth) */ + gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3; + unsigned k; + int sign; + + u = mpi_copy(a); + v = mpi_copy(n); + for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { + mpi_rshift(u, u, 1); + mpi_rshift(v, v, 1); + } + + + u1 = mpi_alloc_set_ui(1); + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_copy(v); /* !-- used as const 1 */ + v2 = mpi_alloc( mpi_get_nlimbs(u) ); mpi_sub( v2, u1, u ); + v3 = mpi_copy(v); + if( mpi_test_bit(u, 0) ) { /* u is odd */ + t1 = mpi_alloc_set_ui(0); + t2 = mpi_alloc_set_ui(1); t2->sign = 1; + t3 = mpi_copy(v); t3->sign = !t3->sign; + goto Y4; + } + else { + t1 = mpi_alloc_set_ui(1); + t2 = mpi_alloc_set_ui(0); + t3 = mpi_copy(u); + } + do { + do { + if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + mpi_rshift(t1, t1, 1); + mpi_rshift(t2, t2, 1); + mpi_rshift(t3, t3, 1); + Y4: + ; + } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ + + if( !t3->sign ) { + mpi_set(u1, t1); + mpi_set(u2, t2); + mpi_set(u3, t3); + } + else { + mpi_sub(v1, v, t1); + sign = u->sign; u->sign = !u->sign; + mpi_sub(v2, u, t2); + u->sign = sign; + sign = t3->sign; t3->sign = !t3->sign; + mpi_set(v3, t3); + t3->sign = sign; + } + mpi_sub(t1, u1, v1); + mpi_sub(t2, u2, v2); + mpi_sub(t3, u3, v3); + if( t1->sign ) { + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ + /* mpi_lshift( u3, k ); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(u2); + mpi_free(u3); + mpi_free(v1); + mpi_free(v2); + mpi_free(v3); + mpi_free(t1); + mpi_free(t2); + mpi_free(t3); +#else + /* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X) + * modified according to Michael Penk's solution for Exercise 35 + * with further enhancement */ + gcry_mpi_t u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3; + unsigned k; + int sign; + int odd ; + + u = mpi_copy(a); + v = mpi_copy(n); + + for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { + mpi_rshift(u, u, 1); + mpi_rshift(v, v, 1); + } + odd = mpi_test_bit(v,0); + + u1 = mpi_alloc_set_ui(1); + if( !odd ) + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_copy(v); + if( !odd ) { + v2 = mpi_alloc( mpi_get_nlimbs(u) ); + mpi_sub( v2, u1, u ); /* U is used as const 1 */ + } + v3 = mpi_copy(v); + if( mpi_test_bit(u, 0) ) { /* u is odd */ + t1 = mpi_alloc_set_ui(0); + if( !odd ) { + t2 = mpi_alloc_set_ui(1); t2->sign = 1; + } + t3 = mpi_copy(v); t3->sign = !t3->sign; + goto Y4; + } + else { + t1 = mpi_alloc_set_ui(1); + if( !odd ) + t2 = mpi_alloc_set_ui(0); + t3 = mpi_copy(u); + } + do { + do { + if( !odd ) { + if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + mpi_rshift(t1, t1, 1); + mpi_rshift(t2, t2, 1); + mpi_rshift(t3, t3, 1); + } + else { + if( mpi_test_bit(t1, 0) ) + mpi_add(t1, t1, v); + mpi_rshift(t1, t1, 1); + mpi_rshift(t3, t3, 1); + } + Y4: + ; + } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ + + if( !t3->sign ) { + mpi_set(u1, t1); + if( !odd ) + mpi_set(u2, t2); + mpi_set(u3, t3); + } + else { + mpi_sub(v1, v, t1); + sign = u->sign; u->sign = !u->sign; + if( !odd ) + mpi_sub(v2, u, t2); + u->sign = sign; + sign = t3->sign; t3->sign = !t3->sign; + mpi_set(v3, t3); + t3->sign = sign; + } + mpi_sub(t1, u1, v1); + if( !odd ) + mpi_sub(t2, u2, v2); + mpi_sub(t3, u3, v3); + if( t1->sign ) { + mpi_add(t1, t1, v); + if( !odd ) + mpi_sub(t2, t2, u); + } + } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ + /* mpi_lshift( u3, k ); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(v1); + mpi_free(t1); + if( !odd ) { + mpi_free(u2); + mpi_free(v2); + mpi_free(t2); + } + mpi_free(u3); + mpi_free(v3); + mpi_free(t3); + + mpi_free(u); + mpi_free(v); +#endif + return 1; +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-mod.c b/grub-core/lib/libgcrypt-grub/mpi/mpi-mod.c new file mode 100644 index 0000000..6d9a6a3 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-mod.c @@ -0,0 +1,186 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-mod.c - Modular reduction + Copyright (C) 1998, 1999, 2001, 2002, 2003, + 2007 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "mpi-internal.h" +#include "longlong.h" +#include "g10lib.h" + + +/* Context used with Barrett reduction. */ +struct barrett_ctx_s +{ + gcry_mpi_t m; /* The modulus - may not be modified. */ + int m_copied; /* If true, M needs to be released. */ + int k; + gcry_mpi_t y; + gcry_mpi_t r1; /* Helper MPI. */ + gcry_mpi_t r2; /* Helper MPI. */ + gcry_mpi_t r3; /* Helper MPI allocated on demand. */ +}; + + + +void +_gcry_mpi_mod (gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor) +{ + _gcry_mpi_fdiv_r (rem, dividend, divisor); + rem->sign = 0; +} + + +/* This function returns a new context for Barrett based operations on + the modulus M. This context needs to be released using + _gcry_mpi_barrett_free. If COPY is true M will be transferred to + the context and the user may change M. If COPY is false, M may not + be changed until gcry_mpi_barrett_free has been called. */ +mpi_barrett_t +_gcry_mpi_barrett_init (gcry_mpi_t m, int copy) +{ + mpi_barrett_t ctx; + gcry_mpi_t tmp; + + mpi_normalize (m); + ctx = gcry_xcalloc (1, sizeof *ctx); + + if (copy) + { + ctx->m = mpi_copy (m); + ctx->m_copied = 1; + } + else + ctx->m = m; + + ctx->k = mpi_get_nlimbs (m); + tmp = mpi_alloc (ctx->k + 1); + + /* Barrett precalculation: y = floor(b^(2k) / m). */ + mpi_set_ui (tmp, 1); + mpi_lshift_limbs (tmp, 2 * ctx->k); + mpi_fdiv_q (tmp, tmp, m); + + ctx->y = tmp; + ctx->r1 = mpi_alloc ( 2 * ctx->k + 1 ); + ctx->r2 = mpi_alloc ( 2 * ctx->k + 1 ); + + return ctx; +} + +void +_gcry_mpi_barrett_free (mpi_barrett_t ctx) +{ + if (ctx) + { + mpi_free (ctx->y); + mpi_free (ctx->r1); + mpi_free (ctx->r2); + if (ctx->r3) + mpi_free (ctx->r3); + if (ctx->m_copied) + mpi_free (ctx->m); + gcry_free (ctx); + } +} + + +/* R = X mod M + + Using Barrett reduction. Before using this function + _gcry_mpi_barrett_init must have been called to do the + precalculations. CTX is the context created by this precalculation + and also conveys M. If the Barret reduction could no be done a + starightforward reduction method is used. + + We assume that these conditions are met: + Input: x =(x_2k-1 ...x_0)_b + m =(m_k-1 ....m_0)_b with m_k-1 != 0 + Output: r = x mod m + */ +void +_gcry_mpi_mod_barrett (gcry_mpi_t r, gcry_mpi_t x, mpi_barrett_t ctx) +{ + gcry_mpi_t m = ctx->m; + int k = ctx->k; + gcry_mpi_t y = ctx->y; + gcry_mpi_t r1 = ctx->r1; + gcry_mpi_t r2 = ctx->r2; + + mpi_normalize (x); + if (mpi_get_nlimbs (x) > 2*k ) + { + mpi_mod (r, x, m); + return; + } + + /* 1. q1 = floor( x / b^k-1) + * q2 = q1 * y + * q3 = floor( q2 / b^k+1 ) + * Actually, we don't need qx, we can work direct on r2 + */ + mpi_set ( r2, x ); + mpi_rshift_limbs ( r2, k-1 ); + mpi_mul ( r2, r2, y ); + mpi_rshift_limbs ( r2, k+1 ); + + /* 2. r1 = x mod b^k+1 + * r2 = q3 * m mod b^k+1 + * r = r1 - r2 + * 3. if r < 0 then r = r + b^k+1 + */ + mpi_set ( r1, x ); + if ( r1->nlimbs > k+1 ) /* Quick modulo operation. */ + r1->nlimbs = k+1; + mpi_mul ( r2, r2, m ); + if ( r2->nlimbs > k+1 ) /* Quick modulo operation. */ + r2->nlimbs = k+1; + mpi_sub ( r, r1, r2 ); + + if ( mpi_is_neg( r ) ) + { + if (!ctx->r3) + { + ctx->r3 = mpi_alloc ( k + 2 ); + mpi_set_ui (ctx->r3, 1); + mpi_lshift_limbs (ctx->r3, k + 1 ); + } + mpi_add ( r, r, ctx->r3 ); + } + + /* 4. while r >= m do r = r - m */ + while ( mpi_cmp( r, m ) >= 0 ) + mpi_sub ( r, r, m ); + +} + + +void +_gcry_mpi_mul_barrett (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, + mpi_barrett_t ctx) +{ + gcry_mpi_mul (w, u, v); + mpi_mod_barrett (w, w, ctx); +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-mpow.c b/grub-core/lib/libgcrypt-grub/mpi/mpi-mpow.c new file mode 100644 index 0000000..afef433 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-mpow.c @@ -0,0 +1,225 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-mpow.c - MPI functions + * Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "mpi-internal.h" +#include "longlong.h" +#include "g10lib.h" + + +/* Barrett is slower than the classical way. It can be tweaked by + * using partial multiplications + */ +/*#define USE_BARRETT*/ + + + +#ifdef USE_BARRETT +static void barrett_mulm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m, gcry_mpi_t y, int k, gcry_mpi_t r1, gcry_mpi_t r2 ); +static gcry_mpi_t init_barrett( gcry_mpi_t m, int *k, gcry_mpi_t *r1, gcry_mpi_t *r2 ); +static int calc_barrett( gcry_mpi_t r, gcry_mpi_t x, gcry_mpi_t m, gcry_mpi_t y, int k, gcry_mpi_t r1, gcry_mpi_t r2 ); +#else +#define barrett_mulm( w, u, v, m, y, k, r1, r2 ) gcry_mpi_mulm( (w), (u), (v), (m) ) +#endif + + +static int +build_index( gcry_mpi_t *exparray, int k, int i, int t ) +{ + int j, bitno; + int idx = 0; + + bitno = t-i; + for(j=k-1; j >= 0; j-- ) { + idx <<= 1; + if( mpi_test_bit( exparray[j], bitno ) ) + idx |= 1; + } + /*log_debug("t=%d i=%d idx=%d\n", t, i, idx );*/ + return idx; +} + +/**************** + * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M + */ +void +_gcry_mpi_mulpowm( gcry_mpi_t res, gcry_mpi_t *basearray, gcry_mpi_t *exparray, gcry_mpi_t m) +{ + int k; /* number of elements */ + int t; /* bit size of largest exponent */ + int i, j, idx; + gcry_mpi_t *G; /* table with precomputed values of size 2^k */ + gcry_mpi_t tmp; +#ifdef USE_BARRETT + gcry_mpi_t barrett_y, barrett_r1, barrett_r2; + int barrett_k; +#endif + + for(k=0; basearray[k]; k++ ) + ; + gcry_assert(k); + for(t=0, i=0; (tmp=exparray[i]); i++ ) { + /*log_mpidump("exp: ", tmp );*/ + j = mpi_get_nbits(tmp); + if( j > t ) + t = j; + } + /*log_mpidump("mod: ", m );*/ + gcry_assert (i==k); + gcry_assert (t); + gcry_assert (k < 10); + + G = gcry_xcalloc( (1<<k) , sizeof *G ); +#ifdef USE_BARRETT + barrett_y = init_barrett( m, &barrett_k, &barrett_r1, &barrett_r2 ); +#endif + /* and calculate */ + tmp = mpi_alloc( mpi_get_nlimbs(m)+1 ); + mpi_set_ui( res, 1 ); + for(i = 1; i <= t; i++ ) { + barrett_mulm(tmp, res, res, m, barrett_y, barrett_k, + barrett_r1, barrett_r2 ); + idx = build_index( exparray, k, i, t ); + gcry_assert (idx >= 0 && idx < (1<<k)); + if( !G[idx] ) { + if( !idx ) + G[0] = mpi_alloc_set_ui( 1 ); + else { + for(j=0; j < k; j++ ) { + if( (idx & (1<<j) ) ) { + if( !G[idx] ) + G[idx] = mpi_copy( basearray[j] ); + else + barrett_mulm( G[idx], G[idx], basearray[j], + m, barrett_y, barrett_k, barrett_r1, barrett_r2 ); + } + } + if( !G[idx] ) + G[idx] = mpi_alloc(0); + } + } + barrett_mulm(res, tmp, G[idx], m, barrett_y, barrett_k, barrett_r1, barrett_r2 ); + } + + /* cleanup */ + mpi_free(tmp); +#ifdef USE_BARRETT + mpi_free(barrett_y); + mpi_free(barrett_r1); + mpi_free(barrett_r2); +#endif + for(i=0; i < (1<<k); i++ ) + mpi_free(G[i]); + gcry_free(G); +} + + + +#ifdef USE_BARRETT +static void +barrett_mulm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m, gcry_mpi_t y, int k, gcry_mpi_t r1, gcry_mpi_t r2 ) +{ + mpi_mul(w, u, v); + if( calc_barrett( w, w, m, y, k, r1, r2 ) ) + mpi_fdiv_r( w, w, m ); +} + +/**************** + * Barrett precalculation: y = floor(b^(2k) / m) + */ +static gcry_mpi_t +init_barrett( gcry_mpi_t m, int *k, gcry_mpi_t *r1, gcry_mpi_t *r2 ) +{ + gcry_mpi_t tmp; + + mpi_normalize( m ); + *k = mpi_get_nlimbs( m ); + tmp = mpi_alloc( *k + 1 ); + mpi_set_ui( tmp, 1 ); + mpi_lshift_limbs( tmp, 2 * *k ); + mpi_fdiv_q( tmp, tmp, m ); + *r1 = mpi_alloc( 2* *k + 1 ); + *r2 = mpi_alloc( 2* *k + 1 ); + return tmp; +} + +/**************** + * Barrett reduction: We assume that these conditions are met: + * Given x =(x_2k-1 ...x_0)_b + * m =(m_k-1 ....m_0)_b with m_k-1 != 0 + * Output r = x mod m + * Before using this function init_barret must be used to calucalte y and k. + * Returns: false = no error + * true = can't perform barret reduction + */ +static int +calc_barrett( gcry_mpi_t r, gcry_mpi_t x, gcry_mpi_t m, gcry_mpi_t y, int k, gcry_mpi_t r1, gcry_mpi_t r2 ) +{ + int xx = k > 3 ? k-3:0; + + mpi_normalize( x ); + if( mpi_get_nlimbs(x) > 2*k ) + return 1; /* can't do it */ + + /* 1. q1 = floor( x / b^k-1) + * q2 = q1 * y + * q3 = floor( q2 / b^k+1 ) + * Actually, we don't need qx, we can work direct on r2 + */ + mpi_set( r2, x ); + mpi_rshift_limbs( r2, k-1 ); + mpi_mul( r2, r2, y ); + mpi_rshift_limbs( r2, k+1 ); + + /* 2. r1 = x mod b^k+1 + * r2 = q3 * m mod b^k+1 + * r = r1 - r2 + * 3. if r < 0 then r = r + b^k+1 + */ + mpi_set( r1, x ); + if( r1->nlimbs > k+1 ) /* quick modulo operation */ + r1->nlimbs = k+1; + mpi_mul( r2, r2, m ); + if( r2->nlimbs > k+1 ) /* quick modulo operation */ + r2->nlimbs = k+1; + mpi_sub( r, r1, r2 ); + + if( mpi_is_neg( r ) ) { + gcry_mpi_t tmp; + + tmp = mpi_alloc( k + 2 ); + mpi_set_ui( tmp, 1 ); + mpi_lshift_limbs( tmp, k+1 ); + mpi_add( r, r, tmp ); + mpi_free(tmp); + } + + /* 4. while r >= m do r = r - m */ + while( mpi_cmp( r, m ) >= 0 ) + mpi_sub( r, r, m ); + + return 0; +} +#endif /* USE_BARRETT */ diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-mul.c b/grub-core/lib/libgcrypt-grub/mpi/mpi-mul.c new file mode 100644 index 0000000..d305547 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-mul.c @@ -0,0 +1,214 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-mul.c - MPI functions + * Copyright (C) 1994, 1996, 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + + +void +gcry_mpi_mul_ui( gcry_mpi_t prod, gcry_mpi_t mult, unsigned long small_mult ) +{ + mpi_size_t size, prod_size; + mpi_ptr_t prod_ptr; + mpi_limb_t cy; + int sign; + + size = mult->nlimbs; + sign = mult->sign; + + if( !size || !small_mult ) { + prod->nlimbs = 0; + prod->sign = 0; + return; + } + + prod_size = size + 1; + if( prod->alloced < prod_size ) + mpi_resize( prod, prod_size ); + prod_ptr = prod->d; + + cy = _gcry_mpih_mul_1( prod_ptr, mult->d, size, (mpi_limb_t)small_mult ); + if( cy ) + prod_ptr[size++] = cy; + prod->nlimbs = size; + prod->sign = sign; +} + + +void +gcry_mpi_mul_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt) +{ + mpi_size_t usize, wsize, limb_cnt; + mpi_ptr_t wp; + mpi_limb_t wlimb; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + + if( !usize ) { + w->nlimbs = 0; + w->sign = 0; + return; + } + + limb_cnt = cnt / BITS_PER_MPI_LIMB; + wsize = usize + limb_cnt + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize ); + wp = w->d; + wsize = usize + limb_cnt; + wsign = usign; + + cnt %= BITS_PER_MPI_LIMB; + if( cnt ) { + wlimb = _gcry_mpih_lshift( wp + limb_cnt, u->d, usize, cnt ); + if( wlimb ) { + wp[wsize] = wlimb; + wsize++; + } + } + else { + MPN_COPY_DECR( wp + limb_cnt, u->d, usize ); + } + + /* Zero all whole limbs at low end. Do it here and not before calling + * mpn_lshift, not to lose for U == W. */ + MPN_ZERO( wp, limb_cnt ); + + w->nlimbs = wsize; + w->sign = wsign; +} + + +void +gcry_mpi_mul( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v) +{ + mpi_size_t usize, vsize, wsize; + mpi_ptr_t up, vp, wp; + mpi_limb_t cy; + int usign, vsign, usecure, vsecure, sign_product; + int assign_wp=0; + mpi_ptr_t tmp_limb=NULL; + unsigned int tmp_limb_nlimbs = 0; + + if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ + usize = v->nlimbs; + usign = v->sign; + usecure = mpi_is_secure(v); + up = v->d; + vsize = u->nlimbs; + vsign = u->sign; + vsecure = mpi_is_secure(u); + vp = u->d; + } + else { + usize = u->nlimbs; + usign = u->sign; + usecure = mpi_is_secure(u); + up = u->d; + vsize = v->nlimbs; + vsign = v->sign; + vsecure = mpi_is_secure(v); + vp = v->d; + } + sign_product = usign ^ vsign; + wp = w->d; + + /* Ensure W has space enough to store the result. */ + wsize = usize + vsize; + if ( !mpi_is_secure (w) && (mpi_is_secure (u) || mpi_is_secure (v)) ) { + /* w is not allocated in secure space but u or v is. To make sure + * that no temporray results are stored in w, we temporary use + * a newly allocated limb space for w */ + wp = mpi_alloc_limb_space( wsize, 1 ); + assign_wp = 2; /* mark it as 2 so that we can later copy it back to + * mormal memory */ + } + else if( w->alloced < wsize ) { + if( wp == up || wp == vp ) { + wp = mpi_alloc_limb_space( wsize, mpi_is_secure(w) ); + assign_wp = 1; + } + else { + mpi_resize(w, wsize ); + wp = w->d; + } + } + else { /* Make U and V not overlap with W. */ + if( wp == up ) { + /* W and U are identical. Allocate temporary space for U. */ + tmp_limb_nlimbs = usize; + up = tmp_limb = mpi_alloc_limb_space( usize, usecure ); + /* Is V identical too? Keep it identical with U. */ + if( wp == vp ) + vp = up; + /* Copy to the temporary space. */ + MPN_COPY( up, wp, usize ); + } + else if( wp == vp ) { + /* W and V are identical. Allocate temporary space for V. */ + tmp_limb_nlimbs = vsize; + vp = tmp_limb = mpi_alloc_limb_space( vsize, vsecure ); + /* Copy to the temporary space. */ + MPN_COPY( vp, wp, vsize ); + } + } + + if( !vsize ) + wsize = 0; + else { + cy = _gcry_mpih_mul( wp, up, usize, vp, vsize ); + wsize -= cy? 0:1; + } + + if( assign_wp ) { + if (assign_wp == 2) { + /* copy the temp wp from secure memory back to normal memory */ + mpi_ptr_t tmp_wp = mpi_alloc_limb_space (wsize, 0); + MPN_COPY (tmp_wp, wp, wsize); + _gcry_mpi_free_limb_space (wp, 0); + wp = tmp_wp; + } + _gcry_mpi_assign_limb_space( w, wp, wsize ); + } + w->nlimbs = wsize; + w->sign = sign_product; + if( tmp_limb ) + _gcry_mpi_free_limb_space (tmp_limb, tmp_limb_nlimbs); +} + + +void +gcry_mpi_mulm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) +{ + gcry_mpi_mul(w, u, v); + _gcry_mpi_fdiv_r( w, w, m ); +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpi-pow.c b/grub-core/lib/libgcrypt-grub/mpi/mpi-pow.c new file mode 100644 index 0000000..f6b3f58 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpi-pow.c @@ -0,0 +1,340 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpi-pow.c - MPI functions for exponentiation + * Copyright (C) 1994, 1996, 1998, 2000, 2002 + * 2003 Free Software Foundation, Inc. + * 2013 g10 Code GmbH + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "mpi-internal.h" +#include "longlong.h" + + +/**************** + * RES = BASE ^ EXPO mod MOD + */ +void +gcry_mpi_powm (gcry_mpi_t res, + gcry_mpi_t base, gcry_mpi_t expo, gcry_mpi_t mod) +{ + /* Pointer to the limbs of the arguments, their size and signs. */ + mpi_ptr_t rp, ep, mp, bp; + mpi_size_t esize, msize, bsize, rsize; + int msign, bsign, rsign; + /* Flags telling the secure allocation status of the arguments. */ + int esec, msec, bsec; + /* Size of the result including space for temporary values. */ + mpi_size_t size; + /* Helper. */ + int mod_shift_cnt; + int negative_result; + mpi_ptr_t mp_marker = NULL; + mpi_ptr_t bp_marker = NULL; + mpi_ptr_t ep_marker = NULL; + mpi_ptr_t xp_marker = NULL; + unsigned int mp_nlimbs = 0; + unsigned int bp_nlimbs = 0; + unsigned int ep_nlimbs = 0; + unsigned int xp_nlimbs = 0; + mpi_ptr_t tspace = NULL; + mpi_size_t tsize = 0; + + + esize = expo->nlimbs; + msize = mod->nlimbs; + size = 2 * msize; + msign = mod->sign; + + esec = mpi_is_secure(expo); + msec = mpi_is_secure(mod); + bsec = mpi_is_secure(base); + + rp = res->d; + ep = expo->d; + + if (!msize) + grub_fatal ("mpi division by zero"); + + if (!esize) + { + /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 depending + on if MOD equals 1. */ + res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; + if (res->nlimbs) + { + RESIZE_IF_NEEDED (res, 1); + rp = res->d; + rp[0] = 1; + } + res->sign = 0; + goto leave; + } + + /* Normalize MOD (i.e. make its most significant bit set) as + required by mpn_divrem. This will make the intermediate values + in the calculation slightly larger, but the correct result is + obtained after a final reduction using the original MOD value. */ + mp_nlimbs = msec? msize:0; + mp = mp_marker = mpi_alloc_limb_space(msize, msec); + count_leading_zeros (mod_shift_cnt, mod->d[msize-1]); + if (mod_shift_cnt) + _gcry_mpih_lshift (mp, mod->d, msize, mod_shift_cnt); + else + MPN_COPY( mp, mod->d, msize ); + + bsize = base->nlimbs; + bsign = base->sign; + if (bsize > msize) + { + /* The base is larger than the module. Reduce it. + + Allocate (BSIZE + 1) with space for remainder and quotient. + (The quotient is (bsize - msize + 1) limbs.) */ + bp_nlimbs = bsec ? (bsize + 1):0; + bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec ); + MPN_COPY ( bp, base->d, bsize ); + /* We don't care about the quotient, store it above the + * remainder, at BP + MSIZE. */ + _gcry_mpih_divrem( bp + msize, 0, bp, bsize, mp, msize ); + bsize = msize; + /* Canonicalize the base, since we are going to multiply with it + quite a few times. */ + MPN_NORMALIZE( bp, bsize ); + } + else + bp = base->d; + + if (!bsize) + { + res->nlimbs = 0; + res->sign = 0; + goto leave; + } + + + /* Make BASE, EXPO and MOD not overlap with RES. */ + if ( rp == bp ) + { + /* RES and BASE are identical. Allocate temp. space for BASE. */ + gcry_assert (!bp_marker); + bp_nlimbs = bsec? bsize:0; + bp = bp_marker = mpi_alloc_limb_space( bsize, bsec ); + MPN_COPY(bp, rp, bsize); + } + if ( rp == ep ) + { + /* RES and EXPO are identical. Allocate temp. space for EXPO. */ + ep_nlimbs = esec? esize:0; + ep = ep_marker = mpi_alloc_limb_space( esize, esec ); + MPN_COPY(ep, rp, esize); + } + if ( rp == mp ) + { + /* RES and MOD are identical. Allocate temporary space for MOD.*/ + gcry_assert (!mp_marker); + mp_nlimbs = msec?msize:0; + mp = mp_marker = mpi_alloc_limb_space( msize, msec ); + MPN_COPY(mp, rp, msize); + } + + /* Copy base to the result. */ + if (res->alloced < size) + { + mpi_resize (res, size); + rp = res->d; + } + MPN_COPY ( rp, bp, bsize ); + rsize = bsize; + rsign = bsign; + + /* Main processing. */ + { + mpi_size_t i; + mpi_ptr_t xp; + int c; + mpi_limb_t e; + mpi_limb_t carry_limb; + struct karatsuba_ctx karactx; + + xp_nlimbs = msec? (2 * (msize + 1)):0; + xp = xp_marker = mpi_alloc_limb_space( 2 * (msize + 1), msec ); + + memset( &karactx, 0, sizeof karactx ); + negative_result = (ep[0] & 1) && base->sign; + + i = esize - 1; + e = ep[i]; + count_leading_zeros (c, e); + e = (e << c) << 1; /* Shift the expo bits to the left, lose msb. */ + c = BITS_PER_MPI_LIMB - 1 - c; + + /* Main loop. + + Make the result be pointed to alternately by XP and RP. This + helps us avoid block copying, which would otherwise be + necessary with the overlap restrictions of + _gcry_mpih_divmod. With 50% probability the result after this + loop will be in the area originally pointed by RP (==RES->d), + and with 50% probability in the area originally pointed to by XP. */ + for (;;) + { + while (c) + { + mpi_ptr_t tp; + mpi_size_t xsize; + + /*mpih_mul_n(xp, rp, rp, rsize);*/ + if ( rsize < KARATSUBA_THRESHOLD ) + _gcry_mpih_sqr_n_basecase( xp, rp, rsize ); + else + { + if ( !tspace ) + { + tsize = 2 * rsize; + tspace = mpi_alloc_limb_space( tsize, 0 ); + } + else if ( tsize < (2*rsize) ) + { + _gcry_mpi_free_limb_space (tspace, 0); + tsize = 2 * rsize; + tspace = mpi_alloc_limb_space (tsize, 0 ); + } + _gcry_mpih_sqr_n (xp, rp, rsize, tspace); + } + + xsize = 2 * rsize; + if ( xsize > msize ) + { + _gcry_mpih_divrem(xp + msize, 0, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + + /* To mitigate the Yarom/Falkner flush+reload cache + * side-channel attack on the RSA secret exponent, we do + * the multiplication regardless of the value of the + * high-bit of E. But to avoid this performance penalty + * we do it only if the exponent has been stored in secure + * memory and we can thus assume it is a secret exponent. */ + if (esec || (mpi_limb_signed_t)e < 0) + { + /*mpih_mul( xp, rp, rsize, bp, bsize );*/ + if( bsize < KARATSUBA_THRESHOLD ) + _gcry_mpih_mul ( xp, rp, rsize, bp, bsize ); + else + _gcry_mpih_mul_karatsuba_case (xp, rp, rsize, bp, bsize, + &karactx); + + xsize = rsize + bsize; + if ( xsize > msize ) + { + _gcry_mpih_divrem(xp + msize, 0, xp, xsize, mp, msize); + xsize = msize; + } + } + if ( (mpi_limb_signed_t)e < 0 ) + { + tp = rp; rp = xp; xp = tp; + rsize = xsize; + } + e <<= 1; + c--; + } + + i--; + if ( i < 0 ) + break; + e = ep[i]; + c = BITS_PER_MPI_LIMB; + } + + /* We shifted MOD, the modulo reduction argument, left + MOD_SHIFT_CNT steps. Adjust the result by reducing it with the + original MOD. + + Also make sure the result is put in RES->d (where it already + might be, see above). */ + if ( mod_shift_cnt ) + { + carry_limb = _gcry_mpih_lshift( res->d, rp, rsize, mod_shift_cnt); + rp = res->d; + if ( carry_limb ) + { + rp[rsize] = carry_limb; + rsize++; + } + } + else if (res->d != rp) + { + MPN_COPY (res->d, rp, rsize); + rp = res->d; + } + + if ( rsize >= msize ) + { + _gcry_mpih_divrem(rp + msize, 0, rp, rsize, mp, msize); + rsize = msize; + } + + /* Remove any leading zero words from the result. */ + if ( mod_shift_cnt ) + _gcry_mpih_rshift( rp, rp, rsize, mod_shift_cnt); + MPN_NORMALIZE (rp, rsize); + + _gcry_mpih_release_karatsuba_ctx (&karactx ); + } + + /* Fixup for negative results. */ + if ( negative_result && rsize ) + { + if ( mod_shift_cnt ) + _gcry_mpih_rshift( mp, mp, msize, mod_shift_cnt); + _gcry_mpih_sub( rp, mp, msize, rp, rsize); + rsize = msize; + rsign = msign; + MPN_NORMALIZE(rp, rsize); + } + gcry_assert (res->d == rp); + res->nlimbs = rsize; + res->sign = rsign; + + leave: + if (mp_marker) + _gcry_mpi_free_limb_space( mp_marker, mp_nlimbs ); + if (bp_marker) + _gcry_mpi_free_limb_space( bp_marker, bp_nlimbs ); + if (ep_marker) + _gcry_mpi_free_limb_space( ep_marker, ep_nlimbs ); + if (xp_marker) + _gcry_mpi_free_limb_space( xp_marker, xp_nlimbs ); + if (tspace) + _gcry_mpi_free_limb_space( tspace, 0 ); +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpicoder.c b/grub-core/lib/libgcrypt-grub/mpi/mpicoder.c new file mode 100644 index 0000000..e734dcf --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpicoder.c @@ -0,0 +1,755 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpicoder.c - Coder for the external representation of MPIs + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 + * 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "mpi-internal.h" +#include "g10lib.h" + +#define MAX_EXTERN_MPI_BITS 16384 + +/* Helper used to scan PGP style MPIs. Returns NULL on failure. */ +static gcry_mpi_t +mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread, + int secure) +{ + int i, j; + unsigned int nbits, nbytes, nlimbs, nread=0; + mpi_limb_t a; + gcry_mpi_t val = MPI_NULL; + + if ( *ret_nread < 2 ) + goto leave; + nbits = buffer[0] << 8 | buffer[1]; + if ( nbits > MAX_EXTERN_MPI_BITS ) + { +/* log_debug ("mpi too large (%u bits)\n", nbits); */ + goto leave; + } + buffer += 2; + nread = 2; + + nbytes = (nbits+7) / 8; + nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; + val = secure? mpi_alloc_secure (nlimbs) : mpi_alloc (nlimbs); + i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; + i %= BYTES_PER_MPI_LIMB; + j= val->nlimbs = nlimbs; + val->sign = 0; + for ( ; j > 0; j-- ) + { + a = 0; + for (; i < BYTES_PER_MPI_LIMB; i++ ) + { + if ( ++nread > *ret_nread ) + { +/* log_debug ("mpi larger than buffer"); */ + mpi_free (val); + val = NULL; + goto leave; + } + a <<= 8; + a |= *buffer++; + } + i = 0; + val->d[j-1] = a; + } + + leave: + *ret_nread = nread; + return val; +} + + +/**************** + * Fill the mpi VAL from the hex string in STR. + */ +static int +mpi_fromstr (gcry_mpi_t val, const char *str) +{ + int sign = 0; + int prepend_zero = 0; + int i, j, c, c1, c2; + unsigned int nbits, nbytes, nlimbs; + mpi_limb_t a; + + if ( *str == '-' ) + { + sign = 1; + str++; + } + + /* Skip optional hex prefix. */ + if ( *str == '0' && str[1] == 'x' ) + str += 2; + + nbits = 4 * strlen (str); + if ((nbits % 8)) + prepend_zero = 1; + + nbytes = (nbits+7) / 8; + nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; + + if ( val->alloced < nlimbs ) + mpi_resize (val, nlimbs); + + i = BYTES_PER_MPI_LIMB - (nbytes % BYTES_PER_MPI_LIMB); + i %= BYTES_PER_MPI_LIMB; + j = val->nlimbs = nlimbs; + val->sign = sign; + for (; j > 0; j--) + { + a = 0; + for (; i < BYTES_PER_MPI_LIMB; i++) + { + if (prepend_zero) + { + c1 = '0'; + prepend_zero = 0; + } + else + c1 = *str++; + + if (!c1) + { + mpi_clear (val); + return 1; /* Error. */ + } + c2 = *str++; + if (!c2) + { + mpi_clear (val); + return 1; /* Error. */ + } + if ( c1 >= '0' && c1 <= '9' ) + c = c1 - '0'; + else if ( c1 >= 'a' && c1 <= 'f' ) + c = c1 - 'a' + 10; + else if ( c1 >= 'A' && c1 <= 'F' ) + c = c1 - 'A' + 10; + else + { + mpi_clear (val); + return 1; /* Error. */ + } + c <<= 4; + if ( c2 >= '0' && c2 <= '9' ) + c |= c2 - '0'; + else if( c2 >= 'a' && c2 <= 'f' ) + c |= c2 - 'a' + 10; + else if( c2 >= 'A' && c2 <= 'F' ) + c |= c2 - 'A' + 10; + else + { + mpi_clear(val); + return 1; /* Error. */ + } + a <<= 8; + a |= c; + } + i = 0; + val->d[j-1] = a; + } + + return 0; /* Okay. */ +} + + +/* Dump the value of A in a format suitable for debugging to + Libgcrypt's logging stream. Note that one leading space but no + trailing space or linefeed will be printed. It is okay to pass + NULL for A. */ +void +gcry_mpi_dump (const gcry_mpi_t a) +{ + int i; + + log_printf (" "); + if (!a) + log_printf ("[MPI_NULL]"); + else + { + if (a->sign) + log_printf ( "-"); +#if BYTES_PER_MPI_LIMB == 2 +# define X "4" +#elif BYTES_PER_MPI_LIMB == 4 +# define X "8" +#elif BYTES_PER_MPI_LIMB == 8 +# define X "16" +#elif BYTES_PER_MPI_LIMB == 16 +# define X "32" +#else +# error please define the format here +#endif + for (i=a->nlimbs; i > 0 ; i-- ) + { + log_printf (i != a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]); + } +#undef X + if (!a->nlimbs) + log_printf ("0"); + } +} + +/* Convience function used internally. */ +void +_gcry_log_mpidump (const char *text, gcry_mpi_t a) +{ + log_printf ("%s:", text); + gcry_mpi_dump (a); + log_printf ("\n"); +} + + +/* Return an allocated buffer with the MPI (msb first). NBYTES + receives the length of this buffer. Caller must free the return + string. This function returns an allocated buffer with NBYTES set + to zero if the value of A is zero. If sign is not NULL, it will be + set to the sign of the A. On error NULL is returned and ERRNO set + appropriately. */ +static unsigned char * +do_get_buffer (gcry_mpi_t a, unsigned int *nbytes, int *sign, int force_secure) +{ + unsigned char *p, *buffer; + mpi_limb_t alimb; + int i; + size_t n; + + if (sign) + *sign = a->sign; + + *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB; + n = *nbytes? *nbytes:1; /* Allocate at least one byte. */ + p = buffer = (force_secure || mpi_is_secure(a))? gcry_malloc_secure (n) + : gcry_malloc (n); + if (!buffer) + return NULL; + + for (i=a->nlimbs-1; i >= 0; i--) + { + alimb = a->d[i]; +#if BYTES_PER_MPI_LIMB == 4 + *p++ = alimb >> 24; + *p++ = alimb >> 16; + *p++ = alimb >> 8; + *p++ = alimb ; +#elif BYTES_PER_MPI_LIMB == 8 + *p++ = alimb >> 56; + *p++ = alimb >> 48; + *p++ = alimb >> 40; + *p++ = alimb >> 32; + *p++ = alimb >> 24; + *p++ = alimb >> 16; + *p++ = alimb >> 8; + *p++ = alimb ; +#else +# error please implement for this limb size. +#endif + } + + /* This is sub-optimal but we need to do the shift operation because + the caller has to free the returned buffer. */ + for (p=buffer; *nbytes && !*p; p++, --*nbytes) + ; + if (p != buffer) + memmove (buffer,p, *nbytes); + return buffer; +} + + +byte * +_gcry_mpi_get_buffer (gcry_mpi_t a, unsigned int *nbytes, int *sign) +{ + return do_get_buffer (a, nbytes, sign, 0); +} + +byte * +_gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned *nbytes, int *sign) +{ + return do_get_buffer (a, nbytes, sign, 1); +} + + +/* + * Use the NBYTES at BUFFER_ARG to update A. Set the sign of a to + * SIGN. + */ +void +_gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg, + unsigned int nbytes, int sign) +{ + const unsigned char *buffer = (const unsigned char*)buffer_arg; + const unsigned char *p; + mpi_limb_t alimb; + int nlimbs; + int i; + + nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; + RESIZE_IF_NEEDED(a, nlimbs); + a->sign = sign; + + for (i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) + { +#if BYTES_PER_MPI_LIMB == 4 + alimb = *p-- ; + alimb |= *p-- << 8 ; + alimb |= *p-- << 16 ; + alimb |= *p-- << 24 ; +#elif BYTES_PER_MPI_LIMB == 8 + alimb = (mpi_limb_t)*p-- ; + alimb |= (mpi_limb_t)*p-- << 8 ; + alimb |= (mpi_limb_t)*p-- << 16 ; + alimb |= (mpi_limb_t)*p-- << 24 ; + alimb |= (mpi_limb_t)*p-- << 32 ; + alimb |= (mpi_limb_t)*p-- << 40 ; + alimb |= (mpi_limb_t)*p-- << 48 ; + alimb |= (mpi_limb_t)*p-- << 56 ; +#else +# error please implement for this limb size. +#endif + a->d[i++] = alimb; + } + if ( p >= buffer ) + { +#if BYTES_PER_MPI_LIMB == 4 + alimb = *p--; + if (p >= buffer) + alimb |= *p-- << 8; + if (p >= buffer) + alimb |= *p-- << 16; + if (p >= buffer) + alimb |= *p-- << 24; +#elif BYTES_PER_MPI_LIMB == 8 + alimb = (mpi_limb_t)*p--; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 8; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 16; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 24; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 32; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 40; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 48; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 56; +#else +# error please implement for this limb size. +#endif + a->d[i++] = alimb; + } + a->nlimbs = i; + gcry_assert (i == nlimbs); +} + + +/* Convert the external representation of an integer stored in BUFFER + with a length of BUFLEN into a newly create MPI returned in + RET_MPI. If NBYTES is not NULL, it will receive the number of + bytes actually scanned after a successful operation. */ +gcry_error_t +gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format, + const void *buffer_arg, size_t buflen, size_t *nscanned) +{ + const unsigned char *buffer = (const unsigned char*)buffer_arg; + struct gcry_mpi *a = NULL; + unsigned int len; + int secure = (buffer && gcry_is_secure (buffer)); + + if (!buffer) + return gcry_error (GPG_ERR_INV_ARG); + + if (format == GCRYMPI_FMT_SSH) + len = 0; + else + len = buflen; + + if (format == GCRYMPI_FMT_STD) + { + const unsigned char *s = buffer; + + a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1) + /BYTES_PER_MPI_LIMB) + : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); + if (len) + { + a->sign = !!(*s & 0x80); + if (a->sign) + { + /* FIXME: we have to convert from 2compl to magnitude format */ + mpi_free (a); + return gcry_error (GPG_ERR_INTERNAL); + } + else + _gcry_mpi_set_buffer (a, s, len, 0); + } + if (ret_mpi) + { + mpi_normalize ( a ); + *ret_mpi = a; + } + else + mpi_free(a); + return 0; + } + else if (format == GCRYMPI_FMT_USG) + { + a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1) + /BYTES_PER_MPI_LIMB) + : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); + + if (len) + _gcry_mpi_set_buffer (a, buffer, len, 0); + if (ret_mpi) + { + mpi_normalize ( a ); + *ret_mpi = a; + } + else + mpi_free(a); + return 0; + } + else if (format == GCRYMPI_FMT_PGP) + { + a = mpi_read_from_buffer (buffer, &len, secure); + if (nscanned) + *nscanned = len; + if (ret_mpi && a) + { + mpi_normalize (a); + *ret_mpi = a; + } + else if (a) + { + mpi_free(a); + a = NULL; + } + return a? 0 : gcry_error (GPG_ERR_INV_OBJ); + } + else if (format == GCRYMPI_FMT_SSH) + { + const unsigned char *s = buffer; + size_t n; + + /* This test is not strictly necessary and an assert (!len) + would be sufficient. We keep this test in case we later + allow the BUFLEN argument to act as a sanitiy check. Same + below. */ + if (len && len < 4) + return gcry_error (GPG_ERR_TOO_SHORT); + + n = ((size_t)s[0] << 24 | (size_t)s[1] << 16 | (size_t)s[2] << 8 | (size_t)s[3]); + s += 4; + if (len) + len -= 4; + if (len && n > len) + return gcry_error (GPG_ERR_TOO_LARGE); + + a = secure? mpi_alloc_secure ((n+BYTES_PER_MPI_LIMB-1) + /BYTES_PER_MPI_LIMB) + : mpi_alloc ((n+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); + if (n) + { + a->sign = !!(*s & 0x80); + if (a->sign) + { + /* FIXME: we have to convert from 2compl to magnitude format */ + mpi_free(a); + return gcry_error (GPG_ERR_INTERNAL); + } + else + _gcry_mpi_set_buffer( a, s, n, 0 ); + } + if (nscanned) + *nscanned = n+4; + if (ret_mpi) + { + mpi_normalize ( a ); + *ret_mpi = a; + } + else + mpi_free(a); + return 0; + } + else if (format == GCRYMPI_FMT_HEX) + { + /* We can only handle C strings for now. */ + if (buflen) + return gcry_error (GPG_ERR_INV_ARG); + + a = secure? mpi_alloc_secure (0) : mpi_alloc(0); + if (mpi_fromstr (a, (const char *)buffer)) + { + mpi_free (a); + return gcry_error (GPG_ERR_INV_OBJ); + } + if (ret_mpi) + { + mpi_normalize ( a ); + *ret_mpi = a; + } + else + mpi_free(a); + return 0; + } + else + return gcry_error (GPG_ERR_INV_ARG); +} + + +/* Convert the big integer A into the external representation + described by FORMAT and store it in the provided BUFFER which has + been allocated by the user with a size of BUFLEN bytes. NWRITTEN + receives the actual length of the external representation unless it + has been passed as NULL. BUFFER may be NULL to query the required + length. */ +gcry_error_t +gcry_mpi_print (enum gcry_mpi_format format, + unsigned char *buffer, size_t buflen, + size_t *nwritten, struct gcry_mpi *a) +{ + unsigned int nbits = mpi_get_nbits (a); + size_t len; + size_t dummy_nwritten; + + if (!nwritten) + nwritten = &dummy_nwritten; + + len = buflen; + *nwritten = 0; + if (format == GCRYMPI_FMT_STD) + { + unsigned char *tmp; + int extra = 0; + unsigned int n; + + if (a->sign) + return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */ + + tmp = _gcry_mpi_get_buffer (a, &n, NULL); + if (!tmp) + return gpg_error_from_syserror (); + if (n && (*tmp & 0x80)) + { + n++; + extra=1; + } + + if (buffer && n > len) + { + /* The provided buffer is too short. */ + gcry_free (tmp); + return gcry_error (GPG_ERR_TOO_SHORT); + } + if (buffer) + { + unsigned char *s = buffer; + + if (extra) + *s++ = 0; + memcpy (s, tmp, n-extra); + } + gcry_free(tmp); + *nwritten = n; + return 0; + } + else if (format == GCRYMPI_FMT_USG) + { + unsigned int n = (nbits + 7)/8; + + /* Note: We ignore the sign for this format. */ + /* FIXME: for performance reasons we should put this into + mpi_aprint because we can then use the buffer directly. */ + if (buffer && n > len) + return gcry_error (GPG_ERR_TOO_SHORT); + if (buffer) + { + unsigned char *tmp; + + tmp = _gcry_mpi_get_buffer (a, &n, NULL); + if (!tmp) + return gpg_error_from_syserror (); + memcpy (buffer, tmp, n); + gcry_free (tmp); + } + *nwritten = n; + return 0; + } + else if (format == GCRYMPI_FMT_PGP) + { + unsigned int n = (nbits + 7)/8; + + /* The PGP format can only handle unsigned integers. */ + if( a->sign ) + return gcry_error (GPG_ERR_INV_ARG); + + if (buffer && n+2 > len) + return gcry_error (GPG_ERR_TOO_SHORT); + + if (buffer) + { + unsigned char *tmp; + unsigned char *s = buffer; + + s[0] = nbits >> 8; + s[1] = nbits; + + tmp = _gcry_mpi_get_buffer (a, &n, NULL); + if (!tmp) + return gpg_error_from_syserror (); + memcpy (s+2, tmp, n); + gcry_free (tmp); + } + *nwritten = n+2; + return 0; + } + else if (format == GCRYMPI_FMT_SSH) + { + unsigned char *tmp; + int extra = 0; + unsigned int n; + + if (a->sign) + return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */ + + tmp = _gcry_mpi_get_buffer (a, &n, NULL); + if (!tmp) + return gpg_error_from_syserror (); + if (n && (*tmp & 0x80)) + { + n++; + extra=1; + } + + if (buffer && n+4 > len) + { + gcry_free(tmp); + return gcry_error (GPG_ERR_TOO_SHORT); + } + + if (buffer) + { + unsigned char *s = buffer; + + *s++ = n >> 24; + *s++ = n >> 16; + *s++ = n >> 8; + *s++ = n; + if (extra) + *s++ = 0; + + memcpy (s, tmp, n-extra); + } + gcry_free (tmp); + *nwritten = 4+n; + return 0; + } + else if (format == GCRYMPI_FMT_HEX) + { + unsigned char *tmp; + int i; + int extra = 0; + unsigned int n = 0; + + tmp = _gcry_mpi_get_buffer (a, &n, NULL); + if (!tmp) + return gpg_error_from_syserror (); + if (!n || (*tmp & 0x80)) + extra = 2; + + if (buffer && 2*n + extra + !!a->sign + 1 > len) + { + gcry_free(tmp); + return gcry_error (GPG_ERR_TOO_SHORT); + } + if (buffer) + { + unsigned char *s = buffer; + + if (a->sign) + *s++ = '-'; + if (extra) + { + *s++ = '0'; + *s++ = '0'; + } + + for (i=0; i < n; i++) + { + unsigned int c = tmp[i]; + + *s++ = (c >> 4) < 10? '0'+(c>>4) : 'A'+(c>>4)-10 ; + c &= 15; + *s++ = c < 10? '0'+c : 'A'+c-10 ; + } + *s++ = 0; + *nwritten = s - buffer; + } + else + { + *nwritten = 2*n + extra + !!a->sign + 1; + } + gcry_free (tmp); + return 0; + } + else + return gcry_error (GPG_ERR_INV_ARG); +} + + +/* + * Like gcry_mpi_print but this function allocates the buffer itself. + * The caller has to supply the address of a pointer. NWRITTEN may be + * NULL. + */ +gcry_error_t +gcry_mpi_aprint (enum gcry_mpi_format format, + unsigned char **buffer, size_t *nwritten, + struct gcry_mpi *a) +{ + size_t n; + gcry_error_t rc; + + *buffer = NULL; + rc = gcry_mpi_print (format, NULL, 0, &n, a); + if (rc) + return rc; + + *buffer = mpi_is_secure(a) ? gcry_malloc_secure (n) : gcry_malloc (n); + if (!*buffer) + return gpg_error_from_syserror (); + rc = gcry_mpi_print( format, *buffer, n, &n, a ); + if (rc) + { + gcry_free(*buffer); + *buffer = NULL; + } + else if (nwritten) + *nwritten = n; + return rc; +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpih-add1.c b/grub-core/lib/libgcrypt-grub/mpi/mpih-add1.c new file mode 100644 index 0000000..4a84df6 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpih-add1.c @@ -0,0 +1,65 @@ +/* mpihelp-add_1.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, + * 2000, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +_gcry_mpih_add_n (mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size) +{ + mpi_limb_t x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to one addend */ + cy = y < cy; /* get out carry from that addition */ + y += x; /* add other addend */ + cy += y < x; /* get out carry from that add, combine */ + res_ptr[j] = y; + } + while ( ++j ); + + return cy; +} + diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpih-div.c b/grub-core/lib/libgcrypt-grub/mpi/mpih-div.c new file mode 100644 index 0000000..797c083 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpih-div.c @@ -0,0 +1,536 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpih-div.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 2000, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +#ifndef UMUL_TIME +#define UMUL_TIME 1 +#endif +#ifndef UDIV_TIME +#define UDIV_TIME UMUL_TIME +#endif + +/* FIXME: We should be using invert_limb (or invert_normalized_limb) + * here (not udiv_qrnnd). + */ + +mpi_limb_t +_gcry_mpih_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb) +{ + mpi_size_t i; + mpi_limb_t n1, n0, r; + int dummy; + + /* Botch: Should this be handled at all? Rely on callers? */ + if( !dividend_size ) + return 0; + + /* If multiplication is much faster than division, and the + * dividend is large, pre-invert the divisor, and use + * only multiplications in the inner loop. + * + * This test should be read: + * Does it ever help to use udiv_qrnnd_preinv? + * && Does what we save compensate for the inversion overhead? + */ + if( UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { + int normalization_steps; + + count_leading_zeros( normalization_steps, divisor_limb ); + if( normalization_steps ) { + mpi_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + * + * Special case for DIVISOR_LIMB == 100...000. + */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV(dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + UDIV_QRNND_PREINV(dummy, r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else { + mpi_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + * + * Special case for DIVISOR_LIMB == 100...000. + */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if( r >= divisor_limb ) + r = 0; + else + i--; + + for( ; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV(dummy, r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else { + if( UDIV_NEEDS_NORMALIZATION ) { + int normalization_steps; + + count_leading_zeros(normalization_steps, divisor_limb); + if( normalization_steps ) { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for(i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (dummy, r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + * it, or because DIVISOR_LIMB is already normalized. */ + i = dividend_size - 1; + r = dividend_ptr[i]; + + if(r >= divisor_limb) + r = 0; + else + i--; + + for(; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, n0, divisor_limb); + } + return r; + } +} + +/* Divide num (NP/NSIZE) by den (DP/DSIZE) and write + * the NSIZE-DSIZE least significant quotient limbs at QP + * and the DSIZE long remainder at NP. If QEXTRA_LIMBS is + * non-zero, generate that many fraction bits and append them after the + * other quotient limbs. + * Return the most significant limb of the quotient, this is always 0 or 1. + * + * Preconditions: + * 0. NSIZE >= DSIZE. + * 1. The most significant bit of the divisor must be set. + * 2. QP must either not overlap with the input operands at all, or + * QP + DSIZE >= NP must hold true. (This means that it's + * possible to put the quotient in the high part of NUM, right after the + * remainder in NUM. + * 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero. + */ + +mpi_limb_t +_gcry_mpih_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, + mpi_ptr_t np, mpi_size_t nsize, + mpi_ptr_t dp, mpi_size_t dsize) +{ + mpi_limb_t most_significant_q_limb = 0; + + switch(dsize) { + case 0: + /* We are asked to divide by zero, so go ahead and do it! (To make + the compiler not remove this statement, return the value.) */ + grub_fatal ("mpi division by zero"); + return 0; + + case 1: + { + mpi_size_t i; + mpi_limb_t n1; + mpi_limb_t d; + + d = dp[0]; + n1 = np[nsize - 1]; + + if( n1 >= d ) { + n1 -= d; + most_significant_q_limb = 1; + } + + qp += qextra_limbs; + for( i = nsize - 2; i >= 0; i--) + udiv_qrnnd( qp[i], n1, n1, np[i], d ); + qp -= qextra_limbs; + + for( i = qextra_limbs - 1; i >= 0; i-- ) + udiv_qrnnd (qp[i], n1, n1, 0, d); + + np[0] = n1; + } + break; + + case 2: + { + mpi_size_t i; + mpi_limb_t n1, n0, n2; + mpi_limb_t d1, d0; + + np += nsize - 2; + d1 = dp[1]; + d0 = dp[0]; + n1 = np[1]; + n0 = np[0]; + + if( n1 >= d1 && (n1 > d1 || n0 >= d0) ) { + sub_ddmmss (n1, n0, n1, n0, d1, d0); + most_significant_q_limb = 1; + } + + for( i = qextra_limbs + nsize - 2 - 1; i >= 0; i-- ) { + mpi_limb_t q; + mpi_limb_t r; + + if( i >= qextra_limbs ) + np--; + else + np[0] = 0; + + if( n1 == d1 ) { + /* Q should be either 111..111 or 111..110. Need special + * treatment of this rare case as normal division would + * give overflow. */ + q = ~(mpi_limb_t)0; + + r = n0 + d1; + if( r < d1 ) { /* Carry in the addition? */ + add_ssaaaa( n1, n0, r - d0, np[0], 0, d0 ); + qp[i] = q; + continue; + } + n1 = d0 - (d0 != 0?1:0); + n0 = -d0; + } + else { + udiv_qrnnd (q, r, n1, n0, d1); + umul_ppmm (n1, n0, d0, q); + } + + n2 = np[0]; + q_test: + if( n1 > r || (n1 == r && n0 > n2) ) { + /* The estimated Q was too large. */ + q--; + sub_ddmmss (n1, n0, n1, n0, 0, d0); + r += d1; + if( r >= d1 ) /* If not carry, test Q again. */ + goto q_test; + } + + qp[i] = q; + sub_ddmmss (n1, n0, r, n2, n1, n0); + } + np[1] = n1; + np[0] = n0; + } + break; + + default: + { + mpi_size_t i; + mpi_limb_t dX, d1, n0; + + np += nsize - dsize; + dX = dp[dsize - 1]; + d1 = dp[dsize - 2]; + n0 = np[dsize - 1]; + + if( n0 >= dX ) { + if(n0 > dX || _gcry_mpih_cmp(np, dp, dsize - 1) >= 0 ) { + _gcry_mpih_sub_n(np, np, dp, dsize); + n0 = np[dsize - 1]; + most_significant_q_limb = 1; + } + } + + for( i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) { + mpi_limb_t q; + mpi_limb_t n1, n2; + mpi_limb_t cy_limb; + + if( i >= qextra_limbs ) { + np--; + n2 = np[dsize]; + } + else { + n2 = np[dsize - 1]; + MPN_COPY_DECR (np + 1, np, dsize - 1); + np[0] = 0; + } + + if( n0 == dX ) { + /* This might over-estimate q, but it's probably not worth + * the extra code here to find out. */ + q = ~(mpi_limb_t)0; + } + else { + mpi_limb_t r; + + udiv_qrnnd(q, r, n0, np[dsize - 1], dX); + umul_ppmm(n1, n0, d1, q); + + while( n1 > r || (n1 == r && n0 > np[dsize - 2])) { + q--; + r += dX; + if( r < dX ) /* I.e. "carry in previous addition?" */ + break; + n1 -= n0 < d1; + n0 -= d1; + } + } + + /* Possible optimization: We already have (q * n0) and (1 * n1) + * after the calculation of q. Taking advantage of that, we + * could make this loop make two iterations less. */ + cy_limb = _gcry_mpih_submul_1(np, dp, dsize, q); + + if( n2 != cy_limb ) { + _gcry_mpih_add_n(np, np, dp, dsize); + q--; + } + + qp[i] = q; + n0 = np[dsize - 1]; + } + } + } + + return most_significant_q_limb; +} + + +/**************** + * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. + * Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. + * Return the single-limb remainder. + * There are no constraints on the value of the divisor. + * + * QUOT_PTR and DIVIDEND_PTR might point to the same limb. + */ + +mpi_limb_t +_gcry_mpih_divmod_1( mpi_ptr_t quot_ptr, + mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb) +{ + mpi_size_t i; + mpi_limb_t n1, n0, r; + int dummy; + + if( !dividend_size ) + return 0; + + /* If multiplication is much faster than division, and the + * dividend is large, pre-invert the divisor, and use + * only multiplications in the inner loop. + * + * This test should be read: + * Does it ever help to use udiv_qrnnd_preinv? + * && Does what we save compensate for the inversion overhead? + */ + if( UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { + int normalization_steps; + + count_leading_zeros( normalization_steps, divisor_limb ); + if( normalization_steps ) { + mpi_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + */ + /* Special case for DIVISOR_LIMB == 100...000. */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV( quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + UDIV_QRNND_PREINV( quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else { + mpi_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + */ + /* Special case for DIVISOR_LIMB == 100...000. */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t) 0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if( r >= divisor_limb ) + r = 0; + else + quot_ptr[i--] = 0; + + for( ; i >= 0; i-- ) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV( quot_ptr[i], r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else { + if(UDIV_NEEDS_NORMALIZATION) { + int normalization_steps; + + count_leading_zeros (normalization_steps, divisor_limb); + if( normalization_steps ) { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + * it, or because DIVISOR_LIMB is already normalized. */ + i = dividend_size - 1; + r = dividend_ptr[i]; + + if(r >= divisor_limb) + r = 0; + else + quot_ptr[i--] = 0; + + for(; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd( quot_ptr[i], r, r, n0, divisor_limb ); + } + return r; + } +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpih-lshift.c b/grub-core/lib/libgcrypt-grub/mpi/mpih-lshift.c new file mode 100644 index 0000000..f48c12c --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpih-lshift.c @@ -0,0 +1,68 @@ +/* mpi-lshift.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + +/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left + * and store the USIZE least significant digits of the result at WP. + * Return the bits shifted out from the most significant digit. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be >= UP. + */ + +mpi_limb_t +_gcry_mpih_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned int cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp += 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + i = usize - 1; + low_limb = up[i]; + retval = low_limb >> sh_2; + high_limb = low_limb; + while ( --i >= 0 ) + { + low_limb = up[i]; + wp[i] = (high_limb << sh_1) | (low_limb >> sh_2); + high_limb = low_limb; + } + wp[i] = high_limb << sh_1; + + return retval; +} + + diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpih-mul.c b/grub-core/lib/libgcrypt-grub/mpi/mpih-mul.c new file mode 100644 index 0000000..44b3686 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpih-mul.c @@ -0,0 +1,530 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpih-mul.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 1999, 2000, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "mpi-internal.h" +#include "longlong.h" +#include "g10lib.h" + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if( (size) < KARATSUBA_THRESHOLD ) \ + mul_n_basecase (prodp, up, vp, size); \ + else \ + mul_n (prodp, up, vp, size, tspace); \ + } while (0); + +#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \ + do { \ + if ((size) < KARATSUBA_THRESHOLD) \ + _gcry_mpih_sqr_n_basecase (prodp, up, size); \ + else \ + _gcry_mpih_sqr_n (prodp, up, size, tspace); \ + } while (0); + + + + +/* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP), + * both with SIZE limbs, and store the result at PRODP. 2 * SIZE limbs are + * always stored. Return the most significant limb. + * + * Argument constraints: + * 1. PRODP != UP and PRODP != VP, i.e. the destination + * must be distinct from the multiplier and the multiplicand. + * + * + * Handle simple cases with traditional multiplication. + * + * This is the most critical code of multiplication. All multiplies rely + * on this, both small and huge. Small ones arrive here immediately. Huge + * ones arrive here as this is the base case for Karatsuba's recursive + * algorithm below. + */ + +static mpi_limb_t +mul_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, + mpi_ptr_t vp, mpi_size_t size) +{ + mpi_size_t i; + mpi_limb_t cy; + mpi_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, size ); + else + MPN_ZERO( prodp, size ); + cy = 0; + } + else + cy = _gcry_mpih_mul_1( prodp, up, size, v_limb ); + + prodp[size] = cy; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i = 1; i < size; i++ ) { + v_limb = vp[i]; + if( v_limb <= 1 ) { + cy = 0; + if( v_limb == 1 ) + cy = _gcry_mpih_add_n(prodp, prodp, up, size); + } + else + cy = _gcry_mpih_addmul_1(prodp, up, size, v_limb); + + prodp[size] = cy; + prodp++; + } + + return cy; +} + + +static void +mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, + mpi_size_t size, mpi_ptr_t tspace ) +{ + if( size & 1 ) { + /* The size is odd, and the code below doesn't handle that. + * Multiply the least significant (size - 1) limbs with a recursive + * call, and handle the most significant limb of S1 and S2 + * separately. + * A slightly faster way to do this would be to make the Karatsuba + * code below behave as if the size were even, and let it check for + * odd size in the end. I.e., in essence move this code to the end. + * Doing so would save us a recursive call, and potentially make the + * stack grow a lot less. + */ + mpi_size_t esize = size - 1; /* even size */ + mpi_limb_t cy_limb; + + MPN_MUL_N_RECURSE( prodp, up, vp, esize, tspace ); + cy_limb = _gcry_mpih_addmul_1( prodp + esize, up, esize, vp[esize] ); + prodp[esize + esize] = cy_limb; + cy_limb = _gcry_mpih_addmul_1( prodp + esize, vp, size, up[esize] ); + prodp[esize + size] = cy_limb; + } + else { + /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm. + * + * Split U in two pieces, U1 and U0, such that + * U = U0 + U1*(B**n), + * and V in V1 and V0, such that + * V = V0 + V1*(B**n). + * + * UV is then computed recursively using the identity + * + * 2n n n n + * UV = (B + B )U V + B (U -U )(V -V ) + (B + 1)U V + * 1 1 1 0 0 1 0 0 + * + * Where B = 2**BITS_PER_MP_LIMB. + */ + mpi_size_t hsize = size >> 1; + mpi_limb_t cy; + int negflg; + + /* Product H. ________________ ________________ + * |_____U1 x V1____||____U0 x V0_____| + * Put result in upper part of PROD and pass low part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(prodp + size, up + hsize, vp + hsize, hsize, tspace); + + /* Product M. ________________ + * |_(U1-U0)(V0-V1)_| + */ + if( _gcry_mpih_cmp(up + hsize, up, hsize) >= 0 ) { + _gcry_mpih_sub_n(prodp, up + hsize, up, hsize); + negflg = 0; + } + else { + _gcry_mpih_sub_n(prodp, up, up + hsize, hsize); + negflg = 1; + } + if( _gcry_mpih_cmp(vp + hsize, vp, hsize) >= 0 ) { + _gcry_mpih_sub_n(prodp + hsize, vp + hsize, vp, hsize); + negflg ^= 1; + } + else { + _gcry_mpih_sub_n(prodp + hsize, vp, vp + hsize, hsize); + /* No change of NEGFLG. */ + } + /* Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(tspace, prodp, prodp + hsize, hsize, tspace + size); + + /* Add/copy product H. */ + MPN_COPY (prodp + hsize, prodp + size, hsize); + cy = _gcry_mpih_add_n( prodp + size, prodp + size, + prodp + size + hsize, hsize); + + /* Add product M (if NEGFLG M is a negative number) */ + if(negflg) + cy -= _gcry_mpih_sub_n(prodp + hsize, prodp + hsize, tspace, size); + else + cy += _gcry_mpih_add_n(prodp + hsize, prodp + hsize, tspace, size); + + /* Product L. ________________ ________________ + * |________________||____U0 x V0_____| + * Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(tspace, up, vp, hsize, tspace + size); + + /* Add/copy Product L (twice) */ + + cy += _gcry_mpih_add_n(prodp + hsize, prodp + hsize, tspace, size); + if( cy ) + _gcry_mpih_add_1(prodp + hsize + size, prodp + hsize + size, hsize, cy); + + MPN_COPY(prodp, tspace, hsize); + cy = _gcry_mpih_add_n(prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if( cy ) + _gcry_mpih_add_1(prodp + size, prodp + size, size, 1); + } +} + + +void +_gcry_mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ) +{ + mpi_size_t i; + mpi_limb_t cy_limb; + mpi_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = up[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, size ); + else + MPN_ZERO(prodp, size); + cy_limb = 0; + } + else + cy_limb = _gcry_mpih_mul_1( prodp, up, size, v_limb ); + + prodp[size] = cy_limb; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i=1; i < size; i++) { + v_limb = up[i]; + if( v_limb <= 1 ) { + cy_limb = 0; + if( v_limb == 1 ) + cy_limb = _gcry_mpih_add_n(prodp, prodp, up, size); + } + else + cy_limb = _gcry_mpih_addmul_1(prodp, up, size, v_limb); + + prodp[size] = cy_limb; + prodp++; + } +} + + +void +_gcry_mpih_sqr_n( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace) +{ + if( size & 1 ) { + /* The size is odd, and the code below doesn't handle that. + * Multiply the least significant (size - 1) limbs with a recursive + * call, and handle the most significant limb of S1 and S2 + * separately. + * A slightly faster way to do this would be to make the Karatsuba + * code below behave as if the size were even, and let it check for + * odd size in the end. I.e., in essence move this code to the end. + * Doing so would save us a recursive call, and potentially make the + * stack grow a lot less. + */ + mpi_size_t esize = size - 1; /* even size */ + mpi_limb_t cy_limb; + + MPN_SQR_N_RECURSE( prodp, up, esize, tspace ); + cy_limb = _gcry_mpih_addmul_1( prodp + esize, up, esize, up[esize] ); + prodp[esize + esize] = cy_limb; + cy_limb = _gcry_mpih_addmul_1( prodp + esize, up, size, up[esize] ); + + prodp[esize + size] = cy_limb; + } + else { + mpi_size_t hsize = size >> 1; + mpi_limb_t cy; + + /* Product H. ________________ ________________ + * |_____U1 x U1____||____U0 x U0_____| + * Put result in upper part of PROD and pass low part of TSPACE + * as new TSPACE. + */ + MPN_SQR_N_RECURSE(prodp + size, up + hsize, hsize, tspace); + + /* Product M. ________________ + * |_(U1-U0)(U0-U1)_| + */ + if( _gcry_mpih_cmp( up + hsize, up, hsize) >= 0 ) + _gcry_mpih_sub_n( prodp, up + hsize, up, hsize); + else + _gcry_mpih_sub_n (prodp, up, up + hsize, hsize); + + /* Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. */ + MPN_SQR_N_RECURSE(tspace, prodp, hsize, tspace + size); + + /* Add/copy product H */ + MPN_COPY(prodp + hsize, prodp + size, hsize); + cy = _gcry_mpih_add_n(prodp + size, prodp + size, + prodp + size + hsize, hsize); + + /* Add product M (if NEGFLG M is a negative number). */ + cy -= _gcry_mpih_sub_n (prodp + hsize, prodp + hsize, tspace, size); + + /* Product L. ________________ ________________ + * |________________||____U0 x U0_____| + * Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. */ + MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size); + + /* Add/copy Product L (twice). */ + cy += _gcry_mpih_add_n (prodp + hsize, prodp + hsize, tspace, size); + if( cy ) + _gcry_mpih_add_1(prodp + hsize + size, prodp + hsize + size, + hsize, cy); + + MPN_COPY(prodp, tspace, hsize); + cy = _gcry_mpih_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if( cy ) + _gcry_mpih_add_1 (prodp + size, prodp + size, size, 1); + } +} + + +/* This should be made into an inline function in gmp.h. */ +void +_gcry_mpih_mul_n( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) +{ + int secure; + + if( up == vp ) { + if( size < KARATSUBA_THRESHOLD ) + _gcry_mpih_sqr_n_basecase( prodp, up, size ); + else { + mpi_ptr_t tspace; + secure = gcry_is_secure( up ); + tspace = mpi_alloc_limb_space( 2 * size, secure ); + _gcry_mpih_sqr_n( prodp, up, size, tspace ); + _gcry_mpi_free_limb_space (tspace, 2 * size ); + } + } + else { + if( size < KARATSUBA_THRESHOLD ) + mul_n_basecase( prodp, up, vp, size ); + else { + mpi_ptr_t tspace; + secure = gcry_is_secure( up ) || gcry_is_secure( vp ); + tspace = mpi_alloc_limb_space( 2 * size, secure ); + mul_n (prodp, up, vp, size, tspace); + _gcry_mpi_free_limb_space (tspace, 2 * size ); + } + } +} + + + +void +_gcry_mpih_mul_karatsuba_case( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize, + struct karatsuba_ctx *ctx ) +{ + mpi_limb_t cy; + + if( !ctx->tspace || ctx->tspace_size < vsize ) { + if( ctx->tspace ) + _gcry_mpi_free_limb_space( ctx->tspace, ctx->tspace_nlimbs ); + ctx->tspace_nlimbs = 2 * vsize; + ctx->tspace = mpi_alloc_limb_space( 2 * vsize, + (gcry_is_secure( up ) + || gcry_is_secure( vp )) ); + ctx->tspace_size = vsize; + } + + MPN_MUL_N_RECURSE( prodp, up, vp, vsize, ctx->tspace ); + + prodp += vsize; + up += vsize; + usize -= vsize; + if( usize >= vsize ) { + if( !ctx->tp || ctx->tp_size < vsize ) { + if( ctx->tp ) + _gcry_mpi_free_limb_space( ctx->tp, ctx->tp_nlimbs ); + ctx->tp_nlimbs = 2 * vsize; + ctx->tp = mpi_alloc_limb_space( 2 * vsize, gcry_is_secure( up ) + || gcry_is_secure( vp ) ); + ctx->tp_size = vsize; + } + + do { + MPN_MUL_N_RECURSE( ctx->tp, up, vp, vsize, ctx->tspace ); + cy = _gcry_mpih_add_n( prodp, prodp, ctx->tp, vsize ); + _gcry_mpih_add_1( prodp + vsize, ctx->tp + vsize, vsize, cy ); + prodp += vsize; + up += vsize; + usize -= vsize; + } while( usize >= vsize ); + } + + if( usize ) { + if( usize < KARATSUBA_THRESHOLD ) { + _gcry_mpih_mul( ctx->tspace, vp, vsize, up, usize ); + } + else { + if( !ctx->next ) { + ctx->next = gcry_xcalloc( 1, sizeof *ctx ); + } + _gcry_mpih_mul_karatsuba_case( ctx->tspace, + vp, vsize, + up, usize, + ctx->next ); + } + + cy = _gcry_mpih_add_n( prodp, prodp, ctx->tspace, vsize); + _gcry_mpih_add_1( prodp + vsize, ctx->tspace + vsize, usize, cy ); + } +} + + +void +_gcry_mpih_release_karatsuba_ctx( struct karatsuba_ctx *ctx ) +{ + struct karatsuba_ctx *ctx2; + + if( ctx->tp ) + _gcry_mpi_free_limb_space( ctx->tp, ctx->tp_nlimbs ); + if( ctx->tspace ) + _gcry_mpi_free_limb_space( ctx->tspace, ctx->tspace_nlimbs ); + for( ctx=ctx->next; ctx; ctx = ctx2 ) { + ctx2 = ctx->next; + if( ctx->tp ) + _gcry_mpi_free_limb_space( ctx->tp, ctx->tp_nlimbs ); + if( ctx->tspace ) + _gcry_mpi_free_limb_space( ctx->tspace, ctx->tspace_nlimbs ); + gcry_free( ctx ); + } +} + +/* Multiply the natural numbers u (pointed to by UP, with USIZE limbs) + * and v (pointed to by VP, with VSIZE limbs), and store the result at + * PRODP. USIZE + VSIZE limbs are always stored, but if the input + * operands are normalized. Return the most significant limb of the + * result. + * + * NOTE: The space pointed to by PRODP is overwritten before finished + * with U and V, so overlap is an error. + * + * Argument constraints: + * 1. USIZE >= VSIZE. + * 2. PRODP != UP and PRODP != VP, i.e. the destination + * must be distinct from the multiplier and the multiplicand. + */ + +mpi_limb_t +_gcry_mpih_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize) +{ + mpi_ptr_t prod_endp = prodp + usize + vsize - 1; + mpi_limb_t cy; + struct karatsuba_ctx ctx; + + if( vsize < KARATSUBA_THRESHOLD ) { + mpi_size_t i; + mpi_limb_t v_limb; + + if( !vsize ) + return 0; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, usize ); + else + MPN_ZERO( prodp, usize ); + cy = 0; + } + else + cy = _gcry_mpih_mul_1( prodp, up, usize, v_limb ); + + prodp[usize] = cy; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i = 1; i < vsize; i++ ) { + v_limb = vp[i]; + if( v_limb <= 1 ) { + cy = 0; + if( v_limb == 1 ) + cy = _gcry_mpih_add_n(prodp, prodp, up, usize); + } + else + cy = _gcry_mpih_addmul_1(prodp, up, usize, v_limb); + + prodp[usize] = cy; + prodp++; + } + + return cy; + } + + memset( &ctx, 0, sizeof ctx ); + _gcry_mpih_mul_karatsuba_case( prodp, up, usize, vp, vsize, &ctx ); + _gcry_mpih_release_karatsuba_ctx( &ctx ); + return *prod_endp; +} diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpih-mul1.c b/grub-core/lib/libgcrypt-grub/mpi/mpih-mul1.c new file mode 100644 index 0000000..0e8197d --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpih-mul1.c @@ -0,0 +1,62 @@ +/* mpihelp-mul_1.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +_gcry_mpih_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + + /* The loop counter and index J goes from -S1_SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + res_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + res_ptr[j] = prod_low; + } + while( ++j ); + + return cy_limb; +} + diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpih-mul2.c b/grub-core/lib/libgcrypt-grub/mpi/mpih-mul2.c new file mode 100644 index 0000000..3b75496 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpih-mul2.c @@ -0,0 +1,68 @@ +/* mpih-mul2.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +mpi_limb_t +_gcry_mpih_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x + prod_low; + cy_limb += prod_low < x?1:0; + res_ptr[j] = prod_low; + } + while ( ++j ); + + return cy_limb; +} + + diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpih-mul3.c b/grub-core/lib/libgcrypt-grub/mpi/mpih-mul3.c new file mode 100644 index 0000000..5e84f94 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpih-mul3.c @@ -0,0 +1,68 @@ +/* mpih-mul3.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +mpi_limb_t +_gcry_mpih_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x - prod_low; + cy_limb += prod_low > x?1:0; + res_ptr[j] = prod_low; + } + while( ++j ); + + return cy_limb; +} + + diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpih-rshift.c b/grub-core/lib/libgcrypt-grub/mpi/mpih-rshift.c new file mode 100644 index 0000000..e40794f --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpih-rshift.c @@ -0,0 +1,67 @@ +/* mpih-rshift.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 1999, + * 2000, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + + +/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right + * and store the USIZE least significant limbs of the result at WP. + * The bits shifted out to the right are returned. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be <= UP. + */ + +mpi_limb_t +_gcry_mpih_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp -= 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + high_limb = up[0]; + retval = high_limb << sh_2; + low_limb = high_limb; + for (i=1; i < usize; i++) + { + high_limb = up[i]; + wp[i] = (low_limb >> sh_1) | (high_limb << sh_2); + low_limb = high_limb; + } + wp[i] = low_limb >> sh_1; + + return retval; +} + diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpih-sub1.c b/grub-core/lib/libgcrypt-grub/mpi/mpih-sub1.c new file mode 100644 index 0000000..e88821b --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpih-sub1.c @@ -0,0 +1,66 @@ +/* mpihelp-add_2.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +_gcry_mpih_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size) +{ + mpi_limb_t x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to subtrahend */ + cy = y < cy; /* get out carry from that addition */ + y = x - y; /* main subtract */ + cy += y > x; /* get out carry from the subtract, combine */ + res_ptr[j] = y; + } + while( ++j ); + + return cy; +} + + diff --git a/grub-core/lib/libgcrypt-grub/mpi/mpiutil.c b/grub-core/lib/libgcrypt-grub/mpi/mpiutil.c new file mode 100644 index 0000000..3fec8db --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/mpi/mpiutil.c @@ -0,0 +1,435 @@ +/* This file was automatically imported with + import_gcry.py. Please don't modify it */ +/* mpiutil.ac - Utility functions for MPI + * Copyright (C) 1998, 2000, 2001, 2002, 2003, + * 2007 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "g10lib.h" +#include "mpi-internal.h" + + + + +/**************** + * Note: It was a bad idea to use the number of limbs to allocate + * because on a alpha the limbs are large but we normally need + * integers of n bits - So we should change this to bits (or bytes). + * + * But mpi_alloc is used in a lot of places :-(. New code + * should use mpi_new. + */ +gcry_mpi_t +_gcry_mpi_alloc( unsigned nlimbs ) +{ + gcry_mpi_t a; + + a = gcry_xmalloc( sizeof *a ); + a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL; + a->alloced = nlimbs; + a->nlimbs = 0; + a->sign = 0; + a->flags = 0; + return a; +} + +void +_gcry_mpi_m_check( gcry_mpi_t a ) +{ + _gcry_check_heap(a); + _gcry_check_heap(a->d); +} + +gcry_mpi_t +_gcry_mpi_alloc_secure( unsigned nlimbs ) +{ + gcry_mpi_t a; + + a = gcry_xmalloc( sizeof *a ); + a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL; + a->alloced = nlimbs; + a->flags = 1; + a->nlimbs = 0; + a->sign = 0; + return a; +} + + + +mpi_ptr_t +_gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure ) +{ + mpi_ptr_t p; + size_t len; + + len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t); + p = secure ? gcry_xmalloc_secure (len) : gcry_xmalloc (len); + if (! nlimbs) + *p = 0; + + return p; +} + +void +_gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs) +{ + if (a) + { + size_t len = nlimbs * sizeof(mpi_limb_t); + + /* If we have information on the number of allocated limbs, we + better wipe that space out. This is a failsafe feature if + secure memory has been disabled or was not properly + implemented in user provided allocation functions. */ + if (len) + wipememory (a, len); + gcry_free(a); + } +} + + +void +_gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned int nlimbs ) +{ + _gcry_mpi_free_limb_space (a->d, a->alloced); + a->d = ap; + a->alloced = nlimbs; +} + + + +/**************** + * Resize the array of A to NLIMBS. The additional space is cleared + * (set to 0). + */ +void +_gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs) +{ + size_t i; + + if (nlimbs <= a->alloced) + { + /* We only need to clear the new space (this is a nop if the + limb space is already of the correct size. */ + for (i=a->nlimbs; i < a->alloced; i++) + a->d[i] = 0; + return; + } + + /* Actually resize the limb space. */ + if (a->d) + { + a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t)); + for (i=a->alloced; i < nlimbs; i++) + a->d[i] = 0; + } + else + { + if (a->flags & 1) + /* Secure memory is wanted. */ + a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t)); + else + /* Standard memory. */ + a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t)); + } + a->alloced = nlimbs; +} + +void +_gcry_mpi_clear( gcry_mpi_t a ) +{ + a->nlimbs = 0; + a->flags = 0; +} + + +void +_gcry_mpi_free( gcry_mpi_t a ) +{ + if (!a ) + return; + if ((a->flags & 4)) + gcry_free( a->d ); + else + { + _gcry_mpi_free_limb_space(a->d, a->alloced); + } + if ((a->flags & ~7)) + log_bug("invalid flag value in mpi\n"); + gcry_free(a); +} + +static void +mpi_set_secure( gcry_mpi_t a ) +{ + mpi_ptr_t ap, bp; + + if ( (a->flags & 1) ) + return; + a->flags |= 1; + ap = a->d; + if (!a->nlimbs) + { + gcry_assert (!ap); + return; + } + bp = mpi_alloc_limb_space (a->nlimbs, 1); + MPN_COPY( bp, ap, a->nlimbs ); + a->d = bp; + _gcry_mpi_free_limb_space (ap, a->alloced); +} + + +gcry_mpi_t +gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits ) +{ + if (!a) + a = mpi_alloc(0); + + if( a->flags & 4 ) + gcry_free( a->d ); + else + _gcry_mpi_free_limb_space (a->d, a->alloced); + + a->d = p; + a->alloced = 0; + a->nlimbs = 0; + a->sign = nbits; + a->flags = 4; + return a; +} + + +void * +gcry_mpi_get_opaque( gcry_mpi_t a, unsigned int *nbits ) +{ + if( !(a->flags & 4) ) + log_bug("mpi_get_opaque on normal mpi\n"); + if( nbits ) + *nbits = a->sign; + return a->d; +} + + +/**************** + * Note: This copy function should not interpret the MPI + * but copy it transparently. + */ +gcry_mpi_t +gcry_mpi_copy( gcry_mpi_t a ) +{ + int i; + gcry_mpi_t b; + + if( a && (a->flags & 4) ) { + void *p = gcry_is_secure(a->d)? gcry_xmalloc_secure( (a->sign+7)/8 ) + : gcry_xmalloc( (a->sign+7)/8 ); + memcpy( p, a->d, (a->sign+7)/8 ); + b = gcry_mpi_set_opaque( NULL, p, a->sign ); + } + else if( a ) { + b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) + : mpi_alloc( a->nlimbs ); + b->nlimbs = a->nlimbs; + b->sign = a->sign; + b->flags = a->flags; + for(i=0; i < b->nlimbs; i++ ) + b->d[i] = a->d[i]; + } + else + b = NULL; + return b; +} + + +/**************** + * This function allocates an MPI which is optimized to hold + * a value as large as the one given in the argument and allocates it + * with the same flags as A. + */ +gcry_mpi_t +_gcry_mpi_alloc_like( gcry_mpi_t a ) +{ + gcry_mpi_t b; + + if( a && (a->flags & 4) ) { + int n = (a->sign+7)/8; + void *p = gcry_is_secure(a->d)? gcry_malloc_secure( n ) + : gcry_malloc( n ); + memcpy( p, a->d, n ); + b = gcry_mpi_set_opaque( NULL, p, a->sign ); + } + else if( a ) { + b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) + : mpi_alloc( a->nlimbs ); + b->nlimbs = 0; + b->sign = 0; + b->flags = a->flags; + } + else + b = NULL; + return b; +} + + +gcry_mpi_t +gcry_mpi_set( gcry_mpi_t w, gcry_mpi_t u) +{ + mpi_ptr_t wp, up; + mpi_size_t usize = u->nlimbs; + int usign = u->sign; + + if (!w) + w = _gcry_mpi_alloc( mpi_get_nlimbs(u) ); + RESIZE_IF_NEEDED(w, usize); + wp = w->d; + up = u->d; + MPN_COPY( wp, up, usize ); + w->nlimbs = usize; + w->flags = u->flags; + w->sign = usign; + return w; +} + + +gcry_mpi_t +gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u) +{ + if (!w) + w = _gcry_mpi_alloc (1); + /* FIXME: If U is 0 we have no need to resize and thus possible + allocating the the limbs. */ + RESIZE_IF_NEEDED(w, 1); + w->d[0] = u; + w->nlimbs = u? 1:0; + w->sign = 0; + w->flags = 0; + return w; +} + +gcry_err_code_t +_gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + unsigned long x = 0; + + if (w->nlimbs > 1) + err = GPG_ERR_TOO_LARGE; + else if (w->nlimbs == 1) + x = w->d[0]; + else + x = 0; + + if (! err) + *u = x; + + return err; +} + +gcry_error_t +gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + err = _gcry_mpi_get_ui (w, u); + + return gcry_error (err); +} + +gcry_mpi_t +_gcry_mpi_alloc_set_ui( unsigned long u) +{ + gcry_mpi_t w = mpi_alloc(1); + w->d[0] = u; + w->nlimbs = u? 1:0; + w->sign = 0; + return w; +} + +void +gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b) +{ + struct gcry_mpi tmp; + + tmp = *a; *a = *b; *b = tmp; +} + + +gcry_mpi_t +gcry_mpi_new( unsigned int nbits ) +{ + return _gcry_mpi_alloc ( (nbits+BITS_PER_MPI_LIMB-1) + / BITS_PER_MPI_LIMB ); +} + + +gcry_mpi_t +gcry_mpi_snew( unsigned int nbits ) +{ + return _gcry_mpi_alloc_secure ( (nbits+BITS_PER_MPI_LIMB-1) + / BITS_PER_MPI_LIMB ); +} + +void +gcry_mpi_release( gcry_mpi_t a ) +{ + _gcry_mpi_free( a ); +} + + + +void +gcry_mpi_set_flag( gcry_mpi_t a, enum gcry_mpi_flag flag ) +{ + switch( flag ) { + case GCRYMPI_FLAG_SECURE: mpi_set_secure(a); break; + case GCRYMPI_FLAG_OPAQUE: + default: log_bug("invalid flag value\n"); + } +} + +void +gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag ) +{ + (void)a; /* Not yet used. */ + + switch (flag) + { + case GCRYMPI_FLAG_SECURE: + case GCRYMPI_FLAG_OPAQUE: + default: log_bug("invalid flag value\n"); + } +} + +int +gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag flag ) +{ + switch (flag) + { + case GCRYMPI_FLAG_SECURE: return (a->flags & 1); + case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4); + default: log_bug("invalid flag value\n"); + } + /*NOTREACHED*/ + return 0; +} diff --git a/grub-core/lib/libgcrypt-grub/src/ath.h b/grub-core/lib/libgcrypt-grub/src/ath.h new file mode 100644 index 0000000..8769551 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/src/ath.h @@ -0,0 +1,147 @@ +/* ath.h - Thread-safeness library. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with Libgcrypt; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef ATH_H +#define ATH_H + +#include <config.h> + +#ifdef _WIN32 +# include <windows.h> +#else /* !_WIN32 */ +# ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +# else +# include <sys/time.h> +# endif +# include <sys/types.h> +# ifdef HAVE_SYS_MSG_H +# include <sys/msg.h> /* (e.g. for zOS) */ +# endif +# include <sys/socket.h> +#endif /* !_WIN32 */ +#include <gpg-error.h> + + + +/* Define _ATH_EXT_SYM_PREFIX if you want to give all external symbols + a prefix. */ +#define _ATH_EXT_SYM_PREFIX _gcry_ + +#ifdef _ATH_EXT_SYM_PREFIX +#define _ATH_PREFIX1(x,y) x ## y +#define _ATH_PREFIX2(x,y) _ATH_PREFIX1(x,y) +#define _ATH_PREFIX(x) _ATH_PREFIX2(_ATH_EXT_SYM_PREFIX,x) +#define ath_install _ATH_PREFIX(ath_install) +#define ath_init _ATH_PREFIX(ath_init) +#define ath_mutex_init _ATH_PREFIX(ath_mutex_init) +#define ath_mutex_destroy _ATH_PREFIX(ath_mutex_destroy) +#define ath_mutex_lock _ATH_PREFIX(ath_mutex_lock) +#define ath_mutex_unlock _ATH_PREFIX(ath_mutex_unlock) +#define ath_read _ATH_PREFIX(ath_read) +#define ath_write _ATH_PREFIX(ath_write) +#define ath_select _ATH_PREFIX(ath_select) +#define ath_waitpid _ATH_PREFIX(ath_waitpid) +#define ath_connect _ATH_PREFIX(ath_connect) +#define ath_accept _ATH_PREFIX(ath_accept) +#define ath_sendmsg _ATH_PREFIX(ath_sendmsg) +#define ath_recvmsg _ATH_PREFIX(ath_recvmsg) +#endif + + +enum ath_thread_option + { + ATH_THREAD_OPTION_DEFAULT = 0, + ATH_THREAD_OPTION_USER = 1, + ATH_THREAD_OPTION_PTH = 2, + ATH_THREAD_OPTION_PTHREAD = 3 + }; + +struct ath_ops +{ + /* The OPTION field encodes the thread model and the version number + of this structure. + Bits 7 - 0 are used for the thread model + Bits 15 - 8 are used for the version number. + */ + unsigned int option; + + int (*init) (void); + int (*mutex_init) (void **priv); + int (*mutex_destroy) (void *priv); + int (*mutex_lock) (void *priv); + int (*mutex_unlock) (void *priv); + ssize_t (*read) (int fd, void *buf, size_t nbytes); + ssize_t (*write) (int fd, const void *buf, size_t nbytes); +#ifdef _WIN32 + ssize_t (*select) (int nfd, void *rset, void *wset, void *eset, + struct timeval *timeout); + ssize_t (*waitpid) (pid_t pid, int *status, int options); + int (*accept) (int s, void *addr, int *length_ptr); + int (*connect) (int s, void *addr, int length); + int (*sendmsg) (int s, const void *msg, int flags); + int (*recvmsg) (int s, void *msg, int flags); +#else + ssize_t (*select) (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout); + ssize_t (*waitpid) (pid_t pid, int *status, int options); + int (*accept) (int s, struct sockaddr *addr, socklen_t *length_ptr); + int (*connect) (int s, struct sockaddr *addr, socklen_t length); + int (*sendmsg) (int s, const struct msghdr *msg, int flags); + int (*recvmsg) (int s, struct msghdr *msg, int flags); +#endif +}; + +gpg_err_code_t ath_install (struct ath_ops *ath_ops, int check_only); +int ath_init (void); + + +/* Functions for mutual exclusion. */ +typedef void *ath_mutex_t; +#define ATH_MUTEX_INITIALIZER 0 + +int ath_mutex_init (ath_mutex_t *mutex); +int ath_mutex_destroy (ath_mutex_t *mutex); +int ath_mutex_lock (ath_mutex_t *mutex); +int ath_mutex_unlock (ath_mutex_t *mutex); + +/* Replacement for the POSIX functions, which can be used to allow + other (user-level) threads to run. */ +ssize_t ath_read (int fd, void *buf, size_t nbytes); +ssize_t ath_write (int fd, const void *buf, size_t nbytes); +#ifdef _WIN32 +ssize_t ath_select (int nfd, void *rset, void *wset, void *eset, + struct timeval *timeout); +ssize_t ath_waitpid (pid_t pid, int *status, int options); +int ath_accept (int s, void *addr, int *length_ptr); +int ath_connect (int s, void *addr, int length); +int ath_sendmsg (int s, const void *msg, int flags); +int ath_recvmsg (int s, void *msg, int flags); +#else +ssize_t ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout); +ssize_t ath_waitpid (pid_t pid, int *status, int options); +int ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr); +int ath_connect (int s, struct sockaddr *addr, socklen_t length); +int ath_sendmsg (int s, const struct msghdr *msg, int flags); +int ath_recvmsg (int s, struct msghdr *msg, int flags); +#endif + +#endif /* ATH_H */ diff --git a/grub-core/lib/libgcrypt-grub/src/cipher-proto.h b/grub-core/lib/libgcrypt-grub/src/cipher-proto.h new file mode 100644 index 0000000..347681f --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/src/cipher-proto.h @@ -0,0 +1,124 @@ +/* cipher-proto.h - Internal declarations + * Copyright (C) 2008, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* This file has been factored out from cipher.h so that it can be + used standalone in visibility.c . */ + +#ifndef G10_CIPHER_PROTO_H +#define G10_CIPHER_PROTO_H + +/* Definition of a function used to report selftest failures. + DOMAIN is a string describing the function block: + "cipher", "digest", "pubkey or "random", + ALGO is the algorithm under test, + WHAT is a string describing what has been tested, + DESC is a string describing the error. */ +typedef void (*selftest_report_func_t)(const char *domain, + int algo, + const char *what, + const char *errdesc); + +/* Definition of the selftest functions. */ +typedef gpg_err_code_t (*selftest_func_t) + (int algo, int extended, selftest_report_func_t report); + + +/* An extended type of the generate function. */ +typedef gcry_err_code_t (*pk_ext_generate_t) + (int algo, + unsigned int nbits, + unsigned long evalue, + gcry_sexp_t genparms, + gcry_mpi_t *skey, + gcry_mpi_t **retfactors, + gcry_sexp_t *extrainfo); + +/* The type used to compute the keygrip. */ +typedef gpg_err_code_t (*pk_comp_keygrip_t) + (gcry_md_hd_t md, gcry_sexp_t keyparm); + +/* The type used to query ECC curve parameters. */ +typedef gcry_err_code_t (*pk_get_param_t) + (const char *name, gcry_mpi_t *pkey); + +/* The type used to query an ECC curve name. */ +typedef const char *(*pk_get_curve_t)(gcry_mpi_t *pkey, int iterator, + unsigned int *r_nbits); + +/* The type used to query ECC curve parameters by name. */ +typedef gcry_sexp_t (*pk_get_curve_param_t)(const char *name); + +/* The type used to convey additional information to a cipher. */ +typedef gpg_err_code_t (*cipher_set_extra_info_t) + (void *c, int what, const void *buffer, size_t buflen); + + +/* Extra module specification structures. These are used for internal + modules which provide more functions than available through the + public algorithm register APIs. */ +typedef struct cipher_extra_spec +{ + selftest_func_t selftest; + cipher_set_extra_info_t set_extra_info; +} cipher_extra_spec_t; + +typedef struct md_extra_spec +{ + selftest_func_t selftest; +} md_extra_spec_t; + +typedef struct pk_extra_spec +{ + selftest_func_t selftest; + pk_ext_generate_t ext_generate; + pk_comp_keygrip_t comp_keygrip; + pk_get_param_t get_param; + pk_get_curve_t get_curve; + pk_get_curve_param_t get_curve_param; +} pk_extra_spec_t; + + + +/* The private register functions. */ +gcry_error_t _gcry_cipher_register (gcry_cipher_spec_t *cipher, + cipher_extra_spec_t *extraspec, + int *algorithm_id, + gcry_module_t *module); +gcry_error_t _gcry_md_register (gcry_md_spec_t *cipher, + md_extra_spec_t *extraspec, + unsigned int *algorithm_id, + gcry_module_t *module); +gcry_error_t _gcry_pk_register (gcry_pk_spec_t *cipher, + pk_extra_spec_t *extraspec, + unsigned int *algorithm_id, + gcry_module_t *module); + +/* The selftest functions. */ +gcry_error_t _gcry_cipher_selftest (int algo, int extended, + selftest_report_func_t report); +gcry_error_t _gcry_md_selftest (int algo, int extended, + selftest_report_func_t report); +gcry_error_t _gcry_pk_selftest (int algo, int extended, + selftest_report_func_t report); +gcry_error_t _gcry_hmac_selftest (int algo, int extended, + selftest_report_func_t report); + +gcry_error_t _gcry_random_selftest (selftest_report_func_t report); + +#endif /*G10_CIPHER_PROTO_H*/ diff --git a/grub-core/lib/libgcrypt-grub/src/cipher.h b/grub-core/lib/libgcrypt-grub/src/cipher.h new file mode 100644 index 0000000..48eeeda --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/src/cipher.h @@ -0,0 +1,182 @@ +/* cipher.h + * Copyright (C) 1998, 2002, 2003, 2009 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef G10_CIPHER_H +#define G10_CIPHER_H + +#include <gcrypt.h> + +#define DBG_CIPHER _gcry_get_debug_flag( 1 ) + +#include "../random/random.h" + +#define PUBKEY_FLAG_NO_BLINDING (1 << 0) + +enum pk_operation + { + PUBKEY_OP_ENCRYPT, + PUBKEY_OP_DECRYPT, + PUBKEY_OP_SIGN, + PUBKEY_OP_VERIFY + }; + +enum pk_encoding + { + PUBKEY_ENC_RAW, + PUBKEY_ENC_PKCS1, + PUBKEY_ENC_OAEP, + PUBKEY_ENC_PSS, + PUBKEY_ENC_UNKNOWN + }; + +struct pk_encoding_ctx +{ + enum pk_operation op; + unsigned int nbits; + + enum pk_encoding encoding; + int flags; + + int hash_algo; + + /* for OAEP */ + unsigned char *label; + size_t labellen; + + /* for PSS */ + size_t saltlen; + + int (* verify_cmp) (void *opaque, gcry_mpi_t tmp); + void *verify_arg; +}; + +#define CIPHER_INFO_NO_WEAK_KEY 1 + +#include "cipher-proto.h" + + +/*-- rmd160.c --*/ +void _gcry_rmd160_hash_buffer (void *outbuf, + const void *buffer, size_t length); +/*-- sha1.c --*/ +void _gcry_sha1_hash_buffer (void *outbuf, + const void *buffer, size_t length); + +/*-- rijndael.c --*/ +void _gcry_aes_cfb_enc (void *context, unsigned char *iv, + void *outbuf, const void *inbuf, + unsigned int nblocks); +void _gcry_aes_cfb_dec (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); +void _gcry_aes_cbc_enc (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks, int cbc_mac); +void _gcry_aes_cbc_dec (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); +void _gcry_aes_ctr_enc (void *context, unsigned char *ctr, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); + + +/*-- dsa.c --*/ +void _gcry_register_pk_dsa_progress (gcry_handler_progress_t cbc, void *cb_data); + +/*-- elgamal.c --*/ +void _gcry_register_pk_elg_progress (gcry_handler_progress_t cb, + void *cb_data); + + +/*-- ecc.c --*/ +void _gcry_register_pk_ecc_progress (gcry_handler_progress_t cbc, + void *cb_data); + + +/*-- primegen.c --*/ +void _gcry_register_primegen_progress (gcry_handler_progress_t cb, + void *cb_data); + +/*-- pubkey.c --*/ +const char * _gcry_pk_aliased_algo_name (int algorithm); + +/* Declarations for the cipher specifications. */ +extern gcry_cipher_spec_t _gcry_cipher_spec_blowfish; +extern gcry_cipher_spec_t _gcry_cipher_spec_des; +extern gcry_cipher_spec_t _gcry_cipher_spec_tripledes; +extern gcry_cipher_spec_t _gcry_cipher_spec_arcfour; +extern gcry_cipher_spec_t _gcry_cipher_spec_cast5; +extern gcry_cipher_spec_t _gcry_cipher_spec_aes; +extern gcry_cipher_spec_t _gcry_cipher_spec_aes192; +extern gcry_cipher_spec_t _gcry_cipher_spec_aes256; +extern gcry_cipher_spec_t _gcry_cipher_spec_twofish; +extern gcry_cipher_spec_t _gcry_cipher_spec_twofish128; +extern gcry_cipher_spec_t _gcry_cipher_spec_serpent128; +extern gcry_cipher_spec_t _gcry_cipher_spec_serpent192; +extern gcry_cipher_spec_t _gcry_cipher_spec_serpent256; +extern gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_40; +extern gcry_cipher_spec_t _gcry_cipher_spec_seed; +extern gcry_cipher_spec_t _gcry_cipher_spec_camellia128; +extern gcry_cipher_spec_t _gcry_cipher_spec_camellia192; +extern gcry_cipher_spec_t _gcry_cipher_spec_camellia256; +extern gcry_cipher_spec_t _gcry_cipher_spec_idea; + +extern cipher_extra_spec_t _gcry_cipher_extraspec_tripledes; +extern cipher_extra_spec_t _gcry_cipher_extraspec_aes; +extern cipher_extra_spec_t _gcry_cipher_extraspec_aes192; +extern cipher_extra_spec_t _gcry_cipher_extraspec_aes256; + + +/* Declarations for the digest specifications. */ +extern gcry_md_spec_t _gcry_digest_spec_crc32; +extern gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510; +extern gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440; +extern gcry_md_spec_t _gcry_digest_spec_md4; +extern gcry_md_spec_t _gcry_digest_spec_md5; +extern gcry_md_spec_t _gcry_digest_spec_rmd160; +extern gcry_md_spec_t _gcry_digest_spec_sha1; +extern gcry_md_spec_t _gcry_digest_spec_sha224; +extern gcry_md_spec_t _gcry_digest_spec_sha256; +extern gcry_md_spec_t _gcry_digest_spec_sha512; +extern gcry_md_spec_t _gcry_digest_spec_sha384; +extern gcry_md_spec_t _gcry_digest_spec_tiger; +extern gcry_md_spec_t _gcry_digest_spec_tiger1; +extern gcry_md_spec_t _gcry_digest_spec_tiger2; +extern gcry_md_spec_t _gcry_digest_spec_whirlpool; + +extern md_extra_spec_t _gcry_digest_extraspec_sha1; +extern md_extra_spec_t _gcry_digest_extraspec_sha224; +extern md_extra_spec_t _gcry_digest_extraspec_sha256; +extern md_extra_spec_t _gcry_digest_extraspec_sha384; +extern md_extra_spec_t _gcry_digest_extraspec_sha512; + +/* Declarations for the pubkey cipher specifications. */ +extern gcry_pk_spec_t _gcry_pubkey_spec_rsa; +extern gcry_pk_spec_t _gcry_pubkey_spec_elg; +extern gcry_pk_spec_t _gcry_pubkey_spec_dsa; +extern gcry_pk_spec_t _gcry_pubkey_spec_ecdsa; +extern gcry_pk_spec_t _gcry_pubkey_spec_ecdh; + +extern pk_extra_spec_t _gcry_pubkey_extraspec_rsa; +extern pk_extra_spec_t _gcry_pubkey_extraspec_dsa; +extern pk_extra_spec_t _gcry_pubkey_extraspec_elg; +extern pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa; + + +#endif /*G10_CIPHER_H*/ diff --git a/grub-core/lib/libgcrypt-grub/src/g10lib.h b/grub-core/lib/libgcrypt-grub/src/g10lib.h new file mode 100644 index 0000000..85a51be --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/src/g10lib.h @@ -0,0 +1,302 @@ +/* g10lib.h - Internal definitions for libgcrypt + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 + * 2007, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* This header is to be used inside of libgcrypt in place of gcrypt.h. + This way we can better distinguish between internal and external + usage of gcrypt.h. */ + +#ifndef G10LIB_H +#define G10LIB_H 1 + +#ifdef _GCRYPT_H +#error gcrypt.h already included +#endif + +#ifndef _GCRYPT_IN_LIBGCRYPT +#error something is wrong with config.h +#endif + +#include <stdio.h> +#include <stdarg.h> + +#include "visibility.h" +#include "types.h" + + + + +/* Attribute handling macros. */ + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) +#define JNLIB_GCC_M_FUNCTION 1 +#define JNLIB_GCC_A_NR __attribute__ ((noreturn)) +#define JNLIB_GCC_A_PRINTF( f, a ) __attribute__ ((format (__printf__,f,a))) +#define JNLIB_GCC_A_NR_PRINTF( f, a ) \ + __attribute__ ((noreturn, format (__printf__,f,a))) +#define GCC_ATTR_NORETURN __attribute__ ((__noreturn__)) +#else +#define JNLIB_GCC_A_NR +#define JNLIB_GCC_A_PRINTF( f, a ) +#define JNLIB_GCC_A_NR_PRINTF( f, a ) +#define GCC_ATTR_NORETURN +#endif + +#if __GNUC__ >= 3 +/* According to glibc this attribute is available since 2.8 however we + better play safe and use it only with gcc 3 or newer. */ +#define GCC_ATTR_FORMAT_ARG(a) __attribute__ ((format_arg (a))) +#else +#define GCC_ATTR_FORMAT_ARG(a) +#endif + + +/* Gettext macros. */ + +/* Some handy macros */ +#ifndef STR +#define STR(v) #v +#endif +#define STR2(v) STR(v) +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) + + + +/*-- src/global.c -*/ +int _gcry_global_is_operational (void); +gcry_error_t _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr); +void _gcry_check_heap (const void *a); +int _gcry_get_debug_flag (unsigned int mask); + + +/*-- src/misc.c --*/ + +#if defined(JNLIB_GCC_M_FUNCTION) || __STDC_VERSION__ >= 199901L +void _gcry_bug (const char *file, int line, + const char *func) GCC_ATTR_NORETURN; +void _gcry_assert_failed (const char *expr, const char *file, int line, + const char *func) GCC_ATTR_NORETURN; +#else +void _gcry_bug (const char *file, int line); +void _gcry_assert_failed (const char *expr, const char *file, int line); +#endif + +const char *_gcry_gettext (const char *key) GCC_ATTR_FORMAT_ARG(1); +void _gcry_fatal_error(int rc, const char *text ) JNLIB_GCC_A_NR; +void _gcry_log( int level, const char *fmt, ... ) JNLIB_GCC_A_PRINTF(2,3); +void _gcry_log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); +void _gcry_log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); +void _gcry_log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void _gcry_log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +int _gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... ) + JNLIB_GCC_A_PRINTF(2,3); +void _gcry_log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void _gcry_log_printf ( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void _gcry_log_printhex (const char *text, const void *buffer, size_t length); + +void _gcry_set_log_verbosity( int level ); +int _gcry_log_verbosity( int level ); + +#ifdef JNLIB_GCC_M_FUNCTION +#define BUG() _gcry_bug( __FILE__ , __LINE__, __FUNCTION__ ) +#define gcry_assert(expr) ((expr)? (void)0 \ + : _gcry_assert_failed (STR(expr), __FILE__, __LINE__, __FUNCTION__)) +#elif __STDC_VERSION__ >= 199901L +#define BUG() _gcry_bug( __FILE__ , __LINE__, __func__ ) +#define gcry_assert(expr) ((expr)? (void)0 \ + : _gcry_assert_failed (STR(expr), __FILE__, __LINE__, __func__)) +#else +#define BUG() _gcry_bug( __FILE__ , __LINE__ ) +#define gcry_assert(expr) ((expr)? (void)0 \ + : _gcry_assert_failed (STR(expr), __FILE__, __LINE__)) +#endif + + +#define log_bug _gcry_log_bug +#define log_fatal _gcry_log_fatal +#define log_error _gcry_log_error +#define log_info _gcry_log_info +#define log_debug _gcry_log_debug +#define log_printf _gcry_log_printf +#define log_printhex _gcry_log_printhex + + +/*-- src/hwfeatures.c --*/ +/* (Do not change these values unless synced with the asm code.) */ +#define HWF_PADLOCK_RNG 1 +#define HWF_PADLOCK_AES 2 +#define HWF_PADLOCK_SHA 4 +#define HWF_PADLOCK_MMUL 8 + +#define HWF_INTEL_AESNI 256 + + +unsigned int _gcry_get_hw_features (void); +void _gcry_detect_hw_features (unsigned int); + + +/*-- mpi/mpiutil.c --*/ +const char *_gcry_mpi_get_hw_config (void); + + +/*-- cipher/pubkey.c --*/ + +/* FIXME: shouldn't this go into mpi.h? */ +#ifndef mpi_powm +#define mpi_powm(w,b,e,m) gcry_mpi_powm( (w), (b), (e), (m) ) +#endif + +/*-- primegen.c --*/ +gcry_mpi_t _gcry_generate_secret_prime (unsigned int nbits, + gcry_random_level_t random_level, + int (*extra_check)(void*, gcry_mpi_t), + void *extra_check_arg); +gcry_mpi_t _gcry_generate_public_prime (unsigned int nbits, + gcry_random_level_t random_level, + int (*extra_check)(void*, gcry_mpi_t), + void *extra_check_arg); +gcry_mpi_t _gcry_generate_elg_prime (int mode, + unsigned int pbits, unsigned int qbits, + gcry_mpi_t g, gcry_mpi_t **factors); +gcry_mpi_t _gcry_derive_x931_prime (const gcry_mpi_t xp, + const gcry_mpi_t xp1, const gcry_mpi_t xp2, + const gcry_mpi_t e, + gcry_mpi_t *r_p1, gcry_mpi_t *r_p2); +gpg_err_code_t _gcry_generate_fips186_2_prime + (unsigned int pbits, unsigned int qbits, + const void *seed, size_t seedlen, + gcry_mpi_t *r_q, gcry_mpi_t *r_p, + int *r_counter, + void **r_seed, size_t *r_seedlen); +gpg_err_code_t _gcry_generate_fips186_3_prime + (unsigned int pbits, unsigned int qbits, + const void *seed, size_t seedlen, + gcry_mpi_t *r_q, gcry_mpi_t *r_p, + int *r_counter, + void **r_seed, size_t *r_seedlen, int *r_hashalgo); + + +/* Replacements of missing functions (missing-string.c). */ +#ifndef HAVE_STPCPY +char *stpcpy (char *a, const char *b); +#endif +#ifndef HAVE_STRCASECMP +int strcasecmp (const char *a, const char *b) _GCRY_GCC_ATTR_PURE; +#endif + + +/* Macros used to rename missing functions. */ +#ifndef HAVE_STRTOUL +#define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c))) +#endif +#ifndef HAVE_MEMMOVE +#define memmove(d, s, n) bcopy((s), (d), (n)) +#endif +#ifndef HAVE_STRICMP +#define stricmp(a,b) strcasecmp( (a), (b) ) +#endif +#ifndef HAVE_ATEXIT +#define atexit(a) (on_exit((a),0)) +#endif +#ifndef HAVE_RAISE +#define raise(a) kill(getpid(), (a)) +#endif + + +/* Stack burning. */ + +void _gcry_burn_stack (int bytes); + + +/* To avoid that a compiler optimizes certain memset calls away, these + macros may be used instead. */ +#define wipememory2(_ptr,_set,_len) do { \ + volatile char *_vptr=(volatile char *)(_ptr); \ + size_t _vlen=(_len); \ + while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ + } while(0) +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + + + +/* Digit predicates. */ + +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define octdigitp(p) (*(p) >= '0' && *(p) <= '7') +#define alphap(a) ( (*(a) >= 'A' && *(a) <= 'Z') \ + || (*(a) >= 'a' && *(a) <= 'z')) +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) + + +/*-- sexp.c --*/ +gcry_error_t _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff, + const char *format, va_list arg_ptr); +char *_gcry_sexp_nth_string (const gcry_sexp_t list, int number); + + +/*-- fips.c --*/ + +void _gcry_initialize_fips_mode (int force); + +int _gcry_fips_mode (void); +#define fips_mode() _gcry_fips_mode () + +int _gcry_enforced_fips_mode (void); + +void _gcry_set_enforced_fips_mode (void); + +void _gcry_inactivate_fips_mode (const char *text); +int _gcry_is_fips_mode_inactive (void); + + +void _gcry_fips_signal_error (const char *srcfile, + int srcline, + const char *srcfunc, + int is_fatal, + const char *description); +#ifdef JNLIB_GCC_M_FUNCTION +# define fips_signal_error(a) \ + _gcry_fips_signal_error (__FILE__, __LINE__, __FUNCTION__, 0, (a)) +# define fips_signal_fatal_error(a) \ + _gcry_fips_signal_error (__FILE__, __LINE__, __FUNCTION__, 1, (a)) +#else +# define fips_signal_error(a) \ + _gcry_fips_signal_error (__FILE__, __LINE__, NULL, 0, (a)) +# define fips_signal_fatal_error(a) \ + _gcry_fips_signal_error (__FILE__, __LINE__, NULL, 1, (a)) +#endif + +int _gcry_fips_is_operational (void); +#define fips_is_operational() (_gcry_global_is_operational ()) +#define fips_not_operational() (GCRY_GPG_ERR_NOT_OPERATIONAL) + +int _gcry_fips_test_operational (void); +int _gcry_fips_test_error_or_operational (void); + +gpg_err_code_t _gcry_fips_run_selftests (int extended); + +void _gcry_fips_noreturn (void); +#define fips_noreturn() (_gcry_fips_noreturn ()) + + + +#endif /* G10LIB_H */ diff --git a/grub-core/lib/libgcrypt-grub/src/gcrypt-module.h b/grub-core/lib/libgcrypt-grub/src/gcrypt-module.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/src/gcrypt-module.h diff --git a/grub-core/lib/libgcrypt-grub/src/hmac256.h b/grub-core/lib/libgcrypt-grub/src/hmac256.h new file mode 100644 index 0000000..df28e72 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/src/hmac256.h @@ -0,0 +1,36 @@ +/* hmac256.h - Declarations for _gcry_hmac256 + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HMAC256_H +#define HMAC256_H + + +struct hmac256_context; +typedef struct hmac256_context *hmac256_context_t; + +hmac256_context_t _gcry_hmac256_new (const void *key, size_t keylen); +void _gcry_hmac256_update (hmac256_context_t hd, const void *buf, size_t len); +const void *_gcry_hmac256_finalize (hmac256_context_t hd, size_t *r_dlen); +void _gcry_hmac256_release (hmac256_context_t hd); + +int _gcry_hmac256_file (void *result, size_t resultsize, const char *filename, + const void *key, size_t keylen); + + +#endif /*HMAC256_H*/ diff --git a/grub-core/lib/libgcrypt-grub/src/mpi.h b/grub-core/lib/libgcrypt-grub/src/mpi.h new file mode 100644 index 0000000..5883196 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/src/mpi.h @@ -0,0 +1,266 @@ +/* mpi.h - Multi Precision Integers + * Copyright (C) 1994, 1996, 1998, + * 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#ifndef G10_MPI_H +#define G10_MPI_H + +#include <config.h> +#include <stdio.h> +#include <string.h> + +#include "types.h" +#include "../mpi/mpi-asm-defs.h" + +#include "g10lib.h" + +#ifndef _GCRYPT_IN_LIBGCRYPT +#error this file should only be used inside libgcrypt +#endif + +#ifndef BITS_PER_MPI_LIMB +#if BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_INT + typedef unsigned int mpi_limb_t; + typedef signed int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG + typedef unsigned long int mpi_limb_t; + typedef signed long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG_LONG + typedef unsigned long long int mpi_limb_t; + typedef signed long long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_SHORT + typedef unsigned short int mpi_limb_t; + typedef signed short int mpi_limb_signed_t; +#else +#error BYTES_PER_MPI_LIMB does not match any C type +#endif +#define BITS_PER_MPI_LIMB (8*BYTES_PER_MPI_LIMB) +#endif /*BITS_PER_MPI_LIMB*/ + +#define DBG_MPI _gcry_get_debug_flag( 2 ); + +struct gcry_mpi +{ + int alloced; /* Array size (# of allocated limbs). */ + int nlimbs; /* Number of valid limbs. */ + int sign; /* Indicates a negative number and is also used + for opaque MPIs to store the length. */ + unsigned int flags; /* Bit 0: Array to be allocated in secure memory space.*/ + /* Bit 2: the limb is a pointer to some m_alloced data.*/ + mpi_limb_t *d; /* Array with the limbs */ +}; + +#define MPI_NULL NULL + +#define mpi_get_nlimbs(a) ((a)->nlimbs) +#define mpi_is_neg(a) ((a)->sign) + +/*-- mpiutil.c --*/ + +#ifdef M_DEBUG +# define mpi_alloc(n) _gcry_mpi_debug_alloc((n), M_DBGINFO( __LINE__ ) ) +# define mpi_alloc_secure(n) _gcry_mpi_debug_alloc_secure((n), M_DBGINFO( __LINE__ ) ) +# define mpi_free(a) _gcry_mpi_debug_free((a), M_DBGINFO(__LINE__) ) +# define mpi_resize(a,b) _gcry_mpi_debug_resize((a),(b), M_DBGINFO(__LINE__) ) +# define mpi_copy(a) _gcry_mpi_debug_copy((a), M_DBGINFO(__LINE__) ) + gcry_mpi_t _gcry_mpi_debug_alloc( unsigned nlimbs, const char *info ); + gcry_mpi_t _gcry_mpi_debug_alloc_secure( unsigned nlimbs, const char *info ); + void _gcry_mpi_debug_free( gcry_mpi_t a, const char *info ); + void _gcry_mpi_debug_resize( gcry_mpi_t a, unsigned nlimbs, const char *info ); + gcry_mpi_t _gcry_mpi_debug_copy( gcry_mpi_t a, const char *info ); +#else +# define mpi_alloc(n) _gcry_mpi_alloc((n) ) +# define mpi_alloc_secure(n) _gcry_mpi_alloc_secure((n) ) +# define mpi_free(a) _gcry_mpi_free((a) ) +# define mpi_resize(a,b) _gcry_mpi_resize((a),(b)) +# define mpi_copy(a) _gcry_mpi_copy((a)) + gcry_mpi_t _gcry_mpi_alloc( unsigned nlimbs ); + gcry_mpi_t _gcry_mpi_alloc_secure( unsigned nlimbs ); + void _gcry_mpi_free( gcry_mpi_t a ); + void _gcry_mpi_resize( gcry_mpi_t a, unsigned nlimbs ); + gcry_mpi_t _gcry_mpi_copy( gcry_mpi_t a ); +#endif + +#define gcry_mpi_copy _gcry_mpi_copy + +#define mpi_is_opaque(a) ((a) && ((a)->flags&4)) +#define mpi_is_secure(a) ((a) && ((a)->flags&1)) +#define mpi_clear(a) _gcry_mpi_clear ((a)) +#define mpi_alloc_like(a) _gcry_mpi_alloc_like((a)) +#define mpi_set(a,b) gcry_mpi_set ((a),(b)) +#define mpi_set_ui(a,b) gcry_mpi_set_ui ((a),(b)) +#define mpi_get_ui(a,b) _gcry_mpi_get_ui ((a),(b)) +#define mpi_alloc_set_ui(a) _gcry_mpi_alloc_set_ui ((a)) +#define mpi_m_check(a) _gcry_mpi_m_check ((a)) +#define mpi_swap(a,b) _gcry_mpi_swap ((a),(b)) +#define mpi_new(n) _gcry_mpi_new ((n)) +#define mpi_snew(n) _gcry_mpi_snew ((n)) + +void _gcry_mpi_clear( gcry_mpi_t a ); +gcry_mpi_t _gcry_mpi_alloc_like( gcry_mpi_t a ); +gcry_mpi_t _gcry_mpi_alloc_set_ui( unsigned long u); +gcry_err_code_t _gcry_mpi_get_ui (gcry_mpi_t w, ulong *u); +gcry_err_code_t gcry_mpi_get_ui (gcry_mpi_t w, ulong *u); +void _gcry_mpi_m_check( gcry_mpi_t a ); +void _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b); +gcry_mpi_t _gcry_mpi_new (unsigned int nbits); +gcry_mpi_t _gcry_mpi_snew (unsigned int nbits); + +/*-- mpicoder.c --*/ +void _gcry_log_mpidump( const char *text, gcry_mpi_t a ); +u32 _gcry_mpi_get_keyid( gcry_mpi_t a, u32 *keyid ); +byte *_gcry_mpi_get_buffer( gcry_mpi_t a, unsigned *nbytes, int *sign ); +byte *_gcry_mpi_get_secure_buffer( gcry_mpi_t a, unsigned *nbytes, int *sign ); +void _gcry_mpi_set_buffer ( gcry_mpi_t a, const void *buffer, + unsigned int nbytes, int sign ); + +#define log_mpidump _gcry_log_mpidump + +/*-- mpi-add.c --*/ +#define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v)) +#define mpi_add(w,u,v) gcry_mpi_add ((w),(u),(v)) +#define mpi_addm(w,u,v,m) gcry_mpi_addm ((w),(u),(v),(m)) +#define mpi_sub_ui(w,u,v) gcry_mpi_sub_ui ((w),(u),(v)) +#define mpi_sub(w,u,v) gcry_mpi_sub ((w),(u),(v)) +#define mpi_subm(w,u,v,m) gcry_mpi_subm ((w),(u),(v),(m)) + + +/*-- mpi-mul.c --*/ +#define mpi_mul_ui(w,u,v) gcry_mpi_mul_ui ((w),(u),(v)) +#define mpi_mul_2exp(w,u,v) gcry_mpi_mul_2exp ((w),(u),(v)) +#define mpi_mul(w,u,v) gcry_mpi_mul ((w),(u),(v)) +#define mpi_mulm(w,u,v,m) gcry_mpi_mulm ((w),(u),(v),(m)) + + +/*-- mpi-div.c --*/ +#define mpi_fdiv_r_ui(a,b,c) _gcry_mpi_fdiv_r_ui((a),(b),(c)) +#define mpi_fdiv_r(a,b,c) _gcry_mpi_fdiv_r((a),(b),(c)) +#define mpi_fdiv_q(a,b,c) _gcry_mpi_fdiv_q((a),(b),(c)) +#define mpi_fdiv_qr(a,b,c,d) _gcry_mpi_fdiv_qr((a),(b),(c),(d)) +#define mpi_tdiv_r(a,b,c) _gcry_mpi_tdiv_r((a),(b),(c)) +#define mpi_tdiv_qr(a,b,c,d) _gcry_mpi_tdiv_qr((a),(b),(c),(d)) +#define mpi_tdiv_q_2exp(a,b,c) _gcry_mpi_tdiv_q_2exp((a),(b),(c)) +#define mpi_divisible_ui(a,b) _gcry_mpi_divisible_ui((a),(b)) + +ulong _gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor ); +void _gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor ); +void _gcry_mpi_fdiv_q( gcry_mpi_t quot, gcry_mpi_t dividend, gcry_mpi_t divisor ); +void _gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor ); +void _gcry_mpi_tdiv_r( gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den); +void _gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den); +void _gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned count ); +int _gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor ); + + +/*-- mpi-mod.c --*/ +#define mpi_mod(r,a,m) _gcry_mpi_mod ((r), (a), (m)) +#define mpi_barrett_init(m,f) _gcry_mpi_barrett_init ((m),(f)) +#define mpi_barrett_free(c) _gcry_mpi_barrett_free ((c)) +#define mpi_mod_barrett(r,a,c) _gcry_mpi_mod_barrett ((r), (a), (c)) +#define mpi_mul_barrett(r,u,v,c) _gcry_mpi_mul_barrett ((r), (u), (v), (c)) + +void _gcry_mpi_mod (gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor); + +/* Context used with Barrett reduction. */ +struct barrett_ctx_s; +typedef struct barrett_ctx_s *mpi_barrett_t; + +mpi_barrett_t _gcry_mpi_barrett_init (gcry_mpi_t m, int copy); +void _gcry_mpi_barrett_free (mpi_barrett_t ctx); +void _gcry_mpi_mod_barrett (gcry_mpi_t r, gcry_mpi_t x, mpi_barrett_t ctx); +void _gcry_mpi_mul_barrett (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, + mpi_barrett_t ctx); + + + +/*-- mpi-gcd.c --*/ + +/*-- mpi-mpow.c --*/ +#define mpi_mulpowm(a,b,c,d) _gcry_mpi_mulpowm ((a),(b),(c),(d)) +void _gcry_mpi_mulpowm( gcry_mpi_t res, gcry_mpi_t *basearray, gcry_mpi_t *exparray, gcry_mpi_t mod); + +/*-- mpi-cmp.c --*/ +#define mpi_cmp_ui(a,b) gcry_mpi_cmp_ui ((a),(b)) +#define mpi_cmp(a,b) gcry_mpi_cmp ((a),(b)) +int gcry_mpi_cmp_ui( gcry_mpi_t u, ulong v ); +int gcry_mpi_cmp( gcry_mpi_t u, gcry_mpi_t v ); + +/*-- mpi-scan.c --*/ +#define mpi_trailing_zeros(a) _gcry_mpi_trailing_zeros ((a)) +int _gcry_mpi_getbyte( gcry_mpi_t a, unsigned idx ); +void _gcry_mpi_putbyte( gcry_mpi_t a, unsigned idx, int value ); +unsigned _gcry_mpi_trailing_zeros( gcry_mpi_t a ); + +/*-- mpi-bit.c --*/ +#define mpi_normalize(a) _gcry_mpi_normalize ((a)) +#define mpi_get_nbits(a) gcry_mpi_get_nbits ((a)) +#define mpi_test_bit(a,b) gcry_mpi_test_bit ((a),(b)) +#define mpi_set_bit(a,b) gcry_mpi_set_bit ((a),(b)) +#define mpi_set_highbit(a,b) gcry_mpi_set_highbit ((a),(b)) +#define mpi_clear_bit(a,b) gcry_mpi_clear_bit ((a),(b)) +#define mpi_clear_highbit(a,b) gcry_mpi_clear_highbit ((a),(b)) +#define mpi_rshift(a,b,c) gcry_mpi_rshift ((a),(b),(c)) +#define mpi_lshift(a,b,c) gcry_mpi_lshift ((a),(b),(c)) + +void _gcry_mpi_normalize( gcry_mpi_t a ); + +/*-- mpi-inv.c --*/ +#define mpi_invm(a,b,c) gcry_mpi_invm ((a),(b),(c)) + +/*-- ec.c --*/ + +/* Object to represent a point in projective coordinates. */ +struct mpi_point_s; +typedef struct mpi_point_s mpi_point_t; +struct mpi_point_s +{ + gcry_mpi_t x; + gcry_mpi_t y; + gcry_mpi_t z; +}; + +/* Context used with elliptic curve functions. */ +struct mpi_ec_ctx_s; +typedef struct mpi_ec_ctx_s *mpi_ec_t; + +void _gcry_mpi_ec_point_init (mpi_point_t *p); +void _gcry_mpi_ec_point_free (mpi_point_t *p); +mpi_ec_t _gcry_mpi_ec_init (gcry_mpi_t p, gcry_mpi_t a); +void _gcry_mpi_ec_free (mpi_ec_t ctx); +int _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t *point, + mpi_ec_t ctx); +void _gcry_mpi_ec_dup_point (mpi_point_t *result, + mpi_point_t *point, mpi_ec_t ctx); +void _gcry_mpi_ec_add_points (mpi_point_t *result, + mpi_point_t *p1, mpi_point_t *p2, + mpi_ec_t ctx); +void _gcry_mpi_ec_mul_point (mpi_point_t *result, + gcry_mpi_t scalar, mpi_point_t *point, + mpi_ec_t ctx); + + + +#endif /*G10_MPI_H*/ diff --git a/grub-core/lib/libgcrypt-grub/src/secmem.h b/grub-core/lib/libgcrypt-grub/src/secmem.h new file mode 100644 index 0000000..29e151a --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/src/secmem.h @@ -0,0 +1,39 @@ +/* secmem.h - internal definitions for secmem + * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef G10_SECMEM_H +#define G10_SECMEM_H 1 + +void _gcry_secmem_init (size_t npool); +void _gcry_secmem_term (void); +void *_gcry_secmem_malloc (size_t size) _GCRY_GCC_ATTR_MALLOC; +void *_gcry_secmem_realloc (void *a, size_t newsize); +void _gcry_secmem_free (void *a); +void _gcry_secmem_dump_stats (void); +void _gcry_secmem_set_flags (unsigned flags); +unsigned _gcry_secmem_get_flags(void); +int _gcry_private_is_secure (const void *p); + +/* Flags for _gcry_secmem_{set,get}_flags. */ +#define GCRY_SECMEM_FLAG_NO_WARNING (1 << 0) +#define GCRY_SECMEM_FLAG_SUSPEND_WARNING (1 << 1) +#define GCRY_SECMEM_FLAG_NOT_LOCKED (1 << 2) + +#endif /* G10_SECMEM_H */ diff --git a/grub-core/lib/libgcrypt-grub/src/stdmem.h b/grub-core/lib/libgcrypt-grub/src/stdmem.h new file mode 100644 index 0000000..b476e7e --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/src/stdmem.h @@ -0,0 +1,32 @@ +/* stdmem.h - internal definitions for stdmem + * Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef G10_STDMEM_H +#define G10_STDMEM_H 1 + +void _gcry_private_enable_m_guard(void); + +void *_gcry_private_malloc (size_t n) _GCRY_GCC_ATTR_MALLOC; +void *_gcry_private_malloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC; +void *_gcry_private_realloc (void *a, size_t n); +void _gcry_private_check_heap (const void *a); +void _gcry_private_free (void *a); + +#endif /* G10_STDMEM_H */ diff --git a/grub-core/lib/libgcrypt-grub/src/types.h b/grub-core/lib/libgcrypt-grub/src/types.h new file mode 100644 index 0000000..f2c0abf --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/src/types.h @@ -0,0 +1,128 @@ +/* types.h - some common typedefs + * Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef GCRYPT_TYPES_H +#define GCRYPT_TYPES_H + + +/* The AC_CHECK_SIZEOF() in configure fails for some machines. + * we provide some fallback values here */ +#if !SIZEOF_UNSIGNED_SHORT +#undef SIZEOF_UNSIGNED_SHORT +#define SIZEOF_UNSIGNED_SHORT 2 +#endif +#if !SIZEOF_UNSIGNED_INT +#undef SIZEOF_UNSIGNED_INT +#define SIZEOF_UNSIGNED_INT 4 +#endif +#if !SIZEOF_UNSIGNED_LONG +#undef SIZEOF_UNSIGNED_LONG +#define SIZEOF_UNSIGNED_LONG 4 +#endif + + +#include <sys/types.h> + + +#ifndef HAVE_BYTE_TYPEDEF +#undef byte /* maybe there is a macro with this name */ +/* Windows typedefs byte in the rpc headers. Avoid warning about + double definition. */ +#if !(defined(_WIN32) && defined(cbNDRContext)) + typedef unsigned char byte; +#endif +#define HAVE_BYTE_TYPEDEF +#endif + +#ifndef HAVE_USHORT_TYPEDEF +#undef ushort /* maybe there is a macro with this name */ + typedef unsigned short ushort; +#define HAVE_USHORT_TYPEDEF +#endif + +#ifndef HAVE_ULONG_TYPEDEF +#undef ulong /* maybe there is a macro with this name */ + typedef unsigned long ulong; +#define HAVE_ULONG_TYPEDEF +#endif + +#ifndef HAVE_U16_TYPEDEF +#undef u16 /* maybe there is a macro with this name */ +#if SIZEOF_UNSIGNED_INT == 2 + typedef unsigned int u16; +#elif SIZEOF_UNSIGNED_SHORT == 2 + typedef unsigned short u16; +#else +#error no typedef for u16 +#endif +#define HAVE_U16_TYPEDEF +#endif + +#ifndef HAVE_U32_TYPEDEF +#undef u32 /* maybe there is a macro with this name */ +#if SIZEOF_UNSIGNED_INT == 4 + typedef unsigned int u32; +#elif SIZEOF_UNSIGNED_LONG == 4 + typedef unsigned long u32; +#else +#error no typedef for u32 +#endif +#define HAVE_U32_TYPEDEF +#endif + +/**************** + * Warning: Some systems segfault when this u64 typedef and + * the dummy code in cipher/md.c is not available. Examples are + * Solaris and IRIX. + */ +#ifndef HAVE_U64_TYPEDEF +#undef u64 /* maybe there is a macro with this name */ +#if SIZEOF_UNSIGNED_INT == 8 + typedef unsigned int u64; +#define U64_C(c) (c ## U) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UNSIGNED_LONG == 8 + typedef unsigned long u64; +#define U64_C(c) (c ## UL) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UNSIGNED_LONG_LONG == 8 + typedef unsigned long long u64; +#define U64_C(c) (c ## ULL) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UINT64_T == 8 + typedef uint64_t u64; +#define U64_C(c) (UINT64_C(c)) +#define HAVE_U64_TYPEDEF +#endif +#endif + +typedef union { + int a; + short b; + char c[1]; + long d; +#ifdef HAVE_U64_TYPEDEF + u64 e; +#endif + + +} PROPERLY_ALIGNED_TYPE; + +#endif /*GCRYPT_TYPES_H*/ diff --git a/grub-core/lib/libgcrypt-grub/src/visibility.h b/grub-core/lib/libgcrypt-grub/src/visibility.h new file mode 100644 index 0000000..d1fb018 --- /dev/null +++ b/grub-core/lib/libgcrypt-grub/src/visibility.h @@ -0,0 +1 @@ +# include <grub/gcrypt/gcrypt.h> diff --git a/grub-core/lib/libgcrypt/cipher/ChangeLog b/grub-core/lib/libgcrypt/cipher/ChangeLog new file mode 100644 index 0000000..1b3694f --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/ChangeLog @@ -0,0 +1,3990 @@ +2010-08-19 Werner Koch <wk@g10code.com> + + * cipher.c (gcry_cipher_open): Remove double release of the module. + Fixes bug#1263. + +2010-06-10 Jeff Johnson <n3npq@mac.com> (wk) + + * ecc.c (ecc_generate_ext): Parse transient-key flag. + (generate_key): Add arg TRANSIENT_KEY and use it to set the random + level. + +2010-04-12 Brad Hards <bradh@frogmouth.net> (wk) + + Spelling fixes. + +2010-03-26 Werner Koch <wk@g10code.com> + + * tiger.c (asn): Unfetter the old TIGER from an OID. + (TIGER_CONTEXT): Add field VARIANT. + (tiger_init): Factor code out to ... + (do_init): New. + (tiger1_init, tiger2_init): New. + (_gcry_digest_spec_tiger1, _gcry_digest_spec_tiger2): New. + * md.c (digest_table): Add TIGER1 and TIGER2 variants. + +2009-12-11 Werner Koch <wk@g10code.com> + + * sha256.c (Cho, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables + + * sha512.c (ROTR, Ch, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables. + Suggested by Christian Grothoff. + +2009-12-10 Werner Koch <wk@g10code.com> + + * Makefile.am (o_flag_munging): New. + (tiger.o, tiger.lo): Use it. + + * cipher.c (do_ctr_encrypt): Add arg OUTBUFLEN. Check for + suitable value. Add check for valid inputlen. Wipe temporary + memory. + (do_ctr_decrypt): Likewise. + (do_cbc_encrypt, do_cbc_decrypt): Add arg OUTBUFLEN. Check for + suitable value. Move check for valid inputlen to here; change + returned error from INV_ARG to INV_LENGTH. + (do_ecb_encrypt, do_ecb_decrypt): Ditto. + (do_cfb_encrypt, do_cfb_decrypt): Ditto. + (do_ofb_encrypt, do_ofb_decrypt): Ditto. + (cipher_encrypt, cipher_encrypt): Adjust for above changes. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Simplify. + +2009-12-09 Werner Koch <wk@g10code.com> + + * cipher.c (gcry_cipher_open): Allow for GCRY_CIPHER_MODE_AESWRAP. + (cipher_encrypt, cipher_decrypt): Ditto. + (do_aeswrap_encrypt, do_aeswrap_decrypt): New. + (struct gcry_cipher_handle): Add field marks. + (cipher_setkey, cipher_setiv): Update marks flags. + (cipher_reset): Reset marks. + (cipher_encrypt, cipher_decrypt): Add new arg OUTBUFLEN. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Pass outbuflen to + cipher_encrypt. Replace GPG_ERR_TOO_SHORT by + GPG_ERR_BUFFER_TOO_SHORT. + +2009-08-21 Werner Koch <wk@g10code.com> + + * dsa.c (dsa_generate_ext): Release retfactors array before + setting it to NULL. Reported by Daiko Ueno. + +2009-07-02 Werner Koch <wk@g10code.com> + + * md.c (md_read): Fix incomplete check for NULL. + Reported by Fabian Kail. + +2009-03-31 Werner Koch <wk@g10code.com> + + * rsa.c (rsa_check_secret_key): Return GPG_ERR_BAD_SECKEY and not + GPG_ERR_PUBKEY_ALGO. + +2009-02-16 Werner Koch <wk@g10code.com> + + * rsa.c (generate_x931): Do not initialize TBL with automatic + variables. + * whirlpool.c, tiger.c, sha256.c, sha1.c, rmd160.c, md5.c + * md4.c, crc.c: Remove memory.h. This is garbage from gnupg. + Reported by Dan Fandrich. + +2009-01-22 Werner Koch <wk@g10code.com> + + * ecc.c (compute_keygrip): Remove superfluous const. + +2009-01-06 Werner Koch <wk@g10code.com> + + * rmd160.c (oid_spec_rmd160): Add TeleTrust identifier. + +2008-12-10 Werner Koch <wk@g10code.com> + + * dsa.c (generate): Add arg DOMAIN and use it if specified. + (generate_fips186): Ditto. + (dsa_generate_ext): Parse and check the optional "domain" + parameter and pass them to the generate functions. + + * rijndael.c (rijndael_names): Add "AES128" and "AES-128". + (rijndael192_names): Add "AES-192". + (rijndael256_names): Add "AES-256". + +2008-12-05 Werner Koch <wk@g10code.com> + + * dsa.c (generate): Add arg TRANSIENT_KEY and use it to detrmine + the RNG quality needed. + (dsa_generate_ext): Parse the transient-key flag und pass it to + generate. + +2008-11-28 Werner Koch <wk@g10code.com> + + * dsa.c (generate_fips186): Add arg DERIVEPARMS and use the seed + value if available. + + * primegen.c (_gcry_generate_fips186_2_prime): Fix inner p loop. + +2008-11-26 Werner Koch <wk@g10code.com> + + * primegen.c (_gcry_generate_fips186_3_prime): New. + * dsa.c (generate_fips186): Add arg USE_FIPS186_2. + (dsa_generate_ext): Parse new flag use-fips183-2. + +2008-11-25 Werner Koch <wk@g10code.com> + + * dsa.c (generate_fips186): New. + (dsa_generate_ext): Use new function if derive-parms are given or + if in FIPS mode. + * primegen.c (_gcry_generate_fips186_2_prime): New. + +2008-11-24 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Insert code to output extrainfo. + (pubkey_generate): Add arg R_EXTRAINFO and pass it to the extended + key generation function. + * rsa.c (gen_x931_parm_xp, gen_x931_parm_xi): New. + (generate_x931): Generate params if not given. + (rsa_generate_ext): Parse use-x931 flag. Return p-q-swapped + indicator. + * dsa.c (dsa_generate_ext): Put RETFACTORS into R_EXTRAINFO if + possible. + + * pubkey.c (gcry_pk_genkey): Remove parsing of almost all + parameters and pass the parameter S-expression to pubkey_generate. + (pubkey_generate): Simplify by requitring modules to parse the + parameters. Remove the special cases for Elgamal and ECC. + (sexp_elements_extract_ecc): Add arg EXTRASPEC and use it. Fix + small memory leak. + (sexp_to_key): Pass EXTRASPEC to sexp_elements_extract_ecc. + (pubkey_table) [USE_ELGAMAL]: Add real extraspec. + * rsa.c (rsa_generate_ext): Adjust for new calling convention. + * dsa.c (dsa_generate_ext): Ditto. + * elgamal.c (_gcry_elg_generate): Ditto. Rename to elg_generate_ext. + (elg_generate): New. + (_gcry_elg_generate_using_x): Remove after merging code with + elg_generate_ext. + (_gcry_pubkey_extraspec_elg): New. + (_gcry_elg_check_secret_key, _gcry_elg_encrypt, _gcry_elg_sign) + (_gcry_elg_verify, _gcry_elg_get_nbits): Make static and remove + _gcry_ prefix. + * ecc.c (_gcry_ecc_generate): Rename to ecc_generate_ext and + adjust for new calling convention. + (_gcry_ecc_get_param): Rename to ecc_get_param and make static. + (_gcry_pubkey_extraspec_ecdsa): Add ecc_generate_ext and + ecc_get_param. + +2008-11-20 Werner Koch <wk@g10code.com> + + * pubkey.c (pubkey_generate): Add arg DERIVEPARMS. + (gcry_pk_genkey): Parse derive-parms and pass it to above. + * rsa.c (generate_x931): New. + (rsa_generate_ext): Add arg DERIVEPARMS and call new function in + fips mode or if DERIVEPARMS is given. + * primegen.c (_gcry_derive_x931_prime, find_x931_prime): New. + +2008-11-19 Werner Koch <wk@g10code.com> + + * rsa.c (rsa_decrypt): Use gcry_create_nonce for blinding. + (generate): Rename to generate_std. + +2008-11-05 Werner Koch <wk@g10code.com> + + * md.c (md_open): Use a switch to set the Bsize. + (prepare_macpads): Fix long key case for SHA384 and SHA512. + + * cipher.c (gcry_cipher_handle): Add field EXTRASPEC. + (gcry_cipher_open): Set it. + (gcry_cipher_ctl): Add private control code to disable weak key + detection and to return the current input block. + * des.c (_tripledes_ctx): Add field FLAGS. + (do_tripledes_set_extra_info): New. + (_gcry_cipher_extraspec_tripledes): Add new function. + (do_tripledes_setkey): Disable weak key detection. + +2008-10-24 Werner Koch <wk@g10code.com> + + * md.c (digest_table): Allow MD5 in fips mode. + (md_register_default): Take special action for MD5. + (md_enable, gcry_md_hash_buffer): Ditto. + +2008-09-30 Werner Koch <wk@g10code.com> + + * rijndael.c (do_setkey): Properly align "t" and "tk". + (prepare_decryption): Properly align "w". Fixes bug #936. + +2008-09-18 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Parse domain parameter. + (pubkey_generate): Add new arg DOMAIN and remove special case for + DSA with qbits. + * rsa.c (rsa_generate): Add dummy args QBITS, NAME and DOMAIN and + rename to rsa_generate_ext. Change caller. + (_gcry_rsa_generate, _gcry_rsa_check_secret_key) + (_gcry_rsa_encrypt, _gcry_rsa_decrypt, _gcry_rsa_sign) + (_gcry_rsa_verify, _gcry_rsa_get_nbits): Make static and remove + _gcry_ prefix. + (_gcry_pubkey_spec_rsa, _gcry_pubkey_extraspec_rsa): Adjust names. + * dsa.c (dsa_generate_ext): New. + (_gcry_dsa_generate): Replace code by a call to dsa_generate. + (_gcry_dsa_check_secret_key, _gcry_dsa_sign, _gcry_dsa_verify) + (_gcry_dsa_get_nbits): Make static and remove _gcry prefix. + (_gcry_dsa_generate2): Remove. + (_gcry_pubkey_spec_dsa): Adjust to name changes. + (_gcry_pubkey_extraspec_rsa): Add dsa_generate_ext. + +2008-09-16 Werner Koch <wk@g10code.com> + + * ecc.c (run_selftests): Add arg EXTENDED. + +2008-09-12 Werner Koch <wk@g10code.com> + + * rsa.c (test_keys): Do a bad case signature check. + * dsa.c (test_keys): Do a bad case check. + + * cipher.c (_gcry_cipher_selftest): Add arg EXTENDED and pass it + to the called tests. + * md.c (_gcry_md_selftest): Ditto. + * pubkey.c (_gcry_pk_selftest): Ditto. + * rijndael.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftest_fips_128): Add arg EXTENDED and run only one test + non-extended mode. + (selftest_fips_192): Add dummy arg EXTENDED. + (selftest_fips_256): Ditto. + * hmac-tests.c (_gcry_hmac_selftest): Ditto. + (run_selftests): Ditto. + (selftests_sha1): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha224, selftests_sha256): Ditto. + (selftests_sha384, selftests_sha512): Ditto. + * sha1.c (run_selftests): Add arg EXTENDED and pass it to the + called test. + (selftests_sha1): Add arg EXTENDED and run only one test + non-extended mode. + * sha256.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftests_sha224): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha256): Ditto. + * sha512.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftests_sha384): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha512): Ditto. + * des.c (run_selftests): Add arg EXTENDED and pass it to the + called test. + (selftest_fips): Add dummy arg EXTENDED. + * rsa.c (run_selftests): Add dummy arg EXTENDED. + + * dsa.c (run_selftests): Add dummy arg EXTENDED. + + * rsa.c (extract_a_from_sexp): New. + (selftest_encr_1024): Check that the ciphertext does not match the + plaintext. + (test_keys): Improve tests and return an error status. + (generate): Return an error if test_keys fails. + * dsa.c (test_keys): Add comments and return an error status. + (generate): Return an error if test_keys failed. + +2008-09-11 Werner Koch <wk@g10code.com> + + * rsa.c (_gcry_rsa_decrypt): Return an error instead of calling + BUG in case of a practically impossible condition. + (sample_secret_key, sample_public_key): New. + (selftest_sign_1024, selftest_encr_1024): New. + (selftests_rsa): Implement tests. + * dsa.c (sample_secret_key, sample_public_key): New. + (selftest_sign_1024): New. + (selftests_dsa): Implement tests. + +2008-09-09 Werner Koch <wk@g10code.com> + + * hmac-tests.c (selftests_sha1): Add tests. + (selftests_sha224, selftests_sha384, selftests_sha512): Make up tests. + + * hash-common.c, hash-common.h: New. + * sha1.c (selftests_sha1): Add 3 tests. + * sha256.c (selftests_sha256, selftests_sha224): Ditto. + * sha512.c (selftests_sha512, selftests_sha384): Ditto. + +2008-08-29 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_get_keygrip): Remove the special case for RSA + and check whether a custom computation function has been setup. + * rsa.c (compute_keygrip): New. + (_gcry_pubkey_extraspec_rsa): Setup this function. + * ecc.c (compute_keygrip): New. + (_gcry_pubkey_extraspec_ecdsa): Setup this function. + +2008-08-28 Werner Koch <wk@g10code.com> + + * cipher.c (cipher_decrypt, cipher_encrypt): Return an error if + mode NONE is used. + (gcry_cipher_open): Allow mode NONE only with a debug flag set and + if not in FIPS mode. + +2008-08-26 Werner Koch <wk@g10code.com> + + * pubkey.c (pubkey_generate): Add arg KEYGEN_FLAGS. + (gcry_pk_genkey): Implement new parameter "transient-key" and + pass it as flags to pubkey_generate. + (pubkey_generate): Make use of an ext_generate function. + * rsa.c (generate): Add new arg transient_key and pass appropriate + args to the prime generator. + (_gcry_rsa_generate): Factor all code out to ... + (rsa_generate): .. new func with extra arg KEYGEN_FLAGS. + (_gcry_pubkey_extraspec_ecdsa): Setup rsa_generate. + * primegen.c (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Add new arg RANDOM_LEVEL. + +2008-08-21 Werner Koch <wk@g10code.com> + + * primegen.c (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Use a constant macro for the random + level. + +2008-08-19 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_elements_extract_ecc) [!USE_ECC]: Do not allow + allow "curve" parameter. + +2008-08-15 Werner Koch <wk@g10code.com> + + * pubkey.c (_gcry_pk_selftest): New. + * dsa.c (selftests_dsa, run_selftests): New. + * rsa.c (selftests_rsa, run_selftests): New. + * ecc.c (selftests_ecdsa, run_selftests): New. + + * md.c (_gcry_md_selftest): New. + * sha1.c (run_selftests, selftests_sha1): New. + * sha256.c (selftests_sha224, selftests_sha256, run_selftests): New. + * sha512.c (selftests_sha384, selftests_sha512, run_selftests): New. + + * des.c (selftest): Remove static variable form selftest. + (des_setkey): No on-the-fly self test in fips mode. + (tripledes_set3keys): Ditto. + + * cipher.c (_gcry_cipher_setkey, _gcry_cipher_setiv): + + * dsa.c (generate): Bail out in fips mode if NBITS is less than 1024. + * rsa.c (generate): Return an error code if the the requested size + is less than 1024 and we are in fpis mode. + (_gcry_rsa_generate): Take care of that error code. + + * ecc.c (generate_curve): In fips mode enable only NIST curves. + + * cipher.c (_gcry_cipher_selftest): New. + + * sha512.c (_gcry_digest_extraspec_sha384) + (_gcry_digest_extraspec_sha512): New. + * sha256.c (_gcry_digest_extraspec_sha224) + (_gcry_digest_extraspec_sha256): New. + * sha1.c (_gcry_digest_extraspec_sha1): New. + * ecc.c (_gcry_pubkey_extraspec_ecdsa): New. + * dsa.c (_gcry_pubkey_extraspec_dsa): New. + * rsa.c (_gcry_pubkey_extraspec_rsa): New. + * rijndael.c (_gcry_cipher_extraspec_aes) + (_gcry_cipher_extraspec_aes192, _gcry_cipher_extraspec_aes256): New. + * des.c (_gcry_cipher_extraspec_tripledes): New. + + * cipher.c (gcry_cipher_register): Rename to _gcry_cipher_register. + Add arg EXTRASPEC. + (dummy_extra_spec): New. + (cipher_table_entry): Add extraspec field. + * md.c (_gcry_md_register): Rename to _gcry_md_register. Add + arg EXTRASPEC. + (dummy_extra_spec): New. + (digest_table_entry): Add extraspec field. + * pubkey.c (gcry_pk_register): Rename to _gcry_pk_register. Add + arg EXTRASPEC. + (dummy_extra_spec): New. + (pubkey_table_entry): Add extraspec field. + + * ac.c: Let most public functions return GPG_ERR_UNSUPPORTED in + fips mode. + + * pubkey.c (pubkey_table_entry): Add field FIPS_ALLOWED and mark + appropriate algorithms. + (dummy_generate, dummy_check_secret_key, dummy_encrypt) + (dummy_decrypt, dummy_sign, dummy_verify, dummy_get_nbits): Signal + a fips error when used. + (gcry_pk_register): In fips mode do not allow to register new + algorithms. + + * md.c (digest_table): Add field FIPS_ALLOWED and mark appropriate + algorithms. + (md_register_default): In fips mode register only fips algorithms. + (gcry_md_register): In fips mode do not allow to register new + algorithms. + (gcry_md_get): Signal a fips error if called. + (gcry_md_hash_buffer): Do not allow rmd160 when not in fips mode. + (md_start_debug): Disable in fips_mode. + + * md.c (gcry_md_register_default): Rename to .. + (md_register_default): .. this. + (md_digest): Remove this commented fucntion. + * pubkey.c (gcry_pk_register_default): Rename to .. + (pk_register_default): .. this. + + * cipher.c (cipher_table_entry): Add field FIPS_ALLOWED. + (gcry_cipher_register_default): Register only fips approved + algorithms. + (gcry_cipher_register): Do not allow to register new ciphers. + (cipher_setiv): Signal fips error. + + * cipher (gcry_cipher_register_default): Rename to .. + (cipher_register_default): .. this. + (REGISTER_DEFAULT_CIPHERS): Adjust for that change. + +2008-07-05 Werner Koch <wk@g10code.com> + + * random-daemon.c, random.h, rndhw.c, rndunix.c, rand-internal.h + * random.c, rndegd.c, rndlinux.c, rndw32.c: Move to ../cipher. + * Makefile.am: Remove random stuff. + +2008-06-24 Szakats Istvan <szaki.ms@gmail.com> (wk) + + * ac.c (_gcry_ac_key_destroy, _gcry_ac_key_pair_generate): Relase + some more memory. + +2008-04-22 Werner Koch <wk@g10code.com> + + * rijndael.c (_gcry_aes_cfb_enc, _gcry_aes_cbc_enc) + (_gcry_aes_cfb_dec, _gcry_aes_cbc_dec): Use Padlock if possible. + +2008-04-18 Werner Koch <wk@g10code.com> + + * sha1.c (transform_aligned): Remove. That is will obviosuly not + work because we need a scratch working area and our internal API + does not allow to modify the buffers. + + * rijndael.c: Factor tables out to .. + * rijndael-tables.h: .. new. + + * ac.c (ac_data_extract): Make static. + + * camellia.h [HAVE_CONFIG_H]: Include config.h. + + * rndw32.c (registry_poll): Only print the performance data + problem warning once. Suggested by Simon Josefsson. + +2008-03-19 Werner Koch <wk@g10code.com> + + * cipher.c (gcry_cipher_open) [USE_AES]: Init bulk encryption only + if requested. Suggested by Dirk Stoecker. + +2008-03-18 Werner Koch <wk@g10code.com> + + * sha1.c: Include stdint.h. + (transform): Add arg NBLOCKS so that we can work on more than one + block and avoid updates of the chaining variables. Changed all + callers to use 1. + (sha1_write): Replace loop around transform. + (transform_aligned) [WORDS_BIGENDIAN]: New. + (TRANSFORM): New macro to replace all direct calls of transform. + +2008-03-17 Werner Koch <wk@g10code.com> + + * rijndael.c (_gcry_aes_cfb_dec): New. + (do_encrypt): Factor code out to .. + (do_encrypt_aligned): .. New. + (_gcry_aes_cfb_enc, _gcry_aes_cfb_dec): Use new function. + (do_decrypt): Factor code out to .. + (do_decrypt_aligned): .. new. + (_gcry_aes_cbc_enc, _gcry_aes_cbc_dec): New. + * cipher.c (struct gcry_cipher_handle): Put field IV into new + union U_IV to enforce proper alignment. Change all users. + (do_cfb_decrypt): Optimize. + (do_cbc_encrypt, do_cbc_decrypt): Optimize. + +2008-03-15 Werner Koch <wk@g10code.com> + + * rijndael.c (_gcry_aes_cfb_enc): New. + * cipher.c (struct gcry_cipher_handle): Add field ALGO and BULK. + (gcry_cipher_open): Set ALGO and BULK. + (do_cfb_encrypt): Optimize. + +2008-02-18 Werner Koch <wk@g10code.com> + + * rsa.c (_gcry_rsa_verify) [IS_DEVELOPMENT_VERSION]: Print + intermediate results. + +2008-01-08 Werner Koch <wk@g10code.com> + + * random.c (add_randomness): Do not just increment + POOL_FILLED_COUNTER but update it by the actual amount of data. + +2007-12-13 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_data_to_mpi): Support SHA-224. + +2007-12-05 Werner Koch <wk@g10code.com> + + * rijndael.c (USE_PADLOCK): Depend on ENABLE_PADLOCK_SUPPORT. + * rndhw.c (USE_PADLOCK): Ditto + + * rsa.c (secret): Fixed condition test for using CRT. Reported by + Dean Scarff. Fixes bug#864. + (_gcry_rsa_check_secret_key): Return an erro if the optional + parameters are missing. + * pubkey.c (sexp_elements_extract): Add arg ALGO_NAME. Changed all + callers to pass NULL. Add hack to allow for optional RSA + parameters. + (sexp_to_key): Pass algo name to sexp_elements_extract. + +2007-12-03 Werner Koch <wk@g10code.com> + + * random.c (gcry_random_add_bytes): Implement it. + * rand-internal.h (RANDOM_ORIGIN_EXTERNAL): New. + +2007-11-30 Werner Koch <wk@g10code.com> + + * rndhw.c: New. + * rndlinux.c (_gcry_rndlinux_gather_random): Try to read 50% + directly from the hwrng. + * random.c (do_fast_random_poll): Also run the hw rng fast poll. + (_gcry_random_dump_stats): Tell whether the hw rng failed. + +2007-11-29 Werner Koch <wk@g10code.com> + + * rijndael.c (USE_PADLOCK): Define new macro used for ia32. + (RIJNDAEL_context) [USE_PADLOCK]: Add fields USE_PADLOCK and + PADLOCK_KEY. + (do_setkey) [USE_PADLOCK]: Enable padlock if available for 128 bit + AES. + (do_padlock) [USE_PADLOCK]: New. + (rijndael_encrypt, rijndael_decrypt) [USE_PADLOCK]: Divert to + do_padlock. + * cipher.c (cipher_context_alignment_t): New. Use it in this + module in place of PROPERLY_ALIGNED_TYPE. + (NEED_16BYTE_ALIGNED_CONTEXT): Define macro for ia32. + (struct gcry_cipher_handle): Add field HANDLE_OFFSET. + (gcry_cipher_open): Take care of increased alignment requirements. + (gcry_cipher_close): Ditto. + +2007-11-28 Werner Koch <wk@g10code.com> + + * sha256.c (asn224): Fixed wrong template. It happened due to a + bug in RFC4880. SHA-224 is not in the stable version of libgcrypt + so the consequences are limited to users of this devel version. + +2007-10-31 Werner Koch <wk@g10code.com> + + * ac.c (gcry_ac_data_new): Remove due to the visibility wrapper. + (gcry_ac_data_destroy, gcry_ac_data_copy, gcry_ac_data_length) + (gcry_ac_data_set, gcry_ac_data_get_name, gcry_ac_data_get_index) + (gcry_ac_data_to_sexp, gcry_ac_data_from_sexp) + (gcry_ac_data_clear, gcry_ac_io_init, gcry_ac_open) + (gcry_ac_close, gcry_ac_key_init, gcry_ac_key_pair_generate) + (gcry_ac_key_pair_extract, gcry_ac_key_destroy) + (gcry_ac_key_pair_destroy, gcry_ac_key_data_get) + (gcry_ac_key_test, gcry_ac_key_get_nbits, gcry_ac_key_get_grip) + (gcry_ac_data_encrypt, gcry_ac_data_decrypt, gcry_ac_data_sign) + (gcry_ac_data_verify, gcry_ac_data_encode, gcry_ac_data_decode) + (gcry_ac_mpi_to_os, gcry_ac_mpi_to_os_alloc, gcry_ac_os_to_mpi) + (gcry_ac_data_encrypt_scheme, gcry_ac_data_decrypt_scheme) + (gcry_ac_data_sign_scheme, gcry_ac_data_verify_scheme) + (gcry_ac_io_init_va): Ditto. + (gcry_ac_id_to_name, gcry_ac_name_to_id): Remove as these + deprecated functions are now implemented by visibility.c. + +2007-10-26 Werner Koch <wk@g10code.com> + + * rndw32.c: Disable debug flag. + +2007-10-25 Werner Koch <wk@g10code.com> + + * rndw32.c: Updated from current cryptlib snapshot and modified + for our use. Removed support from pre NT systems. + (slow_gatherer_windows95): Remove. + (_gcry_rndw32_gather_random): Require an NT platform. + (init_system_rng, read_system_rng, read_mbm_data): New. + (slow_gatherer_windowsNT): Rename to ... + (slow_gatherer): .. this. Read system RNG and MBM. + (registry_poll): New with code factored out from slow_gatherer. + +2007-08-23 Werner Koch <wk@g10code.com> + + * random.c (pool_filled_counter): New. + (add_randomness): Use it. + +2007-08-22 Werner Koch <wk@g10code.com> + + * rndw32.c, rndunix.c: Switched to LGPL. + +2007-05-30 Werner Koch <wk@g10code.com> + + * camellia.h, camellia.c: Replace by new LGPL version and adjusted + camellia.h. + +2007-05-09 Marcus Brinkmann <marcus@g10code.de> + + * ac.c (_gcry_ac_io_init_va, _gcry_ac_io_write, _gcry_ac_io_read): + Adjust users of gcry_ac_io_t because union is not anonymous + anymore. + +2007-05-02 Werner Koch <wk@g10code.com> + + * camellia-glue.c (camellia_setkey, camellia_encrypt) + (camellia_decrypt): Recalculated used stack size in called + functions. + * camellia.h: Redefine external symbols. + +2007-05-02 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am, cipher.c: Add Camellia. + + * camellia-glue.c: New. The necessary glue to interface libgcrypt + to the stock NTT Camellia distribution. + + * camellia.h, camellia.c: The stock NTT Camellia distribution + (GPL). + +2007-04-30 David Shaw <dshaw@jabberwocky.com> + + * cipher.c: Use #if instead of #ifdef as configure defines the + USE_cipher defines as 0 for disabled. + +2007-04-30 Werner Koch <wk@g10code.com> + + * rndegd.c (_gcry_rndegd_set_socket_name): New. + +2007-04-30 Marcus Brinkmann <marcus@g10code.de> + + * ecc.c (ec2os): Fix relocation of short numbers. + + * ecc.c (generate_key): Do not allocate D, which will be allocated + by GEN_K. Remove G. Fix test if g_x, g_y resp. q_x, q_y are + requested. + (_gcry_ecc_generate): Release unneeded members of SK. + * pubkey.c (sexp_to_key): Release NAME. + +2007-04-28 Marcus Brinkmann <marcus@g10code.de> + + * ac.c (gcry_ac_mpi): Remove member NAME_PROVIDED. + (ac_data_mpi_copy, _gcry_ac_data_set, _gcry_ac_data_get_name) + (_gcry_ac_data_get_index, ac_data_construct): Adjust handling of + NAME accordingly. + +2007-04-20 Werner Koch <wk@g10code.com> + + * ecc.c (domain_parms): Add standard brainpool curves. + +2007-04-18 Werner Koch <wk@g10code.com> + + * ecc.c (generate_curve): Implement alias mechanism. + + * pubkey.c (sexp_elements_extract_ecc): New. + (sexp_to_key): Add special case for ecc. + (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_genkey): Replace + name_terminated stuff by a call to _gcry_sexp_nth_string. + (gcry_pk_get_keygrip): Ditto. + +2007-04-16 Werner Koch <wk@g10code.com> + + * ecc.c (_gcry_ecc_generate): Renamed DUMMY to CURVE and use it. + +2007-04-13 Marcus Brinkmann <marcus@g10code.de> + + * ac.c (ac_data_construct): Cast const away to suppress compiler + warning. + + * ecc.c (ecc_generate): Avoid compiler warning for unused argument + DUMMY. + (ecc_verify): Avoid compiler warning for unused arguments CMP and + OPAQUEV. + +2007-04-06 Werner Koch <wk@g10code.com> + + * sha1.c (oid_spec_sha1): Add another oid from X9.62. + +2007-03-28 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Do not issue misc-key-info if it is + empty. + (gcry_pk_genkey): New parameter "curve". + + * ecc.c: Entirely rewritten with only a few traces of the old + code left. + (_gcry_ecc_generate): New. + (generate_key) New arg NAME. + (generate_curve): Ditto. Return actual number of NBITS. + +2007-03-26 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Increase size of SKEY array and add a + runtime bounds check. + +2007-03-23 Werner Koch <wk@g10code.com> + + * ecc.c (ecc_ctx_init, ecc_ctx_free, ecc_mod, ecc_mulm): New. + (duplicate_point, sum_points, escalar_mult): Don't use a + copy of base->p. Replaced all mpi_mulm by ecc_mulm so that we can + experiment with different algorithms. + (generate_key, check_secret_key, sign, verify): Initialize a + computation context for use by ecc_mulm. + +2007-03-22 Werner Koch <wk@g10code.com> + + * pubkey.c (pubkey_table): Initialize ECC. + * Makefile.am (EXTRA_libcipher_la_SOURCES): Add ecc.c. + * ecc.c: New. Heavily reformatted and changed for use in libgcrypt. + (point_init): New. + (escalar_mult): Make arg R the first arg to be similar to the mpi + functions. + (duplicate_point): Ditto + (sum_points): Ditto + (sign, verify): Remove unneeded copy operations. + (sum_points): Removed memory leaks and optimized some compares. + (verify): Simplified input check. + +2007-03-14 Werner Koch <wk@g10code.com> + + * random.c (MASK_LEVEL): Removed macro as it was used only at one + place. Open coded it there. + (gcry_randomize, _gcry_update_random_seed_file) + (_gcry_fast_random_poll): Factor lock code out to .. + (lock_pool, unlock_pool): .. new. + (initialize): Look the pool while allocating. + (read_random_source, do_fast_random_poll): Moved intialization to ... + (initialize): .. here. + (_gcry_enable_quick_random_gen): No more need for initialization. + (is_initialized): Moved this global flag to .. + (initialize): .. here and changed all users to unconditionally call + initialize. + (add_randomness): Remove initalization here. It simply can't + happen. + + * random.c (enum random_origins): Moved to .. + * rand-internal.h: .. here. + * rndunix.c (_gcry_rndunix_gather_random): Use enum in prototype + for ORIGIN and renamed REQUESTOR to ORIGIN. + * rndegd.c (_gcry_rndegd_gather_random): Ditto. + * rndlinux.c (_gcry_rndlinux_gather_random): Ditto. + * rndw32.c (_gcry_rndw32_gather_random): Ditto. + (_gcry_rndw32_gather_random_fast): Ditto. + +2007-03-13 Werner Koch <wk@g10code.com> + + * random.c (enum random_origins): New. + (add_randomness): Renamed arg SOURCE to ORIGIN. + (read_random_source): Renamed arg REQUESTOR to ORIGIN. + (getfnc_gather_random): Removed static variable because this + function is only called one and thus we don't need this + optimization. + (_gcry_quick_random_gen): Removed and replaced by.. + (_gcry_enable_quick_random_gen): .. this. It is onlyu used to + enable it and it does not make sense to disable it later. Changed + the only one caller too. + (get_random_bytes): Removed. + (gcry_random_bytes, gcry_random_bytes_secure): Implement in terms + of gcry_randomize. + * random-daemon.c (_gcry_daemon_get_random_bytes): Removed. + +2007-02-23 Werner Koch <wk@g10code.com> + + * elgamal.c (generate): Removed unused variable TEMP. + (test_keys): New arg NODIE. + (generate_using_x, _gcry_elg_generate_using_x): New. + * pubkey.c (pubkey_generate): New arg XVALUE and direct call to + the new elgamal generate fucntion. + (gcry_pk_genkey): Parse the new "xvalue" tag. + +2007-02-22 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_data_to_mpi): Handle dynamically allocated + algorithms. Suggested by Neil Dunbar. Fixes bug#596. + + * rndw32.c (_gcry_rndw32_gather_random_fast): Make it return void. + + * cipher.c (gcry_cipher_algo_name): Simplified. + + * random.c: Use the daemon only if compiled with USE_RANDOM_DAEMON. + + * Makefile.am (libcipher_la_SOURCES): Build random-daemon support + only if requested. + +2007-02-21 Werner Koch <wk@g10code.com> + + * random.c (rndpool, keypool): Make unsigned. + (mix_pool): Change char* variables to unsigned char*. + (gcry_randomize): Make arg BUFFER a void*. + (gcry_create_nonce): Ditto. + + * rmd160.c (gcry_rmd160_mixblock): Make BUFFER a void*. + (_gcry_rmd160_hash_buffer): Make OUTBUF and BUFFER void*. + * sha1.c (_gcry_sha1_hash_buffer): Ditto. + + * cipher.c (gcry_cipher_encrypt, cry_cipher_decrypt): Change + buffer args to void*. + (gcry_cipher_register): Make ALGORITHM_ID a int *. + + * md.c (md_start_debug): Make SUFFIX a const char*. Use snprintf. + (gcry_md_debug): New. + (gcry_md_ctl): Changed arg BUFFER from unsigned char*. + + * md.c (md_write): Make INBUF a const void*. + (gcry_md_write): Remove needless cast. + * crc.c (crc32_write): Make INBUF a const void* + (update_crc32, crc24rfc2440_write): Ditto. + * sha512.c (sha512_write, transform): Ditto. + * sha256.c (sha256_write, transform): Ditto. + * rmd160.c (rmd160_write, transform): Ditto. + * md5.c (md5_write, transform): Ditto. + * md4.c (md4_write, transform): Ditto. + * sha1.c (sha1_write, transform): Ditto. + + * tiger.c (tiger_write, transform): Ditto. + * whirlpool.c (whirlpool_write, whirlpool_add, transform): Ditto. + + * elgamal.c (elg_names): Change to a const*. + * dsa.c (dsa_names): Ditto. + * rsa.c (rsa_names): Ditto. + * pubkey.c (gcry_pk_lookup_func_name): Make ALIASES a const. + +2007-02-20 Werner Koch <wk@g10code.com> + + * rndlinux.c (open_device): Remove unsused arg MINOR. + +2007-01-30 Werner Koch <wk@g10code.com> + + * sha256.c (oid_spec_sha256): Add alias from pkcs#1. + * sha512.c (oid_spec_sha512): Ditto. + (oid_spec_sha384): Ditto. + +2006-12-18 Werner Koch <wk@g10code.com> + + * rndlinux.c (set_cloexec_flag): New. + (open_device): Set close-on-exit flags. Suggested by Max + Kellermann. Fixes Debian#403613. + + * Makefile.am (AM_CPPFLAGS, AM_CFLAGS): Splitted and merged + Moritz' changes. + (INCLUDES): Removed. + +2006-11-30 Werner Koch <wk@g10code.com> + + * serpent.c (byte_swap_32): Remove trailing semicolon. + +2006-11-15 Werner Koch <wk@g10code.com> + + * Makefile.am (INCLUDES): Include ../src/ + +2006-11-03 Werner Koch <wk@g10code.com> + + * random.c [HAVE_GETTIMEOFDAY]: Included sys/time.h and not + sys/times.h. Reported by Rafaël Carré. + +2006-11-05 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (AM_CFLAGS): Added -I$(top_builddir)/src so that the + new gcrypt.h is used, not the one installed in the system. + +2006-10-25 Werner Koch <wk@g10code.com> + + * primegen.c (prime_generate_internal): Tweaked use of secure + memory and entropy use. Safe unused primes from the pool. Allocate + at least a pool of 30. + (save_pool_prime, get_pool_prime): New. + +2006-10-23 Werner Koch <wk@g10code.com> + + * ac.c (_gcry_ac_data_from_sexp): Reset sexp_tmp for failsafe + means. Release sexp_cur if needed. Reported by Dirk Stoecker. + + * pubkey.c (pubkeys_registered_lock): Intialized it. It is not + realy needed because this is a mere initialization to 0 anyway. + Noted by Victor Stinner. + +2006-10-17 Werner Koch <wk@g10code.com> + + * dsa.c (_gcry_dsa_generate2): New. + (generate): New arg QBITS. Add sanity checks for reasonable qbits + and nbits. + * pubkey.c (gcry_pk_genkey): Parse an qbits element. + (pubkey_generate): New arg QBITS. Pass it to the DSA generation. + +2006-10-05 Werner Koch <wk@g10code.com> + + * md.c (gcry_md_algo_info) <get_asnoid>: Check that the algo is + available. + +2006-10-04 David Shaw <dshaw@jabberwocky.com> (wk) + + * tiger.c (round): Rename to tiger_round as gcc 4 has a built-in + round function that this conflicts with. + +2006-09-11 Werner Koch <wk@g10code.com> + + * rndw32.c (slow_gatherer_windowsNT): While adding data use the + size of the diskPerformance and not its address. Has been fixed in + GnuPG more than a year ago. Noted by Lee Fisher. + +2006-08-30 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_data_to_mpi): Need to allow "ripemd160" here as + this is the canonical name. + +2006-08-29 Hye-Shik Chang <perky@FreeBSD.org> (wk) + + * seed.c: New. + +2006-08-03 Werner Koch <wk@g10code.com> + + * random-daemon.c (_gcry_daemon_initialize_basics): Don't + initialize the socket. Remove arg SOCKETNAME. + (connect_to_socket): Make sure that daemon is set to -1 on error. + (call_daemon): Initialize the socket on the first call. + (_gcry_daemon_randomize, _gcry_daemon_get_random_bytes) + (_gcry_daemon_create_nonce): New arg SOCKETNAME. + * random.c (initialize): Call new daemon initializator. + (get_random_bytes, gcry_randomize, gcry_create_nonce): Pass socket + name to daemon call and reset allow_daemon on failure. + +2006-07-26 Werner Koch <wk@g10code.com> + + * rmd160.c (_gcry_rmd160_mixblock): Add cast to transform call. + + * blowfish.c (selftest): Cast string to usnigned char*. + + * primegen.c (prime_generate_internal): Cast unsigned/char* + mismatch in calling m_out_of_n. + (is_prime): Changed COUNT to unsigned int *. + + * ac.c (_gcry_ac_data_copy): Initialize DATA_MPIS. + + * random.c (gcry_create_nonce): Update the pid after a fork. + Reported by Uoti Urpala. + +2006-07-04 Marcus Brinkmann <marcus@g10code.de> + + * sha512.c: Fix typo in copyright notice. + +2006-06-21 Werner Koch <wk@g10code.com> + + * rsa.c (_gcry_rsa_generate): Replace xcalloc by calloc. + * pubkey.c (gcry_pk_encrypt, gcry_pk_sign): Ditto. + (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_encrypt) + (gcry_pk_sign, gcry_pk_genkey, gcry_pk_get_keygrip): Ditto. + * md.c (md_copy): Ditto. + +2006-04-22 Moritz Schulte <moritz@g10code.com> + + * random-daemon.c (_gcry_daemon_initialize_basics): New argument: + SOCKETNAME. Passing on to connect_to_socket() if non-NULL. + (connect_to_socket, writen, readn, call_daemon): New functions. + (_gcry_daemon_randomize, _gcry_daemon_get_random_bytes) + (_gcry_daemon_create_nonce): Call call_daemon(). + (RANDOM_DAEMON_SOCKET): New symbol. + (daemon_socket): New static variable. + + * random.h (_gcry_daemon_initialize_basics): New parameter: + SOCKETNAME. + (_gcry_set_random_daemon_socket): New declaration. + + * random.c (initialize_basics): Pass DAEMON_SOCKET_NAME to + _gcry_daemon_initialize_basics. + (_gcry_set_random_daemon_socket): New function, setting + DAEMON_SOCKET_NAME. + +2006-04-01 Moritz Schulte <moritz@g10code.com> + + * ac.c (eme_pkcs_v1_5_encode): Use KEY_SIZE directly, no need to + call gcry_ac_key_get_nbits. + (eme_pkcs_v1_5_decode): Likewise. + (ac_es_dencode_prepare_pkcs_v1_5): Fill options_em structure with + key_size. + (_gcry_ac_data_dump, gcry_ac_data_dump): New functions. + (_gcry_ac_data_to_sexp, _gcry_ac_data_from_sexp): More or less + rewritten; changed S-Expression format so that it matches the one + used in pubkey.c. + +2006-03-15 Werner Koch <wk@g10code.com> + + * random-daemon.c: New. + * random.c (_gcry_use_random_daemon): New. + (get_random_bytes, gcry_randomize, gcry_create_nonce): Try + diverting to the daemon functions. + +2006-03-14 Werner Koch <wk@g10code.com> + + * random.c (lock_seed_file): New. + (read_seed_file, _gcry_update_random_seed_file): Use it. + + * random.c (gcry_create_nonce): Detect a fork and re-seed. + (read_pool): Fixed the fork detection; it used to work only for + multi-threaded processes. + +2006-03-12 Brad Hards <bradh@frogmouth.net> (wk) + + * md.c (md_open): Use new variable macpads_Bsize instead of + hardwiring the block size. Changed at all places. + +2006-03-10 Brad Hards <bradh@frogmouth.net> (wk, patch 2005-04-22) + + * md.c, sha256.c: Add support for SHA-224. + (sha224_init): New. + +2006-01-18 Brad Hards <bradh@frogmouth.net> (wk 2006-03-07) + + * cipher.c (cipher_encrypt, cipher_decrypt, do_ofb_encrypt) + (do_ofb_decrypt, gcry_cipher_open): Implement Output Feedback Mode. + +2005-11-02 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_algo_name): Return "?" instead of NULL for + unknown algorithm IDs. + * cipher.c (cipher_algo_to_string): Likewise. + +2005-11-01 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_algo_info): Don't forget to break after switch + case. + +2005-09-19 Werner Koch <wk@g10code.com> + + * dsa.c (generate): Add preliminary support for 2 and 4 keys. + Return an error code if the key size is not supported. + (_gcry_dsa_generate): Return an error. + +2005-08-22 Werner Koch <wk@g10code.com> + + * primegen.c (check_prime): New arg RM_ROUNDS. + (prime_generate_internal): Call it here with 5 rounds as used + before. + (gcry_prime_check): But here with 64 rounds. + (is_prime): Make sure never to use less than 5 rounds. + +2005-04-16 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_init): New function. + +2005-04-12 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_io_write, _gcry_ac_io_read): Initialize err to + make the compiler happy. + Always use errno, now that gcry_malloc() is guaranteed to set + errno on failure. + (_gcry_ac_data_to_sexp): Don't forget to goto out after error in + loop. + (_gcry_ac_data_to_sexp): Remove unused variable: mpi_list; + (_gcry_ac_data_to_sexp): Always deallocate sexp_buffer. + (_gcry_ac_data_from_sexp): Don't forget to initialize data_set_new. + (_gcry_ac_data_from_sexp): Handle special case, which is + necessary, since gcry_sexp_nth() does not distinguish between + "element does not exist" and "element is the empty list". + (_gcry_ac_io_init_va): Use assert to make sure that mode and type + are correct. + Use gcry_error_t types where gcry_err_code_t types have been used + before. + +2005-04-11 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_data_sign_scheme): Don't forget to initialize + buffer. + + * whirlpool.c: New file. + * md.c (digest_table): Add whirlpool. + * Makefile.am (EXTRA_libcipher_la_SOURCES): Added: whirlpool.c. + +2005-03-30 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_data_from_sexp): Use length of SEXP_CUR, not + length of SEXP; do not forget to set SEXP_TMP to NULL after it has + been released. + + (struct gcry_ac_mpi): New member: name_provided. + (_gcry_ac_data_set): Rename variable `name_final' to `name_cp'; + remove const qualifier; change code to not cast away const + qualifiers; use name_provided member as well. + (_gcry_ac_data_set, _gcry_ac_data_get_name): Use name_provided + member of named mpi structure. + + (gcry_ac_name_to_id): Do not forget to initialize err. + (_gcry_ac_data_get_index): Do not forget to initialize mpi_return; + use gcry_free() instead of free(); remove unnecessary cast; rename + mpi_return and name_return to mpi_cp and name_cp; adjust code. + (ac_data_mpi_copy): Do not cast away const qualifier. + (ac_data_values_destroy): Likewise. + (ac_data_construct): Likewise. + + (ac_data_mpi_copy): Initialize flags to GCRY_AC_FLAG_DEALLOC. + (ac_data_extract): Use GCRY_AC_FLAG_DEALLOC instead of + GCRY_AC_FLAG_COPY. + + (_gcry_ac_io_init_va, _gcry_ac_io_init, gcry_ac_io_init) + (gcry_ac_io_init_va, _gcry_ac_io_write, _gcry_ac_io_read) + (_gcry_ac_io_read_all, _gcry_ac_io_process): New functions. + (gry_ac_em_dencode_t): Use gcry_ac_io_t in prototype instead of + memroy strings directly; adjust encode/decode functions to use io + objects. + (emsa_pkcs_v1_5_encode_data_cb): New function ... + (emsa_pkcs_v1_5_encode): ... use it here. + (ac_data_dencode): Use io objects. + (_gcry_ac_data_encode, _gcry_ac_data_decode, gcry_ac_data_encode) + (gcry_ac_data_decode): Likewise. + (_gcry_ac_data_encrypt_scheme, gcry_ac_data_encrypt_scheme) + (_gcry_ac_data_decrypt_scheme, gcry_ac_data_decrypt_scheme) + (_gcry_ac_data_sign_scheme, gcry_ac_data_sign_scheme) + (_gcry_ac_data_verify_scheme, gcry_ac_data_verify_scheme): + Likewise. + +2005-03-23 Werner Koch <wk@g10code.com> + + * rndw32.c (_gcry_rndw32_gather_random_fast): While adding data + use the size of the object and not the one of its address. Bug + reported by Sascha Kiefer. + +2005-03-19 Moritz Schulte <moritz@g10code.com> + + * cipher.c (do_cbc_encrypt): Be careful to not overwrite data, + which is to be used later on. This happend, in case CTS is + enabled and OUTBUF is equal to INBUF. + +2005-02-25 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_get_keygrip): Allow for shadowed-private-key. + +2005-02-13 Moritz Schulte <moritz@g10code.com> + + * serpent.c: Updated from 1.2 branch: + + s/u32_t/u32/ and s/byte_t/byte/. Too match what we have always + used and are using in all other files too + (serpent_test): Moved prototype out of a fucntion. + +2005-02-07 Moritz Schulte <moritz@g10code.com> + + * ac.c: Major parts rewritten. + * pubkey.c (_gcry_pk_get_elements): New function. + +2004-12-09 Werner Koch <wk@g10code.com> + + * serpent.c (serpent_setkey): Moved prototype of serpent_test to + outer scope. + +2004-09-11 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (pubkey_table): Added an alias entry for GCRY_PK_ELG_E. + +2004-08-23 Moritz Schulte <moritz@g10code.com> + + * ac.c: Do not include <assert.h>. + * rndegd.c: Likewise. + * sha1.c: Likewise. + * rndunix.c: Likewise. + * rndlinux.c: Likewise. + * rmd160.c: Likewise. + * md5.c: Likewise. + * md4.c: Likewise. + * cipher.c: Likewise. + * crc.c: Likewise. + * blowfish.c: Likewise. + + * pubkey.c (dummy_generate, dummy_check_secret_key) + (dummy_encrypt, dummy_decrypt, dummy_sign, dummy_verify): Return + err code GPG_ERR_NOT_IMPLEMENTED instead of aborting through + log_bug(). + (dummy_get_nbits): Return 0 instead of aborting though log_bug(). + +2004-08-19 Werner Koch <wk@g10code.de> + + * pubkey.c (sexp_data_to_mpi): Changed the zero random byte + substituting code to actually do clever things. Thanks to + Matthias Urlichs for noting the implementation problem. + +2004-08-09 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_sign): Fixed memory leak; fix provided by + Modestas Vainius. + +2004-07-16 Werner Koch <wk@gnupg.org> + + * rijndael.c (do_encrypt): Fix alignment problem. Bugs found by + Matthias Urlichs. + (do_decrypt): Ditto. + (keySched, keySched2): Use 2 macros along with unions in the key + schedule context. + +2004-07-14 Moritz Schulte <moritz@g10code.com> + + * rsa.c (_gcry_rsa_decrypt): Don't forget to free "a". Thanks to + Nikos Mavroyanopoulos. + +2004-05-09 Werner Koch <wk@gnupg.org> + + * random.c (read_pool): Mix the PID in to better protect after a + fork. + +2004-07-04 Moritz Schulte <moritz@g10code.com> + + * serpent.c: Use "u32_t" instead of "unsigned long", do not + declare S-Box variables as "register". Fixes failure on + OpenBSD/sparc64, reported by Nikolay Sturm. + +2004-05-07 Werner Koch <wk@gnupg.org> + + * random.c (initialize): Factored out some code to .. + (initialize_basics): .. new function. + (_gcry_random_initialize): Just call initialize_basics unless the + new arg FULL is set to TRUE. + (_gcry_fast_random_poll): Don't do anything unless the random + system has been really initialized. + +2004-05-07 Moritz Schulte <moritz@g10code.de> + + * ac.c (gcry_ac_open): Do not dereference NULL pointer. Reported + by Umberto Salsi. + +2004-02-20 Werner Koch <wk@gnupg.org> + + * primegen.c (check_prime): New args CB_FUNC and CB_ARG; call them + at different stages. Pass these arguments through all callers. + +2004-02-06 Werner Koch <wk@gnupg.org> + + * des.c: Add a new OID as used by pkcs#12. + + * rfc2268.c: New. Taken from libgcrypt. + * cipher.c: Setup the rfc2268 algorithm. + +2004-01-25 Moritz Schulte <mo@g10code.com> + + * primegen.c (prime_generate_internal): Do not forget to free + `q_factor'; fixed by Brieuc Jeunhomme. + (prime_generate_internal): Do not forget to free `prime'. + +2004-01-14 Moritz Schulte <mo@g10code.com> + + * ac.c (gcry_ac_data_set): New argument: flags; slightly + rewritten. + (gcry_ac_data_get_name, gcry_ac_data_get_index): Likewise. + (gcry_ac_key_pair_generate): New argument: misc_data; modified + order of arguments. + (gcry_ac_key_test): New argument: handle. + (gcry_ac_key_get_nbits, gcry_ac_key_get_grip): Likewise. + Use GCRY_AC_FLAG_NO_BLINDING instead of + GCRY_AC_DATA_FLAG_NO_BLINDING. + (gcry_ac_mpi): New member: flags. + (gcry_ac_data_search, gcry_ac_data_add): Removed functions. + +2003-12-22 Werner Koch <wk@gnupg.org> + + * primegen.c (is_prime): Release A2. + +2003-12-19 Werner Koch <wk@gnupg.org> + + * md.c: Moved a couple of functions down below the data structure + definitions. + (struct gcry_md_context): New field ACTUAL_HANDLE_SIZE. + (md_open): Set it here. + (strcut gcry_md_list): New field ACTUAL_STRUCT_SIZE. + (md_enable): Set it here. + (md_close): Wipe the context memory. + secure memory. + * cipher.c (struct gcry_cipher_handle): New field ACTUAL_HANDLE_SIZE. + (gcry_cipher_open): Set it here. + (gcry_cipher_close): Use it to always wipe out the handle data. + + * ac.c (gcry_ac_open): Make sure HANDLE gets initialized even when + the function is not successful. + (gcry_ac_close): Allow a NULL handle. + (gcry_ac_key_destroy, gcry_ac_key_pair_destroy): Ditto. + (gcry_ac_key_get_grip): Return INV_OBJ on error. + + * primegen.c (prime_generate_internal): Fixed error code for + failed malloc. Replaced the !err if chain by gotos. + (gcry_prime_group_generator): Remove the extra sanity check. + + * md.c: Minor code and comment cleanups. + +2003-12-16 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): Doc fix. Thanks to Newton Hammet. + +2003-12-11 Werner Koch <wk@gnupg.org> + + * rndunix.c (slow_poll): Don't use #warning but #error. + + * rndegd.c: Changed indentation. + (my_make_filename): Removd the var_arg cruft becuase we + don't need it here. Changed caller. + + * rndlinux.c: Changed indentation. + (open_device): Remove the superfluous stat call and clarify + comment. + + * rsa.c: Changed indentation. + (secret): Use the standard algorithm if p, q and u are not + available. + (rsa_blind, rsa_unblind): Renamed from _gcry_rsa_blind, + _gcry_rsa_unblind and moved more to the top. + + * md4.c: Changed indentation. Removed unnecessary casts. + * md5.c, rmd160.c, sha1.c, tiger.c: Ditto. + * rijndael.c, twofish.c: Ditto. + * serpent.c: Removed unnecessary casts. + * sha256.c, sha512.c: Ditto. + +2003-12-09 Werner Koch <wk@gnupg.org> + + * dsa.c: Unified indentation style. + * elgamal.c: Ditto. + * des.c (des_key_schedule): Code beautifications. + * blowfish.c: Changed indentation style. + * cast5.c (do_cast_setkey): Ditto. + + * pubkey.c (gcry_pk_encrypt): Replaced the chain of if(!err) tests + by straightforward gotos. Other cleanups. + (gcry_pk_decrypt): Ditto. + (gcry_pk_sign): Ditto. + (gcry_pk_verify): Ditto. + (gcry_pk_genkey): Ditto. Use strtoul instead of strtol. + (gcry_pk_ctl): Use GPG_ERR_INV_ARG to indicate bad arguments. + +2003-12-07 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_register_default): Undef the helper macro. + (gcry_pk_map_name): Allow NULL for string. + (sexp_to_key): Use memcpy and not strncpy. Use gcry_free and not + free. + (sexp_to_sig): Ditto. + (sexp_to_enc): Ditto. Replaced the chain of if(!err) tests by + straightforward gotos. + +2003-12-05 Werner Koch <wk@gnupg.org> + + * cipher.c: Documentation cleanups. + (gcry_cipher_mode_from_oid): Allow NULL for STRING. + +2003-12-03 Werner Koch <wk@gnupg.org> + + * elgamal.c (sign, do_encrypt, gen_k): Make sure that a small K is + only used for encryption. + +2003-11-18 Werner Koch <wk@gnupg.org> + + * random.h (rndw32_set_dll_name): Removed unused prototype. + + * Makefile.am (EXTRA_DIST): Added Manifest. + +2003-11-11 Werner Koch <wk@gnupg.org> + + * Manifest: New. + +2003-11-04 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Use shortcut for SHA1 + * sha1.c (_gcry_sha1_hash_buffer): New. + + * random.c: Reformatted most functions. + (mix_pool): Moved the failsafe_digest from global + scope to here. + (do_fast_random_poll): Use the generic fucntions even if a fast + gathering function has been used. + (read_pool): Detect a fork and retry. + (gcry_randomize, get_random_bytes): Don't distinguish anymore + between weak and strong random. + (gcry_create_nonce): New. + +2003-10-31 Werner Koch <wk@gnupg.org> + + * rndw32.c (slow_gatherer_windowsNT): Use a plain buffer for the + disk performance values and not the W32 API structure. + + * dsa.c (verify): s/exp/ex/ due to shadowing of a builtin. + * elgamal.c (verify): Ditto. + + * ac.c (gcry_ac_data_get_index): s/index/idx/ + (gcry_ac_data_copy_internal): Remove the cast in _gcry_malloc. + (gcry_ac_data_add): Must use gcry_realloc instead of realloc. + * pubkey.c (sexp_elements_extract): s/index/idx/ as tribute to the + forehackers. + (gcry_pk_encrypt): Removed shadowed definition of I. Reordered + arguments to malloc for clarity. + (gcry_pk_sign, gcry_pk_genkey): Ditto. + * primegen.c (prime_generate_internal): s/random/randomlevel/. + +2003-10-27 Moritz Schulte <mo@g10code.com> + + * pubkey.c (gcry_pk_encrypt): Don't forget to deallocate pkey. + +2003-10-27 Werner Koch <wk@gnupg.org> + + * random.c (gcry_random_add_bytes): Return if buflen is zero to + avoid gcc warning about unsed parameter. + (MASK_LEVEL): Simplified; does now work for signed and unsigned + w/o warnings. + + * md.c (md_start_debug): Removed the const from SUFFIX, because + this function is called from the control fucntion which does not + require const. + + Prefixed all (pubkey,digest,cipher}_spec_* globale variables with + _gcry_. + + * ac.c (ac_key_identifiers): Made static. + + * random.c (getfnc_gather_random,getfnc_fast_random_poll): Move + prototypes to .. + * rand-internal.h: .. here + * random.c (getfnc_gather_random): Include rndw32 gatherer. + * rndunix.c, rndw32.c, rndegd.c: Include them here. + * rndlinux.c (_gcry_rndlinux_gather_random): Prepend the _gcry_ + prefix. Changed all callers. + * rndegd.c (_gcry_rndegd_gather_random): Likewise. + (_gcry_rndegd_connect_socket): Likewise. + * rndunix.c (_gcry_rndunix_gather_random): Likewise. + (waitpid): Made static. + * rndw32.c: Removed the old and unused winseed.dll cruft. + (_gcry_rndw32_gather_random_fast): Renamed from + gather_random_fast. + (_gcry_rndw32_gather_random): Renamed from gather_random. Note, + that the changes 2003-04-08 somehow got lost. + + * sha512.c (sha512_init, sha384_init): Made static. + + * cipher.c (do_ctr_decrypt): Removed "return" from this void + function. + +2003-10-24 Moritz Schulte <mo@g10code.com> + + * serpent.c: Fix an issue on big-endian systems. + + * rndw32.c: Removed IS_MODULE -cruft. + * rndlinux.c (rndlinux_gather_random): Likewise. + +2003-10-10 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): Bail out if NBITS is less than 16. + (prime_generate_internal): Initialize prime variable to suppress + compiler warning. Check pbits, initialize qbits when passed as + zero. + + * primegen.c (prime_generate_internal): New arg + ALL_FACTORS. Changed all callers. + (gcry_prime_generate): Make the factors arg optional. Request + all_factors. Make sure PRIME is set to NULL even on error. + (gcry_prime_group_generator): New. + (gcry_prime_release_factors): New. + +2003-10-06 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): Assert that NBITS is never zero, it + would cause a segv. + +2003-09-28 Moritz Schulte <mo@g10code.com> + + * ac.c: Include "cipher.h". + +2003-09-27 Moritz Schulte <mo@g10code.com> + + * rndegd.c (do_read): Return nread instead of nbytes; thanks to + Michael Caerwyn. + +2003-09-04 Werner Koch <wk@gnupg.org> + + * pubkey.c (_gcry_pk_aliased_algo_name): New. + * ac.c (gcry_ac_open): Use it here. + + * Makefile.am (EXTRA_libcipher_la_SOURCES): Add serpent.c + +2003-09-02 Moritz Schulte <mo@g10code.com> + + * primegen.c (gcry_prime_check, gcry_prime_generate): New + functions. + (prime_generate_internal): New function, based on + _gcry_generate_elg_prime. + (_gcry_generate_elg_prime): Rewritten as a wrapper for + prime_generate_internal. + +2003-08-28 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_encrypt): Don't include the flags list in the + return value. This does not make sense and breaks any programs + parsing the output strictly (e.g. current gpgsm). + (gcry_pk_encrypt): If aliases for the algorithm name exists, take + the first one instead of the regular name to adhere to SPKI + conventions. + (gcry_pk_genkey): Ditto. + (gcry_pk_sign): Ditto. Removed unused KEY_ALGO_NAME. + +2003-08-19 Moritz Schulte <mo@g10code.com> + + * cipher.c: Add support for Serpent + * serpent.c: New file. + +2003-08-10 Moritz Schulte <moritz@g10code.com> + + * rsa.c (_gcry_rsa_blind, _gcry_rsa_unblind): Declare static. + +2003-08-09 Timo Schulz <twoaday@freakmail.de> + + * random.c (getfnc_gather_random): Don't check NAME_OF_DEV_RANDOM + two times, but also the NAME_OF_DEV_URANDOM device. + +2003-08-08 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_to_enc): Fixed extraction of S-Expression: do not + fail if no `flags' sub S-Expression is found. + +2003-07-27 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_lookup_func_oid): Allow for empty OID lists. + +2003-07-23 Moritz Schulte <moritz@g10code.com> + + * ac.c (gcry_ac_data_construct): New argument: include_flags, only + include `flags' S-expression, if include_flags is true. Adjust + callers. Thanks for triggering a bug caused by `flags' + sub-S-expression where they are not expected to Ralf Schneider. + +2003-07-21 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_lookup_func_name): Use new member name + `aliases' instead of `sexp_names'. + + * ac.c (gcry_ac_key_data_get): New function. + + * cipher.c (gcry_cipher_lookup_func_name): Fix return value. + +2003-07-20 Moritz Schulte <moritz@g10code.com> + + * blowfish.c: Adjusted for new gcry_cipher_spec_t structure. + * cast5.c: Likewise. + * twofish.c: Likewise. + * arcfour.c: Likewise. + * rijndael.c (rijndael_oids, rijndael192_oids, rijndael256_oids): + New variables, adjust for new gcry_cipher_spec_t structure. + * des.c (oids_tripledes): New variable, adjust for new + gcry_cipher_spec_t structure. + + * md.c (oid_table): Removed. + + * tiger.c (oid_spec_tiger): New variable. + (digest_spec_tiger): Adjusted for new gry_md_spec_t structure. + + * sha512.c (oid_spec_sha512): New variable. + (digest_spec_sha512): Adjusted for new gry_md_spec_t structure. + + * sha512.c (oid_spec_sha384): New variable. + (digest_spec_sha384): Adjusted for new gry_md_spec_t structure. + + * sha256.c (oid_spec_sha256): New variable. + (digest_spec_sha256): Adjusted for new gry_md_spec_t structure. + + * sha1.c (oid_spec_sha1): New variable. + (digest_spec_sha1): Adjusted for new gry_md_spec_t structure. + + * rmd160.c (oid_spec_rmd160): New variable. + (digest_spec_rnd160): Adjusted for new gry_md_spec_t structure. + + * md5.c (oid_spec_md5): New variable. + (digest_spec_md5): Adjusted for new gry_md_spec_t structure. + + * md4.c (oid_spec_md4): New variable. + (digest_spec_md4): Adjusted for new gry_md_spec_t structure. + + * crc.c (digest_spec_crc32, digest_spec_crc32_rfc1510, + digest_spec_crc32_rfc2440): Adjusted for new gry_md_spec_t + structure. + +2003-07-19 Moritz Schulte <moritz@g10code.com> + + * md.c (gcry_md_lookup_func_oid): New function. + (search_oid): New function, copied from cipher.c. + (gcry_md_map_name): Adjust for new search_oid_interface. + + * cipher.c (oid_table): Removed table. + (gcry_cipher_lookup_func_oid): New function. + (search_oid): Rewritten to use the module functions. + (gcry_cipher_map_name): Adjust for new search_oid interface. + (gcry_cipher_mode_from_oid): Likewise. + +2003-07-18 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Convert ERR to gpg_error_t in + gpg_strerror. + +2003-07-14 Moritz Schulte <moritz@g10code.com> + + * cipher.c (gcry_cipher_lookup_func_name): Also check the cipher + name aliases, not just the primary name. + (gcry_cipher_map_name): Remove kludge for aliasing Rijndael to + AES. + + * arcfour.c, blowfish.c, cast5.c, des.c, twofish.c: Adjust cipher + specification structures. + + * rijndael.c (rijndael_names, rijndael192_names, + rijndael256_names): New variables, use them in the cipher + specifications. + + * rmd160test.c: Removed file. + + * ac.c, arcfour.c, blowfish.c, cast5.c, cipher.c, des.c, dsa.c, + elgamal.c, md.c, pubkey.c, random.c, rijndael.c, rsa.c, twofish.c: + Used gcry_err* wrappers for libgpg symbols. + + * primegen.c (gen_prime): Correct the order arguments to + extra_check. + +2003-07-12 Moritz Schulte <moritz@g10code.com> + + * ac.c: Replaced all public occurences of gpg_error_t with + gcry_error_t. + * cipher.c: Likewise. + * md.c: Likewise. + * pubkey.c: Likewise. + * random.c: Likewise. + + * cipher.c: Added support for TWOFISH128. + +2003-07-08 Moritz Schulte <moritz@g10code.com> + + * ac.c (gcry_ac_data_copy_internal): New function, based on + gcry_ac_data_copy. + (gcry_ac_data_copy): Made public, use gcry_ac_data_copy_internal. + (gcry_ac_key_init): Use gcry_ac_data_copy_internal. + +2003-07-07 Moritz Schulte <moritz@g10code.com> + + * ac.c (gcry_ac_data_set): Only release old MPI value if it is + different from the new value. Bug reported by Simon Josefsson + <jas@extundo.com>. + + * pubkey.c (gcry_pk_list): New function. + * md.c (gcry_md_list): New function. + + * ac.c (gcry_ac_key_pair_generate): Fix calculation of format + string size. + +2003-07-05 Moritz Schulte <moritz@g10code.com> + + * md.c: Named struct of digest_table `digest_table_entry'. + (digest_table_entry): New member: algorithm; filled in. + (digest_table_entry): Removed unused member: flags. + (gcry_md_register): New argument: algorithm_id, filled in. + (gcry_md_register_default): Used algorithm ID from module + structure. + (gcry_md_map_name): Likewise. + (md_enable): Likewise. + (md_read): Likewise. + (gcry_md_info): Likewise. + + * pubkey.c: Named truct for pubkey_table `pubkey_table_entry'. + (pubkey_table_entry): New member: algorithm; filled in. + (gcry_pk_register_default): Used algorithm ID from pubkey_table. + (gcry_pk_register): New argument: algorithm_id, filled in. + (gcry_pk_map_name): Used algorithm ID from module structure. + (gcry_pk_decrypt): Likewise. + (gcry_pk_encrypt): Likewise. + (gcry_pk_verify): Likewise. + (gcry_pk_sign): Likewise. + (gcry_pk_testkey): Likewise. + (gcry_pk_genkey): Likewise. + (gcry_pk_get_nbits): Likewise. + (sexp_to_key): Removed unused variable: algo. + (sexp_to_sig): Likewise. + + * cipher.c: Named struct for cipher_table `cipher_table_entry'. + (cipher_table_entry): New member: algorithm; filled in. + (gcry_cipher_register_default): Used algorithm ID from + cipher_table. + (gcry_cipher_register): New argument: algorithm_id, filled in. + (gcry_cipher_map_name): Used algorithm ID from module structure. + + * arcfour.c (cipher_spec_arcfour): Removed algorithm ID. + * blowfish.c (cipher_spec_blowfish): Likewise. + * cast5.c (cipher_spec_cast5): Likewise. + * crc.c (digest_spec_crc32): Likewise. + * crc.c (digest_spec_crc32_rfc1510): Likewise. + * crc.c (digest_spec_crc32_rfc2440): Likewise. + * des.c (cipher_spec_des): Likewise. + * des.c (cipher_spec_tripledes): Likewise. + * dsa.c (pubkey_spec_dsa): Likewise. + * elgamal.c (pubkey_spec_elg): Likewise. + * md4.c (digest_spec_md4): Likewise. + * md5.c (digest_spec_md5): Likewise. + * aes.c (cipher_spec_aes): Likewise. + * aes.c (cipher_spec_aes192): Likewise. + * aes.c (cipher_spec_aes256): Likewise. + * rsa.c (pubkey_spec_rsa): Likewise. + * sha1.c (digest_spec_sha1): Likewise. + * sha256.c (digest_spec_sha256): Likewise. + * sha512.c (digest_spec_sha512): Likewise. + * tiger.c (digest_spec_tiger): Likewise. + * twofish.c (cipher_spec_twofish): Likewise. + * twofish.c (cipher_spec_twofish128): Likewise. + + * Makefile.am (EXTRA_libcipher_la_SOURCES): Fix list of source + files; reported by Simon Josefsson <jas@extundo.com>. + + * pubkey.c: Replaced all occurences of `id' with `algorithm', + since `id' is a keyword in obj-c. + * md.c: Likewise. + * cipher.c: Likewise. + + * crc.c, md4.c, md5.c, rmd160.c, sha1.c, sha256.c, tiger.c: + Replaced all occurences of gcry_digest_spec_t with gcry_md_spec_t. + + * dsa.c, rsa.c, elgamal.c: Replaced all occurencens of + gcry_pubkey_spec_t with gcry_pk_spec_t. + + * md.c: Replaced all occurences of gcry_digest_spec_t with + gcry_md_spec_t. + (gcry_digest_register_default): Renamed to ... + (gcry_md_register_default): ... this; adjusted callers. + (gcry_digest_lookup_func_name): Renamed to ... + (gcry_md_lookup_func_name): ... this; adjusted callers. + (gcry_digest_lookup_name): Renamed to ... + (gcry_md_lookup_name): ... this; adjusted callers. + (gcry_digest_register): Renamed to ... + (gcry_md_register): ... this. + (gcry_digest_unregister): Renamed to ... + (gcry_md_unregister): ... this. + + * pubkey.c (gcry_pubkey_register): Renamed to ... + (gcry_pk_register): ... this. + (gcry_pubkey_unregister): Renamed to ... + (gcry_pk_unregister): ... this. + Replaced all occurences of gcry_pubkey_spec_t with gcry_pk_spec_t. + (gcry_pubkey_register_default): Renamed to ... + (gcry_pk_register_default): ... this; adjusted callers. + (gcry_pubkey_lookup_func_name): Renamed to ... + (gcry_pk_lookup_func_name): ... this; adjusted callers. + (gcry_pubkey_lookup_name): Renamed to ... + (gcry_pk_lookup_name): ... this; adjusted callers. + + * md.c (gcry_md_hash_buffer): Fix error checking. Thanks to Simon + Josefsson <jas@extunde.com>. + +2003-07-04 Moritz Schulte <moritz@g10code.com> + + * cipher.c (gcry_cipher_list): New function. + +2003-07-01 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_to_sig): Accept a `flags' S-expression to be more + consistent with sexp_to_enc. + +2003-06-30 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (libcipher_la_SOURCES): Added: ac.c. + + * pubkey.c (_gcry_pk_module_lookup): New function. + (_gcry_pk_module_release): New function. + +2003-06-29 Moritz Schulte <moritz@g10code.com> + + * ac.c: New file. + +2003-06-26 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Trigger BUG correcly with new API. + +2003-06-19 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_is_enabled): Fixed. + +2003-06-18 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_get_algo_keylen): New. + (gcry_cipher_get_algo_blklen): New. + +2003-06-18 Moritz Schulte <moritz@g10code.com> + + * arcfour.c, cipher.c, blowfish.c, md.c, cast5.c, pubkey.c, crc.c, + des.c, dsa.c, elgamal.c, md4.c, md5.c, random.c, rijndael.c, + rmd160.c, rsa.c, sha1.c, sha256.c, sha512.c, tiger.c, twofish.c: + Replaced older types GcryDigestSpec, GcryCipherSpec and + GcryPubkeySpec with newer types: gcry_digest_spec_t, + gcry_cipher_spec_t and gcry_pubkey_spec_t. + + * md.c (gcry_digest_id_new): Removed function. + (gcry_digest_register): Removed code for generating a new module + ID. + + * pubkey.c (gcry_pubkey_id_new): Removed function. + (gcry_pubkey_register): Removed code for generating a new module + ID. + + * cipher.c, md.c, pubkey.c: Replace old type GcryModule with newer + one: gcry_module_t. + (gcry_cipher_id_new): Removed function. + (gcry_cipher_register): Removed code for generating a new module + ID. + + * cipher.c (gcry_cipher_register): Adjust call to + _gcry_module_add. + (gcry_cipher_register_default): Likewise. + * pubkey.c (gcry_pubkey_register_default): Likewise. + (gcry_pubkey_register): Likewise. + * md.c (gcry_digest_register_default): Likewise. + (gcry_digest_register): Likewise. + + * md.c (gcry_digest_lookup_func_id): Removed function. + (gcry_digest_lookup_id): Likewise. + (gcry_digest_id_new): Use _gcry_module_lookup_id instead of + gcry_digest_lookup_id. + (digest_algo_to_string): Likewise. + (check_digest_algo): Likewise. + (md_enable): Likewise. + (md_digest_length): Likewise. + (md_asn_oid): Likewise. + + * pubkey.c (gcry_pubkey_lookup_id): Removed function. + (gcry_pubkey_lookup_func_id): Likewise. + (gcry_pubkey_id_new): Use _gcry_module_lookup_id instead of + gcry_pubkey_id_new. + (gcry_pk_algo_name): Likewise. + (disable_pubkey_algo): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_get_npkey): Likewise. + (pubkey_get_nskey): Likewise. + (pubkey_get_nsig): Likewise. + (pubkey_get_nenc): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (gcry_pk_algo_info): Likewise. + + * cipher.c (gcry_cipher_lookup_func_id): Removed function. + (gcry_cipher_lookup_id): Likewise. + (cipher_algo_to_string): use _gcry_module_lookup_id instead of + gcry_cipher_lookup_id. + (disable_cipher_algo): Likewise. + (check_cipher_algo): Likewise. + (cipher_get_blocksize): Likewise. + (gcry_cipher_open): Likewise. + (gcry_cipher_id_new): Likewise. + +2003-06-17 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (GCRYPT_MODULES): Set to @GCRYPT_CIPHERS@, + @GCRYPT_PUBKEY_CIPHERS@, @GCRYPT_DIGESTS@ and @GCRYPT_RANDOM@. + (libcipher_la_DEPENDENCIES): Set to $(GCRYPT_MODULES). + (libcipher_la_LIBADD): Likewise. + (AM_CFLAGS): Added: @GPG_ERROR_CFLAGS@. + (EXTRA_libcipher_la_SOURCES): Added all conditional sources. + + * md.c (md_open): Use _gcry_fast_random_poll instead of + fast_random_poll. + * cipher.c (gcry_cipher_open): Likewise. + + * random.h (fast_random_poll): Removed macro. + + * blowfish.c, md4.c, md5.c, rmd160.c, sha1.c, sha256.c, sha512.c, + tiger.c: Use Autoconf's WORDS_BIGENDIAN instead of our own + BIG_ENDIAN_HOST. + +2003-06-16 Moritz Schulte <moritz@g10code.com> + + * random.c (getfnc_gather_random): Do not special-case + USE_ALL_RANDOM_MODULES, make it the default. + + * dsa.c: Replace last occurences of old type names with newer + names (i.e. replace MPI with gcry_mpi_t). + * elgamal.c: Likewise. + * primegen.c: Likewise. + * pubkey.c: Likewise. + * rsa.c: Likewise. + +2003-06-14 Moritz Schulte <moritz@g10code.com> + + * des.c (des_setkey): Add selftest check. + (tripledes_set3keys): Likewise. + (do_tripledes_setkey): Remove selftest check. + (do_des_setkey): Likewise. + +2003-06-11 Moritz Schulte <moritz@g10code.com> + + * md.c (_gcry_md_init): New function. + * cipher.c (_gcry_cipher_init): New function. + * pubkey.c (_gcry_pk_init): New function. + +2003-06-13 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_get_algo): Reverted to old API. This is a + convenience function anyway and error checking is not approriate. + (gcry_md_is_secure): New. + (gcry_md_is_enabled): New. + +2003-06-12 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_open): Make sure HANDLE is set to NULL on + error. + +2003-06-11 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_open): Make sure H receives either NULL or an + valid handle. + (gcry_md_copy): Swapped arguments so that it is more in lione with + md_open and most other API fucntions like memcpy (destination + comes first). Make sure HANDLE is set to NULL on error. + + * rijndael.c (do_encrypt): Hack to force correct alignment. It + seems not to be not sufficient, though. We should rework this + fucntions and remove all these ugly casts. Let the compiler + optimize or have an assembler implementation. + +2003-06-09 Moritz Schulte <moritz@g10code.com> + + * Makefile.am: Removed rules serpent, since that is not commited + yet. + +2003-06-08 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_encrypt): Improve calculation for size of the + format string. + +2003-06-07 Moritz Schulte <moritz@g10code.com> + + * arcfour.c, bithelp.h, blowfish.c, cast5.c, cipher.c, crc.c, + des.c, dsa.c, elgamal.c, md4.c, md5.c, md.c, primegen.c, pubkey.c, + rand-internal.h, random.c, random.h, rijndael.c, rmd160.c, + rmd160test.c, rmd.h, rndeged.c, rndlinux.c, rndunix.c, rndw32.c, + rsa.c, sha1.c, sha256.c, sha512.c, tiger.c, twofish.c: Edited all + preprocessor instructions to remove whitespace before the '#'. + This is not required by C89, but there are some compilers out + there that don't like it. Replaced any occurence of the now + deprecated type names with the new ones. + +2003-06-04 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_encrypt): Construct an arg_list and use + gcry_sexp_build_array instead of gcry_sexp_build. + (gcry_pk_sign): Likewise. + (gcry_pk_genkey): Likewise. + +2003-06-01 Moritz Schulte <moritz@g10code.com> + + * dsa.c (_gcry_dsa_generate): Do not check wether the algorithm ID + does indeed belong to DSA. + (_gcry_dsa_sign): Likewise. + (_gcry_dsa_verify): Likewise. + (_gcry_dsa_get_nbits): Likewise. + + * elgamal.c (_gcry_elg_check_secret_key): Do not check wether the + algorithm ID does indeed belong to ElGamal. + (_gcry_elg_encrypt): Likewise. + (_gcry_elg_decrypt): Likewise. + (_gcry_elg_sign): Likewise. + (_gcry_elg_verify): Likewise. + (_gcry_elg_get_nbits): Likewise. + (_gcry_elg_generate): Likewise. + + * rsa.c (_gcry_rsa_generate): Do not check wether the algorithm ID + does indeed belong to RSA. + (_gcry_rsa_encrypt): Likewise. + (_gcry_rsa_decrypt): Likewise. + (_gcry_rsa_sign): Likewise. + (_gcry_rsa_verify): Likewise. + (_gcry_rsa_get_nbits): Likewise. + +2003-05-30 Moritz Schulte <moritz@g10code.com> + + * md.c (md_get_algo): Return zero in case to algorithm is enabled. + + * md.c (gcry_md_info): Adjusted for new no-errno-API. + (md_final): Likewise. + (gcry_md_get_algo): Likewise. + * pubkey.c (gcry_pk_get_keygrip): Likewise. + (gcry_pk_ctl): Likewise. + (gcry_pk_algo_info): Likewise. + * des.c (selftest): Likewise. + +2003-05-29 Moritz Schulte <moritz@g10code.com> + + * md.c (md_enable): Do not forget to release module on error. + (gcry_md_open): Adjusted for new no-errno-API. + (md_open): Likewise. + (md_copy): Likewise. + (gcry_md_copy): Likewise. + (gcry_md_setkey): Likewise. + (gcry_md_algo_info): Likewise. + + * cipher.c (gcry_cipher_open): Adjusted for new no-errno-API and + also fixed a locking bug. + (gcry_cipher_encrypt): Adjusted for new no-errno-API. + (gcry_cipher_decrypt): Likewise. + (gcry_cipher_ctl): Likewise. + (gcry_cipher_info): Likewise. + (gcry_cipher_algo_info): Likewise. + +2003-05-28 Moritz Schulte <moritz@g10code.com> + + * md.c (md_enable): Adjusted for libgpg-error. + (gcry_md_enable): Likewise. + (gcry_digest_register_default): Likewise. + (gcry_digest_register): Likewise. + (check_digest_algo): Likewise. + (prepare_macpads): Likewise. + (gcry_md_setkey): Likewise. + (gcry_md_ctl): Likewise. + (gcry_md_get): Likewise. + (gcry_md_algo_info): Likewise. + (gcry_md_info): Likewise. + * dsa.c (_gcry_dsa_generate): Likewise. + (_gcry_dsa_check_secret_key): Likewise. + (_gcry_dsa_sign): Likewie. + (_gcry_dsa_verify): Likewise. + * twofish.c (do_twofish_setkey): Likewise. + (twofish_setkey): Likewise. + * cipher.c (gcry_cipher_register): Likewise. + +2003-05-25 Moritz Schulte <moritz@g10code.com> + + * rijndael.c (do_setkey): Adjusted for libgpg-error. + (rijndael_setkey): Likewise. + * random.c (gcry_random_add_bytes): Likewise. + * elgamal.c (_gcry_elg_generate): Likewise. + (_gcry_elg_check_secret_key): Likewise. + (_gcry_elg_encrypt): Likewise. + (_gcry_elg_decrypt): Likewise. + (_gcry_elg_sign): Likewise. + (_gcry_elg_verify): Likewise. + * rsa.c (_gcry_rsa_generate): Likewise. + (_gcry_rsa_check_secret_key): Likewise. + (_gcry_rsa_encrypt): Likewise. + (_gcry_rsa_decrypt): Likewise. + (_gcry_rsa_sign): Likewise. + (_gcry_rsa_verify): Likewise. + * pubkey.c (dummy_generate, dummy_check_secret_key, dummy_encrypt, + dummy_decrypt, dummy_sign, dummy_verify): Likewise. + (gcry_pubkey_register): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (sexp_elements_extract): Likewise. + (sexp_to_key): Likewise. + (sexp_to_sig): Likewise. + (sexp_to_enc): Likewise. + (sexp_data_to_mpi): Likewise. + (gcry_pk_encrypt): Likewise. + (gcry_pk_decrypt): Likewise. + (gcry_pk_sign): Likewise. + (gcry_pk_verify): Likewise. + (gcry_pk_testkey): Likewise. + (gcry_pk_genkey): Likewise. + (gcry_pk_ctl): Likewise. + * cipher.c (dummy_setkey): Likewise. + (check_cipher_algo): Likewise. + (gcry_cipher_open): Likewise. + (cipher_setkey): Likewise. + (gcry_cipher_ctl): Likewise. + (cipher_encrypt): Likewise. + (gcry_cipher_encrypt): Likewise. + (cipher_decrypt): Likewise. + (gcry_cipher_decrypt): Likewise. + (gcry_cipher_info): Likewise. + (gcry_cipher_algo_info): Likewise. + * cast5.c (cast_setkey): Likewise. + (do_cast_setkey): Likewise. + * arcfour.c (arcfour_setkey): Likewise. + (do_arcfour_setkey): Likewise. + * blowfish.c (do_bf_setkey): Likewise. + (bf_setkey): Likewise. + * des.c (do_des_setkey): Likewise. + (do_tripledes_setkey): Likewise. + +2003-05-22 Moritz Schulte <moritz@g10code.com> + + * tiger.c: Merged code ussing the U64_C macro from GnuPG. + + * sha512.c: Likewise. + +2003-05-17 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_genkey): Fix type: acquire a lock, instead of + releasing it. + +2003-05-11 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_testkey): Call REGISTER_DEFAULT_CIPHERS. + (gcry_pk_ctl): Likewise. + +2003-04-27 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_genkey): Release sexp after extracted data has + been used. + + * md.c (gcry_md_get_algo_dlen): Simplified, simply call + md_digest_length to do the job. + + * des.c (do_des_setkey): Check for selftest failure not only + during initialization. + (do_tripledes_setkey): Include check for selftest failure. + + * pubkey.c (gcry_pubkey_register_default): New macro + `pubkey_use_dummy', use it. + + * elgamal.c (elg_names): New variable. + (pubkey_spec_elg): Include elg_names. + + * dsa.c (dsa_names): New variable. + (pubkey_spec_dsa): Include dsa_names. + + * rsa.c (rsa_names): New variable. + (pubkey_spec_rsa): Include rsa_names. + + * pubkey.c (gcry_pubkey_lookup_func_name): Compare name also with + the names listed in `sexp_names'. + +2003-04-24 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_to_key): New variables: module, pubkey. Adjusted + to new module interface. + (sexp_to_key): Changend type of argument `retalgo' from `int *' to + `GcryModule **'. Adjusted all callers. Removed argument: + r_algotblidx. + (sexp_to_sig): Changend type of argument `retalgo' from `int *' to + `GcryModule **'. Adjusted all callers. + (sexp_to_enc): Likewise. + + (pubkey_get_npkey, pubkey_get_nskey, pubkey_get_nsig, + pubkey_get_nenc): Use strlen to find out the number. + + * rsa.c: Adjust pubkey_spec_rsa to new internal interface. + * dsa.c: Likewise. + * elgamal.c: Likewise. + +2003-04-17 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_elements_extract): New function. + * pubkey.c (sexp_to_key): Removed variable `idx', added `err', use + sexp_elements_extract. + (sexp_to_sig): Likewise. + (sexp_to_enc): Likewise. + + * pubkey.c: Terminate list correctly. + * md.c: Include sha512/sha384 in digest_table. + +2003-04-16 Moritz Schulte <moritz@g10code.com> + + * Makefile.am: Include support for sha512.c. + + * sha512.c: New file, merged from GnuPG, with few modifications + for libgcrypt. + + * rand-internal.h: Removed declarations for constructor functions. + + * md.c (md_copy): Call _gcry_module_use for incrementing the usage + counter of the digest modules. + + * rsa.c: Do not include "rsa.h". + * dsa.c: Do not include "dsa.h". + * elgamal.c: Do not include "elgamal.h". + * des.c: Do not include "des.h". + * cast5.c: Do not include "cast5.h". + * blowfish.c: Do not include "blowfish.h". + * arcfour.c: Do not include "arcfour.h". + + * Makefile.am (libcipher_la_DEPENDENCIES): Removed. + (libcipher_la_LIBADD): Removed. + Use Automake conditionals for conditional compilation. + +2003-04-13 Moritz Schulte <moritz@g10code.com> + + * cipher.c (gcry_cipher_open): Call REGISTER_DEFAULT_CIPHERS. + + * md.c (gcry_md_list): New member: module. + (md_enable): New variable: module, changed use of module and + digest. + (md_enable): Initialize member: module. + (md_close): Call _gcry_module_release. + + * cipher.c (gcry_cipher_open): New variable: module, changed use of + module and cipher. + (struct gcry_cipher_handle): New member: module. + (gcry_cipher_open): Initialize member: module. + (gcry_cipher_close): Call _gcry_module_release. + +2003-04-09 Moritz Schulte <moritz@g10code.com> + + * cipher.c: Include "ath.h". + * md.c: Likewise. + * pubkey.c: Likewise. + + * cipher.c (ciphers_registered_lock): New variable. + * md.c (digests_registered_lock): New variable. + * pubkey.c (pubkeys_registered_lock): New variable. + + * rndlinux.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndlinux_constructor): Removed function. + + * rndegd.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndegd_constructor): Removed function. + + * rndunix.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndunix_constructor): Removed function. + + * rndw32.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndw32_constructor): Removed function. + + * rndegd.c (rndegd_connect_socket): Simplify code for creating the + egd socket address. + (rndegd_connect_socket): Call log_fatal use instead of + g10_log_fatal. + (egd_gather_random): Renamed to ... + (rndegd_gather_random): ... here. + +2003-04-08 Moritz Schulte <moritz@g10code.com> + + * rndlinux.c: Do not include "dynload.h". + * rndunix.c: Likewise. + * rndw32.c: Likewise. + + * rndegd.c (rndegd_connect_socket): Factored out from ... + (egd_gather_random): here; call it. + (egd_socket): New variable. + (egd_gather_random): Initialize fd with egd_socket, do not declare + fd static. + (do_read): Merged few changes from GnuPG. FIXME - not finished? + Do not include "dynload.h". + + * rndw32.c (gather_random): Renamed to rndw32_gather_random, do + not declare static. + (gather_random_fast): Renamed to rndw32_gather_random_fast, do not + declare static. + + * rndunix.c (gather_random): Renamed to rndunix_gather_random, do + not declare static. + * rndegd.c (gather_random): Renamed to rndegd_gather_random, do + not declare static. + * rndlinux.c (gather_random): Renamed to rndlinux_gather_random, + do not declare static. + +2003-04-07 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (libcipher_la_SOURCES): Removed construct.c. + (libcipher_la_SOURCES): Added sha1.c, sha256.c, rmd160.c, md4.c, + md5.c, tiger.c and crc.c + (EXTRA_PROGRAMS): Removed sha1, sha256, rmd160, md4, md5, tiger + and crc. Removed definitions: EXTRA_md4_SOURCES, + EXTRA_md5_SOURCES, EXTRA_rmd160_SOURCES, EXTRA_sha1_SOURCES, + EXTRA_sha256_SOURCES, EXTRA_tiger_SOURCES and EXTRA_crc_SOURCES, + BUILT_SOURCES, DISTCLEANFILES. + + * pubkey.c: Do not include "elgamal.h", "dsa.h" and "rsa.h". + + * Makefile.am (libcipher_la_SOURCES): Removed rsa.h, elgamal.h, + dsa.h, des.h, cast5.h, arcfour.h and blowfish.h. + + * rsa.h: Removed file. + * elgamal.h: Removed file. + * dsa.h: Removed file. + * des.h: Removed file. + * cast5.h: Removed file. + * arcfour.h: Removed file. + * blowfish.h: Removed file. + + * Makefile.am (libcipher_la_SOURCES): Removed dynload.c and + dynload.h. + + * rsa.c (pubkey_spec_rsa): New variable. + * dsa.c (pubkey_spec_rsa): New variable. + * elgamal.c (pubkey_spec_elg): New variable. + + * rsa.c (_gcry_rsa_get_info): Removed function. + * elgamal.c (_gcry_elg_get_info): Removed function. + * dsa.c (_gcry_dsa_get_info): Removed function. + + * tiger.c (tiger_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_tiger_constructor): Removed function. + + * sha1.c (sha1_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_sha1_constructor): Removed function. + + * sha256.c (sha256_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_sha256_constructor): Removed function. + + * rmd160.c (rmd160_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rmd160_constructor): Removed function. + + * md5.c (md5_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_md5_constructor): Removed function. + + * md4.c (md4_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_md4_constructor): Removed function. + + * crc.c (crc_get_info): Removed function. + + * arcfour.c (do_arcfour_setkey): Changed type of context argument + to `void *', added local variable for cast, adjusted callers. + (arcfour_setkey): Likewise. + (encrypt_stream): Likewise. + * cast5.c (cast_setkey): Likewise. + (encrypt_block): Likewise. + * rijndael.c (rijndael_setkey): Likewise. + (rijndael_encrypt): Likewise. + (rijndael_decrypt): Likewise. + * twofish.c (twofish_setkey): Likewise. + (twofish_encrypt): Likewise. + (twofish_decrypt): Likewise. + * des.c (do_des_setkey): Likewise. + (do_des_encrypt): Likewise. + (do_des_encrypt): Likewise. + (do_tripledes_encrypt): Likewise. + (do_tripledes_encrypt): Likewise. + * blowfish.c (bf_setkey: Likewise. + (encrypt_block): Likewise. + (decrypt_block): Likewise. + + * arcfour.c (encrypt_stream): Likewise. + + * rijndael.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func) Removed function. + + * twofish.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func) Removed function. + + * cast5.c (CIPHER_ALGO_CAST5): Removed. + + * blowfish.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Removed macros. + (CIPHER_ALGO_BLOWFISH): Removed symbol. + * cast5.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Likewise. + * des.c (selftest_failed): Removed. + (initialized): New variable. + (do_des_setkey): Run selftest, if not yet done. + (FNCCAST_SETKEY, FNCCAST_CRYPT): Removed macros. + + * arcfour.c (_gcry_arcfour_get_info): Removed function. + * blowfish.c (_gcry_blowfish_get_info): Removed function. + * cast5.c (_gcry_cast5_get_info): Removed function. + * des.c (_gcry_des_get_info): Removed function. + * rijndael.c (_gcry_rijndael_get_info): Removed function. + * twofish.c (_gcry_twofish_get_info): Removed function. + + * arcfour.c (cipher_spec_arcfour): New variable. + * twofish.c (cipher_spec_twofish, cipher_spec_twofish128): New + variables. + * rijndael.c (cipher_spec_aes, cipher_spec_aes192, + cipher_spec256): New variables. + * des.c (cipher_spec_des, cipher_spec_tripledes): New variables. + * cast5.c (cipher_spec_cast5): New variable. + * blowfish.c (cipher_spec_blowfish): Likewise. + + * twofish.c: Do not include "dynload.h". + * rijndael.c: Likewise. + * des.c: Likewise. + * cast5.c: Likewise. + * blowfish.c: Likewise. + * cipher.c: Likewise. + * crc.c: Likewise. + * md4.c: Likewise. + * md5.c: Likewise. + * md.c: Likewise. + * pubkey.c: Likewise. + * rijndael.c: Likewise. + * sha1.c: Likewise. + * sha256.c: Likewise. + + * arcfour.c: Include "cipher.h". + * twofish.c: Likewise. + * rijndael.c: Likewise. + * des.c: Likewise. + * cast5.c: Likewise. + * blowfish.c: Likewise. + + * twofish.c (twofish_setkey): Declared argument `key' const. + (twofish_encrypt): Declared argument `inbuf' const. + (twofish_decrypt): Likewise. + + * rijndael.c (rijndael_setkey): Declared argument `key' const. + (rijndael_encrypt): Declared argument `inbuf' const. + (rijndael_decrypt): Likewise. + + * des.c (do_des_setkey): Declared argument `key' const. + (do_tripledes_setkey): Likewise. + (do_des_encrypt): Declared argument `inbuf' const. + (do_des_decrypt): Likewise. + (do_tripledes_encrypt): Likewise. + (do_tripledes_decrypt): Likewise. + + * cast5.c (encrypt_block): Declared argument `inbuf' const. + (decrypt_block): Likewise. + (cast_setkey): Declared argument `key' const. + + * blowfish.c (do_bf_setkey): Declared argument `key' const. + (encrypt_block): Declared argument `inbuf' const. + (encrypt_block): Likewise. + + + + * cipher.c: Remove CIPHER_ALGO_DUMMY related code. + Removed struct cipher_table_s. + Changed definition of cipher_table. + Removed definition of disabled_algos. + (ciphers_registered, default_ciphers_registered): New variables. + (REGISTER_DEFAULT_CIPHERS): New macro. + (dummy_setkey): Declared argument `key' const. + (dummy_encrypt_block): Declared argument `inbuf' const. + (dummy_encrypt_block): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_setkey): Use `unsigned char' instead of `byte'. + (dummy_encrypt_block): Likewise. + (dummy_decrypt_block): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_decrypt_stream): Likewise. + (gcry_cipher_register_default): New function. + (gcry_cipher_lookup_func_id): New function. + (gcry_cipher_lookup_func_name): New function. + (gcry_cipher_lookup_id): New function. + (gcry_cipher_lookup_name): New function. + (gcry_cipher_id_new): New function. + (gcry_cipher_register): New function. + (gcry_cipher_unregister): New function. + (setup_cipher_table): Removed function. + (load_cipher_modules): Removed function. + (gcry_cipher_map_name): Adjusted to use new module management. + (cipher_algo_to_string): Likewise. + (disable_cipher_algo): Likewise. + (check_cipher_algo): Likewise. + (cipher_get_keylen): Likewise. + (cipher_get_blocksize): Likewise. + (gcry_cipher_open): Likewise. + (struct gcry_cipher_handle): Replaced members algo, algo_index, + blocksize, setkey, encrypt, decrypt, stencrypt, stdecrypt with one + member: cipher. + (gcry_cipher_open): Adjusted code for new handle structure. + (cipher_setkey): Likewise. + (cipher_setiv): Likewise. + (cipher_reset): Likewise. + (do_ecb_encrypt): Likewise. + (do_ecb_decrypt): Likewise. + (do_cbc_encrypt): Likewise. + (do_cbc_decrypt): Likewise. + (do_cfb_encrypt): Likewise. + (do_cfb_decrypt): Likewise. + (do_ctr_encrypt): Likewise. + (cipher_encrypt): Likewise. + (gcry_cipher_encrypt): Likewise. + (cipher_decrypt): Likewise. + (gcry_cipher_decrypt): Likewise. + (cipher_sync): Likewise. + (gcry_cipher_ctl): Likewise. + + * pubkey.c: Removed struct pubkey_table_s. + Changed definition of pubkey_table. + Removed definition of disabled_algos. + (pubkeys_registered, default_pubkeys_registered): New variables. + (REGISTER_DEFAULT_PUBKEYS): New macro. + (setup_pubkey_table): Removed function. + (load_pubkey_modules): Removed function. + (gcry_pubkey_register_default): New function. + (gcry_pubkey_lookup_func_id): New function. + (gcry_pubkey_lookup_func_name): New function. + (gcry_pubkey_lookup_id): New function. + (gcry_pubkey_lookup_name): New function. + (gcry_pubkey_id_new): New function. + (gcry_pubkey_register): New function. + (gcry_pubkey_unregister): New function. + (gcry_pk_map_name): Adjusted to use new module management. + (gcry_pk_algo_name): Likewise. + (disable_pubkey_algo): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_get_npkey): Likewise. + (pubkey_get_nskey): Likewise. + (pubkey_get_nsig): Likewise. + (pubkey_get_nenc): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (gcry_pk_get_nbits): Likewise. + (gcry_pk_algo_info): Likewise. + + * md.c: Removed struct md_digest_list_s. + (digest_list): Changed definition. + (digests_registered, default_digests_registered): New variables. + (REGISTER_DEFAULT_DIGESTS): New macro. + (new_list_item): Removed function. + (setup_md_table): Removed function. + (load_digest_module): Removed function. + (gcry_digest_register_default): New function. + (gcry_digest_lookup_func_id): New function. + (gcry_digest_lookup_func_name): New function. + (gcry_digest_lookup_id): New function. + (gcry_digest_lookup_name): New function. + (gcry_digest_id_new): New function. + (gcry_digest_register): New function. + (gcry_digest_unregister): New function. + (GcryDigestEntry): New type. + (struct gcry_md_context): Adjusted type of `list'. + (gcry_md_map_name): Adjusted to use new module management. + (digest_algo_to_string): Likewise. + (check_digest_algo): Likewise. + (md_enable): Likewise. + (md_digest_length): Likewise. + (md_asn_oid): Likewise. + +2003-04-07 Moritz Schulte <moritz@g10code.com> + + * pubkey.c: Replaced PUBKEY_ALGO_DSA with GCRY_PK_DSA, + PUBKEY_ALGO_RSA with GCRY_PK_RSA and PUBKEY_ALGO_ELGAMAL with + GCRY_PK_ELG. + + * dsa.c: Replaced PUBKEY_ALGO_DSA with GCRY_PK_DSA. + +2003-04-01 Moritz Schulte <moritz@g10code.com> + + * des.c: Removed checks for GCRY_CIPHER_3DES and GCRY_CIPHER_DES. + +2003-03-31 Moritz Schulte <moritz@g10code.com> + + * tiger.c (tiger_get_info): Do not declare static. + * sha256.c (sha256_get_info): Likewise. + * sha1.c (sha1_get_info): Likewise. + * rmd160.c (rmd160_get_info): Likewise. + * md5.c (md5_get_info): Likewise. + * md4.c (md4_get_info): Likewise. + * crc.c (crc_get_info): Likewise. + + * md.c (load_digest_module): Call setup_md_table during + initialization. + (new_list_item): Link new element into digest_list. + + * cipher.c (do_ctr_decrypt): Made do_ctr_encrypt act as a wrapper + for do_ctr_encrypt, since these functions are identical. + +2003-03-30 Simon Josefsson <jas@extundo.com> + + * cipher.c (struct gcry_cipher_handle): Add counter field. + (gcry_cipher_open): Add CTR. + (cipher_reset): Clear counter field. + (do_ctr_encrypt, do_ctr_decrypt): New functions. + (cipher_encrypt, cipher_decrypt): Call CTR functions. + (gcry_cipher_ctl): Add SET_CTR to set counter. + +2003-03-30 Moritz Schulte <moritz@g10code.com> + + * rsa.c (_gcry_rsa_blind): New function. + (_gcry_rsa_unblind): New function. + (_gcry_rsa_decrypt): Use _gcry_rsa_blind and _gcry_rsa_decrypt. + +2003-03-26 Moritz Schulte <moritz@g10code.com> + + * dynload.c (_gcry_enum_gnupgext_pubkeys): Adjust `encrypt' and + `decrypt' function arguments. + (_gcry_enum_gnupgext_pubkeys): Likewise. + * dynload.h: Likewise. + + * pubkey.c (dummy_decrypt): Add argument: int flags. + (dummy_encrypt): Likewise. + + * elgamal.c (_gcry_elg_encrypt): Add argument: int flags. + (_gcry_elg_decrypt): Likewise. + + * rsa.c (_gcry_rsa_encrypt): Add argument: int flags. + (_gcry_rsa_decrypt): Likewise. + + * pubkey.c: Add `flags' argument to members `encrypt' and + `decrypt' of struct `pubkey_table_s'. + + * rsa.h: Add `flags' argument to function declarations. + * elgamal.h: Likewise. + + * pubkey.c (sexp_data_to_mpi): New variable: int parsed_flags. + (sexp_data_to_mpi): Set `parsed_flags'. + (sexp_data_to_mpi): New argument: int *flags. + (gcry_pk_encrypt): New variable: int flags. + (gcry_pk_encrypt): Pass `flags' to pubkey_encrypt. + (pubkey_encrypt): New variable: int flags. + (pubkey_encrypt): Pass `flags' to pubkey encrypt function. + (pubkey_decrypt): Likewise. + (pubkey_decrypt): Pass `flags' to pubkey encrypt function. + (gcry_pk_encrypt): Include `flags' s-exp in return list. + (sexp_to_enc): New argument: int *flags. + (gcry_pk_decrypt): New variable: int flags. + (gcry_pk_decrypt): Pass `flags' to pubkey_decrypt. + (sexp_to_enc): New variable: int parsed_flags. + (sexp_to_enc): Set `parsed_flags'. + +2003-03-22 Simon Josefsson <jas@extundo.com> + + * cipher.c (gcry_cipher_open, do_cbc_encrypt) + (gcry_cipher_encrypt): Support GCRY_CIPHER_CBC_MAC. + (gcry_cipher_ctl): Support GCRYCTL_SET_CBC_MAC. + +2003-03-19 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): New args EXTRA_CHECK and EXTRA_CHECK_ARG + to allow for a user callback. Changed all callers. + (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Ditto, pass them to gen_prime. + * rsa.c (check_exponent): New. + (generate): Use a callback to ensure that a given exponent is + actually generated. + +2003-03-12 Moritz Schulte <moritz@g10code.com> + + * primegen.c: Initialize `no_of_small_prime_numbers' statically. + (gen_prime): Remove calculation of `no_of_small_prime_numbers'. + +2003-03-03 Moritz Schulte <moritz@g10code.com> + + * md.c (gcry_md_ctl): Rewritten to use same style like the other + functions dispatchers. + +2003-03-02 Moritz Schulte <moritz@g10code.com> + + * cipher.c (struct gcry_cipher_handle): New member: algo_index. + (gcry_cipher_open): Allocate memory for two cipher contexts. + Initialize algo_index. + (cipher_setkey): Duplicate context into reserved memory. + (cipher_reset): New function, which resets the context and clear + the IV. + (gcry_cipher_ctl): Call cipher_reset. + +2003-02-23 Moritz Schulte <moritz@g10code.com> + + * cipher.c: Remove (bogus) `digitp' macro definition. + * md.c: Likewise. + + * blowfish.c (burn_stack): Removed. + * arcfour.c (burn_stack): Likewise. + * cast5.c (burn_stack): Likewise. + * des.c (burn_stack): Likewise. + * md4.c (burn_stack): Likewise. + * md5.c (burn_stack): Likewise. + * random.c (burn_stack): Likewise. + * rijndael.c (burn_stack): Likewise. + * rmd160.c (burn_stack): Likewise. + * sha1.c (burn_stack): Likewise. + * sha256.c (burn_stack): Likewise. + * tiger.c (burn_stack): Likewise. + * twofish.c (burn_stack): Likewise. + + * blowfish.c: Changed all occurences of burn_stack to + _gcry_burn_stack. + * arcfour.c: Likewise. + * cast5.c: Likewise. + * des.c: Likewise. + * md4.c: Likewise. + * md5.c: Likewise. + * random.c: Likewise. + * rijndael.c: Likewise. + * rmd160.c: Likewise. + * sha1.c: Likewise. + * sha256.c: Likewise. + * tiger.c: Likewise. + * twofish.c: Likewise. + + * arcfour.c (_gcry_arcfour_get_info): Use GCRY_CIPHER_ARCFOUR + instead of hard-coded value `301'. + +2003-01-24 Werner Koch <wk@gnupg.org> + + * random.c (_gcry_register_random_progress): New. + (_gcry_random_progress): New. + + * rndlinux.c (gather_random): Call the random progress function. + +2003-01-23 Werner Koch <wk@gnupg.org> + + * rsa.c (generate): New arg USE_E to request a specific public + exponent. + (_gcry_rsa_generate): Ditto. + * elgamal.c (_gcry_elg_generate): Must add an dummy argument + instead of USE_E. + * dsa.c (_gcry_dsa_generate): Ditto. + * pubkey.c (dummy_generate): Ditto. + (pubkey_generate): Add USE_E arg and pass it down. + (gcry_pk_genkey): Detect "rsa-use-e" parameter and pass it to generate. + + * pubkey.c (sexp_to_enc): New arg RET_MODERN. + (gcry_pk_decrypt): Make use of it to return a real S-expression. + Return better error codes. + (gcry_pk_verify): Return better error codes. + +2003-01-21 Werner Koch <wk@gnupg.org> + + * random.c (gcry_random_add_bytes): Add QUALITY argument, let + function return an error code and disable its core for now. + +2003-01-21 Timo Schulz <twoaday@freakmail.de> + + * random.c (gcry_random_add_bytes): New. Function to add external + random to the pool. + +2003-01-20 Simon Josefsson <jas@extundo.com> + + * crc.c: New. + * Makefile.am (EXTRA_PROGRAMS, EXTRA_crc_SOURCES): Add crc.c. + * md.c (gcry_md_get_algo_dlen): Add values for CRC. + +2003-01-20 Werner Koch <wk@gnupg.org> + + * sha256.c: New. + * bithelp.h (ror): New. + * Makfile.am: Add sha256.c. + * md.c (oid_table): Add values for SHA256 et al. + (gcry_md_get_algo_dlen): Likewise + +2003-01-20 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_get_keygrip): Implemented keygrips for DSA + and ElGamal. + +2003-01-17 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_encrypt): Reworked so that the output will + never contain the plaintext even if the caller did not checked the + return value. + + * md.c (gcry_md_get_algo): Changed error code to GCRYERR_GENERAL + because we don't have an invalid md algo but no algorithm enabled. + + * pubkey.c (gcry_pk_genkey): Changed error code for bounds check + of table parameters to GCRYERR_INTERNAL. + + * md.c (gcry_md_open): Partly reverted Timo's change from + 2002-10-10 by removing the check for the algorithm. An algorithm + of 0 is allowed and anyway we should not double check it or check + it using a different function. Also fixed the flags check. + + * pubkey.c (gcry_pk_encrypt): Make sure that R_CIPH points to NULL + on error. + (gcry_pk_decrypt): Ditto for R_PLAIN. + (gcry_pk_sign): Ditto for R_SIG. + (gcry_pk_genkey): Ditto for R_KEY. + +2003-01-16 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_write): Changed 2nd argument type to void*. + (gcry_md_hash_buffer): Changed type of boths buffers to void*. + (gcry_md_setkey): Changed 2nd argument type to void*. + +2003-01-15 Werner Koch <wk@gnupg.org> + + * pubkey.c (sexp_data_to_mpi): New. This handles pkcs1 padding. + (gcry_pk_sign, gcry_pk_verify): Use it here. + (gcry_pk_encrypt): And here. + (pubkey_verify): Add debug code. + (sexp_to_enc): Handle flags in the input and return the pkcs1 flag + in a new parameter. + (gcry_pk_decrypt): Prepare for future pkcs1 handling. + +2002-12-19 Werner Koch <wk@gnupg.org> + + * random.c (_gcry_random_initialize): New. + +2002-12-16 Werner Koch <wk@gnupg.org> + + * cipher.c: Added a Teletrust specific OID for 3DES. + +2002-12-12 Werner Koch <wk@gnupg.org> + + * md.c: Added another oddball OIW OID (sha-1WithRSAEncryption). + +2002-11-23 Werner Koch <wk@gnupg.org> + + * md.c (load_digest_module): Enlarged checked_algos bitmap. + * md4.c (func_table): Fixed entry for md4. + Both by Simon Josephson. + (transform): Copy data to get the alignment straight. Tested only + on i386. + +2002-11-10 Simon Josefsson <jas@extundo.com> + + * cipher.c (gcry_cipher_open): Don't reject CTS flag. + (do_cbc_encrypt, do_cbc_decrypt, cipher_encrypt) + (gcry_cipher_encrypt, cipher_decrypt) + (gcry_cipher_decrypt): Support CTS flag. + (gcry_cipher_ctl): Toggle CTS flag. + +2002-11-10 Werner Koch <wk@gnupg.org> + + * md4.c: New. By Simon Josefsson. + * Makefile.am (EXTRA_PROGRAMS): Add md4.c. + * md.c (oid_table,gcry_md_get_algo_dlen): MD4 support. + +2002-10-14 Werner Koch <wk@gnupg.org> + + * arcfour.c (do_encrypt_stream): Don't use increment op when + assigning to the same variable. + +2002-10-10 Timo Schulz <ts@winpt.org> + + * pubkey.c (gcry_pk_genkey): Check boundaries. + + * md.c (gcry_md_open): Check that algo is available and only + valid flag values are used. + (gcry_md_get_algo): Add error handling. + +2002-09-26 Werner Koch <wk@gnupg.org> + + * md.c: Include an OID for TIGER. + * tiger.c (tiger_get_info): Use a regular OID. + +2002-09-17 Werner Koch <wk@gnupg.org> + + * random.c: Replaced mutex.h by the new ath.h. Changed all calls. + +2002-09-16 Werner Koch <wk@gnupg.org> + + * arcfour.c (do_encrypt_stream): Use register modifier and modulo. + According to Nikos Mavroyanopoulos this increases perfromace on + i386 system noticable. And I always tought gcc is clever enough. + * md5.c (transform): Use register modifier. + * rmd160.c (transform): Ditto. + * sha1.c (transform): Ditto. We hope that there are 6 free registers. + * random.c (gcry_randomize): Rewrote to avoid malloc calls. + + * rndlinux.c (gather_random): Replaced remaining fprintfs by log_*. + * arcfour.c (do_arcfour_setkey): Ditto. + * twofish.c (do_twofish_setkey): Ditto. + * rndegd.c (gather_random): Ditto. + * rijndael.c (do_setkey): Ditto. + * random.c (_gcry_random_dump_stats): Ditto. + * primegen.c (_gcry_generate_elg_prime): Ditto. + * des.c (_gcry_des_get_info): Ditto. + * cast5.c (do_cast_setkey): Ditto. + * blowfish.c (do_bf_setkey): Ditto. + +2002-08-26 Werner Koch <wk@gnupg.org> + + * des.c (weak_keys): Fixed one entry in the table and compared + all entries against the literature. + (selftest): Checksum the weak key table. + +2002-08-21 Werner Koch <wk@gnupg.org> + + * pubkey.c: Enable keygrip calculation for "openpgp-rsa". + +2002-08-17 Werner Koch <wk@gnupg.org> + + * cipher.c (setup_cipher_table): Don't overwrite the DES entry + with the entry for DUMMY. + +2002-08-14 Werner Koch <wk@gnupg.org> + + * des.c (do_des_setkey,do_des_encrypt, do_des_decrypt): New. + (_gcry_des_get_info): Support plain old DES. + * cipher.c (setup_cipher_table): Put DES into the table. + +2002-07-25 Werner Koch <wk@gnupg.org> + + * rndunix.c (_gcry_rndunix_constructor): Prefixed with _gcry_. + Noted by Stephan Austermuehle. + +2002-07-08 Timo Schulz <ts@winpt.org> + + * rndw32.c: Replaced the m_ memory functions with the real + gcry_ functions. Renamed all g10_ prefixed functions to log_. + +2002-06-12 Werner Koch <wk@gnupg.org> + + * rsa.c (generate): Use e = 65537 for now. + +2002-06-11 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_get_keygrip): Allow a "protected-private-key". + +2002-06-05 Timo Schulz <ts@winpt.org> + + * cipher.c (gcry_cipher_encrypt, gcry_cipher_decrypt): + Check that the input size is a multiple of the blocksize. + +2002-05-23 Werner Koch <wk@gnupg.org> + + * md.c (oid_table): Add an rsadsi OID for MD5. + +2002-05-21 Werner Koch <wk@gnupg.org> + + * primegen.c, elgamal.c, dsa.c (progress): Do not print anything + by default. Pass an extra identifying string to the callback and + reserved 2 argumenst for current and total counters. Changed the + register function prototype. + +2002-05-17 Werner Koch <wk@gnupg.org> + + * rndegd.c (rndegd_constructor): Fixed name of register function + and prefixed the function name with _gcry_. + * rndw32.c (rndw32_constructor): Ditto. + * tiger.c (tiger_constructor): Ditto. + + * Makefile.am: Removed all dynamic loading stuff. + * dynload.c: Ditto. Now only used for the constructor system. + +2002-05-15 Werner Koch <wk@gnupg.org> + + * random.c (gcry_random_bytes,gcry_random_bytes_secure) + (gcry_randomize): Make sure we are initialized. + +2002-05-14 Werner Koch <wk@gnupg.org> + + Changed license of most files to the LGPL. + +2002-05-02 Werner Koch <wk@gnupg.org> + + * random.c (_gcry_fast_random_poll): Initialize the module so the + mutex can be used. + + * primegen.c (small_prime_numbers): Moved table from smallprime.c + * smallprime.c: File removed. + + * des.c (leftkey_swap, rightkey_swap, working_memcmp): Made static. + + * cipher.c (gcry_cipher_map_name): Map "RIJNDAEL" to "AES". + * rijndael.c (rijndael_get_info): We do only support a 128 bit + blocksize so it makes sense to change the algorithm strings to + AES. + + * tiger.c (tiger_final): Removed superfluous token pasting operators. + * md5.c (md5_final): Ditto. + +2002-04-30 Werner Koch <wk@gnupg.org> + + * cipher.c: Fixed list of copyright years. + +2002-03-18 Werner Koch <wk@gnupg.org> + + * random.c (initialize): Initialize the new pool lock mutex. + (_gcry_fast_random_poll): Add locking and moved main + code out to... + (do_fast_random_poll): new function. + (read_pool): Use the new function here. + (get_random_bytes): Add locking. + (_gcry_update_random_seed_file): Ditto. + +2002-03-11 Werner Koch <wk@gnupg.org> + + * md.c: Add rsaSignatureWithripemd160 to OID table. + +2002-02-20 Werner Koch <wk@gnupg.org> + + * sha1.c: Removed a left over comment note. The code has been + rewritten from scratch in 1998. Thanks to Niels Möller for + reporting this misleading comment. + +2002-02-18 Werner Koch <wk@gnupg.org> + + * rndunix.c (rndunix_constructor): Use the the new prefixed + function name. Reported by Jordi Mallach. + +2002-02-10 Werner Koch <wk@gnupg.org> + + * random.c (mix_pool): Carry an extra failsafe_digest buffer + around to make the function more robust. + +2002-02-08 Werner Koch <wk@gnupg.org> + + * random.c (add_randomness): Xor new data into the pool and not + just copy it. This avoids any choosen input attacks which are not + serious in our setting because an outsider won't be able to mix + data in and even then we keep going with a PRNG. Thanks to Stefan + Keller for pointing this out. + +2002-01-04 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_genkey): Do not release skey - it is static. + + * primegen.c (gen_prime): Of course we should use set_bit + and not set_highbit to set the second high bit. + +2001-12-18 Werner Koch <wk@gnupg.org> + + * rsa.c (generate): Loop until we find the exact modulus size. + Changed the exponent to 41. + (rsa_get_info): s/usage/r_usage/ to avoid shadow warnings. + * primegen.c (gen_prime): Set 2 high order bits for secret primes. + + * Makefile.am (DISTCLEANFILES): Include construct.c. + +2001-12-17 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_get_keygrip): New - experimental. + +2001-12-11 Werner Koch <wk@gnupg.org> + + * cipher.c: Added OIDs for AES. + (gcry_cipher_mode_from_oid): New. + (gcry_cipher_map_name): Moved OID search code to .. + (search_oid): .. new function. + +2001-12-10 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_encrypt): Find the signature algorithm by name + and not by number. + + * pubkey.c (gcry_pk_encrypt,gcry_pk_decrypt,gcry_pk_sign) + (gcry_pk_verify,gcry_pk_testkey, gcry_pk_genkey) + (gcry_pk_get_nbits): Release the arrays. Noted by Nikos + Mavroyanopoulos. + +2001-12-06 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_map_name): Look also for OIDs prefixed + with "oid." or "OID.". + +2001-12-05 Werner Koch <wk@gnupg.org> + + * pubkey.c (algo_info_table): Fixed entry for openpgp-rsa. + +2001-11-24 Werner Koch <wk@gnupg.org> + + * pubkey.c: Added the rsaEncryption OID to the tables. + (sexp_to_key): Add an arg to return the index of the algorithm, + changed all callers. + (gcry_pk_sign): Find the signature algorithm by name and not by + number. + (gcry_pk_get_nbits): Fixed so that we can now really pass a secret + key to get the result. + + * md.c (gcry_md_map_name): Look also for OIDs prefixed with "oid." + or "OID." so that an OID string can be used as an S-Exp token. + +2001-11-20 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_map_name): Lookup by OID if the the name begins + with a digit. + (oid_table): New. + +2001-11-16 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_info): New operator GCRYCTL_IS_ALGO_ENABLED. + +2001-11-07 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Close the handle which was left open + for algorithms other than rmd160. + +2001-08-08 Werner Koch <wk@gnupg.org> + + * rndw32.c (gather_random): Use toolhelp in addition to the NT + gatherer for Windows2000. Suggested by Sami Tolvanen. + + * random.c (read_pool): Fixed length check, this used to be one + byte to strict. Made an assert out of it because the caller has + already made sure that only poolsize bytes are requested. + Reported by Marcus Brinkmann. + +2001-08-03 Werner Koch <wk@gnupg.org> + + * cipher.c (cipher_encrypt, cipher_decrypt): Prepare to return + errors. We have to change the interface to all ciphers to make + this really work but we should do so to prepare for hardware + encryption modules. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Return the error and + set lasterr. + (gcry_cipher_ctl): Make sure that errors from setkey are returned. + +2001-08-02 Werner Koch <wk@gnupg.org> + + * rndlinux.c (gather_random): casted a size_t arg to int so that + the format string is correct. Casting is okay here and avoids + translation changes. + + * random.c (fast_random_poll): Do not check the return code of + getrusage. + + * rndunix.c: Add a signal.h header to avoid warnings on Solaris 7 + and 8. + + * tiger.c (print_abc,print_data): Removed. + + * rijndael.c, des.c, blowfish.c, twofish.c, cast5.c, arcfour.c + (burn_stack): New. Add wrappers for most functions to be able to + call burn_stack after the function invocation. This methods seems + to be the most portable way to zeroise the stack used. It does + only work on stack frame based machines but it is highly portable + and has no side effects. Just setting the automatic variables at + the end of a function to zero does not work well because the + compiler will optimize them away - marking them as volatile would + be bad for performance. + * md5.c, sha1.c, rmd160.c, tiger.c (burn_stack): Likewise. + * random.c (burn_stack): New. + (mix_pool): Use it here to burn the stack of the mixblock function. + + * primegen.c (_gcry_generate_elg_prime): Freed q at 3 places. + Thanks to Tommi Komulainen. + + * arcfour.c (arcfour_setkey): Check the minimim keylength against + bytes and not bits. + (selftest): Must reset the key before decryption. + +2001-05-31 Werner Koch <wk@gnupg.org> + + * sha1.c (sha1_init): Made static. + + Changed all g10_ prefixed function names as well as some mpi_ + function names to cope with the introduced naming changes. + + * md.c (prepare_macpads): Made key const. + +2001-05-28 Werner Koch <wk@gnupg.org> + + * rndegd.c (gather_random): Removed the use of tty_printf. + +2001-03-29 Werner Koch <wk@gnupg.org> + + * md5.c (md5_final): Fixed calculation of hashed length. Thanks + to disastry@saiknes.lv for pointing out that it was horrible wrong + for more than 512MB of input. + * sha1.c (sha1_final): Ditto. + * rmd160.c (rmd160_final): Ditto. + * tiger.c (tiger_final): Ditto. + + * blowfish.c (encrypt,do_encrypt): Changed name to do_encrypt to + avoid name clashes with an encrypt function in stdlib.h of + Dynix/PIX. Thanks to Gene Carter. + * elgamal.c (encrypt,do_encrypt): Ditto. + + * twofish.c (gnupgext_enum_func): Use only when when compiled as a + module. + * rijndael.c (gnupgext_enum_func): Ditto. + + * tiger.c (tiger_get_info): Return "TIGER192" and not just + "TIGER". By Edwin Woudt. + + * random.c: Always include time.h - standard requirement. Thanks + to James Troup. + + * rndw32.c: Fixes to the macros. + +2001-01-11 Werner Koch <wk@gnupg.org> + + * cipher.c (cipher_encrypt,gcry_cipher_encrypt): Use blocksize and + not 8. + +2000-12-19 Werner Koch <wk@gnupg.org> + + Major change: + Removed all GnuPG stuff and renamed this piece of software + to gcrypt. + +2000-11-14 Werner Koch <wk@gnupg.org> + + * dsa.c (test_keys): Replaced mpi_alloc by gcry_mpi_new and + mpi_free by gcry_mpi_release. + * elgamal.c (test_keys,generate): Ditto, also for mpi_alloc_secure. + * rsa.c (test_keys,generate,rsa_verify): Ditto. + * primegen.c (generate_elg_prime): Ditto. + (gen_prime): Ditto and removed nlimbs. + + * rsa.c (generate): Allocate 2 more vars in secure memory. + + * Makefile.am (OMIT_DEPENDENCIES): Hack to work around dependency + problems. + +2000-10-09 Werner Koch <wk@gnupg.org> + + * arcfour.c, arcfour.h: New. + * cipher.c (cipher_encrypt, cipher_decrypt): Add stream mode. + (setup_cipher_table): Add Arcfour. + (gcry_cipher_open): Kludge to allow stream mode. + +Wed Oct 4 13:16:18 CEST 2000 Werner Koch <wk@openit.de> + + * sha1.c (transform): Use rol() macro. Actually this is not needed + for a newer gcc but there are still aoter compilers. + + * rsa.c (test_keys): Use new random function. + + * md.c (gcry_md_setkey): New function to overcome problems with + const conflics. + (gcry_md_ctl): Pass set key to the new functions. + + * rijndael.c: New. + * cipher.c: Add Rijndael support. + +Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de> + + * rndlinux.c (open_device): Loose random device checking. + By Nils Ellmenreich. + + * random.c (fast_random_poll): Check ENOSYS for getrusage. + * rndunix.c: Add 2 sources for QNX. By Sam Roberts. + + * pubkey.c (gcry_pk_algo_info): Add GCRYCTL_GET_ALGO_USAGE. + + * rsa.c: Changed the comment about the patent. + (secret): Speed up by using the CRT. For a 2k keys this + is about 3 times faster. + (stronger_key_check): New but unused code to check the secret key. + * Makefile.am: Included rsa.[ch]. + * pubkey.c: Enabled RSA support. + (pubkey_get_npkey): Removed RSA workaround. + +Mon Jul 31 10:04:47 CEST 2000 Werner Koch <wk@openit.de> + + * pubkey.c: Replaced all gcry_sexp_{car,cdr}_{data,mpi} by the new + gcry_sexp_nth_{data,mpi} functions. + +Tue Jul 25 17:44:15 CEST 2000 Werner Koch <wk@openit.de> + + * pubkey.c (exp_to_key,sexp_to_sig,sexp_to_enc,gcry_pk_encrypt, + gcry_pk_decrypt,gcry_pk_sign,gcry_pk_genkey): Changed to work with + the new S-Exp interface. + +Mon Jul 17 16:35:47 CEST 2000 Werner Koch <wk@> + + * random.c (gather_faked): Replaced make_timestamp by time(2) again. + +Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@> + + * md.c (gcry_md_ctl): Support GCRYCTL_{START,STOP}_DUMP. + + * Makefile.am: Never compile mingw32 as module. + + * Makefile.am: Tweaked module build and removed libtool + + * Makefile.am: Replaced -O1 by -O. Suggested by Alec Habig. + + * elgamal.c (sign): Removed inactive code. + + * rsa.c, rsa.h: New based on the old module version (only in CVS for now). + * pubkey.c (setup_pubkey_table): Added commented support for RSA. + + * rndunix.c (waitpid): New. For UTS 2.1. All by Dave Dykstra. + (my_popen): Do the FD_CLOEXEC only if it is available + (start_gatherer): Cope with missing _SC_OPEN_MAX + + * rndunix.c: Add some more headers for QNX. By Sam Roberts. + + * rndegd.c (gather_random): Shortcut level 0. + * rndunix.c (gather_random): Ditto. + * rndw32.c (gather_random): Ditto. + + * rndw32.c: Replaced with code from Cryptlib and commented the old stuff. + * rndw32.c: Add some debuging code enabled by an environment variable. + + * random.c (read_seed_file): Binary open for DOSish system + (update_random_seed_file): Ditto. + * random.c [MINGW32]: Include process.h for getpid. + * random.c (fast_random_poll): Add clock_gettime() as fallback for + system which support this POSIX.4 fucntion. By Sam Roberts. + + * random.c (read_seed_file): Removed the S_ISLNK test becuase it + is already covered by !S_ISREG and is not defined in Unixware. + Reported by Dave Dykstra. + (update_random_seed_file): Silently ignore update request when pool + is not filled. + + * random.c (read_seed_file): New. + (set_random_seed_file): New. + (read_pool): Try to read the seeding file. + (update_random_seed_file): New. + + (read_pool): Do an initial extra seeding when level 2 quality random + is requested the first time. This requestes at least POOLSIZE/2 bytes + of entropy. Compined with the seeding file this should make normal + random bytes cheaper and increase the quality of the random bytes + used for key generation. + + * random.c (read_pool): Print a more friendly error message in + cases when too much random is requested in one call. + + * random.c (fast_random_poll): Check whether RUSAGE_SELF is defined; + this is not the case for some ESIX and Unixware, although they have + getrusage(). + + * primegen.c (generate_elg_prime): All primes are now generated with + the lowest random quality level. Because they are public anyway we + don't need stronger random and by this we do not drain the systems + entropy so much. + + * primegen.c (register_primegen_progress): New. + * dsa.c (register_pk_dsa_progress): New. + * elgamal.c (register_pk_elg_progress): New. + + * elgamal.c (wiener_map): New. + (gen_k): Use a much smaller k. + (generate): Calculate the qbits using the wiener map and + choose an x at a size comparable to the one choosen in gen_k + + * rmd160.c (rmd160_get_info): Moved casting to the left side due to a + problem with UTS4.3. Suggested by Dave Dykstra. + * sha1.c (sha1_get_info): Ditto. + * tiger.c (tiger_get_info): Ditto. + * md5.c (md5_get_info): Ditto + * des.c (des_get_info): Ditto. + * blowfish.c (blowfish_get_info): Ditto. + * cast5.c (cast5_get_info): Ditto. + * twofish.c (twofish_get_info): Ditto. + +Fri Mar 24 11:25:45 CET 2000 Werner Koch <wk@openit.de> + + * md.c (md_open): Add hmac arg and allocate space for the pads. + (md_finalize): Add HMAC support. + (md_copy): Ditto. + (md_close): Ditto. + (gcry_md_reset): Ditto. + (gcry_md_ctl): Ditto. + (prepare_macpdas): New. + +Mon Mar 13 19:22:46 CET 2000 Werner Koch <wk@openit.de> + + * md.c (gcry_md_hash_buffer): Add support for the other algorithms. + +Mon Jan 31 16:37:34 CET 2000 Werner Koch <wk@gnupg.de> + + * genprime.c (generate_elg_prime): Fixed returned factors which never + worked for non-DSA keys. + +Thu Jan 27 18:00:44 CET 2000 Werner Koch <wk@gnupg.de> + + * pubkey.c (sexp_to_key): Fixed mem leaks in case of errors. + +Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de> + + * pubkey.c (gcry_pk_decrypt): Implemented. + (gcry_pk_encrypt): Implemented. + (gcry_pk_testkey): New. + (gcry_pk_genkey): New. + (pubkey_decrypt): Made static. + (pubkey_encrypt): Ditto. + (pubkey_check_secret_key): Ditto. + (pubkey_generate): Ditto. + +Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de> + + * pubkey.c (pubkey_nbits): Removed and replaced by ... + (gcry_pk_get_nbits): this new one. + +Wed Dec 8 21:58:32 CET 1999 Werner Koch <wk@gnupg.de> + + * dsa.c: s/mpi_powm/gcry_mpi_powm/g + * elgamal.c: Ditto. + * primegen.c: Ditto. + + * : Replaced g10_opt_verbose by g10_log_verbosity(). + + * Makefile.am (INCLUDES): removed intl, add ../gcrypt + +Fri Nov 19 17:15:20 CET 1999 Werner Koch <wk@gnupg.de> + + * dynload.c (cmp_filenames): New to replaced compare_filename() in + module. + (register_cipher_extension): Removed the tilde expansion stuff. + * rndeg.c (my_make_filename): New. + + * : Replaced header util.h by g10lib.h + + * random.c (gather_faked): Replaced make_timestamp by time(2). + Disabled wrning printed with tty_printf. + * rndlinux.c (gather_random): Always use fprintf instead of tty_xxx; + this should be replaced by a callback function. + + * primegen.c (gen_prime): Use gcry_mpi_randomize. + (is_prime): Ditto. + * elgamal.c (test_keys): Ditto. + * dsa.c (test_keys): Ditto. + + * cipher.c (gcry_cipher_close): Die on invalid handle. + +Mon Nov 15 21:36:02 CET 1999 Werner Koch <wk@gnupg.de> + + * elgamal.c (gen_k): Use the new random API. + (generate): Ditto. + * dsa.c (gen_k): Ditto. + (generate): Ditto. + +Sat Nov 13 17:44:23 CET 1999 Werner Koch <wk@gnupg.de> + + * pubkey.c (disable_pubkey_algo): Made static. + (gcry_pk_ctl): New. + + * random.c (get_random_bits): Renamed to ... + (get_random_bytes): ... this and made static. + (gcry_random_bytes): New. + (gcry_random_bytes_secure): New. + (randomize_buffer): Renamed to ... + (gcry_randomize): ...this. + + * md.c (gcry_md_hash_buffer): New. + + * pubkey.c (gcry_pk_algo_info): 4 new commands. + (pubkey_get_npkey): Made static. + (pubkey_get_nskey): Made static. + (pubkey_get_nsig): Made static. + (pubkey_get_nenc): Made static. + + * pubkey.c: Removed all G10ERR_xxx. + * cipher.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_CIPHER_ALGO. + * md.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_MD_ALGO. + * cast5.c (cast_setkey): Changed errocodes to GCRYERR_xxx. + * blowfish.c: Ditto. + * des.c: Ditto. + * twofish.c: Ditto. + * dsa.c: Ditto. + * elgamal.c: Ditto. + + * g10c.c: Removed + + * cipher.c (gcry_cipher_open): Replaced alloc functions and return NULL + if we are out of core. + * dynload.c: Replaced all memory allocation functions. + * md.c: Ditto. + * primegen.c: Ditto. + * pubkey.c: Ditto. + * random.c: Ditto. + * rndw32.c: Ditto. + * elgamal.c: Ditto. + * dsa.c: Ditto. + +Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de> + + * elgamal.c (sign): Hugh found strange code here. Replaced by BUG(). + + * cipher.c: Merged with gcrypt/symapi.c. + + * pubkey.c (string_to_pubkey_algo): Renamed function to ... + (gcry_pk_map_name): ... this. + (pubkey_algo_to_string): Renamed function to ... + (gcry_pk_algo_name): ... this. + (gcry_pk_algo_info): New. + * pubkey.c: Merged with gcrypt/pkapi.c. + + * md.c (md_reset): Clear finalized; thanks to Ulf Moeller for + fixing this bug. + + * md.c: Merged with gcrypt/mdapi.c + +Wed Sep 15 14:39:59 CEST 1999 Michael Roth <mroth@nessie.de> + + * des.c: Various speed improvements: One bit pre rotation + trick after initial permutation (Richard Outerbridge). + Finished test of SSLeay Tripple-DES patterns. + +Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndw32.c: New. + +Mon Sep 13 10:51:29 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * bithelp.h: New. + * rmd160.h, sha1.h, md5.h: Use the rol macro from bithelp.h + +Tue Sep 7 16:23:36 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Fixed seds for latest egcc. By Ollivier Robert. + +Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * des.c (selftest): Add some testpattern + +Mon Aug 30 20:38:33 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (do_cbc_encrypt): Fixed serious bug occuring when not using + in place encryption. Pointed out by Frank Stajano. + +Mon Jul 26 09:34:46 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * md5.c (md5_final): Fix for a SCO cpp bug. + +Thu Jul 15 10:15:35 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * elgamal.c (elg_check_secret_key,elg_encrypt + elg_decrypt,elg_sign,elg_verify): Sanity check on the args. + * dsa.c (dsa_check_secret_key,dsa_sign,dsa_verify): Ditto. + + * pubkey.c (disable_pubkey_algo): New. + (check_pubkey_algo2): Look at disabled algo table. + * cipher.c (disable_cipher_algo): New. + (check_cipher_algo): Look at disabled algo table. + +Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Support for libtool. + +Fri Jul 2 11:45:54 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * dsa.c (gen_k): Changed algorithm to consume less random bytes + * elgamal.c (gen_k): Ditto. + + * random.c (random_dump_stats): New. + +Thu Jul 1 12:47:31 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * primegen.c, elgamal.c, dsa.c (progess): New and replaced all + fputc with a call to this function. + +Sat Jun 26 12:15:59 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndegd.c (do_write): s/ssize_t/int/ due to SunOS 4.1 probs. + + * cipher.c (do_cbc_encrypt, do_cbc_decrypt): New. + + * dynload.c (HAVE_DL_SHL_LOAD): Map hpux API to dlopen (Dave Dykstra). + * Makefile.am (install-exec-hook): Removed. + +Sun May 23 14:20:22 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (setup_cipher_table): Enable Twofish + + * random.c (fast_random_poll): Disable use of times() for mingw32. + +Mon May 17 21:54:43 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (register_internal_cipher_extension): Minor init fix. + +Tue May 4 15:47:53 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * primegen.c (gen_prime): Readded the Fermat test. Fixed the bug + that we didn't correct for step when passing the prime to the + Rabin-Miller test which led to bad performance (Stefan Keller). + (check_prime): Add a first Fermat test. + +Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (cipher_setiv): Add ivlen arg, changed all callers. + + * random.c (randomize_buffer): alway use secure memory because + we can't use m_is_secure() on a statically allocated buffer. + + * twofish.c: Replaced some macros by a loop to reduce text size. + * Makefile.am (twofish): No more need for sed editing. + +Fri Apr 9 12:26:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (cipher_open): Reversed the changes for AUTO_CFB. + + * blowfish.c: Dropped the Blowfish 160 mode. + * cipher.c (cipher_open): Ditto. + (setup_cipher_table): Ditto. And removed support of twofish128 + +Wed Apr 7 20:51:39 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (get_random_bits): Can now handle requests > POOLSIZE + + * cipher.c (cipher_open): Now uses standard CFB for automode if + the blocksize is gt 8 (according to rfc2440). + + * twofish.c: Applied Matthew Skala's patches for 256 bit key. + +Tue Apr 6 19:58:12 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (get_random_bits): Can now handle requests > POOLSIZE + + * cipher.c (cipher_open): Now uses standard CFB for automode if + the blocksize is gt 8 (according to rfc2440). + +Sat Mar 20 11:44:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndlinux.c (tty_printf) [IS_MODULE]: Removed. + + * rndegd.c (gather_random): Some fixes. + +Wed Mar 17 13:09:03 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndegd.c (do_read): New. + (gather_random): Changed the implementation. + +Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed. + +Fri Feb 26 17:55:41 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * md.c: Nearly a total rewrote. + +Wed Feb 24 11:07:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (context): Fixed alignment + * md.c: Ditto. + + * rndegd.c: New + +Mon Feb 22 20:04:00 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndegd.c: New. + +Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Modules are now figured out by configure + * construct.c: New. Generated by configure. Changed all modules + to work with that. + * sha1.h: Removed. + * md5.h: Removed. + + * twofish.c: Changed interface to allow Twofish/256 + + * rndunix.c (start_gatherer): Die on SIGPIPE. + +Wed Jan 20 18:59:49 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndunix.c (gather_random): Fix to avoid infinite loop. + +Sun Jan 17 11:04:33 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * des.c (is_weak_key): Replace system memcmp due to bugs + in SunOS's memcmp. + (des_get_info): Return error on failed selftest. + * twofish.c (twofish_setkey): Return error on failed selftest or + invalid keylength. + * cast5.c (cast_setkey): Ditto. + * blowfish.c (bf_setkey): Return error on failed selftest. + +Tue Jan 12 11:17:18 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (random_is_faked): New. + + * tiger.c: Only compile if we have the u64 type + +Sat Jan 9 16:02:23 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndunix.c (gather_random): check for setuid. + + * Makefile.am: Add a way to staically link random modules + +Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * md.c (md_stop_debug): Do a flush first. + (md_open): size of buffer now depends on the secure parameter + +Sun Jan 3 15:28:44 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndunix.c (start_gatherer): Fixed stupid ==/= bug + +1998-12-31 Geoff Keating <geoffk@ozemail.com.au> + + * des.c (is_weak_key): Rewrite loop end condition. + +Tue Dec 29 14:41:47 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * random.c: add unistd.h for getpid(). + (RAND_MAX): Fallback value for Sun. + +Wed Dec 23 17:12:24 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * md.c (md_copy): Reset debug. + +Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (read_random_source): Changed the interface to the + random gathering function. + (gather_faked): Use new interface. + * dynload.c (dynload_getfnc_fast_random_poll): Ditto. + (dynload_getfnc_gather_random): Ditto. + * rndlinux.c (gather_random): Ditto. + * rndunix.c (gather_random): Ditto. + +Sat Dec 12 18:40:32 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (SYMBOL_VERSION): New to cope with system which needs + underscores. + + * rndunix.c: Rewrote large parts + +Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (load_extension): increased needed verbosity level. + + * random.c (fast_random_poll): Fallback to a default fast random + poll function. + (read_random_source): Always use the faked entroy gatherer if no + gather module is available. + * rndlinux.c (fast_poll): Removed. + * rndunix.c (fast_poll): Removed. + + +Wed Nov 25 12:33:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-*.c: Removed. + * rndlinux.c : New. + * rndunix.c : New. + * random.c : Restructured the interface to the gather modules. + (intialize): Call constructor functions + (read_radnom_source): Moved to here. + * dynload.c (dynload_getfnc_gather_random): New. + (dynload_getfnc_fast_random_poll): New. + (register_internal_cipher_extension): New. + (register_cipher_extension): Support of internal modules. + +Sun Nov 8 17:44:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c (read_random_source): Removed the assert. + +Mon Oct 19 18:34:30 1998 me,,, (wk@tobold) + + * pubkey.c: Hack to allow us to give some info about RSA keys back. + +Thu Oct 15 11:47:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dynload.c: Support for DLD + +Wed Oct 14 12:13:07 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c: Now uses names from configure for /dev/random. + +1998-10-10 SL Baur <steve@altair.xemacs.org> + + * Makefile.am: fix sed -O substitutions to catch -O6, etc. + +Tue Oct 6 10:06:32 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c (HAVE_GETTIMEOFDAY): Fixed (was ..GETTIMEOFTIME :-) + * rand-dummy.c (HAVE_GETTIMEOFDAY): Ditto. + +Mon Sep 28 13:23:09 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_digest): New. + (md_reset): New. + +Wed Sep 23 12:27:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c (TIGER_CONTEXT): moved "buf", so that it is 64 bit aligned. + +Mon Sep 21 06:22:53 1998 Werner Koch (wk@(none)) + + * des.c: Some patches from Michael. + +Thu Sep 17 19:00:06 1998 Werner Koch (wk@(none)) + + * des.c : New file from Michael Roth <mroth@nessie.de> + +Mon Sep 14 11:10:55 1998 Werner Koch (wk@(none)) + + * blowfish.c (bf_setkey): Niklas Hernaeus patch to detect weak keys. + +Mon Sep 14 09:19:25 1998 Werner Koch (wk@(none)) + + * dynload.c (RTLD_NOW): Now defined to 1 if it is undefined. + +Mon Sep 7 17:04:33 1998 Werner Koch (wk@(none)) + + * Makefile.am: Fixes to allow a different build directory + +Thu Aug 6 17:25:38 1998 Werner Koch,mobil,,, (wk@tobold) + + * random.c (get_random_byte): Removed and changed all callers + to use get_random_bits() + +Mon Jul 27 10:30:22 1998 Werner Koch (wk@(none)) + + * cipher.c : Support for other blocksizes + (cipher_get_blocksize): New. + * twofish.c: New. + * Makefile.am: Add twofish module. + +Mon Jul 13 21:30:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (read_pool): Simple alloc if secure_alloc is not set. + (get_random_bits): Ditto. + +Thu Jul 9 13:01:14 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dynload.c (load_extension): Function now nbails out if + the program is run setuid. + +Wed Jul 8 18:58:23 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (rmd160_hash_buffer): New. + +Thu Jul 2 10:50:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c (cipher_open): algos >=100 use standard CFB + +Thu Jun 25 11:18:25 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am: Support for extensions + +Thu Jun 18 12:09:38 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (mix_pool): simpler handling for level 0 + +Mon Jun 15 14:40:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c: Removed from dist, will reappear as dynload module + +Sat Jun 13 14:16:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * pubkey.c: Major changes to allow extensions. Changed the inteface + of all public key ciphers and added the ability to load extensions + on demand. + + * misc.c: Removed. + +Wed Jun 10 07:52:08 1998 Werner Koch,mobil,,, (wk@tobold) + + * dynload.c: New. + * cipher.c: Major changes to allow extensions. + +Mon Jun 8 22:43:00 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: Major internal chnages to support extensions. + * blowfish.c (blowfish_get_info): New and made all internal + functions static, changed heder. + * cast5.c (cast5_get_info): Likewise. + +Mon Jun 8 12:27:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c (transform): Fix for big endian + + * cipher.c (do_cfb_decrypt): Big endian fix. + +Fri May 22 07:30:39 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_get_oid): Add a new one for TIGER. + +Thu May 21 13:24:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: Add support for a dummy cipher + +Thu May 14 15:40:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (transform): fixed sigbus - I should better + add Christian von Roques's new implemenation of rmd160_write. + +Fri May 8 18:07:44 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-internal.h, rand-unix.c, rand-w32.c, rand_dummy.c: New + * random.c: Moved system specific functions to rand-****.c + +Fri May 8 14:01:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (fast_random_poll): add call to gethrtime. + +Tue May 5 21:28:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * elgamal.c (elg_generate): choosing x was not correct, could + yield 6 bytes which are not from the random pool, tsss, tsss.. + +Tue May 5 14:09:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * primegen.c (generate_elg_prime): Add arg mode, changed all + callers and implemented mode 1. + +Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c (cipher_get_keylen): New. + +Sun Apr 26 14:44:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c, tiger.h: New. + +Wed Apr 8 14:57:11 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (check_pubkey_algo2): New. + +Tue Apr 7 18:46:49 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: New + * misc.c (check_cipher_algo): Moved to cipher.c + * cast5.c: Moved many functions to cipher.c + * blowfish.c: Likewise. + +Sat Apr 4 19:52:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cast5.c: Implemented and tested. + +Wed Apr 1 16:38:27 1998 Werner Koch (wk@isil.d.shuttle.de) + + * elgamal.c (elg_generate): Faster generation of x in some cases. + +Thu Mar 19 13:54:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * blowfish.c (blowfish_decode_cfb): changed XOR operation + (blowfish_encode_cfb): Ditto. + +Thu Mar 12 14:04:05 1998 Werner Koch (wk@isil.d.shuttle.de) + + * sha1.c (transform): Rewrote + + * blowfish.c (encrypt): Unrolled for rounds == 16 + (decrypt): Ditto. + +Tue Mar 10 16:32:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (transform): Unrolled the loop. + +Tue Mar 10 13:05:14 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (read_pool): Add pool_balance stuff. + (get_random_bits): New. + + * elgamal.c (elg_generate): Now uses get_random_bits to generate x. + + +Tue Mar 10 11:33:51 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_digest_length): New. + +Tue Mar 10 11:27:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dsa.c (dsa_verify): Works. + +Mon Mar 9 12:59:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dsa.c, dsa.h: Removed some unused code. + +Wed Mar 4 10:39:22 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_open): Add call to fast_random_poll. + blowfish.c (blowfish_setkey): Ditto. + +Tue Mar 3 13:32:54 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (rmd160_mixblock): New. + * random.c: Restructured to start with a new RNG implementation. + * random.h: New. + +Mon Mar 2 19:21:46 1998 Werner Koch (wk@isil.d.shuttle.de) + + * gost.c, gost.h: Removed because they did only contain trash. + +Sun Mar 1 16:42:29 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (fill_buffer): removed error message if n == -1. + +Fri Feb 27 16:39:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_enable): No init if called twice. + +Thu Feb 26 07:57:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * primegen.c (generate_elg_prime): Changed the progress printing. + (gen_prime): Ditto. + +Tue Feb 24 12:28:42 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md5.c, md.5 : Replaced by a modified version of md5.c from + GNU textutils 1.22. + +Wed Feb 18 14:08:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c, md.h : New debugging support + +Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (cipher_algo_to_string): New + (pubkey_algo_to_string): New. + (digest_algo_to_string): New. + + + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/grub-core/lib/libgcrypt/cipher/ChangeLog-2011 b/grub-core/lib/libgcrypt/cipher/ChangeLog-2011 new file mode 100644 index 0000000..05516c9 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/ChangeLog-2011 @@ -0,0 +1,4247 @@ +2011-12-01 Werner Koch <wk@g10code.com> + + NB: ChangeLog files are no longer manually maintained. Starting + on December 1st, 2011 we put change information only in the GIT + commit log, and generate a top-level ChangeLog file from logs at + "make dist". See doc/HACKING for details. + +2011-06-29 Werner Koch <wk@g10code.com> + + * cipher.c (cipher_get_keylen): Return zero for an invalid algorithm. + (cipher_get_blocksize): Ditto. + +2011-06-13 Werner Koch <wk@g10code.com> + + * dsa.c (selftest_sign_1024): Use the raw and not the pkcs1 flag. + + * pubkey.c (gcry_pk_sign): Special case output generation for PKCS1. + (sexp_data_to_mpi): Parse "random-override" for pkcs1 encryption. + (pkcs1_encode_for_encryption): Add args RANDOM_OVERRIDE and + RANDOM_OVERRIDE_LEN. + (gcry_pk_encrypt): Special case output generation for PKCS1. + (sexp_data_to_mpi): Use GCRYMPI_FMT_USG for raw encoding. + +2011-06-10 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_sign): Use format specifier '%M' to avoid + leading zeroes. Special case output generation for PSS. + (gcry_pk_encrypt): Special case output generation for OAEP. + (sexp_data_to_mpi): Use GCRYMPI_FMT_USG for PSS verify. + +2011-06-09 Werner Koch <wk@g10code.com> + + * pubkey.c (oaep_decode): Make use of octet_string_from_mpi. + (sexp_to_enc): Skip "random-override". + + * pubkey.c (oaep_encode, pss_encode): Add args RANDOM_OVERRIDE and + RANDOM_OVERRIDE_LEN. + (sexp_data_to_mpi): Extract new random-override parameter. + + * pubkey.c (pss_encode, pss_verify): Use VALUE verbatim for MHASH. + (octet_string_from_mpi): Add arg SPACE. + +2011-06-08 Werner Koch <wk@g10code.com> + + * pubkey.c (pss_encode, pss_verify): Restructure and comment code + to match rfc-3447. Replace secure allocs by plain allocs and + wipememory. Use gcry_md_hash_buffer. + (octet_string_from_mpi): New. + +2011-06-03 Werner Koch <wk@g10code.com> + + * pubkey.c (oaep_decode): Add more comments and restructure to + match the description in RFC-3447. + (oaep_encode): Check for mgf1 error. s/dlen/hlen/. + +2011-05-31 Werner Koch <wk@g10code.com> + + * pubkey.c (mgf1): Optimize by using gcry_md_reset. Re-implement + for easier readability. + (oaep_encode): Add more comments and restructure to match the + description in RFC-3447. + + * pubkey.c (pkcs1_encode_for_signature, oaep_decode): Change + return value from one MPI to a buffer. + (gcry_pk_decrypt): Adjust for this change. + +2011-05-30 Werner Koch <wk@g10code.com> + + * pubkey.c (pkcs1_decode_for_encryption): Change handling of + leading zero byte. + +2011-05-27 Daiki Ueno <ueno@unixuser.org> + + * pubkey.c (gcry_pk_decrypt): Fix double-free when un-padding + invalid data. Thanks to Tom Ritter. + +2011-05-24 Daiki Ueno <ueno@unixuser.org> + + * rsa.c (rsa_verify): Use CMP if given, to check the decrypted + sig. + + * pubkey.c (sexp_to_enc, sexp_data_to_mpi): Factor out + CTX initialization to ... + (init_encoding_ctx): .. new. + (gcry_pk_verify): Pass verify func and the arg to pubkey_verify. + (pss_encode, pss_verify, pss_verify_cmp): New. + +2011-05-23 Daiki Ueno <ueno@unixuser.org> + + * pubkey.c (pkcs1_decode_for_encryption, oaep_decode): Fix memleak + when gcry_mpi_print fails. + +2011-05-18 Daiki Ueno <ueno@unixuser.org> + + * pubkey.c (sexp_data_to_mpi): Factor some code out to ... + (pkcs1_encode_for_encryption): .. new, + (pkcs1_encode_for_signature): .. new. + (pkcs1_decode_for_encryption): New. + (gcry_pk_decrypt): Do un-padding for PKCS#1 as well as OAEP. + (sexp_to_enc): Abolish "unpad" flag, which is not necessary since + we can do un-padding implicitly when "pkcs1" or "oaep" is given. + +2011-05-11 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_to_enc, sexp_data_to_mpi): Set LABEL to NULL + after free. + (sexp_to_enc, sexp_data_to_mpi): Do not allow multiple encoding + flags. + (oaep_encode, oaep_decode, sexp_to_key, sexp_to_sig) + (sexp_to_enc, sexp_data_to_mpi, gcry_pk_encrypt, gcry_pk_sign) + (gcry_pk_genkey, _gcry_pk_get_elements): Replace access to ERRNO + by gpg_err_code_from_syserror. + +2011-05-11 Daiki Ueno <ueno@unixuser.org> + + * pubkey.c (sexp_data_to_mpi): Factor some code out to ... + (get_hash_algo): .. new. + (mgf1, oaep_encode, oaep_decode): New. + (sexp_to_enc): Add arg CTX. Remove arg RET_WANT_PKCS1. Support + OAEP. + (sexp_data_to_mpi): Add arg CTX. Support OAEP. + (gcry_pk_encrypt): Pass a CTX to sexp_data_to_mpi. + (gcry_pk_decrypt): Pass a CTX tp sexp_to_enc and replace + WANT_PKCS1. Implement unpadding for OAEP. + (gcry_pk_sign): Pass NULL for CTX arg of sexp_data_to_mpi. + (gcry_pk_verify): Ditto. + +2011-04-19 Werner Koch <wk@g10code.com> + + * cipher.c (gcry_cipher_open): Replace gpg_err_code_from_errno by + gpg_err_code_from_syserror. + +2011-04-11 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_get_keygrip): Avoid double free of L2. + + * cipher.c (_gcry_cipher_setctr): Clear unused lastiv info. + (gcry_cipher_ctl) <GCRYCTL_SET_CTR>: Implement by calling + _gcry_cipher_setctr. + (do_ctr_encrypt): Save last counter and reuse it. + + * cipher.c (do_ctr_encrypt): Allow arbitrary length inputs to + match the 1.4 behaviour. + +2011-04-04 Werner Koch <wk@g10code.com> + + * ecc.c (compute_keygrip): Release L1 while parsing "curve". + + * pubkey.c (gcry_pk_get_keygrip): Always release NAME and L2. + Reported by Ben Kibbey. + +2011-03-28 Werner Koch <wk@g10code.com> + + * primegen.c (_gcry_generate_elg_prime): Make sure that PRIME is + NULL if the called func ever returns an error. + + * pubkey.c (gcry_pk_decrypt): Remove unused var PUBKEY. + +2011-03-09 Werner Koch <wk@g10code.com> + + * kdf.c: New. + +2011-02-22 Werner Koch <wk@g10code.com> + + * rijndael.c (aesni_cleanup_2_4): New. + (aesenc_xmm1_xmm0, do_aesni_ctr_4): New. + (_gcry_aes_ctr_enc): New. + * cipher.c (struct gcry_cipher_handle): Add CTR_ENC. Move field + CTR into an u_ctr union and adjust all users. + (gcry_cipher_open): Use _gcry_aes_ctr_enc. + (do_ctr_encrypt): Use bulk mode. + +2011-02-18 Werner Koch <wk@g10code.com> + + * rijndael.c (u32_a_t): New. + (do_encrypt_aligned, do_encrypt_aligned): Use the new type to + avoid problems with strict aliasing rules. + +2011-02-16 Werner Koch <wk@g10code.com> + + * rijndael.c (do_aesni_cfb) [USE_AESNI]: New. + (_gcry_aes_cfb_enc, _gcry_aes_cfb_dec) [USE_AESNI]: Use new fucntion. + +2011-02-15 Werner Koch <wk@g10code.com> + + * rijndael.c (do_aesni_enc_aligned, do_aesni_dec_aligned): Use + movdqa for the key but keep using movdqu for the data. + (do_aesni): Remove alignment detection. Don't burn the stack. + (aesni_prepare, aesni_cleanup): New macros. + (rijndael_encrypt, _gcry_aes_cfb_enc, _gcry_aes_cbc_enc) + (rijndael_decrypt, _gcry_aes_cfb_dec, _gcry_aes_cbc_dec): Use + these macros. Don't burn the stack in the USE_AESNI case. + (do_setkey): Add disabled code to use aeskeygenassist. + +2011-02-14 Werner Koch <wk@g10code.com> + + * rijndael.c (ATTR_ALIGNED_16): New + (do_aesni): Do not copy if already aligned. + (do_encrypt, do_decrypt): Ditto. + (rijndael_decrypt, rijndael_encrypt): Increase stack burning amount. + + * rijndael.c (RIJNDAEL_context): Reorder fields. Change fieldname + ROUNDS to rounds. Move padlock_key into u1. + (keySched, keySched2): Rename macros to keyscherr and keyschdec + and change all users. + (padlockkey): New macro. Change all users of padlock_key. + * cipher.c (NEED_16BYTE_ALIGNED_CONTEXT): Always define if using gcc. + (struct gcry_cipher_handle): Align U_IV to at least 16 byte. + +2011-02-13 Werner Koch <wk@g10code.com> + + * rijndael.c (USE_AESNI): New. Define for ia32 and gcc >= 4. + (m128i_t) [USE_AESNI]: New. + (RIJNDAEL_context) [USE_AESNI]: Add field use_aesni. + (do_setkey): Set USE_AESNI for all key lengths. + (prepare_decryption) [USE_AESNI]: Use aesimc instn if requested. + (do_aesni_enc_aligned, do_aesni_dec_aligned) + (do_aesni) [USE_AESNI]: New. + (rijndael_encrypt, _gcry_aes_cfb_enc, _gcry_aes_cbc_enc) + (rijndael_decrypt, _gcry_aes_cfb_dec) + (_gcry_aes_cbc_dec) [USE_AESNI]: Use do_aesni. + +2011-02-01 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_get_curve): New. + (sexp_to_key): Add arg OVERRIDE_ELEMS. + (sexp_elements_extract_ecc): Allow for params only. + (gcry_pk_get_param): New. + * ecc.c (ecc_get_curve): New. + (ecc_get_param_sexp): New. + +2011-01-28 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Hack to insert the used curve name. + +2011-01-27 Werner Koch <wk@g10code.com> + + * ecc.c (fill_in_curve): Remove. + (generate_curve): Rename to .. + (fill_in_curve): this. Remove setting of NAME_OID. + (ecc_encrypt_raw): Change name of arg DATA to K for better + readability. Use ECC_public_key instead of ECC_secret_key. + Require a caller to pass a complete pkey array. + (ecc_decrypt_raw): Require a caller to pass a complete skey array. + (elliptic_curve_t): Add field NAME. + (fill_in_curve): Set field. + (generate_key): Add arg R_USED_CURVE. + (ecc_generate_ext): Return used curve name. + +2011-01-13 Andrey Jivsov <openpgp@brainhub.org> (wk) + + * ecc.c (ec2os): Do not free passed parameters X and Y. Adjust + callers. + (ecc_encrypt_raw, ecc_decrypt_raw): New. + (ecdh_names, _gcry_pubkey_spec_ecdh): New. + * pubkey.c (pubkey_table): Support ECDH. + +2010-08-19 Werner Koch <wk@g10code.com> + + * cipher.c (gcry_cipher_open): Remove double release of the module. + Fixes bug#1263. + +2010-06-10 Jeff Johnson <n3npq@mac.com> (wk) + + * ecc.c (ecc_generate_ext): Parse transient-key flag. + (generate_key): Add arg TRANSIENT_KEY and use it to set the random + level. + +2010-04-12 Brad Hards <bradh@frogmouth.net> (wk) + + Spelling fixes. + +2010-03-26 Werner Koch <wk@g10code.com> + + * tiger.c (asn): Unfetter the old TIGER from an OID. + (TIGER_CONTEXT): Add field VARIANT. + (tiger_init): Factor code out to ... + (do_init): New. + (tiger1_init, tiger2_init): New. + (_gcry_digest_spec_tiger1, _gcry_digest_spec_tiger2): New. + * md.c (digest_table): Add TIGER1 and TIGER2 variants. + +2009-12-11 Werner Koch <wk@g10code.com> + + * sha256.c (Cho, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables + + * sha512.c (ROTR, Ch, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables. + Suggested by Christian Grothoff. + +2009-12-10 Werner Koch <wk@g10code.com> + + * Makefile.am (o_flag_munging): New. + (tiger.o, tiger.lo): Use it. + + * cipher.c (do_ctr_encrypt): Add arg OUTBUFLEN. Check for + suitable value. Add check for valid inputlen. Wipe temporary + memory. + (do_ctr_decrypt): Likewise. + (do_cbc_encrypt, do_cbc_decrypt): Add arg OUTBUFLEN. Check for + suitable value. Move check for valid inputlen to here; change + returned error from INV_ARG to INV_LENGTH. + (do_ecb_encrypt, do_ecb_decrypt): Ditto. + (do_cfb_encrypt, do_cfb_decrypt): Ditto. + (do_ofb_encrypt, do_ofb_decrypt): Ditto. + (cipher_encrypt, cipher_encrypt): Adjust for above changes. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Simplify. + +2009-12-09 Werner Koch <wk@g10code.com> + + * cipher.c (gcry_cipher_open): Allow for GCRY_CIPHER_MODE_AESWRAP. + (cipher_encrypt, cipher_decrypt): Ditto. + (do_aeswrap_encrypt, do_aeswrap_decrypt): New. + (struct gcry_cipher_handle): Add field marks. + (cipher_setkey, cipher_setiv): Update marks flags. + (cipher_reset): Reset marks. + (cipher_encrypt, cipher_decrypt): Add new arg OUTBUFLEN. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Pass outbuflen to + cipher_encrypt. Replace GPG_ERR_TOO_SHORT by + GPG_ERR_BUFFER_TOO_SHORT. + +2009-08-21 Werner Koch <wk@g10code.com> + + * dsa.c (dsa_generate_ext): Release retfactors array before + setting it to NULL. Reported by Daiko Ueno. + +2009-07-02 Werner Koch <wk@g10code.com> + + * md.c (md_read): Fix incomplete check for NULL. + Reported by Fabian Kail. + +2009-03-31 Werner Koch <wk@g10code.com> + + * rsa.c (rsa_check_secret_key): Return GPG_ERR_BAD_SECKEY and not + GPG_ERR_PUBKEY_ALGO. + +2009-02-16 Werner Koch <wk@g10code.com> + + * rsa.c (generate_x931): Do not initialize TBL with automatic + variables. + * whirlpool.c, tiger.c, sha256.c, sha1.c, rmd160.c, md5.c + * md4.c, crc.c: Remove memory.h. This is garbage from gnupg. + Reported by Dan Fandrich. + +2009-01-22 Werner Koch <wk@g10code.com> + + * ecc.c (compute_keygrip): Remove superfluous const. + +2009-01-06 Werner Koch <wk@g10code.com> + + * rmd160.c (oid_spec_rmd160): Add TeleTrust identifier. + +2008-12-10 Werner Koch <wk@g10code.com> + + * dsa.c (generate): Add arg DOMAIN and use it if specified. + (generate_fips186): Ditto. + (dsa_generate_ext): Parse and check the optional "domain" + parameter and pass them to the generate functions. + + * rijndael.c (rijndael_names): Add "AES128" and "AES-128". + (rijndael192_names): Add "AES-192". + (rijndael256_names): Add "AES-256". + +2008-12-05 Werner Koch <wk@g10code.com> + + * dsa.c (generate): Add arg TRANSIENT_KEY and use it to detrmine + the RNG quality needed. + (dsa_generate_ext): Parse the transient-key flag und pass it to + generate. + +2008-11-28 Werner Koch <wk@g10code.com> + + * dsa.c (generate_fips186): Add arg DERIVEPARMS and use the seed + value if available. + + * primegen.c (_gcry_generate_fips186_2_prime): Fix inner p loop. + +2008-11-26 Werner Koch <wk@g10code.com> + + * primegen.c (_gcry_generate_fips186_3_prime): New. + * dsa.c (generate_fips186): Add arg USE_FIPS186_2. + (dsa_generate_ext): Parse new flag use-fips183-2. + +2008-11-25 Werner Koch <wk@g10code.com> + + * dsa.c (generate_fips186): New. + (dsa_generate_ext): Use new function if derive-parms are given or + if in FIPS mode. + * primegen.c (_gcry_generate_fips186_2_prime): New. + +2008-11-24 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Insert code to output extrainfo. + (pubkey_generate): Add arg R_EXTRAINFO and pass it to the extended + key generation function. + * rsa.c (gen_x931_parm_xp, gen_x931_parm_xi): New. + (generate_x931): Generate params if not given. + (rsa_generate_ext): Parse use-x931 flag. Return p-q-swapped + indicator. + * dsa.c (dsa_generate_ext): Put RETFACTORS into R_EXTRAINFO if + possible. + + * pubkey.c (gcry_pk_genkey): Remove parsing of almost all + parameters and pass the parameter S-expression to pubkey_generate. + (pubkey_generate): Simplify by requitring modules to parse the + parameters. Remove the special cases for Elgamal and ECC. + (sexp_elements_extract_ecc): Add arg EXTRASPEC and use it. Fix + small memory leak. + (sexp_to_key): Pass EXTRASPEC to sexp_elements_extract_ecc. + (pubkey_table) [USE_ELGAMAL]: Add real extraspec. + * rsa.c (rsa_generate_ext): Adjust for new calling convention. + * dsa.c (dsa_generate_ext): Ditto. + * elgamal.c (_gcry_elg_generate): Ditto. Rename to elg_generate_ext. + (elg_generate): New. + (_gcry_elg_generate_using_x): Remove after merging code with + elg_generate_ext. + (_gcry_pubkey_extraspec_elg): New. + (_gcry_elg_check_secret_key, _gcry_elg_encrypt, _gcry_elg_sign) + (_gcry_elg_verify, _gcry_elg_get_nbits): Make static and remove + _gcry_ prefix. + * ecc.c (_gcry_ecc_generate): Rename to ecc_generate_ext and + adjust for new calling convention. + (_gcry_ecc_get_param): Rename to ecc_get_param and make static. + (_gcry_pubkey_extraspec_ecdsa): Add ecc_generate_ext and + ecc_get_param. + +2008-11-20 Werner Koch <wk@g10code.com> + + * pubkey.c (pubkey_generate): Add arg DERIVEPARMS. + (gcry_pk_genkey): Parse derive-parms and pass it to above. + * rsa.c (generate_x931): New. + (rsa_generate_ext): Add arg DERIVEPARMS and call new function in + fips mode or if DERIVEPARMS is given. + * primegen.c (_gcry_derive_x931_prime, find_x931_prime): New. + +2008-11-19 Werner Koch <wk@g10code.com> + + * rsa.c (rsa_decrypt): Use gcry_create_nonce for blinding. + (generate): Rename to generate_std. + +2008-11-05 Werner Koch <wk@g10code.com> + + * md.c (md_open): Use a switch to set the Bsize. + (prepare_macpads): Fix long key case for SHA384 and SHA512. + + * cipher.c (gcry_cipher_handle): Add field EXTRASPEC. + (gcry_cipher_open): Set it. + (gcry_cipher_ctl): Add private control code to disable weak key + detection and to return the current input block. + * des.c (_tripledes_ctx): Add field FLAGS. + (do_tripledes_set_extra_info): New. + (_gcry_cipher_extraspec_tripledes): Add new function. + (do_tripledes_setkey): Disable weak key detection. + +2008-10-24 Werner Koch <wk@g10code.com> + + * md.c (digest_table): Allow MD5 in fips mode. + (md_register_default): Take special action for MD5. + (md_enable, gcry_md_hash_buffer): Ditto. + +2008-09-30 Werner Koch <wk@g10code.com> + + * rijndael.c (do_setkey): Properly align "t" and "tk". + (prepare_decryption): Properly align "w". Fixes bug #936. + +2008-09-18 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Parse domain parameter. + (pubkey_generate): Add new arg DOMAIN and remove special case for + DSA with qbits. + * rsa.c (rsa_generate): Add dummy args QBITS, NAME and DOMAIN and + rename to rsa_generate_ext. Change caller. + (_gcry_rsa_generate, _gcry_rsa_check_secret_key) + (_gcry_rsa_encrypt, _gcry_rsa_decrypt, _gcry_rsa_sign) + (_gcry_rsa_verify, _gcry_rsa_get_nbits): Make static and remove + _gcry_ prefix. + (_gcry_pubkey_spec_rsa, _gcry_pubkey_extraspec_rsa): Adjust names. + * dsa.c (dsa_generate_ext): New. + (_gcry_dsa_generate): Replace code by a call to dsa_generate. + (_gcry_dsa_check_secret_key, _gcry_dsa_sign, _gcry_dsa_verify) + (_gcry_dsa_get_nbits): Make static and remove _gcry prefix. + (_gcry_dsa_generate2): Remove. + (_gcry_pubkey_spec_dsa): Adjust to name changes. + (_gcry_pubkey_extraspec_rsa): Add dsa_generate_ext. + +2008-09-16 Werner Koch <wk@g10code.com> + + * ecc.c (run_selftests): Add arg EXTENDED. + +2008-09-12 Werner Koch <wk@g10code.com> + + * rsa.c (test_keys): Do a bad case signature check. + * dsa.c (test_keys): Do a bad case check. + + * cipher.c (_gcry_cipher_selftest): Add arg EXTENDED and pass it + to the called tests. + * md.c (_gcry_md_selftest): Ditto. + * pubkey.c (_gcry_pk_selftest): Ditto. + * rijndael.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftest_fips_128): Add arg EXTENDED and run only one test + non-extended mode. + (selftest_fips_192): Add dummy arg EXTENDED. + (selftest_fips_256): Ditto. + * hmac-tests.c (_gcry_hmac_selftest): Ditto. + (run_selftests): Ditto. + (selftests_sha1): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha224, selftests_sha256): Ditto. + (selftests_sha384, selftests_sha512): Ditto. + * sha1.c (run_selftests): Add arg EXTENDED and pass it to the + called test. + (selftests_sha1): Add arg EXTENDED and run only one test + non-extended mode. + * sha256.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftests_sha224): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha256): Ditto. + * sha512.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftests_sha384): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha512): Ditto. + * des.c (run_selftests): Add arg EXTENDED and pass it to the + called test. + (selftest_fips): Add dummy arg EXTENDED. + * rsa.c (run_selftests): Add dummy arg EXTENDED. + + * dsa.c (run_selftests): Add dummy arg EXTENDED. + + * rsa.c (extract_a_from_sexp): New. + (selftest_encr_1024): Check that the ciphertext does not match the + plaintext. + (test_keys): Improve tests and return an error status. + (generate): Return an error if test_keys fails. + * dsa.c (test_keys): Add comments and return an error status. + (generate): Return an error if test_keys failed. + +2008-09-11 Werner Koch <wk@g10code.com> + + * rsa.c (_gcry_rsa_decrypt): Return an error instead of calling + BUG in case of a practically impossible condition. + (sample_secret_key, sample_public_key): New. + (selftest_sign_1024, selftest_encr_1024): New. + (selftests_rsa): Implement tests. + * dsa.c (sample_secret_key, sample_public_key): New. + (selftest_sign_1024): New. + (selftests_dsa): Implement tests. + +2008-09-09 Werner Koch <wk@g10code.com> + + * hmac-tests.c (selftests_sha1): Add tests. + (selftests_sha224, selftests_sha384, selftests_sha512): Make up tests. + + * hash-common.c, hash-common.h: New. + * sha1.c (selftests_sha1): Add 3 tests. + * sha256.c (selftests_sha256, selftests_sha224): Ditto. + * sha512.c (selftests_sha512, selftests_sha384): Ditto. + +2008-08-29 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_get_keygrip): Remove the special case for RSA + and check whether a custom computation function has been setup. + * rsa.c (compute_keygrip): New. + (_gcry_pubkey_extraspec_rsa): Setup this function. + * ecc.c (compute_keygrip): New. + (_gcry_pubkey_extraspec_ecdsa): Setup this function. + +2008-08-28 Werner Koch <wk@g10code.com> + + * cipher.c (cipher_decrypt, cipher_encrypt): Return an error if + mode NONE is used. + (gcry_cipher_open): Allow mode NONE only with a debug flag set and + if not in FIPS mode. + +2008-08-26 Werner Koch <wk@g10code.com> + + * pubkey.c (pubkey_generate): Add arg KEYGEN_FLAGS. + (gcry_pk_genkey): Implement new parameter "transient-key" and + pass it as flags to pubkey_generate. + (pubkey_generate): Make use of an ext_generate function. + * rsa.c (generate): Add new arg transient_key and pass appropriate + args to the prime generator. + (_gcry_rsa_generate): Factor all code out to ... + (rsa_generate): .. new func with extra arg KEYGEN_FLAGS. + (_gcry_pubkey_extraspec_ecdsa): Setup rsa_generate. + * primegen.c (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Add new arg RANDOM_LEVEL. + +2008-08-21 Werner Koch <wk@g10code.com> + + * primegen.c (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Use a constant macro for the random + level. + +2008-08-19 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_elements_extract_ecc) [!USE_ECC]: Do not allow + allow "curve" parameter. + +2008-08-15 Werner Koch <wk@g10code.com> + + * pubkey.c (_gcry_pk_selftest): New. + * dsa.c (selftests_dsa, run_selftests): New. + * rsa.c (selftests_rsa, run_selftests): New. + * ecc.c (selftests_ecdsa, run_selftests): New. + + * md.c (_gcry_md_selftest): New. + * sha1.c (run_selftests, selftests_sha1): New. + * sha256.c (selftests_sha224, selftests_sha256, run_selftests): New. + * sha512.c (selftests_sha384, selftests_sha512, run_selftests): New. + + * des.c (selftest): Remove static variable form selftest. + (des_setkey): No on-the-fly self test in fips mode. + (tripledes_set3keys): Ditto. + + * cipher.c (_gcry_cipher_setkey, _gcry_cipher_setiv): + + * dsa.c (generate): Bail out in fips mode if NBITS is less than 1024. + * rsa.c (generate): Return an error code if the the requested size + is less than 1024 and we are in fpis mode. + (_gcry_rsa_generate): Take care of that error code. + + * ecc.c (generate_curve): In fips mode enable only NIST curves. + + * cipher.c (_gcry_cipher_selftest): New. + + * sha512.c (_gcry_digest_extraspec_sha384) + (_gcry_digest_extraspec_sha512): New. + * sha256.c (_gcry_digest_extraspec_sha224) + (_gcry_digest_extraspec_sha256): New. + * sha1.c (_gcry_digest_extraspec_sha1): New. + * ecc.c (_gcry_pubkey_extraspec_ecdsa): New. + * dsa.c (_gcry_pubkey_extraspec_dsa): New. + * rsa.c (_gcry_pubkey_extraspec_rsa): New. + * rijndael.c (_gcry_cipher_extraspec_aes) + (_gcry_cipher_extraspec_aes192, _gcry_cipher_extraspec_aes256): New. + * des.c (_gcry_cipher_extraspec_tripledes): New. + + * cipher.c (gcry_cipher_register): Rename to _gcry_cipher_register. + Add arg EXTRASPEC. + (dummy_extra_spec): New. + (cipher_table_entry): Add extraspec field. + * md.c (_gcry_md_register): Rename to _gcry_md_register. Add + arg EXTRASPEC. + (dummy_extra_spec): New. + (digest_table_entry): Add extraspec field. + * pubkey.c (gcry_pk_register): Rename to _gcry_pk_register. Add + arg EXTRASPEC. + (dummy_extra_spec): New. + (pubkey_table_entry): Add extraspec field. + + * ac.c: Let most public functions return GPG_ERR_UNSUPPORTED in + fips mode. + + * pubkey.c (pubkey_table_entry): Add field FIPS_ALLOWED and mark + appropriate algorithms. + (dummy_generate, dummy_check_secret_key, dummy_encrypt) + (dummy_decrypt, dummy_sign, dummy_verify, dummy_get_nbits): Signal + a fips error when used. + (gcry_pk_register): In fips mode do not allow to register new + algorithms. + + * md.c (digest_table): Add field FIPS_ALLOWED and mark appropriate + algorithms. + (md_register_default): In fips mode register only fips algorithms. + (gcry_md_register): In fips mode do not allow to register new + algorithms. + (gcry_md_get): Signal a fips error if called. + (gcry_md_hash_buffer): Do not allow rmd160 when not in fips mode. + (md_start_debug): Disable in fips_mode. + + * md.c (gcry_md_register_default): Rename to .. + (md_register_default): .. this. + (md_digest): Remove this commented fucntion. + * pubkey.c (gcry_pk_register_default): Rename to .. + (pk_register_default): .. this. + + * cipher.c (cipher_table_entry): Add field FIPS_ALLOWED. + (gcry_cipher_register_default): Register only fips approved + algorithms. + (gcry_cipher_register): Do not allow to register new ciphers. + (cipher_setiv): Signal fips error. + + * cipher (gcry_cipher_register_default): Rename to .. + (cipher_register_default): .. this. + (REGISTER_DEFAULT_CIPHERS): Adjust for that change. + +2008-07-05 Werner Koch <wk@g10code.com> + + * random-daemon.c, random.h, rndhw.c, rndunix.c, rand-internal.h + * random.c, rndegd.c, rndlinux.c, rndw32.c: Move to ../cipher. + * Makefile.am: Remove random stuff. + +2008-06-24 Szakats Istvan <szaki.ms@gmail.com> (wk) + + * ac.c (_gcry_ac_key_destroy, _gcry_ac_key_pair_generate): Relase + some more memory. + +2008-04-22 Werner Koch <wk@g10code.com> + + * rijndael.c (_gcry_aes_cfb_enc, _gcry_aes_cbc_enc) + (_gcry_aes_cfb_dec, _gcry_aes_cbc_dec): Use Padlock if possible. + +2008-04-18 Werner Koch <wk@g10code.com> + + * sha1.c (transform_aligned): Remove. That is will obviosuly not + work because we need a scratch working area and our internal API + does not allow to modify the buffers. + + * rijndael.c: Factor tables out to .. + * rijndael-tables.h: .. new. + + * ac.c (ac_data_extract): Make static. + + * camellia.h [HAVE_CONFIG_H]: Include config.h. + + * rndw32.c (registry_poll): Only print the performance data + problem warning once. Suggested by Simon Josefsson. + +2008-03-19 Werner Koch <wk@g10code.com> + + * cipher.c (gcry_cipher_open) [USE_AES]: Init bulk encryption only + if requested. Suggested by Dirk Stoecker. + +2008-03-18 Werner Koch <wk@g10code.com> + + * sha1.c: Include stdint.h. + (transform): Add arg NBLOCKS so that we can work on more than one + block and avoid updates of the chaining variables. Changed all + callers to use 1. + (sha1_write): Replace loop around transform. + (transform_aligned) [WORDS_BIGENDIAN]: New. + (TRANSFORM): New macro to replace all direct calls of transform. + +2008-03-17 Werner Koch <wk@g10code.com> + + * rijndael.c (_gcry_aes_cfb_dec): New. + (do_encrypt): Factor code out to .. + (do_encrypt_aligned): .. New. + (_gcry_aes_cfb_enc, _gcry_aes_cfb_dec): Use new function. + (do_decrypt): Factor code out to .. + (do_decrypt_aligned): .. new. + (_gcry_aes_cbc_enc, _gcry_aes_cbc_dec): New. + * cipher.c (struct gcry_cipher_handle): Put field IV into new + union U_IV to enforce proper alignment. Change all users. + (do_cfb_decrypt): Optimize. + (do_cbc_encrypt, do_cbc_decrypt): Optimize. + +2008-03-15 Werner Koch <wk@g10code.com> + + * rijndael.c (_gcry_aes_cfb_enc): New. + * cipher.c (struct gcry_cipher_handle): Add field ALGO and BULK. + (gcry_cipher_open): Set ALGO and BULK. + (do_cfb_encrypt): Optimize. + +2008-02-18 Werner Koch <wk@g10code.com> + + * rsa.c (_gcry_rsa_verify) [IS_DEVELOPMENT_VERSION]: Print + intermediate results. + +2008-01-08 Werner Koch <wk@g10code.com> + + * random.c (add_randomness): Do not just increment + POOL_FILLED_COUNTER but update it by the actual amount of data. + +2007-12-13 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_data_to_mpi): Support SHA-224. + +2007-12-05 Werner Koch <wk@g10code.com> + + * rijndael.c (USE_PADLOCK): Depend on ENABLE_PADLOCK_SUPPORT. + * rndhw.c (USE_PADLOCK): Ditto + + * rsa.c (secret): Fixed condition test for using CRT. Reported by + Dean Scarff. Fixes bug#864. + (_gcry_rsa_check_secret_key): Return an erro if the optional + parameters are missing. + * pubkey.c (sexp_elements_extract): Add arg ALGO_NAME. Changed all + callers to pass NULL. Add hack to allow for optional RSA + parameters. + (sexp_to_key): Pass algo name to sexp_elements_extract. + +2007-12-03 Werner Koch <wk@g10code.com> + + * random.c (gcry_random_add_bytes): Implement it. + * rand-internal.h (RANDOM_ORIGIN_EXTERNAL): New. + +2007-11-30 Werner Koch <wk@g10code.com> + + * rndhw.c: New. + * rndlinux.c (_gcry_rndlinux_gather_random): Try to read 50% + directly from the hwrng. + * random.c (do_fast_random_poll): Also run the hw rng fast poll. + (_gcry_random_dump_stats): Tell whether the hw rng failed. + +2007-11-29 Werner Koch <wk@g10code.com> + + * rijndael.c (USE_PADLOCK): Define new macro used for ia32. + (RIJNDAEL_context) [USE_PADLOCK]: Add fields USE_PADLOCK and + PADLOCK_KEY. + (do_setkey) [USE_PADLOCK]: Enable padlock if available for 128 bit + AES. + (do_padlock) [USE_PADLOCK]: New. + (rijndael_encrypt, rijndael_decrypt) [USE_PADLOCK]: Divert to + do_padlock. + * cipher.c (cipher_context_alignment_t): New. Use it in this + module in place of PROPERLY_ALIGNED_TYPE. + (NEED_16BYTE_ALIGNED_CONTEXT): Define macro for ia32. + (struct gcry_cipher_handle): Add field HANDLE_OFFSET. + (gcry_cipher_open): Take care of increased alignment requirements. + (gcry_cipher_close): Ditto. + +2007-11-28 Werner Koch <wk@g10code.com> + + * sha256.c (asn224): Fixed wrong template. It happened due to a + bug in RFC4880. SHA-224 is not in the stable version of libgcrypt + so the consequences are limited to users of this devel version. + +2007-10-31 Werner Koch <wk@g10code.com> + + * ac.c (gcry_ac_data_new): Remove due to the visibility wrapper. + (gcry_ac_data_destroy, gcry_ac_data_copy, gcry_ac_data_length) + (gcry_ac_data_set, gcry_ac_data_get_name, gcry_ac_data_get_index) + (gcry_ac_data_to_sexp, gcry_ac_data_from_sexp) + (gcry_ac_data_clear, gcry_ac_io_init, gcry_ac_open) + (gcry_ac_close, gcry_ac_key_init, gcry_ac_key_pair_generate) + (gcry_ac_key_pair_extract, gcry_ac_key_destroy) + (gcry_ac_key_pair_destroy, gcry_ac_key_data_get) + (gcry_ac_key_test, gcry_ac_key_get_nbits, gcry_ac_key_get_grip) + (gcry_ac_data_encrypt, gcry_ac_data_decrypt, gcry_ac_data_sign) + (gcry_ac_data_verify, gcry_ac_data_encode, gcry_ac_data_decode) + (gcry_ac_mpi_to_os, gcry_ac_mpi_to_os_alloc, gcry_ac_os_to_mpi) + (gcry_ac_data_encrypt_scheme, gcry_ac_data_decrypt_scheme) + (gcry_ac_data_sign_scheme, gcry_ac_data_verify_scheme) + (gcry_ac_io_init_va): Ditto. + (gcry_ac_id_to_name, gcry_ac_name_to_id): Remove as these + deprecated functions are now implemented by visibility.c. + +2007-10-26 Werner Koch <wk@g10code.com> + + * rndw32.c: Disable debug flag. + +2007-10-25 Werner Koch <wk@g10code.com> + + * rndw32.c: Updated from current cryptlib snapshot and modified + for our use. Removed support from pre NT systems. + (slow_gatherer_windows95): Remove. + (_gcry_rndw32_gather_random): Require an NT platform. + (init_system_rng, read_system_rng, read_mbm_data): New. + (slow_gatherer_windowsNT): Rename to ... + (slow_gatherer): .. this. Read system RNG and MBM. + (registry_poll): New with code factored out from slow_gatherer. + +2007-08-23 Werner Koch <wk@g10code.com> + + * random.c (pool_filled_counter): New. + (add_randomness): Use it. + +2007-08-22 Werner Koch <wk@g10code.com> + + * rndw32.c, rndunix.c: Switched to LGPL. + +2007-05-30 Werner Koch <wk@g10code.com> + + * camellia.h, camellia.c: Replace by new LGPL version and adjusted + camellia.h. + +2007-05-09 Marcus Brinkmann <marcus@g10code.de> + + * ac.c (_gcry_ac_io_init_va, _gcry_ac_io_write, _gcry_ac_io_read): + Adjust users of gcry_ac_io_t because union is not anonymous + anymore. + +2007-05-02 Werner Koch <wk@g10code.com> + + * camellia-glue.c (camellia_setkey, camellia_encrypt) + (camellia_decrypt): Recalculated used stack size in called + functions. + * camellia.h: Redefine external symbols. + +2007-05-02 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am, cipher.c: Add Camellia. + + * camellia-glue.c: New. The necessary glue to interface libgcrypt + to the stock NTT Camellia distribution. + + * camellia.h, camellia.c: The stock NTT Camellia distribution + (GPL). + +2007-04-30 David Shaw <dshaw@jabberwocky.com> + + * cipher.c: Use #if instead of #ifdef as configure defines the + USE_cipher defines as 0 for disabled. + +2007-04-30 Werner Koch <wk@g10code.com> + + * rndegd.c (_gcry_rndegd_set_socket_name): New. + +2007-04-30 Marcus Brinkmann <marcus@g10code.de> + + * ecc.c (ec2os): Fix relocation of short numbers. + + * ecc.c (generate_key): Do not allocate D, which will be allocated + by GEN_K. Remove G. Fix test if g_x, g_y resp. q_x, q_y are + requested. + (_gcry_ecc_generate): Release unneeded members of SK. + * pubkey.c (sexp_to_key): Release NAME. + +2007-04-28 Marcus Brinkmann <marcus@g10code.de> + + * ac.c (gcry_ac_mpi): Remove member NAME_PROVIDED. + (ac_data_mpi_copy, _gcry_ac_data_set, _gcry_ac_data_get_name) + (_gcry_ac_data_get_index, ac_data_construct): Adjust handling of + NAME accordingly. + +2007-04-20 Werner Koch <wk@g10code.com> + + * ecc.c (domain_parms): Add standard brainpool curves. + +2007-04-18 Werner Koch <wk@g10code.com> + + * ecc.c (generate_curve): Implement alias mechanism. + + * pubkey.c (sexp_elements_extract_ecc): New. + (sexp_to_key): Add special case for ecc. + (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_genkey): Replace + name_terminated stuff by a call to _gcry_sexp_nth_string. + (gcry_pk_get_keygrip): Ditto. + +2007-04-16 Werner Koch <wk@g10code.com> + + * ecc.c (_gcry_ecc_generate): Renamed DUMMY to CURVE and use it. + +2007-04-13 Marcus Brinkmann <marcus@g10code.de> + + * ac.c (ac_data_construct): Cast const away to suppress compiler + warning. + + * ecc.c (ecc_generate): Avoid compiler warning for unused argument + DUMMY. + (ecc_verify): Avoid compiler warning for unused arguments CMP and + OPAQUEV. + +2007-04-06 Werner Koch <wk@g10code.com> + + * sha1.c (oid_spec_sha1): Add another oid from X9.62. + +2007-03-28 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Do not issue misc-key-info if it is + empty. + (gcry_pk_genkey): New parameter "curve". + + * ecc.c: Entirely rewritten with only a few traces of the old + code left. + (_gcry_ecc_generate): New. + (generate_key) New arg NAME. + (generate_curve): Ditto. Return actual number of NBITS. + +2007-03-26 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_genkey): Increase size of SKEY array and add a + runtime bounds check. + +2007-03-23 Werner Koch <wk@g10code.com> + + * ecc.c (ecc_ctx_init, ecc_ctx_free, ecc_mod, ecc_mulm): New. + (duplicate_point, sum_points, escalar_mult): Don't use a + copy of base->p. Replaced all mpi_mulm by ecc_mulm so that we can + experiment with different algorithms. + (generate_key, check_secret_key, sign, verify): Initialize a + computation context for use by ecc_mulm. + +2007-03-22 Werner Koch <wk@g10code.com> + + * pubkey.c (pubkey_table): Initialize ECC. + * Makefile.am (EXTRA_libcipher_la_SOURCES): Add ecc.c. + * ecc.c: New. Heavily reformatted and changed for use in libgcrypt. + (point_init): New. + (escalar_mult): Make arg R the first arg to be similar to the mpi + functions. + (duplicate_point): Ditto + (sum_points): Ditto + (sign, verify): Remove unneeded copy operations. + (sum_points): Removed memory leaks and optimized some compares. + (verify): Simplified input check. + +2007-03-14 Werner Koch <wk@g10code.com> + + * random.c (MASK_LEVEL): Removed macro as it was used only at one + place. Open coded it there. + (gcry_randomize, _gcry_update_random_seed_file) + (_gcry_fast_random_poll): Factor lock code out to .. + (lock_pool, unlock_pool): .. new. + (initialize): Look the pool while allocating. + (read_random_source, do_fast_random_poll): Moved intialization to ... + (initialize): .. here. + (_gcry_enable_quick_random_gen): No more need for initialization. + (is_initialized): Moved this global flag to .. + (initialize): .. here and changed all users to unconditionally call + initialize. + (add_randomness): Remove initalization here. It simply can't + happen. + + * random.c (enum random_origins): Moved to .. + * rand-internal.h: .. here. + * rndunix.c (_gcry_rndunix_gather_random): Use enum in prototype + for ORIGIN and renamed REQUESTOR to ORIGIN. + * rndegd.c (_gcry_rndegd_gather_random): Ditto. + * rndlinux.c (_gcry_rndlinux_gather_random): Ditto. + * rndw32.c (_gcry_rndw32_gather_random): Ditto. + (_gcry_rndw32_gather_random_fast): Ditto. + +2007-03-13 Werner Koch <wk@g10code.com> + + * random.c (enum random_origins): New. + (add_randomness): Renamed arg SOURCE to ORIGIN. + (read_random_source): Renamed arg REQUESTOR to ORIGIN. + (getfnc_gather_random): Removed static variable because this + function is only called one and thus we don't need this + optimization. + (_gcry_quick_random_gen): Removed and replaced by.. + (_gcry_enable_quick_random_gen): .. this. It is onlyu used to + enable it and it does not make sense to disable it later. Changed + the only one caller too. + (get_random_bytes): Removed. + (gcry_random_bytes, gcry_random_bytes_secure): Implement in terms + of gcry_randomize. + * random-daemon.c (_gcry_daemon_get_random_bytes): Removed. + +2007-02-23 Werner Koch <wk@g10code.com> + + * elgamal.c (generate): Removed unused variable TEMP. + (test_keys): New arg NODIE. + (generate_using_x, _gcry_elg_generate_using_x): New. + * pubkey.c (pubkey_generate): New arg XVALUE and direct call to + the new elgamal generate fucntion. + (gcry_pk_genkey): Parse the new "xvalue" tag. + +2007-02-22 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_data_to_mpi): Handle dynamically allocated + algorithms. Suggested by Neil Dunbar. Fixes bug#596. + + * rndw32.c (_gcry_rndw32_gather_random_fast): Make it return void. + + * cipher.c (gcry_cipher_algo_name): Simplified. + + * random.c: Use the daemon only if compiled with USE_RANDOM_DAEMON. + + * Makefile.am (libcipher_la_SOURCES): Build random-daemon support + only if requested. + +2007-02-21 Werner Koch <wk@g10code.com> + + * random.c (rndpool, keypool): Make unsigned. + (mix_pool): Change char* variables to unsigned char*. + (gcry_randomize): Make arg BUFFER a void*. + (gcry_create_nonce): Ditto. + + * rmd160.c (gcry_rmd160_mixblock): Make BUFFER a void*. + (_gcry_rmd160_hash_buffer): Make OUTBUF and BUFFER void*. + * sha1.c (_gcry_sha1_hash_buffer): Ditto. + + * cipher.c (gcry_cipher_encrypt, cry_cipher_decrypt): Change + buffer args to void*. + (gcry_cipher_register): Make ALGORITHM_ID a int *. + + * md.c (md_start_debug): Make SUFFIX a const char*. Use snprintf. + (gcry_md_debug): New. + (gcry_md_ctl): Changed arg BUFFER from unsigned char*. + + * md.c (md_write): Make INBUF a const void*. + (gcry_md_write): Remove needless cast. + * crc.c (crc32_write): Make INBUF a const void* + (update_crc32, crc24rfc2440_write): Ditto. + * sha512.c (sha512_write, transform): Ditto. + * sha256.c (sha256_write, transform): Ditto. + * rmd160.c (rmd160_write, transform): Ditto. + * md5.c (md5_write, transform): Ditto. + * md4.c (md4_write, transform): Ditto. + * sha1.c (sha1_write, transform): Ditto. + + * tiger.c (tiger_write, transform): Ditto. + * whirlpool.c (whirlpool_write, whirlpool_add, transform): Ditto. + + * elgamal.c (elg_names): Change to a const*. + * dsa.c (dsa_names): Ditto. + * rsa.c (rsa_names): Ditto. + * pubkey.c (gcry_pk_lookup_func_name): Make ALIASES a const. + +2007-02-20 Werner Koch <wk@g10code.com> + + * rndlinux.c (open_device): Remove unsused arg MINOR. + +2007-01-30 Werner Koch <wk@g10code.com> + + * sha256.c (oid_spec_sha256): Add alias from pkcs#1. + * sha512.c (oid_spec_sha512): Ditto. + (oid_spec_sha384): Ditto. + +2006-12-18 Werner Koch <wk@g10code.com> + + * rndlinux.c (set_cloexec_flag): New. + (open_device): Set close-on-exit flags. Suggested by Max + Kellermann. Fixes Debian#403613. + + * Makefile.am (AM_CPPFLAGS, AM_CFLAGS): Splitted and merged + Moritz' changes. + (INCLUDES): Removed. + +2006-11-30 Werner Koch <wk@g10code.com> + + * serpent.c (byte_swap_32): Remove trailing semicolon. + +2006-11-15 Werner Koch <wk@g10code.com> + + * Makefile.am (INCLUDES): Include ../src/ + +2006-11-03 Werner Koch <wk@g10code.com> + + * random.c [HAVE_GETTIMEOFDAY]: Included sys/time.h and not + sys/times.h. Reported by Rafaël Carré. + +2006-11-05 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (AM_CFLAGS): Added -I$(top_builddir)/src so that the + new gcrypt.h is used, not the one installed in the system. + +2006-10-25 Werner Koch <wk@g10code.com> + + * primegen.c (prime_generate_internal): Tweaked use of secure + memory and entropy use. Safe unused primes from the pool. Allocate + at least a pool of 30. + (save_pool_prime, get_pool_prime): New. + +2006-10-23 Werner Koch <wk@g10code.com> + + * ac.c (_gcry_ac_data_from_sexp): Reset sexp_tmp for failsafe + means. Release sexp_cur if needed. Reported by Dirk Stoecker. + + * pubkey.c (pubkeys_registered_lock): Intialized it. It is not + realy needed because this is a mere initialization to 0 anyway. + Noted by Victor Stinner. + +2006-10-17 Werner Koch <wk@g10code.com> + + * dsa.c (_gcry_dsa_generate2): New. + (generate): New arg QBITS. Add sanity checks for reasonable qbits + and nbits. + * pubkey.c (gcry_pk_genkey): Parse an qbits element. + (pubkey_generate): New arg QBITS. Pass it to the DSA generation. + +2006-10-05 Werner Koch <wk@g10code.com> + + * md.c (gcry_md_algo_info) <get_asnoid>: Check that the algo is + available. + +2006-10-04 David Shaw <dshaw@jabberwocky.com> (wk) + + * tiger.c (round): Rename to tiger_round as gcc 4 has a built-in + round function that this conflicts with. + +2006-09-11 Werner Koch <wk@g10code.com> + + * rndw32.c (slow_gatherer_windowsNT): While adding data use the + size of the diskPerformance and not its address. Has been fixed in + GnuPG more than a year ago. Noted by Lee Fisher. + +2006-08-30 Werner Koch <wk@g10code.com> + + * pubkey.c (sexp_data_to_mpi): Need to allow "ripemd160" here as + this is the canonical name. + +2006-08-29 Hye-Shik Chang <perky@FreeBSD.org> (wk) + + * seed.c: New. + +2006-08-03 Werner Koch <wk@g10code.com> + + * random-daemon.c (_gcry_daemon_initialize_basics): Don't + initialize the socket. Remove arg SOCKETNAME. + (connect_to_socket): Make sure that daemon is set to -1 on error. + (call_daemon): Initialize the socket on the first call. + (_gcry_daemon_randomize, _gcry_daemon_get_random_bytes) + (_gcry_daemon_create_nonce): New arg SOCKETNAME. + * random.c (initialize): Call new daemon initializator. + (get_random_bytes, gcry_randomize, gcry_create_nonce): Pass socket + name to daemon call and reset allow_daemon on failure. + +2006-07-26 Werner Koch <wk@g10code.com> + + * rmd160.c (_gcry_rmd160_mixblock): Add cast to transform call. + + * blowfish.c (selftest): Cast string to usnigned char*. + + * primegen.c (prime_generate_internal): Cast unsigned/char* + mismatch in calling m_out_of_n. + (is_prime): Changed COUNT to unsigned int *. + + * ac.c (_gcry_ac_data_copy): Initialize DATA_MPIS. + + * random.c (gcry_create_nonce): Update the pid after a fork. + Reported by Uoti Urpala. + +2006-07-04 Marcus Brinkmann <marcus@g10code.de> + + * sha512.c: Fix typo in copyright notice. + +2006-06-21 Werner Koch <wk@g10code.com> + + * rsa.c (_gcry_rsa_generate): Replace xcalloc by calloc. + * pubkey.c (gcry_pk_encrypt, gcry_pk_sign): Ditto. + (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_encrypt) + (gcry_pk_sign, gcry_pk_genkey, gcry_pk_get_keygrip): Ditto. + * md.c (md_copy): Ditto. + +2006-04-22 Moritz Schulte <moritz@g10code.com> + + * random-daemon.c (_gcry_daemon_initialize_basics): New argument: + SOCKETNAME. Passing on to connect_to_socket() if non-NULL. + (connect_to_socket, writen, readn, call_daemon): New functions. + (_gcry_daemon_randomize, _gcry_daemon_get_random_bytes) + (_gcry_daemon_create_nonce): Call call_daemon(). + (RANDOM_DAEMON_SOCKET): New symbol. + (daemon_socket): New static variable. + + * random.h (_gcry_daemon_initialize_basics): New parameter: + SOCKETNAME. + (_gcry_set_random_daemon_socket): New declaration. + + * random.c (initialize_basics): Pass DAEMON_SOCKET_NAME to + _gcry_daemon_initialize_basics. + (_gcry_set_random_daemon_socket): New function, setting + DAEMON_SOCKET_NAME. + +2006-04-01 Moritz Schulte <moritz@g10code.com> + + * ac.c (eme_pkcs_v1_5_encode): Use KEY_SIZE directly, no need to + call gcry_ac_key_get_nbits. + (eme_pkcs_v1_5_decode): Likewise. + (ac_es_dencode_prepare_pkcs_v1_5): Fill options_em structure with + key_size. + (_gcry_ac_data_dump, gcry_ac_data_dump): New functions. + (_gcry_ac_data_to_sexp, _gcry_ac_data_from_sexp): More or less + rewritten; changed S-Expression format so that it matches the one + used in pubkey.c. + +2006-03-15 Werner Koch <wk@g10code.com> + + * random-daemon.c: New. + * random.c (_gcry_use_random_daemon): New. + (get_random_bytes, gcry_randomize, gcry_create_nonce): Try + diverting to the daemon functions. + +2006-03-14 Werner Koch <wk@g10code.com> + + * random.c (lock_seed_file): New. + (read_seed_file, _gcry_update_random_seed_file): Use it. + + * random.c (gcry_create_nonce): Detect a fork and re-seed. + (read_pool): Fixed the fork detection; it used to work only for + multi-threaded processes. + +2006-03-12 Brad Hards <bradh@frogmouth.net> (wk) + + * md.c (md_open): Use new variable macpads_Bsize instead of + hardwiring the block size. Changed at all places. + +2006-03-10 Brad Hards <bradh@frogmouth.net> (wk, patch 2005-04-22) + + * md.c, sha256.c: Add support for SHA-224. + (sha224_init): New. + +2006-01-18 Brad Hards <bradh@frogmouth.net> (wk 2006-03-07) + + * cipher.c (cipher_encrypt, cipher_decrypt, do_ofb_encrypt) + (do_ofb_decrypt, gcry_cipher_open): Implement Output Feedback Mode. + +2005-11-02 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_algo_name): Return "?" instead of NULL for + unknown algorithm IDs. + * cipher.c (cipher_algo_to_string): Likewise. + +2005-11-01 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_algo_info): Don't forget to break after switch + case. + +2005-09-19 Werner Koch <wk@g10code.com> + + * dsa.c (generate): Add preliminary support for 2 and 4 keys. + Return an error code if the key size is not supported. + (_gcry_dsa_generate): Return an error. + +2005-08-22 Werner Koch <wk@g10code.com> + + * primegen.c (check_prime): New arg RM_ROUNDS. + (prime_generate_internal): Call it here with 5 rounds as used + before. + (gcry_prime_check): But here with 64 rounds. + (is_prime): Make sure never to use less than 5 rounds. + +2005-04-16 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_init): New function. + +2005-04-12 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_io_write, _gcry_ac_io_read): Initialize err to + make the compiler happy. + Always use errno, now that gcry_malloc() is guaranteed to set + errno on failure. + (_gcry_ac_data_to_sexp): Don't forget to goto out after error in + loop. + (_gcry_ac_data_to_sexp): Remove unused variable: mpi_list; + (_gcry_ac_data_to_sexp): Always deallocate sexp_buffer. + (_gcry_ac_data_from_sexp): Don't forget to initialize data_set_new. + (_gcry_ac_data_from_sexp): Handle special case, which is + necessary, since gcry_sexp_nth() does not distinguish between + "element does not exist" and "element is the empty list". + (_gcry_ac_io_init_va): Use assert to make sure that mode and type + are correct. + Use gcry_error_t types where gcry_err_code_t types have been used + before. + +2005-04-11 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_data_sign_scheme): Don't forget to initialize + buffer. + + * whirlpool.c: New file. + * md.c (digest_table): Add whirlpool. + * Makefile.am (EXTRA_libcipher_la_SOURCES): Added: whirlpool.c. + +2005-03-30 Moritz Schulte <moritz@g10code.com> + + * ac.c (_gcry_ac_data_from_sexp): Use length of SEXP_CUR, not + length of SEXP; do not forget to set SEXP_TMP to NULL after it has + been released. + + (struct gcry_ac_mpi): New member: name_provided. + (_gcry_ac_data_set): Rename variable `name_final' to `name_cp'; + remove const qualifier; change code to not cast away const + qualifiers; use name_provided member as well. + (_gcry_ac_data_set, _gcry_ac_data_get_name): Use name_provided + member of named mpi structure. + + (gcry_ac_name_to_id): Do not forget to initialize err. + (_gcry_ac_data_get_index): Do not forget to initialize mpi_return; + use gcry_free() instead of free(); remove unnecessary cast; rename + mpi_return and name_return to mpi_cp and name_cp; adjust code. + (ac_data_mpi_copy): Do not cast away const qualifier. + (ac_data_values_destroy): Likewise. + (ac_data_construct): Likewise. + + (ac_data_mpi_copy): Initialize flags to GCRY_AC_FLAG_DEALLOC. + (ac_data_extract): Use GCRY_AC_FLAG_DEALLOC instead of + GCRY_AC_FLAG_COPY. + + (_gcry_ac_io_init_va, _gcry_ac_io_init, gcry_ac_io_init) + (gcry_ac_io_init_va, _gcry_ac_io_write, _gcry_ac_io_read) + (_gcry_ac_io_read_all, _gcry_ac_io_process): New functions. + (gry_ac_em_dencode_t): Use gcry_ac_io_t in prototype instead of + memroy strings directly; adjust encode/decode functions to use io + objects. + (emsa_pkcs_v1_5_encode_data_cb): New function ... + (emsa_pkcs_v1_5_encode): ... use it here. + (ac_data_dencode): Use io objects. + (_gcry_ac_data_encode, _gcry_ac_data_decode, gcry_ac_data_encode) + (gcry_ac_data_decode): Likewise. + (_gcry_ac_data_encrypt_scheme, gcry_ac_data_encrypt_scheme) + (_gcry_ac_data_decrypt_scheme, gcry_ac_data_decrypt_scheme) + (_gcry_ac_data_sign_scheme, gcry_ac_data_sign_scheme) + (_gcry_ac_data_verify_scheme, gcry_ac_data_verify_scheme): + Likewise. + +2005-03-23 Werner Koch <wk@g10code.com> + + * rndw32.c (_gcry_rndw32_gather_random_fast): While adding data + use the size of the object and not the one of its address. Bug + reported by Sascha Kiefer. + +2005-03-19 Moritz Schulte <moritz@g10code.com> + + * cipher.c (do_cbc_encrypt): Be careful to not overwrite data, + which is to be used later on. This happend, in case CTS is + enabled and OUTBUF is equal to INBUF. + +2005-02-25 Werner Koch <wk@g10code.com> + + * pubkey.c (gcry_pk_get_keygrip): Allow for shadowed-private-key. + +2005-02-13 Moritz Schulte <moritz@g10code.com> + + * serpent.c: Updated from 1.2 branch: + + s/u32_t/u32/ and s/byte_t/byte/. Too match what we have always + used and are using in all other files too + (serpent_test): Moved prototype out of a fucntion. + +2005-02-07 Moritz Schulte <moritz@g10code.com> + + * ac.c: Major parts rewritten. + * pubkey.c (_gcry_pk_get_elements): New function. + +2004-12-09 Werner Koch <wk@g10code.com> + + * serpent.c (serpent_setkey): Moved prototype of serpent_test to + outer scope. + +2004-09-11 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (pubkey_table): Added an alias entry for GCRY_PK_ELG_E. + +2004-08-23 Moritz Schulte <moritz@g10code.com> + + * ac.c: Do not include <assert.h>. + * rndegd.c: Likewise. + * sha1.c: Likewise. + * rndunix.c: Likewise. + * rndlinux.c: Likewise. + * rmd160.c: Likewise. + * md5.c: Likewise. + * md4.c: Likewise. + * cipher.c: Likewise. + * crc.c: Likewise. + * blowfish.c: Likewise. + + * pubkey.c (dummy_generate, dummy_check_secret_key) + (dummy_encrypt, dummy_decrypt, dummy_sign, dummy_verify): Return + err code GPG_ERR_NOT_IMPLEMENTED instead of aborting through + log_bug(). + (dummy_get_nbits): Return 0 instead of aborting though log_bug(). + +2004-08-19 Werner Koch <wk@g10code.de> + + * pubkey.c (sexp_data_to_mpi): Changed the zero random byte + substituting code to actually do clever things. Thanks to + Matthias Urlichs for noting the implementation problem. + +2004-08-09 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_sign): Fixed memory leak; fix provided by + Modestas Vainius. + +2004-07-16 Werner Koch <wk@gnupg.org> + + * rijndael.c (do_encrypt): Fix alignment problem. Bugs found by + Matthias Urlichs. + (do_decrypt): Ditto. + (keySched, keySched2): Use 2 macros along with unions in the key + schedule context. + +2004-07-14 Moritz Schulte <moritz@g10code.com> + + * rsa.c (_gcry_rsa_decrypt): Don't forget to free "a". Thanks to + Nikos Mavroyanopoulos. + +2004-05-09 Werner Koch <wk@gnupg.org> + + * random.c (read_pool): Mix the PID in to better protect after a + fork. + +2004-07-04 Moritz Schulte <moritz@g10code.com> + + * serpent.c: Use "u32_t" instead of "unsigned long", do not + declare S-Box variables as "register". Fixes failure on + OpenBSD/sparc64, reported by Nikolay Sturm. + +2004-05-07 Werner Koch <wk@gnupg.org> + + * random.c (initialize): Factored out some code to .. + (initialize_basics): .. new function. + (_gcry_random_initialize): Just call initialize_basics unless the + new arg FULL is set to TRUE. + (_gcry_fast_random_poll): Don't do anything unless the random + system has been really initialized. + +2004-05-07 Moritz Schulte <moritz@g10code.de> + + * ac.c (gcry_ac_open): Do not dereference NULL pointer. Reported + by Umberto Salsi. + +2004-02-20 Werner Koch <wk@gnupg.org> + + * primegen.c (check_prime): New args CB_FUNC and CB_ARG; call them + at different stages. Pass these arguments through all callers. + +2004-02-06 Werner Koch <wk@gnupg.org> + + * des.c: Add a new OID as used by pkcs#12. + + * rfc2268.c: New. Taken from libgcrypt. + * cipher.c: Setup the rfc2268 algorithm. + +2004-01-25 Moritz Schulte <mo@g10code.com> + + * primegen.c (prime_generate_internal): Do not forget to free + `q_factor'; fixed by Brieuc Jeunhomme. + (prime_generate_internal): Do not forget to free `prime'. + +2004-01-14 Moritz Schulte <mo@g10code.com> + + * ac.c (gcry_ac_data_set): New argument: flags; slightly + rewritten. + (gcry_ac_data_get_name, gcry_ac_data_get_index): Likewise. + (gcry_ac_key_pair_generate): New argument: misc_data; modified + order of arguments. + (gcry_ac_key_test): New argument: handle. + (gcry_ac_key_get_nbits, gcry_ac_key_get_grip): Likewise. + Use GCRY_AC_FLAG_NO_BLINDING instead of + GCRY_AC_DATA_FLAG_NO_BLINDING. + (gcry_ac_mpi): New member: flags. + (gcry_ac_data_search, gcry_ac_data_add): Removed functions. + +2003-12-22 Werner Koch <wk@gnupg.org> + + * primegen.c (is_prime): Release A2. + +2003-12-19 Werner Koch <wk@gnupg.org> + + * md.c: Moved a couple of functions down below the data structure + definitions. + (struct gcry_md_context): New field ACTUAL_HANDLE_SIZE. + (md_open): Set it here. + (strcut gcry_md_list): New field ACTUAL_STRUCT_SIZE. + (md_enable): Set it here. + (md_close): Wipe the context memory. + secure memory. + * cipher.c (struct gcry_cipher_handle): New field ACTUAL_HANDLE_SIZE. + (gcry_cipher_open): Set it here. + (gcry_cipher_close): Use it to always wipe out the handle data. + + * ac.c (gcry_ac_open): Make sure HANDLE gets initialized even when + the function is not successful. + (gcry_ac_close): Allow a NULL handle. + (gcry_ac_key_destroy, gcry_ac_key_pair_destroy): Ditto. + (gcry_ac_key_get_grip): Return INV_OBJ on error. + + * primegen.c (prime_generate_internal): Fixed error code for + failed malloc. Replaced the !err if chain by gotos. + (gcry_prime_group_generator): Remove the extra sanity check. + + * md.c: Minor code and comment cleanups. + +2003-12-16 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): Doc fix. Thanks to Newton Hammet. + +2003-12-11 Werner Koch <wk@gnupg.org> + + * rndunix.c (slow_poll): Don't use #warning but #error. + + * rndegd.c: Changed indentation. + (my_make_filename): Removd the var_arg cruft becuase we + don't need it here. Changed caller. + + * rndlinux.c: Changed indentation. + (open_device): Remove the superfluous stat call and clarify + comment. + + * rsa.c: Changed indentation. + (secret): Use the standard algorithm if p, q and u are not + available. + (rsa_blind, rsa_unblind): Renamed from _gcry_rsa_blind, + _gcry_rsa_unblind and moved more to the top. + + * md4.c: Changed indentation. Removed unnecessary casts. + * md5.c, rmd160.c, sha1.c, tiger.c: Ditto. + * rijndael.c, twofish.c: Ditto. + * serpent.c: Removed unnecessary casts. + * sha256.c, sha512.c: Ditto. + +2003-12-09 Werner Koch <wk@gnupg.org> + + * dsa.c: Unified indentation style. + * elgamal.c: Ditto. + * des.c (des_key_schedule): Code beautifications. + * blowfish.c: Changed indentation style. + * cast5.c (do_cast_setkey): Ditto. + + * pubkey.c (gcry_pk_encrypt): Replaced the chain of if(!err) tests + by straightforward gotos. Other cleanups. + (gcry_pk_decrypt): Ditto. + (gcry_pk_sign): Ditto. + (gcry_pk_verify): Ditto. + (gcry_pk_genkey): Ditto. Use strtoul instead of strtol. + (gcry_pk_ctl): Use GPG_ERR_INV_ARG to indicate bad arguments. + +2003-12-07 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_register_default): Undef the helper macro. + (gcry_pk_map_name): Allow NULL for string. + (sexp_to_key): Use memcpy and not strncpy. Use gcry_free and not + free. + (sexp_to_sig): Ditto. + (sexp_to_enc): Ditto. Replaced the chain of if(!err) tests by + straightforward gotos. + +2003-12-05 Werner Koch <wk@gnupg.org> + + * cipher.c: Documentation cleanups. + (gcry_cipher_mode_from_oid): Allow NULL for STRING. + +2003-12-03 Werner Koch <wk@gnupg.org> + + * elgamal.c (sign, do_encrypt, gen_k): Make sure that a small K is + only used for encryption. + +2003-11-18 Werner Koch <wk@gnupg.org> + + * random.h (rndw32_set_dll_name): Removed unused prototype. + + * Makefile.am (EXTRA_DIST): Added Manifest. + +2003-11-11 Werner Koch <wk@gnupg.org> + + * Manifest: New. + +2003-11-04 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Use shortcut for SHA1 + * sha1.c (_gcry_sha1_hash_buffer): New. + + * random.c: Reformatted most functions. + (mix_pool): Moved the failsafe_digest from global + scope to here. + (do_fast_random_poll): Use the generic fucntions even if a fast + gathering function has been used. + (read_pool): Detect a fork and retry. + (gcry_randomize, get_random_bytes): Don't distinguish anymore + between weak and strong random. + (gcry_create_nonce): New. + +2003-10-31 Werner Koch <wk@gnupg.org> + + * rndw32.c (slow_gatherer_windowsNT): Use a plain buffer for the + disk performance values and not the W32 API structure. + + * dsa.c (verify): s/exp/ex/ due to shadowing of a builtin. + * elgamal.c (verify): Ditto. + + * ac.c (gcry_ac_data_get_index): s/index/idx/ + (gcry_ac_data_copy_internal): Remove the cast in _gcry_malloc. + (gcry_ac_data_add): Must use gcry_realloc instead of realloc. + * pubkey.c (sexp_elements_extract): s/index/idx/ as tribute to the + forehackers. + (gcry_pk_encrypt): Removed shadowed definition of I. Reordered + arguments to malloc for clarity. + (gcry_pk_sign, gcry_pk_genkey): Ditto. + * primegen.c (prime_generate_internal): s/random/randomlevel/. + +2003-10-27 Moritz Schulte <mo@g10code.com> + + * pubkey.c (gcry_pk_encrypt): Don't forget to deallocate pkey. + +2003-10-27 Werner Koch <wk@gnupg.org> + + * random.c (gcry_random_add_bytes): Return if buflen is zero to + avoid gcc warning about unsed parameter. + (MASK_LEVEL): Simplified; does now work for signed and unsigned + w/o warnings. + + * md.c (md_start_debug): Removed the const from SUFFIX, because + this function is called from the control fucntion which does not + require const. + + Prefixed all (pubkey,digest,cipher}_spec_* globale variables with + _gcry_. + + * ac.c (ac_key_identifiers): Made static. + + * random.c (getfnc_gather_random,getfnc_fast_random_poll): Move + prototypes to .. + * rand-internal.h: .. here + * random.c (getfnc_gather_random): Include rndw32 gatherer. + * rndunix.c, rndw32.c, rndegd.c: Include them here. + * rndlinux.c (_gcry_rndlinux_gather_random): Prepend the _gcry_ + prefix. Changed all callers. + * rndegd.c (_gcry_rndegd_gather_random): Likewise. + (_gcry_rndegd_connect_socket): Likewise. + * rndunix.c (_gcry_rndunix_gather_random): Likewise. + (waitpid): Made static. + * rndw32.c: Removed the old and unused winseed.dll cruft. + (_gcry_rndw32_gather_random_fast): Renamed from + gather_random_fast. + (_gcry_rndw32_gather_random): Renamed from gather_random. Note, + that the changes 2003-04-08 somehow got lost. + + * sha512.c (sha512_init, sha384_init): Made static. + + * cipher.c (do_ctr_decrypt): Removed "return" from this void + function. + +2003-10-24 Moritz Schulte <mo@g10code.com> + + * serpent.c: Fix an issue on big-endian systems. + + * rndw32.c: Removed IS_MODULE -cruft. + * rndlinux.c (rndlinux_gather_random): Likewise. + +2003-10-10 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): Bail out if NBITS is less than 16. + (prime_generate_internal): Initialize prime variable to suppress + compiler warning. Check pbits, initialize qbits when passed as + zero. + + * primegen.c (prime_generate_internal): New arg + ALL_FACTORS. Changed all callers. + (gcry_prime_generate): Make the factors arg optional. Request + all_factors. Make sure PRIME is set to NULL even on error. + (gcry_prime_group_generator): New. + (gcry_prime_release_factors): New. + +2003-10-06 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): Assert that NBITS is never zero, it + would cause a segv. + +2003-09-28 Moritz Schulte <mo@g10code.com> + + * ac.c: Include "cipher.h". + +2003-09-27 Moritz Schulte <mo@g10code.com> + + * rndegd.c (do_read): Return nread instead of nbytes; thanks to + Michael Caerwyn. + +2003-09-04 Werner Koch <wk@gnupg.org> + + * pubkey.c (_gcry_pk_aliased_algo_name): New. + * ac.c (gcry_ac_open): Use it here. + + * Makefile.am (EXTRA_libcipher_la_SOURCES): Add serpent.c + +2003-09-02 Moritz Schulte <mo@g10code.com> + + * primegen.c (gcry_prime_check, gcry_prime_generate): New + functions. + (prime_generate_internal): New function, based on + _gcry_generate_elg_prime. + (_gcry_generate_elg_prime): Rewritten as a wrapper for + prime_generate_internal. + +2003-08-28 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_encrypt): Don't include the flags list in the + return value. This does not make sense and breaks any programs + parsing the output strictly (e.g. current gpgsm). + (gcry_pk_encrypt): If aliases for the algorithm name exists, take + the first one instead of the regular name to adhere to SPKI + conventions. + (gcry_pk_genkey): Ditto. + (gcry_pk_sign): Ditto. Removed unused KEY_ALGO_NAME. + +2003-08-19 Moritz Schulte <mo@g10code.com> + + * cipher.c: Add support for Serpent + * serpent.c: New file. + +2003-08-10 Moritz Schulte <moritz@g10code.com> + + * rsa.c (_gcry_rsa_blind, _gcry_rsa_unblind): Declare static. + +2003-08-09 Timo Schulz <twoaday@freakmail.de> + + * random.c (getfnc_gather_random): Don't check NAME_OF_DEV_RANDOM + two times, but also the NAME_OF_DEV_URANDOM device. + +2003-08-08 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_to_enc): Fixed extraction of S-Expression: do not + fail if no `flags' sub S-Expression is found. + +2003-07-27 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_lookup_func_oid): Allow for empty OID lists. + +2003-07-23 Moritz Schulte <moritz@g10code.com> + + * ac.c (gcry_ac_data_construct): New argument: include_flags, only + include `flags' S-expression, if include_flags is true. Adjust + callers. Thanks for triggering a bug caused by `flags' + sub-S-expression where they are not expected to Ralf Schneider. + +2003-07-21 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_lookup_func_name): Use new member name + `aliases' instead of `sexp_names'. + + * ac.c (gcry_ac_key_data_get): New function. + + * cipher.c (gcry_cipher_lookup_func_name): Fix return value. + +2003-07-20 Moritz Schulte <moritz@g10code.com> + + * blowfish.c: Adjusted for new gcry_cipher_spec_t structure. + * cast5.c: Likewise. + * twofish.c: Likewise. + * arcfour.c: Likewise. + * rijndael.c (rijndael_oids, rijndael192_oids, rijndael256_oids): + New variables, adjust for new gcry_cipher_spec_t structure. + * des.c (oids_tripledes): New variable, adjust for new + gcry_cipher_spec_t structure. + + * md.c (oid_table): Removed. + + * tiger.c (oid_spec_tiger): New variable. + (digest_spec_tiger): Adjusted for new gry_md_spec_t structure. + + * sha512.c (oid_spec_sha512): New variable. + (digest_spec_sha512): Adjusted for new gry_md_spec_t structure. + + * sha512.c (oid_spec_sha384): New variable. + (digest_spec_sha384): Adjusted for new gry_md_spec_t structure. + + * sha256.c (oid_spec_sha256): New variable. + (digest_spec_sha256): Adjusted for new gry_md_spec_t structure. + + * sha1.c (oid_spec_sha1): New variable. + (digest_spec_sha1): Adjusted for new gry_md_spec_t structure. + + * rmd160.c (oid_spec_rmd160): New variable. + (digest_spec_rnd160): Adjusted for new gry_md_spec_t structure. + + * md5.c (oid_spec_md5): New variable. + (digest_spec_md5): Adjusted for new gry_md_spec_t structure. + + * md4.c (oid_spec_md4): New variable. + (digest_spec_md4): Adjusted for new gry_md_spec_t structure. + + * crc.c (digest_spec_crc32, digest_spec_crc32_rfc1510, + digest_spec_crc32_rfc2440): Adjusted for new gry_md_spec_t + structure. + +2003-07-19 Moritz Schulte <moritz@g10code.com> + + * md.c (gcry_md_lookup_func_oid): New function. + (search_oid): New function, copied from cipher.c. + (gcry_md_map_name): Adjust for new search_oid_interface. + + * cipher.c (oid_table): Removed table. + (gcry_cipher_lookup_func_oid): New function. + (search_oid): Rewritten to use the module functions. + (gcry_cipher_map_name): Adjust for new search_oid interface. + (gcry_cipher_mode_from_oid): Likewise. + +2003-07-18 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Convert ERR to gpg_error_t in + gpg_strerror. + +2003-07-14 Moritz Schulte <moritz@g10code.com> + + * cipher.c (gcry_cipher_lookup_func_name): Also check the cipher + name aliases, not just the primary name. + (gcry_cipher_map_name): Remove kludge for aliasing Rijndael to + AES. + + * arcfour.c, blowfish.c, cast5.c, des.c, twofish.c: Adjust cipher + specification structures. + + * rijndael.c (rijndael_names, rijndael192_names, + rijndael256_names): New variables, use them in the cipher + specifications. + + * rmd160test.c: Removed file. + + * ac.c, arcfour.c, blowfish.c, cast5.c, cipher.c, des.c, dsa.c, + elgamal.c, md.c, pubkey.c, random.c, rijndael.c, rsa.c, twofish.c: + Used gcry_err* wrappers for libgpg symbols. + + * primegen.c (gen_prime): Correct the order arguments to + extra_check. + +2003-07-12 Moritz Schulte <moritz@g10code.com> + + * ac.c: Replaced all public occurences of gpg_error_t with + gcry_error_t. + * cipher.c: Likewise. + * md.c: Likewise. + * pubkey.c: Likewise. + * random.c: Likewise. + + * cipher.c: Added support for TWOFISH128. + +2003-07-08 Moritz Schulte <moritz@g10code.com> + + * ac.c (gcry_ac_data_copy_internal): New function, based on + gcry_ac_data_copy. + (gcry_ac_data_copy): Made public, use gcry_ac_data_copy_internal. + (gcry_ac_key_init): Use gcry_ac_data_copy_internal. + +2003-07-07 Moritz Schulte <moritz@g10code.com> + + * ac.c (gcry_ac_data_set): Only release old MPI value if it is + different from the new value. Bug reported by Simon Josefsson + <jas@extundo.com>. + + * pubkey.c (gcry_pk_list): New function. + * md.c (gcry_md_list): New function. + + * ac.c (gcry_ac_key_pair_generate): Fix calculation of format + string size. + +2003-07-05 Moritz Schulte <moritz@g10code.com> + + * md.c: Named struct of digest_table `digest_table_entry'. + (digest_table_entry): New member: algorithm; filled in. + (digest_table_entry): Removed unused member: flags. + (gcry_md_register): New argument: algorithm_id, filled in. + (gcry_md_register_default): Used algorithm ID from module + structure. + (gcry_md_map_name): Likewise. + (md_enable): Likewise. + (md_read): Likewise. + (gcry_md_info): Likewise. + + * pubkey.c: Named truct for pubkey_table `pubkey_table_entry'. + (pubkey_table_entry): New member: algorithm; filled in. + (gcry_pk_register_default): Used algorithm ID from pubkey_table. + (gcry_pk_register): New argument: algorithm_id, filled in. + (gcry_pk_map_name): Used algorithm ID from module structure. + (gcry_pk_decrypt): Likewise. + (gcry_pk_encrypt): Likewise. + (gcry_pk_verify): Likewise. + (gcry_pk_sign): Likewise. + (gcry_pk_testkey): Likewise. + (gcry_pk_genkey): Likewise. + (gcry_pk_get_nbits): Likewise. + (sexp_to_key): Removed unused variable: algo. + (sexp_to_sig): Likewise. + + * cipher.c: Named struct for cipher_table `cipher_table_entry'. + (cipher_table_entry): New member: algorithm; filled in. + (gcry_cipher_register_default): Used algorithm ID from + cipher_table. + (gcry_cipher_register): New argument: algorithm_id, filled in. + (gcry_cipher_map_name): Used algorithm ID from module structure. + + * arcfour.c (cipher_spec_arcfour): Removed algorithm ID. + * blowfish.c (cipher_spec_blowfish): Likewise. + * cast5.c (cipher_spec_cast5): Likewise. + * crc.c (digest_spec_crc32): Likewise. + * crc.c (digest_spec_crc32_rfc1510): Likewise. + * crc.c (digest_spec_crc32_rfc2440): Likewise. + * des.c (cipher_spec_des): Likewise. + * des.c (cipher_spec_tripledes): Likewise. + * dsa.c (pubkey_spec_dsa): Likewise. + * elgamal.c (pubkey_spec_elg): Likewise. + * md4.c (digest_spec_md4): Likewise. + * md5.c (digest_spec_md5): Likewise. + * aes.c (cipher_spec_aes): Likewise. + * aes.c (cipher_spec_aes192): Likewise. + * aes.c (cipher_spec_aes256): Likewise. + * rsa.c (pubkey_spec_rsa): Likewise. + * sha1.c (digest_spec_sha1): Likewise. + * sha256.c (digest_spec_sha256): Likewise. + * sha512.c (digest_spec_sha512): Likewise. + * tiger.c (digest_spec_tiger): Likewise. + * twofish.c (cipher_spec_twofish): Likewise. + * twofish.c (cipher_spec_twofish128): Likewise. + + * Makefile.am (EXTRA_libcipher_la_SOURCES): Fix list of source + files; reported by Simon Josefsson <jas@extundo.com>. + + * pubkey.c: Replaced all occurences of `id' with `algorithm', + since `id' is a keyword in obj-c. + * md.c: Likewise. + * cipher.c: Likewise. + + * crc.c, md4.c, md5.c, rmd160.c, sha1.c, sha256.c, tiger.c: + Replaced all occurences of gcry_digest_spec_t with gcry_md_spec_t. + + * dsa.c, rsa.c, elgamal.c: Replaced all occurencens of + gcry_pubkey_spec_t with gcry_pk_spec_t. + + * md.c: Replaced all occurences of gcry_digest_spec_t with + gcry_md_spec_t. + (gcry_digest_register_default): Renamed to ... + (gcry_md_register_default): ... this; adjusted callers. + (gcry_digest_lookup_func_name): Renamed to ... + (gcry_md_lookup_func_name): ... this; adjusted callers. + (gcry_digest_lookup_name): Renamed to ... + (gcry_md_lookup_name): ... this; adjusted callers. + (gcry_digest_register): Renamed to ... + (gcry_md_register): ... this. + (gcry_digest_unregister): Renamed to ... + (gcry_md_unregister): ... this. + + * pubkey.c (gcry_pubkey_register): Renamed to ... + (gcry_pk_register): ... this. + (gcry_pubkey_unregister): Renamed to ... + (gcry_pk_unregister): ... this. + Replaced all occurences of gcry_pubkey_spec_t with gcry_pk_spec_t. + (gcry_pubkey_register_default): Renamed to ... + (gcry_pk_register_default): ... this; adjusted callers. + (gcry_pubkey_lookup_func_name): Renamed to ... + (gcry_pk_lookup_func_name): ... this; adjusted callers. + (gcry_pubkey_lookup_name): Renamed to ... + (gcry_pk_lookup_name): ... this; adjusted callers. + + * md.c (gcry_md_hash_buffer): Fix error checking. Thanks to Simon + Josefsson <jas@extunde.com>. + +2003-07-04 Moritz Schulte <moritz@g10code.com> + + * cipher.c (gcry_cipher_list): New function. + +2003-07-01 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_to_sig): Accept a `flags' S-expression to be more + consistent with sexp_to_enc. + +2003-06-30 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (libcipher_la_SOURCES): Added: ac.c. + + * pubkey.c (_gcry_pk_module_lookup): New function. + (_gcry_pk_module_release): New function. + +2003-06-29 Moritz Schulte <moritz@g10code.com> + + * ac.c: New file. + +2003-06-26 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Trigger BUG correcly with new API. + +2003-06-19 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_is_enabled): Fixed. + +2003-06-18 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_get_algo_keylen): New. + (gcry_cipher_get_algo_blklen): New. + +2003-06-18 Moritz Schulte <moritz@g10code.com> + + * arcfour.c, cipher.c, blowfish.c, md.c, cast5.c, pubkey.c, crc.c, + des.c, dsa.c, elgamal.c, md4.c, md5.c, random.c, rijndael.c, + rmd160.c, rsa.c, sha1.c, sha256.c, sha512.c, tiger.c, twofish.c: + Replaced older types GcryDigestSpec, GcryCipherSpec and + GcryPubkeySpec with newer types: gcry_digest_spec_t, + gcry_cipher_spec_t and gcry_pubkey_spec_t. + + * md.c (gcry_digest_id_new): Removed function. + (gcry_digest_register): Removed code for generating a new module + ID. + + * pubkey.c (gcry_pubkey_id_new): Removed function. + (gcry_pubkey_register): Removed code for generating a new module + ID. + + * cipher.c, md.c, pubkey.c: Replace old type GcryModule with newer + one: gcry_module_t. + (gcry_cipher_id_new): Removed function. + (gcry_cipher_register): Removed code for generating a new module + ID. + + * cipher.c (gcry_cipher_register): Adjust call to + _gcry_module_add. + (gcry_cipher_register_default): Likewise. + * pubkey.c (gcry_pubkey_register_default): Likewise. + (gcry_pubkey_register): Likewise. + * md.c (gcry_digest_register_default): Likewise. + (gcry_digest_register): Likewise. + + * md.c (gcry_digest_lookup_func_id): Removed function. + (gcry_digest_lookup_id): Likewise. + (gcry_digest_id_new): Use _gcry_module_lookup_id instead of + gcry_digest_lookup_id. + (digest_algo_to_string): Likewise. + (check_digest_algo): Likewise. + (md_enable): Likewise. + (md_digest_length): Likewise. + (md_asn_oid): Likewise. + + * pubkey.c (gcry_pubkey_lookup_id): Removed function. + (gcry_pubkey_lookup_func_id): Likewise. + (gcry_pubkey_id_new): Use _gcry_module_lookup_id instead of + gcry_pubkey_id_new. + (gcry_pk_algo_name): Likewise. + (disable_pubkey_algo): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_get_npkey): Likewise. + (pubkey_get_nskey): Likewise. + (pubkey_get_nsig): Likewise. + (pubkey_get_nenc): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (gcry_pk_algo_info): Likewise. + + * cipher.c (gcry_cipher_lookup_func_id): Removed function. + (gcry_cipher_lookup_id): Likewise. + (cipher_algo_to_string): use _gcry_module_lookup_id instead of + gcry_cipher_lookup_id. + (disable_cipher_algo): Likewise. + (check_cipher_algo): Likewise. + (cipher_get_blocksize): Likewise. + (gcry_cipher_open): Likewise. + (gcry_cipher_id_new): Likewise. + +2003-06-17 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (GCRYPT_MODULES): Set to @GCRYPT_CIPHERS@, + @GCRYPT_PUBKEY_CIPHERS@, @GCRYPT_DIGESTS@ and @GCRYPT_RANDOM@. + (libcipher_la_DEPENDENCIES): Set to $(GCRYPT_MODULES). + (libcipher_la_LIBADD): Likewise. + (AM_CFLAGS): Added: @GPG_ERROR_CFLAGS@. + (EXTRA_libcipher_la_SOURCES): Added all conditional sources. + + * md.c (md_open): Use _gcry_fast_random_poll instead of + fast_random_poll. + * cipher.c (gcry_cipher_open): Likewise. + + * random.h (fast_random_poll): Removed macro. + + * blowfish.c, md4.c, md5.c, rmd160.c, sha1.c, sha256.c, sha512.c, + tiger.c: Use Autoconf's WORDS_BIGENDIAN instead of our own + BIG_ENDIAN_HOST. + +2003-06-16 Moritz Schulte <moritz@g10code.com> + + * random.c (getfnc_gather_random): Do not special-case + USE_ALL_RANDOM_MODULES, make it the default. + + * dsa.c: Replace last occurences of old type names with newer + names (i.e. replace MPI with gcry_mpi_t). + * elgamal.c: Likewise. + * primegen.c: Likewise. + * pubkey.c: Likewise. + * rsa.c: Likewise. + +2003-06-14 Moritz Schulte <moritz@g10code.com> + + * des.c (des_setkey): Add selftest check. + (tripledes_set3keys): Likewise. + (do_tripledes_setkey): Remove selftest check. + (do_des_setkey): Likewise. + +2003-06-11 Moritz Schulte <moritz@g10code.com> + + * md.c (_gcry_md_init): New function. + * cipher.c (_gcry_cipher_init): New function. + * pubkey.c (_gcry_pk_init): New function. + +2003-06-13 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_get_algo): Reverted to old API. This is a + convenience function anyway and error checking is not approriate. + (gcry_md_is_secure): New. + (gcry_md_is_enabled): New. + +2003-06-12 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_open): Make sure HANDLE is set to NULL on + error. + +2003-06-11 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_open): Make sure H receives either NULL or an + valid handle. + (gcry_md_copy): Swapped arguments so that it is more in lione with + md_open and most other API fucntions like memcpy (destination + comes first). Make sure HANDLE is set to NULL on error. + + * rijndael.c (do_encrypt): Hack to force correct alignment. It + seems not to be not sufficient, though. We should rework this + fucntions and remove all these ugly casts. Let the compiler + optimize or have an assembler implementation. + +2003-06-09 Moritz Schulte <moritz@g10code.com> + + * Makefile.am: Removed rules serpent, since that is not commited + yet. + +2003-06-08 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_encrypt): Improve calculation for size of the + format string. + +2003-06-07 Moritz Schulte <moritz@g10code.com> + + * arcfour.c, bithelp.h, blowfish.c, cast5.c, cipher.c, crc.c, + des.c, dsa.c, elgamal.c, md4.c, md5.c, md.c, primegen.c, pubkey.c, + rand-internal.h, random.c, random.h, rijndael.c, rmd160.c, + rmd160test.c, rmd.h, rndeged.c, rndlinux.c, rndunix.c, rndw32.c, + rsa.c, sha1.c, sha256.c, sha512.c, tiger.c, twofish.c: Edited all + preprocessor instructions to remove whitespace before the '#'. + This is not required by C89, but there are some compilers out + there that don't like it. Replaced any occurence of the now + deprecated type names with the new ones. + +2003-06-04 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_encrypt): Construct an arg_list and use + gcry_sexp_build_array instead of gcry_sexp_build. + (gcry_pk_sign): Likewise. + (gcry_pk_genkey): Likewise. + +2003-06-01 Moritz Schulte <moritz@g10code.com> + + * dsa.c (_gcry_dsa_generate): Do not check wether the algorithm ID + does indeed belong to DSA. + (_gcry_dsa_sign): Likewise. + (_gcry_dsa_verify): Likewise. + (_gcry_dsa_get_nbits): Likewise. + + * elgamal.c (_gcry_elg_check_secret_key): Do not check wether the + algorithm ID does indeed belong to ElGamal. + (_gcry_elg_encrypt): Likewise. + (_gcry_elg_decrypt): Likewise. + (_gcry_elg_sign): Likewise. + (_gcry_elg_verify): Likewise. + (_gcry_elg_get_nbits): Likewise. + (_gcry_elg_generate): Likewise. + + * rsa.c (_gcry_rsa_generate): Do not check wether the algorithm ID + does indeed belong to RSA. + (_gcry_rsa_encrypt): Likewise. + (_gcry_rsa_decrypt): Likewise. + (_gcry_rsa_sign): Likewise. + (_gcry_rsa_verify): Likewise. + (_gcry_rsa_get_nbits): Likewise. + +2003-05-30 Moritz Schulte <moritz@g10code.com> + + * md.c (md_get_algo): Return zero in case to algorithm is enabled. + + * md.c (gcry_md_info): Adjusted for new no-errno-API. + (md_final): Likewise. + (gcry_md_get_algo): Likewise. + * pubkey.c (gcry_pk_get_keygrip): Likewise. + (gcry_pk_ctl): Likewise. + (gcry_pk_algo_info): Likewise. + * des.c (selftest): Likewise. + +2003-05-29 Moritz Schulte <moritz@g10code.com> + + * md.c (md_enable): Do not forget to release module on error. + (gcry_md_open): Adjusted for new no-errno-API. + (md_open): Likewise. + (md_copy): Likewise. + (gcry_md_copy): Likewise. + (gcry_md_setkey): Likewise. + (gcry_md_algo_info): Likewise. + + * cipher.c (gcry_cipher_open): Adjusted for new no-errno-API and + also fixed a locking bug. + (gcry_cipher_encrypt): Adjusted for new no-errno-API. + (gcry_cipher_decrypt): Likewise. + (gcry_cipher_ctl): Likewise. + (gcry_cipher_info): Likewise. + (gcry_cipher_algo_info): Likewise. + +2003-05-28 Moritz Schulte <moritz@g10code.com> + + * md.c (md_enable): Adjusted for libgpg-error. + (gcry_md_enable): Likewise. + (gcry_digest_register_default): Likewise. + (gcry_digest_register): Likewise. + (check_digest_algo): Likewise. + (prepare_macpads): Likewise. + (gcry_md_setkey): Likewise. + (gcry_md_ctl): Likewise. + (gcry_md_get): Likewise. + (gcry_md_algo_info): Likewise. + (gcry_md_info): Likewise. + * dsa.c (_gcry_dsa_generate): Likewise. + (_gcry_dsa_check_secret_key): Likewise. + (_gcry_dsa_sign): Likewie. + (_gcry_dsa_verify): Likewise. + * twofish.c (do_twofish_setkey): Likewise. + (twofish_setkey): Likewise. + * cipher.c (gcry_cipher_register): Likewise. + +2003-05-25 Moritz Schulte <moritz@g10code.com> + + * rijndael.c (do_setkey): Adjusted for libgpg-error. + (rijndael_setkey): Likewise. + * random.c (gcry_random_add_bytes): Likewise. + * elgamal.c (_gcry_elg_generate): Likewise. + (_gcry_elg_check_secret_key): Likewise. + (_gcry_elg_encrypt): Likewise. + (_gcry_elg_decrypt): Likewise. + (_gcry_elg_sign): Likewise. + (_gcry_elg_verify): Likewise. + * rsa.c (_gcry_rsa_generate): Likewise. + (_gcry_rsa_check_secret_key): Likewise. + (_gcry_rsa_encrypt): Likewise. + (_gcry_rsa_decrypt): Likewise. + (_gcry_rsa_sign): Likewise. + (_gcry_rsa_verify): Likewise. + * pubkey.c (dummy_generate, dummy_check_secret_key, dummy_encrypt, + dummy_decrypt, dummy_sign, dummy_verify): Likewise. + (gcry_pubkey_register): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (sexp_elements_extract): Likewise. + (sexp_to_key): Likewise. + (sexp_to_sig): Likewise. + (sexp_to_enc): Likewise. + (sexp_data_to_mpi): Likewise. + (gcry_pk_encrypt): Likewise. + (gcry_pk_decrypt): Likewise. + (gcry_pk_sign): Likewise. + (gcry_pk_verify): Likewise. + (gcry_pk_testkey): Likewise. + (gcry_pk_genkey): Likewise. + (gcry_pk_ctl): Likewise. + * cipher.c (dummy_setkey): Likewise. + (check_cipher_algo): Likewise. + (gcry_cipher_open): Likewise. + (cipher_setkey): Likewise. + (gcry_cipher_ctl): Likewise. + (cipher_encrypt): Likewise. + (gcry_cipher_encrypt): Likewise. + (cipher_decrypt): Likewise. + (gcry_cipher_decrypt): Likewise. + (gcry_cipher_info): Likewise. + (gcry_cipher_algo_info): Likewise. + * cast5.c (cast_setkey): Likewise. + (do_cast_setkey): Likewise. + * arcfour.c (arcfour_setkey): Likewise. + (do_arcfour_setkey): Likewise. + * blowfish.c (do_bf_setkey): Likewise. + (bf_setkey): Likewise. + * des.c (do_des_setkey): Likewise. + (do_tripledes_setkey): Likewise. + +2003-05-22 Moritz Schulte <moritz@g10code.com> + + * tiger.c: Merged code ussing the U64_C macro from GnuPG. + + * sha512.c: Likewise. + +2003-05-17 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_genkey): Fix type: acquire a lock, instead of + releasing it. + +2003-05-11 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_testkey): Call REGISTER_DEFAULT_CIPHERS. + (gcry_pk_ctl): Likewise. + +2003-04-27 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (gcry_pk_genkey): Release sexp after extracted data has + been used. + + * md.c (gcry_md_get_algo_dlen): Simplified, simply call + md_digest_length to do the job. + + * des.c (do_des_setkey): Check for selftest failure not only + during initialization. + (do_tripledes_setkey): Include check for selftest failure. + + * pubkey.c (gcry_pubkey_register_default): New macro + `pubkey_use_dummy', use it. + + * elgamal.c (elg_names): New variable. + (pubkey_spec_elg): Include elg_names. + + * dsa.c (dsa_names): New variable. + (pubkey_spec_dsa): Include dsa_names. + + * rsa.c (rsa_names): New variable. + (pubkey_spec_rsa): Include rsa_names. + + * pubkey.c (gcry_pubkey_lookup_func_name): Compare name also with + the names listed in `sexp_names'. + +2003-04-24 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_to_key): New variables: module, pubkey. Adjusted + to new module interface. + (sexp_to_key): Changend type of argument `retalgo' from `int *' to + `GcryModule **'. Adjusted all callers. Removed argument: + r_algotblidx. + (sexp_to_sig): Changend type of argument `retalgo' from `int *' to + `GcryModule **'. Adjusted all callers. + (sexp_to_enc): Likewise. + + (pubkey_get_npkey, pubkey_get_nskey, pubkey_get_nsig, + pubkey_get_nenc): Use strlen to find out the number. + + * rsa.c: Adjust pubkey_spec_rsa to new internal interface. + * dsa.c: Likewise. + * elgamal.c: Likewise. + +2003-04-17 Moritz Schulte <moritz@g10code.com> + + * pubkey.c (sexp_elements_extract): New function. + * pubkey.c (sexp_to_key): Removed variable `idx', added `err', use + sexp_elements_extract. + (sexp_to_sig): Likewise. + (sexp_to_enc): Likewise. + + * pubkey.c: Terminate list correctly. + * md.c: Include sha512/sha384 in digest_table. + +2003-04-16 Moritz Schulte <moritz@g10code.com> + + * Makefile.am: Include support for sha512.c. + + * sha512.c: New file, merged from GnuPG, with few modifications + for libgcrypt. + + * rand-internal.h: Removed declarations for constructor functions. + + * md.c (md_copy): Call _gcry_module_use for incrementing the usage + counter of the digest modules. + + * rsa.c: Do not include "rsa.h". + * dsa.c: Do not include "dsa.h". + * elgamal.c: Do not include "elgamal.h". + * des.c: Do not include "des.h". + * cast5.c: Do not include "cast5.h". + * blowfish.c: Do not include "blowfish.h". + * arcfour.c: Do not include "arcfour.h". + + * Makefile.am (libcipher_la_DEPENDENCIES): Removed. + (libcipher_la_LIBADD): Removed. + Use Automake conditionals for conditional compilation. + +2003-04-13 Moritz Schulte <moritz@g10code.com> + + * cipher.c (gcry_cipher_open): Call REGISTER_DEFAULT_CIPHERS. + + * md.c (gcry_md_list): New member: module. + (md_enable): New variable: module, changed use of module and + digest. + (md_enable): Initialize member: module. + (md_close): Call _gcry_module_release. + + * cipher.c (gcry_cipher_open): New variable: module, changed use of + module and cipher. + (struct gcry_cipher_handle): New member: module. + (gcry_cipher_open): Initialize member: module. + (gcry_cipher_close): Call _gcry_module_release. + +2003-04-09 Moritz Schulte <moritz@g10code.com> + + * cipher.c: Include "ath.h". + * md.c: Likewise. + * pubkey.c: Likewise. + + * cipher.c (ciphers_registered_lock): New variable. + * md.c (digests_registered_lock): New variable. + * pubkey.c (pubkeys_registered_lock): New variable. + + * rndlinux.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndlinux_constructor): Removed function. + + * rndegd.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndegd_constructor): Removed function. + + * rndunix.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndunix_constructor): Removed function. + + * rndw32.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndw32_constructor): Removed function. + + * rndegd.c (rndegd_connect_socket): Simplify code for creating the + egd socket address. + (rndegd_connect_socket): Call log_fatal use instead of + g10_log_fatal. + (egd_gather_random): Renamed to ... + (rndegd_gather_random): ... here. + +2003-04-08 Moritz Schulte <moritz@g10code.com> + + * rndlinux.c: Do not include "dynload.h". + * rndunix.c: Likewise. + * rndw32.c: Likewise. + + * rndegd.c (rndegd_connect_socket): Factored out from ... + (egd_gather_random): here; call it. + (egd_socket): New variable. + (egd_gather_random): Initialize fd with egd_socket, do not declare + fd static. + (do_read): Merged few changes from GnuPG. FIXME - not finished? + Do not include "dynload.h". + + * rndw32.c (gather_random): Renamed to rndw32_gather_random, do + not declare static. + (gather_random_fast): Renamed to rndw32_gather_random_fast, do not + declare static. + + * rndunix.c (gather_random): Renamed to rndunix_gather_random, do + not declare static. + * rndegd.c (gather_random): Renamed to rndegd_gather_random, do + not declare static. + * rndlinux.c (gather_random): Renamed to rndlinux_gather_random, + do not declare static. + +2003-04-07 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (libcipher_la_SOURCES): Removed construct.c. + (libcipher_la_SOURCES): Added sha1.c, sha256.c, rmd160.c, md4.c, + md5.c, tiger.c and crc.c + (EXTRA_PROGRAMS): Removed sha1, sha256, rmd160, md4, md5, tiger + and crc. Removed definitions: EXTRA_md4_SOURCES, + EXTRA_md5_SOURCES, EXTRA_rmd160_SOURCES, EXTRA_sha1_SOURCES, + EXTRA_sha256_SOURCES, EXTRA_tiger_SOURCES and EXTRA_crc_SOURCES, + BUILT_SOURCES, DISTCLEANFILES. + + * pubkey.c: Do not include "elgamal.h", "dsa.h" and "rsa.h". + + * Makefile.am (libcipher_la_SOURCES): Removed rsa.h, elgamal.h, + dsa.h, des.h, cast5.h, arcfour.h and blowfish.h. + + * rsa.h: Removed file. + * elgamal.h: Removed file. + * dsa.h: Removed file. + * des.h: Removed file. + * cast5.h: Removed file. + * arcfour.h: Removed file. + * blowfish.h: Removed file. + + * Makefile.am (libcipher_la_SOURCES): Removed dynload.c and + dynload.h. + + * rsa.c (pubkey_spec_rsa): New variable. + * dsa.c (pubkey_spec_rsa): New variable. + * elgamal.c (pubkey_spec_elg): New variable. + + * rsa.c (_gcry_rsa_get_info): Removed function. + * elgamal.c (_gcry_elg_get_info): Removed function. + * dsa.c (_gcry_dsa_get_info): Removed function. + + * tiger.c (tiger_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_tiger_constructor): Removed function. + + * sha1.c (sha1_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_sha1_constructor): Removed function. + + * sha256.c (sha256_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_sha256_constructor): Removed function. + + * rmd160.c (rmd160_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rmd160_constructor): Removed function. + + * md5.c (md5_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_md5_constructor): Removed function. + + * md4.c (md4_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_md4_constructor): Removed function. + + * crc.c (crc_get_info): Removed function. + + * arcfour.c (do_arcfour_setkey): Changed type of context argument + to `void *', added local variable for cast, adjusted callers. + (arcfour_setkey): Likewise. + (encrypt_stream): Likewise. + * cast5.c (cast_setkey): Likewise. + (encrypt_block): Likewise. + * rijndael.c (rijndael_setkey): Likewise. + (rijndael_encrypt): Likewise. + (rijndael_decrypt): Likewise. + * twofish.c (twofish_setkey): Likewise. + (twofish_encrypt): Likewise. + (twofish_decrypt): Likewise. + * des.c (do_des_setkey): Likewise. + (do_des_encrypt): Likewise. + (do_des_encrypt): Likewise. + (do_tripledes_encrypt): Likewise. + (do_tripledes_encrypt): Likewise. + * blowfish.c (bf_setkey: Likewise. + (encrypt_block): Likewise. + (decrypt_block): Likewise. + + * arcfour.c (encrypt_stream): Likewise. + + * rijndael.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func) Removed function. + + * twofish.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func) Removed function. + + * cast5.c (CIPHER_ALGO_CAST5): Removed. + + * blowfish.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Removed macros. + (CIPHER_ALGO_BLOWFISH): Removed symbol. + * cast5.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Likewise. + * des.c (selftest_failed): Removed. + (initialized): New variable. + (do_des_setkey): Run selftest, if not yet done. + (FNCCAST_SETKEY, FNCCAST_CRYPT): Removed macros. + + * arcfour.c (_gcry_arcfour_get_info): Removed function. + * blowfish.c (_gcry_blowfish_get_info): Removed function. + * cast5.c (_gcry_cast5_get_info): Removed function. + * des.c (_gcry_des_get_info): Removed function. + * rijndael.c (_gcry_rijndael_get_info): Removed function. + * twofish.c (_gcry_twofish_get_info): Removed function. + + * arcfour.c (cipher_spec_arcfour): New variable. + * twofish.c (cipher_spec_twofish, cipher_spec_twofish128): New + variables. + * rijndael.c (cipher_spec_aes, cipher_spec_aes192, + cipher_spec256): New variables. + * des.c (cipher_spec_des, cipher_spec_tripledes): New variables. + * cast5.c (cipher_spec_cast5): New variable. + * blowfish.c (cipher_spec_blowfish): Likewise. + + * twofish.c: Do not include "dynload.h". + * rijndael.c: Likewise. + * des.c: Likewise. + * cast5.c: Likewise. + * blowfish.c: Likewise. + * cipher.c: Likewise. + * crc.c: Likewise. + * md4.c: Likewise. + * md5.c: Likewise. + * md.c: Likewise. + * pubkey.c: Likewise. + * rijndael.c: Likewise. + * sha1.c: Likewise. + * sha256.c: Likewise. + + * arcfour.c: Include "cipher.h". + * twofish.c: Likewise. + * rijndael.c: Likewise. + * des.c: Likewise. + * cast5.c: Likewise. + * blowfish.c: Likewise. + + * twofish.c (twofish_setkey): Declared argument `key' const. + (twofish_encrypt): Declared argument `inbuf' const. + (twofish_decrypt): Likewise. + + * rijndael.c (rijndael_setkey): Declared argument `key' const. + (rijndael_encrypt): Declared argument `inbuf' const. + (rijndael_decrypt): Likewise. + + * des.c (do_des_setkey): Declared argument `key' const. + (do_tripledes_setkey): Likewise. + (do_des_encrypt): Declared argument `inbuf' const. + (do_des_decrypt): Likewise. + (do_tripledes_encrypt): Likewise. + (do_tripledes_decrypt): Likewise. + + * cast5.c (encrypt_block): Declared argument `inbuf' const. + (decrypt_block): Likewise. + (cast_setkey): Declared argument `key' const. + + * blowfish.c (do_bf_setkey): Declared argument `key' const. + (encrypt_block): Declared argument `inbuf' const. + (encrypt_block): Likewise. + + + + * cipher.c: Remove CIPHER_ALGO_DUMMY related code. + Removed struct cipher_table_s. + Changed definition of cipher_table. + Removed definition of disabled_algos. + (ciphers_registered, default_ciphers_registered): New variables. + (REGISTER_DEFAULT_CIPHERS): New macro. + (dummy_setkey): Declared argument `key' const. + (dummy_encrypt_block): Declared argument `inbuf' const. + (dummy_encrypt_block): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_setkey): Use `unsigned char' instead of `byte'. + (dummy_encrypt_block): Likewise. + (dummy_decrypt_block): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_decrypt_stream): Likewise. + (gcry_cipher_register_default): New function. + (gcry_cipher_lookup_func_id): New function. + (gcry_cipher_lookup_func_name): New function. + (gcry_cipher_lookup_id): New function. + (gcry_cipher_lookup_name): New function. + (gcry_cipher_id_new): New function. + (gcry_cipher_register): New function. + (gcry_cipher_unregister): New function. + (setup_cipher_table): Removed function. + (load_cipher_modules): Removed function. + (gcry_cipher_map_name): Adjusted to use new module management. + (cipher_algo_to_string): Likewise. + (disable_cipher_algo): Likewise. + (check_cipher_algo): Likewise. + (cipher_get_keylen): Likewise. + (cipher_get_blocksize): Likewise. + (gcry_cipher_open): Likewise. + (struct gcry_cipher_handle): Replaced members algo, algo_index, + blocksize, setkey, encrypt, decrypt, stencrypt, stdecrypt with one + member: cipher. + (gcry_cipher_open): Adjusted code for new handle structure. + (cipher_setkey): Likewise. + (cipher_setiv): Likewise. + (cipher_reset): Likewise. + (do_ecb_encrypt): Likewise. + (do_ecb_decrypt): Likewise. + (do_cbc_encrypt): Likewise. + (do_cbc_decrypt): Likewise. + (do_cfb_encrypt): Likewise. + (do_cfb_decrypt): Likewise. + (do_ctr_encrypt): Likewise. + (cipher_encrypt): Likewise. + (gcry_cipher_encrypt): Likewise. + (cipher_decrypt): Likewise. + (gcry_cipher_decrypt): Likewise. + (cipher_sync): Likewise. + (gcry_cipher_ctl): Likewise. + + * pubkey.c: Removed struct pubkey_table_s. + Changed definition of pubkey_table. + Removed definition of disabled_algos. + (pubkeys_registered, default_pubkeys_registered): New variables. + (REGISTER_DEFAULT_PUBKEYS): New macro. + (setup_pubkey_table): Removed function. + (load_pubkey_modules): Removed function. + (gcry_pubkey_register_default): New function. + (gcry_pubkey_lookup_func_id): New function. + (gcry_pubkey_lookup_func_name): New function. + (gcry_pubkey_lookup_id): New function. + (gcry_pubkey_lookup_name): New function. + (gcry_pubkey_id_new): New function. + (gcry_pubkey_register): New function. + (gcry_pubkey_unregister): New function. + (gcry_pk_map_name): Adjusted to use new module management. + (gcry_pk_algo_name): Likewise. + (disable_pubkey_algo): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_get_npkey): Likewise. + (pubkey_get_nskey): Likewise. + (pubkey_get_nsig): Likewise. + (pubkey_get_nenc): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (gcry_pk_get_nbits): Likewise. + (gcry_pk_algo_info): Likewise. + + * md.c: Removed struct md_digest_list_s. + (digest_list): Changed definition. + (digests_registered, default_digests_registered): New variables. + (REGISTER_DEFAULT_DIGESTS): New macro. + (new_list_item): Removed function. + (setup_md_table): Removed function. + (load_digest_module): Removed function. + (gcry_digest_register_default): New function. + (gcry_digest_lookup_func_id): New function. + (gcry_digest_lookup_func_name): New function. + (gcry_digest_lookup_id): New function. + (gcry_digest_lookup_name): New function. + (gcry_digest_id_new): New function. + (gcry_digest_register): New function. + (gcry_digest_unregister): New function. + (GcryDigestEntry): New type. + (struct gcry_md_context): Adjusted type of `list'. + (gcry_md_map_name): Adjusted to use new module management. + (digest_algo_to_string): Likewise. + (check_digest_algo): Likewise. + (md_enable): Likewise. + (md_digest_length): Likewise. + (md_asn_oid): Likewise. + +2003-04-07 Moritz Schulte <moritz@g10code.com> + + * pubkey.c: Replaced PUBKEY_ALGO_DSA with GCRY_PK_DSA, + PUBKEY_ALGO_RSA with GCRY_PK_RSA and PUBKEY_ALGO_ELGAMAL with + GCRY_PK_ELG. + + * dsa.c: Replaced PUBKEY_ALGO_DSA with GCRY_PK_DSA. + +2003-04-01 Moritz Schulte <moritz@g10code.com> + + * des.c: Removed checks for GCRY_CIPHER_3DES and GCRY_CIPHER_DES. + +2003-03-31 Moritz Schulte <moritz@g10code.com> + + * tiger.c (tiger_get_info): Do not declare static. + * sha256.c (sha256_get_info): Likewise. + * sha1.c (sha1_get_info): Likewise. + * rmd160.c (rmd160_get_info): Likewise. + * md5.c (md5_get_info): Likewise. + * md4.c (md4_get_info): Likewise. + * crc.c (crc_get_info): Likewise. + + * md.c (load_digest_module): Call setup_md_table during + initialization. + (new_list_item): Link new element into digest_list. + + * cipher.c (do_ctr_decrypt): Made do_ctr_encrypt act as a wrapper + for do_ctr_encrypt, since these functions are identical. + +2003-03-30 Simon Josefsson <jas@extundo.com> + + * cipher.c (struct gcry_cipher_handle): Add counter field. + (gcry_cipher_open): Add CTR. + (cipher_reset): Clear counter field. + (do_ctr_encrypt, do_ctr_decrypt): New functions. + (cipher_encrypt, cipher_decrypt): Call CTR functions. + (gcry_cipher_ctl): Add SET_CTR to set counter. + +2003-03-30 Moritz Schulte <moritz@g10code.com> + + * rsa.c (_gcry_rsa_blind): New function. + (_gcry_rsa_unblind): New function. + (_gcry_rsa_decrypt): Use _gcry_rsa_blind and _gcry_rsa_decrypt. + +2003-03-26 Moritz Schulte <moritz@g10code.com> + + * dynload.c (_gcry_enum_gnupgext_pubkeys): Adjust `encrypt' and + `decrypt' function arguments. + (_gcry_enum_gnupgext_pubkeys): Likewise. + * dynload.h: Likewise. + + * pubkey.c (dummy_decrypt): Add argument: int flags. + (dummy_encrypt): Likewise. + + * elgamal.c (_gcry_elg_encrypt): Add argument: int flags. + (_gcry_elg_decrypt): Likewise. + + * rsa.c (_gcry_rsa_encrypt): Add argument: int flags. + (_gcry_rsa_decrypt): Likewise. + + * pubkey.c: Add `flags' argument to members `encrypt' and + `decrypt' of struct `pubkey_table_s'. + + * rsa.h: Add `flags' argument to function declarations. + * elgamal.h: Likewise. + + * pubkey.c (sexp_data_to_mpi): New variable: int parsed_flags. + (sexp_data_to_mpi): Set `parsed_flags'. + (sexp_data_to_mpi): New argument: int *flags. + (gcry_pk_encrypt): New variable: int flags. + (gcry_pk_encrypt): Pass `flags' to pubkey_encrypt. + (pubkey_encrypt): New variable: int flags. + (pubkey_encrypt): Pass `flags' to pubkey encrypt function. + (pubkey_decrypt): Likewise. + (pubkey_decrypt): Pass `flags' to pubkey encrypt function. + (gcry_pk_encrypt): Include `flags' s-exp in return list. + (sexp_to_enc): New argument: int *flags. + (gcry_pk_decrypt): New variable: int flags. + (gcry_pk_decrypt): Pass `flags' to pubkey_decrypt. + (sexp_to_enc): New variable: int parsed_flags. + (sexp_to_enc): Set `parsed_flags'. + +2003-03-22 Simon Josefsson <jas@extundo.com> + + * cipher.c (gcry_cipher_open, do_cbc_encrypt) + (gcry_cipher_encrypt): Support GCRY_CIPHER_CBC_MAC. + (gcry_cipher_ctl): Support GCRYCTL_SET_CBC_MAC. + +2003-03-19 Werner Koch <wk@gnupg.org> + + * primegen.c (gen_prime): New args EXTRA_CHECK and EXTRA_CHECK_ARG + to allow for a user callback. Changed all callers. + (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Ditto, pass them to gen_prime. + * rsa.c (check_exponent): New. + (generate): Use a callback to ensure that a given exponent is + actually generated. + +2003-03-12 Moritz Schulte <moritz@g10code.com> + + * primegen.c: Initialize `no_of_small_prime_numbers' statically. + (gen_prime): Remove calculation of `no_of_small_prime_numbers'. + +2003-03-03 Moritz Schulte <moritz@g10code.com> + + * md.c (gcry_md_ctl): Rewritten to use same style like the other + functions dispatchers. + +2003-03-02 Moritz Schulte <moritz@g10code.com> + + * cipher.c (struct gcry_cipher_handle): New member: algo_index. + (gcry_cipher_open): Allocate memory for two cipher contexts. + Initialize algo_index. + (cipher_setkey): Duplicate context into reserved memory. + (cipher_reset): New function, which resets the context and clear + the IV. + (gcry_cipher_ctl): Call cipher_reset. + +2003-02-23 Moritz Schulte <moritz@g10code.com> + + * cipher.c: Remove (bogus) `digitp' macro definition. + * md.c: Likewise. + + * blowfish.c (burn_stack): Removed. + * arcfour.c (burn_stack): Likewise. + * cast5.c (burn_stack): Likewise. + * des.c (burn_stack): Likewise. + * md4.c (burn_stack): Likewise. + * md5.c (burn_stack): Likewise. + * random.c (burn_stack): Likewise. + * rijndael.c (burn_stack): Likewise. + * rmd160.c (burn_stack): Likewise. + * sha1.c (burn_stack): Likewise. + * sha256.c (burn_stack): Likewise. + * tiger.c (burn_stack): Likewise. + * twofish.c (burn_stack): Likewise. + + * blowfish.c: Changed all occurences of burn_stack to + _gcry_burn_stack. + * arcfour.c: Likewise. + * cast5.c: Likewise. + * des.c: Likewise. + * md4.c: Likewise. + * md5.c: Likewise. + * random.c: Likewise. + * rijndael.c: Likewise. + * rmd160.c: Likewise. + * sha1.c: Likewise. + * sha256.c: Likewise. + * tiger.c: Likewise. + * twofish.c: Likewise. + + * arcfour.c (_gcry_arcfour_get_info): Use GCRY_CIPHER_ARCFOUR + instead of hard-coded value `301'. + +2003-01-24 Werner Koch <wk@gnupg.org> + + * random.c (_gcry_register_random_progress): New. + (_gcry_random_progress): New. + + * rndlinux.c (gather_random): Call the random progress function. + +2003-01-23 Werner Koch <wk@gnupg.org> + + * rsa.c (generate): New arg USE_E to request a specific public + exponent. + (_gcry_rsa_generate): Ditto. + * elgamal.c (_gcry_elg_generate): Must add an dummy argument + instead of USE_E. + * dsa.c (_gcry_dsa_generate): Ditto. + * pubkey.c (dummy_generate): Ditto. + (pubkey_generate): Add USE_E arg and pass it down. + (gcry_pk_genkey): Detect "rsa-use-e" parameter and pass it to generate. + + * pubkey.c (sexp_to_enc): New arg RET_MODERN. + (gcry_pk_decrypt): Make use of it to return a real S-expression. + Return better error codes. + (gcry_pk_verify): Return better error codes. + +2003-01-21 Werner Koch <wk@gnupg.org> + + * random.c (gcry_random_add_bytes): Add QUALITY argument, let + function return an error code and disable its core for now. + +2003-01-21 Timo Schulz <twoaday@freakmail.de> + + * random.c (gcry_random_add_bytes): New. Function to add external + random to the pool. + +2003-01-20 Simon Josefsson <jas@extundo.com> + + * crc.c: New. + * Makefile.am (EXTRA_PROGRAMS, EXTRA_crc_SOURCES): Add crc.c. + * md.c (gcry_md_get_algo_dlen): Add values for CRC. + +2003-01-20 Werner Koch <wk@gnupg.org> + + * sha256.c: New. + * bithelp.h (ror): New. + * Makfile.am: Add sha256.c. + * md.c (oid_table): Add values for SHA256 et al. + (gcry_md_get_algo_dlen): Likewise + +2003-01-20 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_get_keygrip): Implemented keygrips for DSA + and ElGamal. + +2003-01-17 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_encrypt): Reworked so that the output will + never contain the plaintext even if the caller did not checked the + return value. + + * md.c (gcry_md_get_algo): Changed error code to GCRYERR_GENERAL + because we don't have an invalid md algo but no algorithm enabled. + + * pubkey.c (gcry_pk_genkey): Changed error code for bounds check + of table parameters to GCRYERR_INTERNAL. + + * md.c (gcry_md_open): Partly reverted Timo's change from + 2002-10-10 by removing the check for the algorithm. An algorithm + of 0 is allowed and anyway we should not double check it or check + it using a different function. Also fixed the flags check. + + * pubkey.c (gcry_pk_encrypt): Make sure that R_CIPH points to NULL + on error. + (gcry_pk_decrypt): Ditto for R_PLAIN. + (gcry_pk_sign): Ditto for R_SIG. + (gcry_pk_genkey): Ditto for R_KEY. + +2003-01-16 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_write): Changed 2nd argument type to void*. + (gcry_md_hash_buffer): Changed type of boths buffers to void*. + (gcry_md_setkey): Changed 2nd argument type to void*. + +2003-01-15 Werner Koch <wk@gnupg.org> + + * pubkey.c (sexp_data_to_mpi): New. This handles pkcs1 padding. + (gcry_pk_sign, gcry_pk_verify): Use it here. + (gcry_pk_encrypt): And here. + (pubkey_verify): Add debug code. + (sexp_to_enc): Handle flags in the input and return the pkcs1 flag + in a new parameter. + (gcry_pk_decrypt): Prepare for future pkcs1 handling. + +2002-12-19 Werner Koch <wk@gnupg.org> + + * random.c (_gcry_random_initialize): New. + +2002-12-16 Werner Koch <wk@gnupg.org> + + * cipher.c: Added a Teletrust specific OID for 3DES. + +2002-12-12 Werner Koch <wk@gnupg.org> + + * md.c: Added another oddball OIW OID (sha-1WithRSAEncryption). + +2002-11-23 Werner Koch <wk@gnupg.org> + + * md.c (load_digest_module): Enlarged checked_algos bitmap. + * md4.c (func_table): Fixed entry for md4. + Both by Simon Josephson. + (transform): Copy data to get the alignment straight. Tested only + on i386. + +2002-11-10 Simon Josefsson <jas@extundo.com> + + * cipher.c (gcry_cipher_open): Don't reject CTS flag. + (do_cbc_encrypt, do_cbc_decrypt, cipher_encrypt) + (gcry_cipher_encrypt, cipher_decrypt) + (gcry_cipher_decrypt): Support CTS flag. + (gcry_cipher_ctl): Toggle CTS flag. + +2002-11-10 Werner Koch <wk@gnupg.org> + + * md4.c: New. By Simon Josefsson. + * Makefile.am (EXTRA_PROGRAMS): Add md4.c. + * md.c (oid_table,gcry_md_get_algo_dlen): MD4 support. + +2002-10-14 Werner Koch <wk@gnupg.org> + + * arcfour.c (do_encrypt_stream): Don't use increment op when + assigning to the same variable. + +2002-10-10 Timo Schulz <ts@winpt.org> + + * pubkey.c (gcry_pk_genkey): Check boundaries. + + * md.c (gcry_md_open): Check that algo is available and only + valid flag values are used. + (gcry_md_get_algo): Add error handling. + +2002-09-26 Werner Koch <wk@gnupg.org> + + * md.c: Include an OID for TIGER. + * tiger.c (tiger_get_info): Use a regular OID. + +2002-09-17 Werner Koch <wk@gnupg.org> + + * random.c: Replaced mutex.h by the new ath.h. Changed all calls. + +2002-09-16 Werner Koch <wk@gnupg.org> + + * arcfour.c (do_encrypt_stream): Use register modifier and modulo. + According to Nikos Mavroyanopoulos this increases perfromace on + i386 system noticable. And I always tought gcc is clever enough. + * md5.c (transform): Use register modifier. + * rmd160.c (transform): Ditto. + * sha1.c (transform): Ditto. We hope that there are 6 free registers. + * random.c (gcry_randomize): Rewrote to avoid malloc calls. + + * rndlinux.c (gather_random): Replaced remaining fprintfs by log_*. + * arcfour.c (do_arcfour_setkey): Ditto. + * twofish.c (do_twofish_setkey): Ditto. + * rndegd.c (gather_random): Ditto. + * rijndael.c (do_setkey): Ditto. + * random.c (_gcry_random_dump_stats): Ditto. + * primegen.c (_gcry_generate_elg_prime): Ditto. + * des.c (_gcry_des_get_info): Ditto. + * cast5.c (do_cast_setkey): Ditto. + * blowfish.c (do_bf_setkey): Ditto. + +2002-08-26 Werner Koch <wk@gnupg.org> + + * des.c (weak_keys): Fixed one entry in the table and compared + all entries against the literature. + (selftest): Checksum the weak key table. + +2002-08-21 Werner Koch <wk@gnupg.org> + + * pubkey.c: Enable keygrip calculation for "openpgp-rsa". + +2002-08-17 Werner Koch <wk@gnupg.org> + + * cipher.c (setup_cipher_table): Don't overwrite the DES entry + with the entry for DUMMY. + +2002-08-14 Werner Koch <wk@gnupg.org> + + * des.c (do_des_setkey,do_des_encrypt, do_des_decrypt): New. + (_gcry_des_get_info): Support plain old DES. + * cipher.c (setup_cipher_table): Put DES into the table. + +2002-07-25 Werner Koch <wk@gnupg.org> + + * rndunix.c (_gcry_rndunix_constructor): Prefixed with _gcry_. + Noted by Stephan Austermuehle. + +2002-07-08 Timo Schulz <ts@winpt.org> + + * rndw32.c: Replaced the m_ memory functions with the real + gcry_ functions. Renamed all g10_ prefixed functions to log_. + +2002-06-12 Werner Koch <wk@gnupg.org> + + * rsa.c (generate): Use e = 65537 for now. + +2002-06-11 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_get_keygrip): Allow a "protected-private-key". + +2002-06-05 Timo Schulz <ts@winpt.org> + + * cipher.c (gcry_cipher_encrypt, gcry_cipher_decrypt): + Check that the input size is a multiple of the blocksize. + +2002-05-23 Werner Koch <wk@gnupg.org> + + * md.c (oid_table): Add an rsadsi OID for MD5. + +2002-05-21 Werner Koch <wk@gnupg.org> + + * primegen.c, elgamal.c, dsa.c (progress): Do not print anything + by default. Pass an extra identifying string to the callback and + reserved 2 argumenst for current and total counters. Changed the + register function prototype. + +2002-05-17 Werner Koch <wk@gnupg.org> + + * rndegd.c (rndegd_constructor): Fixed name of register function + and prefixed the function name with _gcry_. + * rndw32.c (rndw32_constructor): Ditto. + * tiger.c (tiger_constructor): Ditto. + + * Makefile.am: Removed all dynamic loading stuff. + * dynload.c: Ditto. Now only used for the constructor system. + +2002-05-15 Werner Koch <wk@gnupg.org> + + * random.c (gcry_random_bytes,gcry_random_bytes_secure) + (gcry_randomize): Make sure we are initialized. + +2002-05-14 Werner Koch <wk@gnupg.org> + + Changed license of most files to the LGPL. + +2002-05-02 Werner Koch <wk@gnupg.org> + + * random.c (_gcry_fast_random_poll): Initialize the module so the + mutex can be used. + + * primegen.c (small_prime_numbers): Moved table from smallprime.c + * smallprime.c: File removed. + + * des.c (leftkey_swap, rightkey_swap, working_memcmp): Made static. + + * cipher.c (gcry_cipher_map_name): Map "RIJNDAEL" to "AES". + * rijndael.c (rijndael_get_info): We do only support a 128 bit + blocksize so it makes sense to change the algorithm strings to + AES. + + * tiger.c (tiger_final): Removed superfluous token pasting operators. + * md5.c (md5_final): Ditto. + +2002-04-30 Werner Koch <wk@gnupg.org> + + * cipher.c: Fixed list of copyright years. + +2002-03-18 Werner Koch <wk@gnupg.org> + + * random.c (initialize): Initialize the new pool lock mutex. + (_gcry_fast_random_poll): Add locking and moved main + code out to... + (do_fast_random_poll): new function. + (read_pool): Use the new function here. + (get_random_bytes): Add locking. + (_gcry_update_random_seed_file): Ditto. + +2002-03-11 Werner Koch <wk@gnupg.org> + + * md.c: Add rsaSignatureWithripemd160 to OID table. + +2002-02-20 Werner Koch <wk@gnupg.org> + + * sha1.c: Removed a left over comment note. The code has been + rewritten from scratch in 1998. Thanks to Niels Möller for + reporting this misleading comment. + +2002-02-18 Werner Koch <wk@gnupg.org> + + * rndunix.c (rndunix_constructor): Use the the new prefixed + function name. Reported by Jordi Mallach. + +2002-02-10 Werner Koch <wk@gnupg.org> + + * random.c (mix_pool): Carry an extra failsafe_digest buffer + around to make the function more robust. + +2002-02-08 Werner Koch <wk@gnupg.org> + + * random.c (add_randomness): Xor new data into the pool and not + just copy it. This avoids any choosen input attacks which are not + serious in our setting because an outsider won't be able to mix + data in and even then we keep going with a PRNG. Thanks to Stefan + Keller for pointing this out. + +2002-01-04 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_genkey): Do not release skey - it is static. + + * primegen.c (gen_prime): Of course we should use set_bit + and not set_highbit to set the second high bit. + +2001-12-18 Werner Koch <wk@gnupg.org> + + * rsa.c (generate): Loop until we find the exact modulus size. + Changed the exponent to 41. + (rsa_get_info): s/usage/r_usage/ to avoid shadow warnings. + * primegen.c (gen_prime): Set 2 high order bits for secret primes. + + * Makefile.am (DISTCLEANFILES): Include construct.c. + +2001-12-17 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_get_keygrip): New - experimental. + +2001-12-11 Werner Koch <wk@gnupg.org> + + * cipher.c: Added OIDs for AES. + (gcry_cipher_mode_from_oid): New. + (gcry_cipher_map_name): Moved OID search code to .. + (search_oid): .. new function. + +2001-12-10 Werner Koch <wk@gnupg.org> + + * pubkey.c (gcry_pk_encrypt): Find the signature algorithm by name + and not by number. + + * pubkey.c (gcry_pk_encrypt,gcry_pk_decrypt,gcry_pk_sign) + (gcry_pk_verify,gcry_pk_testkey, gcry_pk_genkey) + (gcry_pk_get_nbits): Release the arrays. Noted by Nikos + Mavroyanopoulos. + +2001-12-06 Werner Koch <wk@gnupg.org> + + * cipher.c (gcry_cipher_map_name): Look also for OIDs prefixed + with "oid." or "OID.". + +2001-12-05 Werner Koch <wk@gnupg.org> + + * pubkey.c (algo_info_table): Fixed entry for openpgp-rsa. + +2001-11-24 Werner Koch <wk@gnupg.org> + + * pubkey.c: Added the rsaEncryption OID to the tables. + (sexp_to_key): Add an arg to return the index of the algorithm, + changed all callers. + (gcry_pk_sign): Find the signature algorithm by name and not by + number. + (gcry_pk_get_nbits): Fixed so that we can now really pass a secret + key to get the result. + + * md.c (gcry_md_map_name): Look also for OIDs prefixed with "oid." + or "OID." so that an OID string can be used as an S-Exp token. + +2001-11-20 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_map_name): Lookup by OID if the the name begins + with a digit. + (oid_table): New. + +2001-11-16 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_info): New operator GCRYCTL_IS_ALGO_ENABLED. + +2001-11-07 Werner Koch <wk@gnupg.org> + + * md.c (gcry_md_hash_buffer): Close the handle which was left open + for algorithms other than rmd160. + +2001-08-08 Werner Koch <wk@gnupg.org> + + * rndw32.c (gather_random): Use toolhelp in addition to the NT + gatherer for Windows2000. Suggested by Sami Tolvanen. + + * random.c (read_pool): Fixed length check, this used to be one + byte to strict. Made an assert out of it because the caller has + already made sure that only poolsize bytes are requested. + Reported by Marcus Brinkmann. + +2001-08-03 Werner Koch <wk@gnupg.org> + + * cipher.c (cipher_encrypt, cipher_decrypt): Prepare to return + errors. We have to change the interface to all ciphers to make + this really work but we should do so to prepare for hardware + encryption modules. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Return the error and + set lasterr. + (gcry_cipher_ctl): Make sure that errors from setkey are returned. + +2001-08-02 Werner Koch <wk@gnupg.org> + + * rndlinux.c (gather_random): casted a size_t arg to int so that + the format string is correct. Casting is okay here and avoids + translation changes. + + * random.c (fast_random_poll): Do not check the return code of + getrusage. + + * rndunix.c: Add a signal.h header to avoid warnings on Solaris 7 + and 8. + + * tiger.c (print_abc,print_data): Removed. + + * rijndael.c, des.c, blowfish.c, twofish.c, cast5.c, arcfour.c + (burn_stack): New. Add wrappers for most functions to be able to + call burn_stack after the function invocation. This methods seems + to be the most portable way to zeroise the stack used. It does + only work on stack frame based machines but it is highly portable + and has no side effects. Just setting the automatic variables at + the end of a function to zero does not work well because the + compiler will optimize them away - marking them as volatile would + be bad for performance. + * md5.c, sha1.c, rmd160.c, tiger.c (burn_stack): Likewise. + * random.c (burn_stack): New. + (mix_pool): Use it here to burn the stack of the mixblock function. + + * primegen.c (_gcry_generate_elg_prime): Freed q at 3 places. + Thanks to Tommi Komulainen. + + * arcfour.c (arcfour_setkey): Check the minimim keylength against + bytes and not bits. + (selftest): Must reset the key before decryption. + +2001-05-31 Werner Koch <wk@gnupg.org> + + * sha1.c (sha1_init): Made static. + + Changed all g10_ prefixed function names as well as some mpi_ + function names to cope with the introduced naming changes. + + * md.c (prepare_macpads): Made key const. + +2001-05-28 Werner Koch <wk@gnupg.org> + + * rndegd.c (gather_random): Removed the use of tty_printf. + +2001-03-29 Werner Koch <wk@gnupg.org> + + * md5.c (md5_final): Fixed calculation of hashed length. Thanks + to disastry@saiknes.lv for pointing out that it was horrible wrong + for more than 512MB of input. + * sha1.c (sha1_final): Ditto. + * rmd160.c (rmd160_final): Ditto. + * tiger.c (tiger_final): Ditto. + + * blowfish.c (encrypt,do_encrypt): Changed name to do_encrypt to + avoid name clashes with an encrypt function in stdlib.h of + Dynix/PIX. Thanks to Gene Carter. + * elgamal.c (encrypt,do_encrypt): Ditto. + + * twofish.c (gnupgext_enum_func): Use only when when compiled as a + module. + * rijndael.c (gnupgext_enum_func): Ditto. + + * tiger.c (tiger_get_info): Return "TIGER192" and not just + "TIGER". By Edwin Woudt. + + * random.c: Always include time.h - standard requirement. Thanks + to James Troup. + + * rndw32.c: Fixes to the macros. + +2001-01-11 Werner Koch <wk@gnupg.org> + + * cipher.c (cipher_encrypt,gcry_cipher_encrypt): Use blocksize and + not 8. + +2000-12-19 Werner Koch <wk@gnupg.org> + + Major change: + Removed all GnuPG stuff and renamed this piece of software + to gcrypt. + +2000-11-14 Werner Koch <wk@gnupg.org> + + * dsa.c (test_keys): Replaced mpi_alloc by gcry_mpi_new and + mpi_free by gcry_mpi_release. + * elgamal.c (test_keys,generate): Ditto, also for mpi_alloc_secure. + * rsa.c (test_keys,generate,rsa_verify): Ditto. + * primegen.c (generate_elg_prime): Ditto. + (gen_prime): Ditto and removed nlimbs. + + * rsa.c (generate): Allocate 2 more vars in secure memory. + + * Makefile.am (OMIT_DEPENDENCIES): Hack to work around dependency + problems. + +2000-10-09 Werner Koch <wk@gnupg.org> + + * arcfour.c, arcfour.h: New. + * cipher.c (cipher_encrypt, cipher_decrypt): Add stream mode. + (setup_cipher_table): Add Arcfour. + (gcry_cipher_open): Kludge to allow stream mode. + +Wed Oct 4 13:16:18 CEST 2000 Werner Koch <wk@openit.de> + + * sha1.c (transform): Use rol() macro. Actually this is not needed + for a newer gcc but there are still aoter compilers. + + * rsa.c (test_keys): Use new random function. + + * md.c (gcry_md_setkey): New function to overcome problems with + const conflics. + (gcry_md_ctl): Pass set key to the new functions. + + * rijndael.c: New. + * cipher.c: Add Rijndael support. + +Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de> + + * rndlinux.c (open_device): Loose random device checking. + By Nils Ellmenreich. + + * random.c (fast_random_poll): Check ENOSYS for getrusage. + * rndunix.c: Add 2 sources for QNX. By Sam Roberts. + + * pubkey.c (gcry_pk_algo_info): Add GCRYCTL_GET_ALGO_USAGE. + + * rsa.c: Changed the comment about the patent. + (secret): Speed up by using the CRT. For a 2k keys this + is about 3 times faster. + (stronger_key_check): New but unused code to check the secret key. + * Makefile.am: Included rsa.[ch]. + * pubkey.c: Enabled RSA support. + (pubkey_get_npkey): Removed RSA workaround. + +Mon Jul 31 10:04:47 CEST 2000 Werner Koch <wk@openit.de> + + * pubkey.c: Replaced all gcry_sexp_{car,cdr}_{data,mpi} by the new + gcry_sexp_nth_{data,mpi} functions. + +Tue Jul 25 17:44:15 CEST 2000 Werner Koch <wk@openit.de> + + * pubkey.c (exp_to_key,sexp_to_sig,sexp_to_enc,gcry_pk_encrypt, + gcry_pk_decrypt,gcry_pk_sign,gcry_pk_genkey): Changed to work with + the new S-Exp interface. + +Mon Jul 17 16:35:47 CEST 2000 Werner Koch <wk@> + + * random.c (gather_faked): Replaced make_timestamp by time(2) again. + +Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@> + + * md.c (gcry_md_ctl): Support GCRYCTL_{START,STOP}_DUMP. + + * Makefile.am: Never compile mingw32 as module. + + * Makefile.am: Tweaked module build and removed libtool + + * Makefile.am: Replaced -O1 by -O. Suggested by Alec Habig. + + * elgamal.c (sign): Removed inactive code. + + * rsa.c, rsa.h: New based on the old module version (only in CVS for now). + * pubkey.c (setup_pubkey_table): Added commented support for RSA. + + * rndunix.c (waitpid): New. For UTS 2.1. All by Dave Dykstra. + (my_popen): Do the FD_CLOEXEC only if it is available + (start_gatherer): Cope with missing _SC_OPEN_MAX + + * rndunix.c: Add some more headers for QNX. By Sam Roberts. + + * rndegd.c (gather_random): Shortcut level 0. + * rndunix.c (gather_random): Ditto. + * rndw32.c (gather_random): Ditto. + + * rndw32.c: Replaced with code from Cryptlib and commented the old stuff. + * rndw32.c: Add some debuging code enabled by an environment variable. + + * random.c (read_seed_file): Binary open for DOSish system + (update_random_seed_file): Ditto. + * random.c [MINGW32]: Include process.h for getpid. + * random.c (fast_random_poll): Add clock_gettime() as fallback for + system which support this POSIX.4 fucntion. By Sam Roberts. + + * random.c (read_seed_file): Removed the S_ISLNK test becuase it + is already covered by !S_ISREG and is not defined in Unixware. + Reported by Dave Dykstra. + (update_random_seed_file): Silently ignore update request when pool + is not filled. + + * random.c (read_seed_file): New. + (set_random_seed_file): New. + (read_pool): Try to read the seeding file. + (update_random_seed_file): New. + + (read_pool): Do an initial extra seeding when level 2 quality random + is requested the first time. This requestes at least POOLSIZE/2 bytes + of entropy. Compined with the seeding file this should make normal + random bytes cheaper and increase the quality of the random bytes + used for key generation. + + * random.c (read_pool): Print a more friendly error message in + cases when too much random is requested in one call. + + * random.c (fast_random_poll): Check whether RUSAGE_SELF is defined; + this is not the case for some ESIX and Unixware, although they have + getrusage(). + + * primegen.c (generate_elg_prime): All primes are now generated with + the lowest random quality level. Because they are public anyway we + don't need stronger random and by this we do not drain the systems + entropy so much. + + * primegen.c (register_primegen_progress): New. + * dsa.c (register_pk_dsa_progress): New. + * elgamal.c (register_pk_elg_progress): New. + + * elgamal.c (wiener_map): New. + (gen_k): Use a much smaller k. + (generate): Calculate the qbits using the wiener map and + choose an x at a size comparable to the one choosen in gen_k + + * rmd160.c (rmd160_get_info): Moved casting to the left side due to a + problem with UTS4.3. Suggested by Dave Dykstra. + * sha1.c (sha1_get_info): Ditto. + * tiger.c (tiger_get_info): Ditto. + * md5.c (md5_get_info): Ditto + * des.c (des_get_info): Ditto. + * blowfish.c (blowfish_get_info): Ditto. + * cast5.c (cast5_get_info): Ditto. + * twofish.c (twofish_get_info): Ditto. + +Fri Mar 24 11:25:45 CET 2000 Werner Koch <wk@openit.de> + + * md.c (md_open): Add hmac arg and allocate space for the pads. + (md_finalize): Add HMAC support. + (md_copy): Ditto. + (md_close): Ditto. + (gcry_md_reset): Ditto. + (gcry_md_ctl): Ditto. + (prepare_macpdas): New. + +Mon Mar 13 19:22:46 CET 2000 Werner Koch <wk@openit.de> + + * md.c (gcry_md_hash_buffer): Add support for the other algorithms. + +Mon Jan 31 16:37:34 CET 2000 Werner Koch <wk@gnupg.de> + + * genprime.c (generate_elg_prime): Fixed returned factors which never + worked for non-DSA keys. + +Thu Jan 27 18:00:44 CET 2000 Werner Koch <wk@gnupg.de> + + * pubkey.c (sexp_to_key): Fixed mem leaks in case of errors. + +Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de> + + * pubkey.c (gcry_pk_decrypt): Implemented. + (gcry_pk_encrypt): Implemented. + (gcry_pk_testkey): New. + (gcry_pk_genkey): New. + (pubkey_decrypt): Made static. + (pubkey_encrypt): Ditto. + (pubkey_check_secret_key): Ditto. + (pubkey_generate): Ditto. + +Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de> + + * pubkey.c (pubkey_nbits): Removed and replaced by ... + (gcry_pk_get_nbits): this new one. + +Wed Dec 8 21:58:32 CET 1999 Werner Koch <wk@gnupg.de> + + * dsa.c: s/mpi_powm/gcry_mpi_powm/g + * elgamal.c: Ditto. + * primegen.c: Ditto. + + * : Replaced g10_opt_verbose by g10_log_verbosity(). + + * Makefile.am (INCLUDES): removed intl, add ../gcrypt + +Fri Nov 19 17:15:20 CET 1999 Werner Koch <wk@gnupg.de> + + * dynload.c (cmp_filenames): New to replaced compare_filename() in + module. + (register_cipher_extension): Removed the tilde expansion stuff. + * rndeg.c (my_make_filename): New. + + * : Replaced header util.h by g10lib.h + + * random.c (gather_faked): Replaced make_timestamp by time(2). + Disabled wrning printed with tty_printf. + * rndlinux.c (gather_random): Always use fprintf instead of tty_xxx; + this should be replaced by a callback function. + + * primegen.c (gen_prime): Use gcry_mpi_randomize. + (is_prime): Ditto. + * elgamal.c (test_keys): Ditto. + * dsa.c (test_keys): Ditto. + + * cipher.c (gcry_cipher_close): Die on invalid handle. + +Mon Nov 15 21:36:02 CET 1999 Werner Koch <wk@gnupg.de> + + * elgamal.c (gen_k): Use the new random API. + (generate): Ditto. + * dsa.c (gen_k): Ditto. + (generate): Ditto. + +Sat Nov 13 17:44:23 CET 1999 Werner Koch <wk@gnupg.de> + + * pubkey.c (disable_pubkey_algo): Made static. + (gcry_pk_ctl): New. + + * random.c (get_random_bits): Renamed to ... + (get_random_bytes): ... this and made static. + (gcry_random_bytes): New. + (gcry_random_bytes_secure): New. + (randomize_buffer): Renamed to ... + (gcry_randomize): ...this. + + * md.c (gcry_md_hash_buffer): New. + + * pubkey.c (gcry_pk_algo_info): 4 new commands. + (pubkey_get_npkey): Made static. + (pubkey_get_nskey): Made static. + (pubkey_get_nsig): Made static. + (pubkey_get_nenc): Made static. + + * pubkey.c: Removed all G10ERR_xxx. + * cipher.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_CIPHER_ALGO. + * md.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_MD_ALGO. + * cast5.c (cast_setkey): Changed errocodes to GCRYERR_xxx. + * blowfish.c: Ditto. + * des.c: Ditto. + * twofish.c: Ditto. + * dsa.c: Ditto. + * elgamal.c: Ditto. + + * g10c.c: Removed + + * cipher.c (gcry_cipher_open): Replaced alloc functions and return NULL + if we are out of core. + * dynload.c: Replaced all memory allocation functions. + * md.c: Ditto. + * primegen.c: Ditto. + * pubkey.c: Ditto. + * random.c: Ditto. + * rndw32.c: Ditto. + * elgamal.c: Ditto. + * dsa.c: Ditto. + +Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de> + + * elgamal.c (sign): Hugh found strange code here. Replaced by BUG(). + + * cipher.c: Merged with gcrypt/symapi.c. + + * pubkey.c (string_to_pubkey_algo): Renamed function to ... + (gcry_pk_map_name): ... this. + (pubkey_algo_to_string): Renamed function to ... + (gcry_pk_algo_name): ... this. + (gcry_pk_algo_info): New. + * pubkey.c: Merged with gcrypt/pkapi.c. + + * md.c (md_reset): Clear finalized; thanks to Ulf Moeller for + fixing this bug. + + * md.c: Merged with gcrypt/mdapi.c + +Wed Sep 15 14:39:59 CEST 1999 Michael Roth <mroth@nessie.de> + + * des.c: Various speed improvements: One bit pre rotation + trick after initial permutation (Richard Outerbridge). + Finished test of SSLeay Tripple-DES patterns. + +Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndw32.c: New. + +Mon Sep 13 10:51:29 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * bithelp.h: New. + * rmd160.h, sha1.h, md5.h: Use the rol macro from bithelp.h + +Tue Sep 7 16:23:36 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Fixed seds for latest egcc. By Ollivier Robert. + +Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * des.c (selftest): Add some testpattern + +Mon Aug 30 20:38:33 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (do_cbc_encrypt): Fixed serious bug occuring when not using + in place encryption. Pointed out by Frank Stajano. + +Mon Jul 26 09:34:46 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * md5.c (md5_final): Fix for a SCO cpp bug. + +Thu Jul 15 10:15:35 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * elgamal.c (elg_check_secret_key,elg_encrypt + elg_decrypt,elg_sign,elg_verify): Sanity check on the args. + * dsa.c (dsa_check_secret_key,dsa_sign,dsa_verify): Ditto. + + * pubkey.c (disable_pubkey_algo): New. + (check_pubkey_algo2): Look at disabled algo table. + * cipher.c (disable_cipher_algo): New. + (check_cipher_algo): Look at disabled algo table. + +Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Support for libtool. + +Fri Jul 2 11:45:54 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * dsa.c (gen_k): Changed algorithm to consume less random bytes + * elgamal.c (gen_k): Ditto. + + * random.c (random_dump_stats): New. + +Thu Jul 1 12:47:31 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * primegen.c, elgamal.c, dsa.c (progess): New and replaced all + fputc with a call to this function. + +Sat Jun 26 12:15:59 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndegd.c (do_write): s/ssize_t/int/ due to SunOS 4.1 probs. + + * cipher.c (do_cbc_encrypt, do_cbc_decrypt): New. + + * dynload.c (HAVE_DL_SHL_LOAD): Map hpux API to dlopen (Dave Dykstra). + * Makefile.am (install-exec-hook): Removed. + +Sun May 23 14:20:22 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (setup_cipher_table): Enable Twofish + + * random.c (fast_random_poll): Disable use of times() for mingw32. + +Mon May 17 21:54:43 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (register_internal_cipher_extension): Minor init fix. + +Tue May 4 15:47:53 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * primegen.c (gen_prime): Readded the Fermat test. Fixed the bug + that we didn't correct for step when passing the prime to the + Rabin-Miller test which led to bad performance (Stefan Keller). + (check_prime): Add a first Fermat test. + +Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (cipher_setiv): Add ivlen arg, changed all callers. + + * random.c (randomize_buffer): alway use secure memory because + we can't use m_is_secure() on a statically allocated buffer. + + * twofish.c: Replaced some macros by a loop to reduce text size. + * Makefile.am (twofish): No more need for sed editing. + +Fri Apr 9 12:26:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (cipher_open): Reversed the changes for AUTO_CFB. + + * blowfish.c: Dropped the Blowfish 160 mode. + * cipher.c (cipher_open): Ditto. + (setup_cipher_table): Ditto. And removed support of twofish128 + +Wed Apr 7 20:51:39 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (get_random_bits): Can now handle requests > POOLSIZE + + * cipher.c (cipher_open): Now uses standard CFB for automode if + the blocksize is gt 8 (according to rfc2440). + + * twofish.c: Applied Matthew Skala's patches for 256 bit key. + +Tue Apr 6 19:58:12 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (get_random_bits): Can now handle requests > POOLSIZE + + * cipher.c (cipher_open): Now uses standard CFB for automode if + the blocksize is gt 8 (according to rfc2440). + +Sat Mar 20 11:44:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndlinux.c (tty_printf) [IS_MODULE]: Removed. + + * rndegd.c (gather_random): Some fixes. + +Wed Mar 17 13:09:03 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndegd.c (do_read): New. + (gather_random): Changed the implementation. + +Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed. + +Fri Feb 26 17:55:41 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * md.c: Nearly a total rewrote. + +Wed Feb 24 11:07:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.c (context): Fixed alignment + * md.c: Ditto. + + * rndegd.c: New + +Mon Feb 22 20:04:00 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndegd.c: New. + +Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Modules are now figured out by configure + * construct.c: New. Generated by configure. Changed all modules + to work with that. + * sha1.h: Removed. + * md5.h: Removed. + + * twofish.c: Changed interface to allow Twofish/256 + + * rndunix.c (start_gatherer): Die on SIGPIPE. + +Wed Jan 20 18:59:49 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndunix.c (gather_random): Fix to avoid infinite loop. + +Sun Jan 17 11:04:33 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * des.c (is_weak_key): Replace system memcmp due to bugs + in SunOS's memcmp. + (des_get_info): Return error on failed selftest. + * twofish.c (twofish_setkey): Return error on failed selftest or + invalid keylength. + * cast5.c (cast_setkey): Ditto. + * blowfish.c (bf_setkey): Return error on failed selftest. + +Tue Jan 12 11:17:18 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (random_is_faked): New. + + * tiger.c: Only compile if we have the u64 type + +Sat Jan 9 16:02:23 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndunix.c (gather_random): check for setuid. + + * Makefile.am: Add a way to staically link random modules + +Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * md.c (md_stop_debug): Do a flush first. + (md_open): size of buffer now depends on the secure parameter + +Sun Jan 3 15:28:44 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * rndunix.c (start_gatherer): Fixed stupid ==/= bug + +1998-12-31 Geoff Keating <geoffk@ozemail.com.au> + + * des.c (is_weak_key): Rewrite loop end condition. + +Tue Dec 29 14:41:47 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * random.c: add unistd.h for getpid(). + (RAND_MAX): Fallback value for Sun. + +Wed Dec 23 17:12:24 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * md.c (md_copy): Reset debug. + +Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * random.c (read_random_source): Changed the interface to the + random gathering function. + (gather_faked): Use new interface. + * dynload.c (dynload_getfnc_fast_random_poll): Ditto. + (dynload_getfnc_gather_random): Ditto. + * rndlinux.c (gather_random): Ditto. + * rndunix.c (gather_random): Ditto. + +Sat Dec 12 18:40:32 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (SYMBOL_VERSION): New to cope with system which needs + underscores. + + * rndunix.c: Rewrote large parts + +Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * dynload.c (load_extension): increased needed verbosity level. + + * random.c (fast_random_poll): Fallback to a default fast random + poll function. + (read_random_source): Always use the faked entroy gatherer if no + gather module is available. + * rndlinux.c (fast_poll): Removed. + * rndunix.c (fast_poll): Removed. + + +Wed Nov 25 12:33:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-*.c: Removed. + * rndlinux.c : New. + * rndunix.c : New. + * random.c : Restructured the interface to the gather modules. + (intialize): Call constructor functions + (read_radnom_source): Moved to here. + * dynload.c (dynload_getfnc_gather_random): New. + (dynload_getfnc_fast_random_poll): New. + (register_internal_cipher_extension): New. + (register_cipher_extension): Support of internal modules. + +Sun Nov 8 17:44:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c (read_random_source): Removed the assert. + +Mon Oct 19 18:34:30 1998 me,,, (wk@tobold) + + * pubkey.c: Hack to allow us to give some info about RSA keys back. + +Thu Oct 15 11:47:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dynload.c: Support for DLD + +Wed Oct 14 12:13:07 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c: Now uses names from configure for /dev/random. + +1998-10-10 SL Baur <steve@altair.xemacs.org> + + * Makefile.am: fix sed -O substitutions to catch -O6, etc. + +Tue Oct 6 10:06:32 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c (HAVE_GETTIMEOFDAY): Fixed (was ..GETTIMEOFTIME :-) + * rand-dummy.c (HAVE_GETTIMEOFDAY): Ditto. + +Mon Sep 28 13:23:09 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_digest): New. + (md_reset): New. + +Wed Sep 23 12:27:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c (TIGER_CONTEXT): moved "buf", so that it is 64 bit aligned. + +Mon Sep 21 06:22:53 1998 Werner Koch (wk@(none)) + + * des.c: Some patches from Michael. + +Thu Sep 17 19:00:06 1998 Werner Koch (wk@(none)) + + * des.c : New file from Michael Roth <mroth@nessie.de> + +Mon Sep 14 11:10:55 1998 Werner Koch (wk@(none)) + + * blowfish.c (bf_setkey): Niklas Hernaeus patch to detect weak keys. + +Mon Sep 14 09:19:25 1998 Werner Koch (wk@(none)) + + * dynload.c (RTLD_NOW): Now defined to 1 if it is undefined. + +Mon Sep 7 17:04:33 1998 Werner Koch (wk@(none)) + + * Makefile.am: Fixes to allow a different build directory + +Thu Aug 6 17:25:38 1998 Werner Koch,mobil,,, (wk@tobold) + + * random.c (get_random_byte): Removed and changed all callers + to use get_random_bits() + +Mon Jul 27 10:30:22 1998 Werner Koch (wk@(none)) + + * cipher.c : Support for other blocksizes + (cipher_get_blocksize): New. + * twofish.c: New. + * Makefile.am: Add twofish module. + +Mon Jul 13 21:30:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (read_pool): Simple alloc if secure_alloc is not set. + (get_random_bits): Ditto. + +Thu Jul 9 13:01:14 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dynload.c (load_extension): Function now nbails out if + the program is run setuid. + +Wed Jul 8 18:58:23 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (rmd160_hash_buffer): New. + +Thu Jul 2 10:50:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c (cipher_open): algos >=100 use standard CFB + +Thu Jun 25 11:18:25 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am: Support for extensions + +Thu Jun 18 12:09:38 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (mix_pool): simpler handling for level 0 + +Mon Jun 15 14:40:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c: Removed from dist, will reappear as dynload module + +Sat Jun 13 14:16:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * pubkey.c: Major changes to allow extensions. Changed the inteface + of all public key ciphers and added the ability to load extensions + on demand. + + * misc.c: Removed. + +Wed Jun 10 07:52:08 1998 Werner Koch,mobil,,, (wk@tobold) + + * dynload.c: New. + * cipher.c: Major changes to allow extensions. + +Mon Jun 8 22:43:00 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: Major internal chnages to support extensions. + * blowfish.c (blowfish_get_info): New and made all internal + functions static, changed heder. + * cast5.c (cast5_get_info): Likewise. + +Mon Jun 8 12:27:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c (transform): Fix for big endian + + * cipher.c (do_cfb_decrypt): Big endian fix. + +Fri May 22 07:30:39 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_get_oid): Add a new one for TIGER. + +Thu May 21 13:24:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: Add support for a dummy cipher + +Thu May 14 15:40:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (transform): fixed sigbus - I should better + add Christian von Roques's new implemenation of rmd160_write. + +Fri May 8 18:07:44 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-internal.h, rand-unix.c, rand-w32.c, rand_dummy.c: New + * random.c: Moved system specific functions to rand-****.c + +Fri May 8 14:01:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (fast_random_poll): add call to gethrtime. + +Tue May 5 21:28:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * elgamal.c (elg_generate): choosing x was not correct, could + yield 6 bytes which are not from the random pool, tsss, tsss.. + +Tue May 5 14:09:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * primegen.c (generate_elg_prime): Add arg mode, changed all + callers and implemented mode 1. + +Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c (cipher_get_keylen): New. + +Sun Apr 26 14:44:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c, tiger.h: New. + +Wed Apr 8 14:57:11 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (check_pubkey_algo2): New. + +Tue Apr 7 18:46:49 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: New + * misc.c (check_cipher_algo): Moved to cipher.c + * cast5.c: Moved many functions to cipher.c + * blowfish.c: Likewise. + +Sat Apr 4 19:52:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cast5.c: Implemented and tested. + +Wed Apr 1 16:38:27 1998 Werner Koch (wk@isil.d.shuttle.de) + + * elgamal.c (elg_generate): Faster generation of x in some cases. + +Thu Mar 19 13:54:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * blowfish.c (blowfish_decode_cfb): changed XOR operation + (blowfish_encode_cfb): Ditto. + +Thu Mar 12 14:04:05 1998 Werner Koch (wk@isil.d.shuttle.de) + + * sha1.c (transform): Rewrote + + * blowfish.c (encrypt): Unrolled for rounds == 16 + (decrypt): Ditto. + +Tue Mar 10 16:32:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (transform): Unrolled the loop. + +Tue Mar 10 13:05:14 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (read_pool): Add pool_balance stuff. + (get_random_bits): New. + + * elgamal.c (elg_generate): Now uses get_random_bits to generate x. + + +Tue Mar 10 11:33:51 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_digest_length): New. + +Tue Mar 10 11:27:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dsa.c (dsa_verify): Works. + +Mon Mar 9 12:59:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dsa.c, dsa.h: Removed some unused code. + +Wed Mar 4 10:39:22 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_open): Add call to fast_random_poll. + blowfish.c (blowfish_setkey): Ditto. + +Tue Mar 3 13:32:54 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (rmd160_mixblock): New. + * random.c: Restructured to start with a new RNG implementation. + * random.h: New. + +Mon Mar 2 19:21:46 1998 Werner Koch (wk@isil.d.shuttle.de) + + * gost.c, gost.h: Removed because they did only contain trash. + +Sun Mar 1 16:42:29 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (fill_buffer): removed error message if n == -1. + +Fri Feb 27 16:39:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_enable): No init if called twice. + +Thu Feb 26 07:57:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * primegen.c (generate_elg_prime): Changed the progress printing. + (gen_prime): Ditto. + +Tue Feb 24 12:28:42 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md5.c, md.5 : Replaced by a modified version of md5.c from + GNU textutils 1.22. + +Wed Feb 18 14:08:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c, md.h : New debugging support + +Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (cipher_algo_to_string): New + (pubkey_algo_to_string): New. + (digest_algo_to_string): New. + + + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/grub-core/lib/libgcrypt/cipher/Makefile.am b/grub-core/lib/libgcrypt/cipher/Makefile.am new file mode 100644 index 0000000..76cdc96 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/Makefile.am @@ -0,0 +1,83 @@ +# Makefile for cipher modules +# Copyright (C) 1998, 1999, 2000, 2001, 2002, +# 2003, 2009 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +# Process this file with automake to produce Makefile.in + +EXTRA_DIST = Manifest + +# Need to include ../src in addition to top_srcdir because gcrypt.h is +# a built header. +AM_CPPFLAGS = -I../src -I$(top_srcdir)/src +AM_CFLAGS = $(GPG_ERROR_CFLAGS) + + +noinst_LTLIBRARIES = libcipher.la + +GCRYPT_MODULES = @GCRYPT_CIPHERS@ @GCRYPT_PUBKEY_CIPHERS@ @GCRYPT_DIGESTS@ + +libcipher_la_DEPENDENCIES = $(GCRYPT_MODULES) +libcipher_la_LIBADD = $(GCRYPT_MODULES) + +libcipher_la_SOURCES = \ +cipher.c pubkey.c ac.c md.c kdf.c \ +hmac-tests.c \ +bithelp.h \ +primegen.c \ +hash-common.c hash-common.h \ +rmd.h + +EXTRA_libcipher_la_SOURCES = \ +arcfour.c \ +blowfish.c \ +cast5.c \ +crc.c \ +des.c \ +dsa.c \ +elgamal.c \ +ecc.c \ +idea.c \ +md4.c \ +md5.c \ +rijndael.c rijndael-tables.h \ +rmd160.c \ +rsa.c \ +seed.c \ +serpent.c \ +sha1.c \ +sha256.c \ +sha512.c \ +tiger.c \ +whirlpool.c \ +twofish.c \ +rfc2268.c \ +camellia.c camellia.h camellia-glue.c + +if ENABLE_O_FLAG_MUNGING +o_flag_munging = sed -e 's/-O\([2-9s][2-9s]*\)/-O1/' -e 's/-Ofast/-O1/g' +else +o_flag_munging = cat +endif + + +# We need to lower the optimization for this module. +tiger.o: $(srcdir)/tiger.c + `echo $(COMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) ` + +tiger.lo: $(srcdir)/tiger.c + `echo $(LTCOMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) ` diff --git a/grub-core/lib/libgcrypt/cipher/Manifest b/grub-core/lib/libgcrypt/cipher/Manifest new file mode 100644 index 0000000..0cd64f7 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/Manifest @@ -0,0 +1,73 @@ +# Manifest - checksums of the cipher directory +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +# Checksums for all source files in this directory. Format is +# filename, blanks, base-64 part of an OpenPGP detached signature +# without the header lines. Blank lines and lines beginning with a +# hash mark are ignored. A tool to process this file is available by +# cvs -d :pserver:anoncvs@cvs.gnupg.org:/cvs/wk co misc-scripts/manifest-tool +# +# The special entry "$names$" holds a signature over all sorted +# filenames excluding itself. + + +# Algorithm API +cipher.c iQCVAwUAQDzrVjEAnp832S/7AQIPDgP+OVJ/YNWY5m7c09EBbPAzL/WsGoj6wrBNMmkRlMOqTHeh+OOtjuFHt1f9uhfM2Nzl7sJ5+h4ryZKLEZmQPRMTZTnAqkvGdsrJWJnigUA9QwYdV0ONqC9C63gpuG465gO9TZVOqlQu/FTxSRuTQYUulkaBNG71n8nZEOusBVwV2YA==58xH +pubkey.c iQCVAwUAP9XQ3jEAnp832S/7AQJ5UgQAyHfEBvPVJ8wTRg8c7ixS2GiVmIgwIo5tvQaiQJTPWASevvYrB+2Z2qa9cATyu50ACjLzbaquGBgPzjJV3dU/qttT1gCqRuN/LCNvXFe5qnIZezejc3RAadFNTw/pOTHq0wxD1Keg66ruei9R36Nba59pEQIWIBXTfubRft2hMYk==E09t +ac.c iQCVAwUAQDzsOzEAnp832S/7AQJCBQP/WI6EV/dsR4rmha6RVhvkjZo17kQ8z6pIl5J3cXOvqEkIFeD2HYu3HHrWST5l7yXlffhpDkVHkfMih4ruK76q6Fm0dxZ98pO4C/dVtgimlvvcy/wOQjpzsE0fYAe1BYdg81LJ09X33vW5x6C29lunfKROO2tPlV5i8ffeoFvmMF8==j26g +md.c iQCVAwUAP+NFGjEAnp832S/7AQJs8wP/Qdk0EAKsyr3O1/pmOSN8AG4rPKbd6KDTzvoBPAN4upFwKYY4hWwvy12Q3YU9DmECrzZkRCXHR7mljVQKs6B7CRZJKjFKmOELpcJDtKvu40vTs1bOH4k9iJYZpGgRA83nkQ+ELAcphAbCA+KIpVr2K4mCJAB0FhpC2uOQ50JHAko==BeF6 +primegen.c iQCVAwUAQDzsoDEAnp832S/7AQKYRwP/TqAQBm1rHTnF0HYE05PqXfWlOqa6EosqVpaOcs/OIW6PaqX0xH1UlrukK7jNOjK3xC4o1qNQ1UKzz2dvQaq1bMvNNizeavxAh10SJZc0hIc/ofc83IbjLh8SZVWQ67JxjsUd3DOXmSmhPZ+Pqd7cUIiw8fDoF+I9EZqy3COu1wY==1ebT + +# Algorithm implementations +arcfour.c iQCVAwUAP9XR/TEAnp832S/7AQJcRwP6AlvYEx++fpT4mIYo0xRDqKEQeqMQvbaRhIg2eV74JxItpHa3q5YsYIl+n1yUz5g35JRWWXSWmAZBwO5wLKsHii4kRUhgrKWnSoQZoPpl49L5+N3R58ON3S0ru5lsBiEJEze3xplf2vqwrH9v1QHVD+gU7UTlfNqrIJoOUXN+1O4==Tq+x +blowfish.c iQCVAwUAP9XTETEAnp832S/7AQJaEgQAgiqqfuO+zQtscgTB0rvOzVymIKjRKjYhFuLjVuc79G4z1RCAffvIn/YM2d7kt+Z/QF7zjcTAOgETCQL1XokpX2zz9HPAMi2tlDY5zsDufTNqj0n4WBL9nM7w6XAvsiwP1B3bqCTv9SjJV4KbxJ58vw1yQE+sqW74R/QIHFvC7mU==wZnX +cast5.c iQCVAwUAP9XT6DEAnp832S/7AQJ3xgP/ehLjEN3GELGudbqeo91Xd+PqitHrkuBbtRIYX7Udd/fyXLN+h8rMJVyIQX2m+mpxbBxudVU3x8/DNT8B0ZHAwK6qqJmEBLLhEYPgIuF76i9LMrP1KqUPhAwRZ2OppjIIugBQ+rP74aD4eLyd/aKQHNuXML8QGWR6KwQShohXM5I==/BRh +crc.c iQCVAwUAP7ouejEAnp832S/7AQIgwQQApg5Nm63tH5DQkbN+zPzMO9Ygoj3ukxfFTyTBPYSXYKMiTjEbESegaU40uN8jnz2vprcIQWcgZfzO4+opEJMcI35aPwzEk0vKOp0S/PrBLUY2rJfnDVkX5XgJFZa2Q7LLe826UEBzTVYW924utiCCe8oOaOEWVNpg1mqdknu3M9o==kz5D +des.c iQCVAwUAQCN2oDEAnp832S/7AQL/jwP6Auoq6nZCDBjpgc9tDzuIRwa9DqyuM3gX94uvgEpUwdHszb2bG43dz03kVmcYxtj1MzXbyCeCZOwox0b2SKmLgxIbrNP6yGbzVdTj6592gDYuf/ZXmc1ZNJ1DDldcPQ0n9fXUipUPwyPaNWo3mSZaNcMKSWWzdK0J6ciG6nk7SWI==9k/t +dsa.c iQCVAwUAP9XZHDEAnp832S/7AQLBRgP/XrBzTEYx5ccMj1MMb6sg37liEHdIyyy49zjvt6jUqxj4RuwVEN8S6v3u4q/QyJkHAi1E0EkREgENlyHW6PKWhYbcrd0vPIAN15yjnl2yqtrCrJImexUCoqJJewK0E4JOicGbabTil8MZjk+mbhEPnjJBqOkyP1w0i31pEDgE/8M==pC8s +elgamal.c iQCVAwUAP9XbYzEAnp832S/7AQLXagQA3HrvspZfbTGgmUH0IqLQTJ0exUPxJv5DET2TvoIy62trDmMN6lTAj5P+a7jQ8udcu0w+mR2vXUHcxUpNA2PxLaMwGzNSY4zRDNe9r3SFTDrFm6m4y9Ko2e8XtEA+WF6P/XLpck4Jn7vMEDmVGPwkNd22kXFFE8dBGwG6i5Hk1Mk==oBUs +md4.c iQCVAwUAP9h50DEAnp832S/7AQJhHgQAzNA/B6MWFDlCtPkIVaW8RpP1Eg0ZNMsy0s7SJkopOCBlu6CwXUOKe+8ppcSxhjYKh4i4uQr/QtfipYlBjzKJGnrafoF/NugXNCOHSTGT11TvK7mCiBuUMVgvZGAlOJImk6eTTfUjRrMfaXM/SWl8bdJ4ZpzdjEyVh89r7I5JrGk==x2UD +md5.c iQCVAwUAP9h7LzEAnp832S/7AQJUGQP/c0cbf6WZXCzmjufHxiE9FAQBzTsA0WtaNqdFcHl7fhmikGtknlaED8n5a7eYd/C481UQW6Wgq/oZdsvgoPWPhG3fOCy2CFP9cZVXITuMSf0ucyZTFUJNO15fnZ+nDfsUv+JPdv1aSeRinAUtfAcSKfkSyR9BCPZvkx+tgU6cphU==Zv+h +rijndael.c iQCVAwUAP9h9cTEAnp832S/7AQKF1AP+P2L/tPqDJRDg+/fwbOk8Ts0MNxnvvYEm3gE73TKuLt1S+B2+jkrZcKNvM5VGPnVMJbnS0lmIK04nmedHCOftGTOwhGulZAHHIaKGystT3Jql4iPws/JMgAjE7Fyxh5WZMtB9yEljKBpJ5XNqhrMvvxcHpnyP3+YzIXNwzk34V+c==dJ5k +rmd160.c iQCVAwUAP9h+bTEAnp832S/7AQK1OgP+PNKF6Nzi6X93easVlksdLqKEsArCAw2QjGWDGyxTnbiJM55qAl9JxR1mn3V+oOL7izLLwTt6EYK9evhzfcxY5N5Mni85RAcsLPsuAfQDEzjI6GUWHtQUKPbM+BaorzfhQjYFSZyvum/dZYJ/WfiwwwhqqIKyVU2ZFSqA38YGC/c==9jdA +rsa.c iQCVAwUAP9iHIzEAnp832S/7AQKAYwQAuWtnMte54QHN+Hij9t4sGuypXogajOb1vQQwGgS0fKsaBZsuSP2amze4o5diIvsQTsFQ4CzjvqoCVuBDoHM3xkSD8wGDizgvtCamAxkdbF7wmzldKFn8SpJqlVwWQMP6kk1IjXHEuYb4IDWGTbVMhfEu+eOlU8+PSK4IhZqNvt4==/3hp +serpent.c iQCVAwUAP9h/VzEAnp832S/7AQLyCwP/d1zbmb7l/PriZNa9/Z7mo01XFe5MnAqCfIwhl9GjeaMszcoS37jECNq5nLvrTTFIIJpm3rvBePwiCG4Wwx1I18HCxaP198pcSaR+BLOJ3Aj52EZPrxtqlDKuFr38ZOP5giyUqUYVYGVdrz4kRMNWAZQK53GeJnGhXCnhxojLEgA==ck46 +sha1.c iQCVAwUAP9iATTEAnp832S/7AQKcSwQAwAs/HnNqho3lU1ZUgCPNt5P2/Brm6W21+wWWGKJkSrra/c4NYVKJGDDwlsFE0b9ln1uZt7bHReFkKXK3JnrKTmNVcx/Cy64iCMRNMhaM72Mqy7wWx5yHBAmMBxzFGnNQKbmeY52zeGih5HsNLSibc2pPuOViWo2JPJ5Ci/wIwl8==/wtO +sha256.c iQCVAwUAP9iAtzEAnp832S/7AQJD2QP/UqvL0hhjG1wEFbGrdkV9tba1sMDXdnnK6X7HdLuRpVAgNiQiFf8JDmntd/dZ2Q71p4Uae2ctqve4WoEijPUZPjACnpuZfx0SEQL0lQBkwxzJp7lz9ujVtwQ2cM/aYexJkXcWgGcloJNLM3JbWPGIJnuYbr/IwJ6RQF9vgj0357o==UWO1 +sha512.c iQCVAwUAP9iBTDEAnp832S/7AQIPBAQA28CJSUQLiW0s2x9u8/OH2eKnxPjA4sZmb50WP7920Lem66P31C3BrOqwfBot4RLhjL+zh/+Uc4s3HPwApZuj9E4BxNMlqLv+Tqk++DAbdaOeYT4jeUt+mlhQQ6mH/RDsy32rZsNsGQ2bUGxazZmfG++PL3JyhawqCy00SUDr/o0==H+0X +tiger.c iQCVAwUAP9iCfjEAnp832S/7AQKufwP/fryv3MqSOYY+90325DH7X3/CtekxeooN0scGsHX0fxBakWSMecTNrj33KPddLS46gU/S89zIc2N/Bw/7EVIAXVFA3/3Ip+OrFOuIMO4Py1sCdB8o2Y+5ygv8iXLcsXIq1O0av79i9g774V3uaXa2qN9ZnXe0AEhcy8FHJ2i/wro==5XVB +twofish.c iQCVAwUAP9iD6TEAnp832S/7AQKUnQP/Rq8FaYeHTG7HbZuqAs9pbPitzjDbkdZddmInWR7NmevBkKvhsJALjVooc0KGQfo2lAAmy3Xi/4QQN8VPn51DVjDIgf7x+DQh/9TFJHMccxI9asUgi4+TNnmMqLU1k3N8S2PjyZ1sjeC8B79fKPpwCzj72WkqPkzZw3l2jArr+dU==NdJT +rfc2268.c iQCVAwUAQCN+3jEAnp832S/7AQLv1gQA1hJh29hAjKi4uLSGxXvJ6cyYmPdmevdKrbLnuHZWtHe4xvCgy/nTdEojEpxgLp/hL/ogasuWRC1W16Wiz9ryxf7YR0uhZWayO/bQNagpfU5MIkJTLuKqqgpwYumCSQfOugXVAqcgEzj+13eeyJaFVrzwrNa67sh84nmbjOjNjvE==0zBq + +# Random number related +random.c iQCVAwUAP7nsITEAnp832S/7AQK4SAQAtvfUgrtGOQ2PlxGMla0qJLPHjJacMwgq0ecusiI79elPdDsFfCCk6dK1Ug2kFbNm22nCGHNcUquqbX7noi7ZVQnmPBQXzyLNZd7GmrawRZfdlRerTUDBpSnR8V8ui/5+YYp627E7kKGC0hPSgqXFql6oBMIfno0LZwFJTjIevRY==L419 +random.h iQCVAwUAP7ovKDEAnp832S/7AQJ3bQQAjnPebnyTC7sphAv2I7uIz+yPgw1ZfbVhLv+OiWDlO9ish+fRyyMpy+HELBOgZjJdgRegqhlZC6qyns5arM/VglYi+PzvdLO3hIqHE/YFfpIFPz8wBrcmlqrYyd3CsGqcYsfjocXNttCBLeSWmoJ09ltKQH8yzJf3oAgN6X1yuc4==eNoU +rand-internal.h iQCVAwUAP7ouvDEAnp832S/7AQLYnAQAhdI7ERoJVCkV8GiV7MjaUxv1WIL7iZ+jIOvVhv4fNyhCGCGoEtTjkyput/lj7Nsh3FXEqRhypGGrCLf47x/gua5n+BwffogxVyUDqiOyyGhNTPpe3fQcNBvbPCtco8yMK4GJO5G3BqzlPyN+BMeogLymyV6Sm1mvh5LZDyAFbfQ==tZSE +rndlinux.c iQCVAwUAP9iPYTEAnp832S/7AQL6/AP/ZDrbOkVuB9qJ7sKeX1MImZEsz3mi0xPovJzaBtBU7a0idcUKrWYOvQFWRlLUeq0iCT6+h2l5bniP7q7hepzlKa+VPY9VWaQthqeJm2l5LN6QQ5PyMfBq04QuBncw9BJnCGmEyTLt3RxIXBAPdxmiVxtcRIFUqCBtQvoUXGLvemw==t37k +rndegd.c iQCVAwUAP9iPRDEAnp832S/7AQImBQP/WHKg+hKXcm1pQvilzML0jZpwK5PAMM4uBnnPJNIXWOYBO6I/Xg9d/tPLg8NlmmtyQCo2Eu0ybDSt+8mu+dWveAys+0LTi0MIqeP9BMzCKz8dnWH6+S8huLXwTF3m0IrqM0JLb6b71GK9SOq6sWQ22yW5vf61hXP8kH9dhIaoMZs==FaHV +rndunix.c iQCVAwUAP9iQlzEAnp832S/7AQL/KgQA29GnvcD4Xb5qjDMBgW9THEE4+4lfex/6k+Fh0IT61OLJsWVLJ7bJpRntburw4uQm4Tf7CO8vaiDFDYhKKrzXeOF1fmdpcL8hA+fNp9I/MUOc4e9kN9+YJ9wikVa0SZj1OBfhzgcFLd1xOtulkr3ii52HLF9vhrxzkgVwvD10Bi8==2cML +rndw32.c iQCVAwUAP9iRKDEAnp832S/7AQIuaAQA3AJr3WqnxNDsWCIdvehf8Suotthj+laX8nJsvDfFhXPKcXDpsg0wTTXSnnKgyED53+uYiMDnVRsxeWAyhKwvx1MjjlaSMMjzbH6isWTH8FaWpLgrxEkXoPeNqYf5FXpdUkcUxGX2RkQeuX/cIfiHLNE9CV0usaF2jysjBX2iERY==EEnO + +# Helper +bithelp.h iQCVAwUAP7ouPTEAnp832S/7AQKXggQAqjcgvihIF3WclOgw1JV2rbARw4ISIDRMFqdaNCqBRx6BwEz3UGsEIlz6+iR1sS/reqN61WvtjLb+D0+tujAkGrgQJhFLG85WtG2tB5UVoI3am1fpkwiRm+bR4rv0rGk0BYk81bC7+l4KrK9o5lVp4lCsrorlUKsd48lNmBHyAXM==mDDN +rmd.h iQCVAwUAP7oumjEAnp832S/7AQJiJQP/V4bJwjZaYndJzV+KRnIDbl1koHuw+ZK5heMYVu8Qk4ylqv//BGyeRa3jZCcfPHI35q6HilCs2VBm8hiBMjHSqY/VPn2ZQ0yg/lt6qEvl7YjsLmyMICvjG+ncszHoq9pRvnF3vTnM18sPIioXLk8fskuM0XOCNBs0ARBAQjY9UGI==olUN + +# Configuration +Makefile.am iQCVAwUAQCN33TEAnp832S/7AQKFJAQAz7BDkC814q+QiuE/jnutJHR5qlgbrm3ikGbQwdRzYUscst4bCCWy3uKL/sIPGLg+JQXtF5FnsQy3s4D9BOYhp72cA9ktYK65hhi4pNm/JQ0lXkZMNfk8Go5lNzKezlWwHvkMwRXR0Fep0wPdyeaKW5BfaW2ABvgep6Bp+hHEbyg==zSyi +$names$ iQCVAwUAQCN3EDEAnp832S/7AQJXLAP8DvHTpm5DkTF35EmzeKpi9ie59AZcZanD19ir/e/7+PaQxr2riuLHDGwFKTju+dcvvBsqrygXOC378GXVWzIF2OZwS4EdDcJ+pgojo9UpsqpKsJHouY4Ugx5cQialxba462kUn8hcihSBnMyc4LzbJ5WQ4puQuqy544d2x94+2ms==G4Ls diff --git a/grub-core/lib/libgcrypt/cipher/ac.c b/grub-core/lib/libgcrypt/cipher/ac.c new file mode 100644 index 0000000..63f6fcd --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/ac.c @@ -0,0 +1,3301 @@ +/* ac.c - Alternative interface for asymmetric cryptography. + Copyright (C) 2003, 2004, 2005, 2006 + 2007, 2008 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser general Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stddef.h> + +#include "g10lib.h" +#include "cipher.h" +#include "mpi.h" + + + +/* At the moment the ac interface is a wrapper around the pk + interface, but this might change somewhen in the future, depending + on how many people prefer the ac interface. */ + +/* Mapping of flag numbers to the according strings as it is expected + for S-expressions. */ +static struct number_string +{ + int number; + const char *string; +} ac_flags[] = + { + { GCRY_AC_FLAG_NO_BLINDING, "no-blinding" }, + }; + +/* The positions in this list correspond to the values contained in + the gcry_ac_key_type_t enumeration list. */ +static const char *ac_key_identifiers[] = + { + "private-key", + "public-key" + }; + +/* These specifications are needed for key-pair generation; the caller + is allowed to pass additional, algorithm-specific `specs' to + gcry_ac_key_pair_generate. This list is used for decoding the + provided values according to the selected algorithm. */ +struct gcry_ac_key_generate_spec +{ + int algorithm; /* Algorithm for which this flag is + relevant. */ + const char *name; /* Name of this flag. */ + size_t offset; /* Offset in the cipher-specific spec + structure at which the MPI value + associated with this flag is to be + found. */ +} ac_key_generate_specs[] = + { + { GCRY_AC_RSA, "rsa-use-e", offsetof (gcry_ac_key_spec_rsa_t, e) }, + { 0 } + }; + +/* Handle structure. */ +struct gcry_ac_handle +{ + int algorithm; /* Algorithm ID associated with this + handle. */ + const char *algorithm_name; /* Name of the algorithm. */ + unsigned int flags; /* Flags, not used yet. */ + gcry_module_t module; /* Reference to the algorithm + module. */ +}; + +/* A named MPI value. */ +typedef struct gcry_ac_mpi +{ + char *name; /* Self-maintained copy of name. */ + gcry_mpi_t mpi; /* MPI value. */ + unsigned int flags; /* Flags. */ +} gcry_ac_mpi_t; + +/* A data set, that is simply a list of named MPI values. */ +struct gcry_ac_data +{ + gcry_ac_mpi_t *data; /* List of named values. */ + unsigned int data_n; /* Number of values in DATA. */ +}; + +/* A single key. */ +struct gcry_ac_key +{ + gcry_ac_data_t data; /* Data in native ac structure. */ + gcry_ac_key_type_t type; /* Type of the key. */ +}; + +/* A key pair. */ +struct gcry_ac_key_pair +{ + gcry_ac_key_t public; + gcry_ac_key_t secret; +}; + + + +/* + * Functions for working with data sets. + */ + +/* Creates a new, empty data set and store it in DATA. */ +gcry_error_t +_gcry_ac_data_new (gcry_ac_data_t *data) +{ + gcry_ac_data_t data_new; + gcry_error_t err; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + data_new = gcry_malloc (sizeof (*data_new)); + if (! data_new) + { + err = gcry_error_from_errno (errno); + goto out; + } + + data_new->data = NULL; + data_new->data_n = 0; + *data = data_new; + err = 0; + + out: + + return err; +} + +/* Destroys all the entries in DATA, but not DATA itself. */ +static void +ac_data_values_destroy (gcry_ac_data_t data) +{ + unsigned int i; + + for (i = 0; i < data->data_n; i++) + if (data->data[i].flags & GCRY_AC_FLAG_DEALLOC) + { + gcry_mpi_release (data->data[i].mpi); + gcry_free (data->data[i].name); + } +} + +/* Destroys the data set DATA. */ +void +_gcry_ac_data_destroy (gcry_ac_data_t data) +{ + if (data) + { + ac_data_values_destroy (data); + gcry_free (data->data); + gcry_free (data); + } +} + +/* This function creates a copy of the array of named MPIs DATA_MPIS, + which is of length DATA_MPIS_N; the copy is stored in + DATA_MPIS_CP. */ +static gcry_error_t +ac_data_mpi_copy (gcry_ac_mpi_t *data_mpis, unsigned int data_mpis_n, + gcry_ac_mpi_t **data_mpis_cp) +{ + gcry_ac_mpi_t *data_mpis_new; + gcry_error_t err; + unsigned int i; + gcry_mpi_t mpi; + char *label; + + data_mpis_new = gcry_calloc (data_mpis_n, sizeof (*data_mpis_new)); + if (! data_mpis_new) + { + err = gcry_error_from_errno (errno); + goto out; + } + memset (data_mpis_new, 0, sizeof (*data_mpis_new) * data_mpis_n); + + err = 0; + for (i = 0; i < data_mpis_n; i++) + { + /* Copy values. */ + + label = gcry_strdup (data_mpis[i].name); + mpi = gcry_mpi_copy (data_mpis[i].mpi); + if (! (label && mpi)) + { + err = gcry_error_from_errno (errno); + gcry_mpi_release (mpi); + gcry_free (label); + break; + } + + data_mpis_new[i].flags = GCRY_AC_FLAG_DEALLOC; + data_mpis_new[i].name = label; + data_mpis_new[i].mpi = mpi; + } + if (err) + goto out; + + *data_mpis_cp = data_mpis_new; + err = 0; + + out: + + if (err) + if (data_mpis_new) + { + for (i = 0; i < data_mpis_n; i++) + { + gcry_mpi_release (data_mpis_new[i].mpi); + gcry_free (data_mpis_new[i].name); + } + gcry_free (data_mpis_new); + } + + return err; +} + +/* Create a copy of the data set DATA and store it in DATA_CP. */ +gcry_error_t +_gcry_ac_data_copy (gcry_ac_data_t *data_cp, gcry_ac_data_t data) +{ + gcry_ac_mpi_t *data_mpis = NULL; + gcry_ac_data_t data_new; + gcry_error_t err; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + /* Allocate data set. */ + data_new = gcry_malloc (sizeof (*data_new)); + if (! data_new) + { + err = gcry_error_from_errno (errno); + goto out; + } + + err = ac_data_mpi_copy (data->data, data->data_n, &data_mpis); + if (err) + goto out; + + data_new->data_n = data->data_n; + data_new->data = data_mpis; + *data_cp = data_new; + + out: + + if (err) + gcry_free (data_new); + + return err; +} + +/* Returns the number of named MPI values inside of the data set + DATA. */ +unsigned int +_gcry_ac_data_length (gcry_ac_data_t data) +{ + return data->data_n; +} + + +/* Add the value MPI to DATA with the label NAME. If FLAGS contains + GCRY_AC_FLAG_COPY, the data set will contain copies of NAME + and MPI. If FLAGS contains GCRY_AC_FLAG_DEALLOC or + GCRY_AC_FLAG_COPY, the values contained in the data set will + be deallocated when they are to be removed from the data set. */ +gcry_error_t +_gcry_ac_data_set (gcry_ac_data_t data, unsigned int flags, + const char *name, gcry_mpi_t mpi) +{ + gcry_error_t err; + gcry_mpi_t mpi_cp; + char *name_cp; + unsigned int i; + + name_cp = NULL; + mpi_cp = NULL; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + if (flags & ~(GCRY_AC_FLAG_DEALLOC | GCRY_AC_FLAG_COPY)) + { + err = gcry_error (GPG_ERR_INV_ARG); + goto out; + } + + if (flags & GCRY_AC_FLAG_COPY) + { + /* Create copies. */ + + flags |= GCRY_AC_FLAG_DEALLOC; + name_cp = gcry_strdup (name); + mpi_cp = gcry_mpi_copy (mpi); + if (! (name_cp && mpi_cp)) + { + err = gcry_error_from_errno (errno); + goto out; + } + } + + /* Search for existing entry. */ + for (i = 0; i < data->data_n; i++) + if (! strcmp (name, data->data[i].name)) + break; + if (i < data->data_n) + { + /* An entry for NAME does already exist. */ + if (data->data[i].flags & GCRY_AC_FLAG_DEALLOC) + { + gcry_mpi_release (data->data[i].mpi); + gcry_free (data->data[i].name); + } + } + else + { + /* Create a new entry. */ + + gcry_ac_mpi_t *ac_mpis; + + ac_mpis = gcry_realloc (data->data, + sizeof (*data->data) * (data->data_n + 1)); + if (! ac_mpis) + { + err = gcry_error_from_errno (errno); + goto out; + } + + if (data->data != ac_mpis) + data->data = ac_mpis; + data->data_n++; + } + + data->data[i].name = name_cp ? name_cp : ((char *) name); + data->data[i].mpi = mpi_cp ? mpi_cp : mpi; + data->data[i].flags = flags; + err = 0; + + out: + + if (err) + { + gcry_mpi_release (mpi_cp); + gcry_free (name_cp); + } + + return err; +} + +/* Stores the value labelled with NAME found in the data set DATA in + MPI. The returned MPI value will be released in case + gcry_ac_data_set is used to associate the label NAME with a + different MPI value. */ +gcry_error_t +_gcry_ac_data_get_name (gcry_ac_data_t data, unsigned int flags, + const char *name, gcry_mpi_t *mpi) +{ + gcry_mpi_t mpi_return; + gcry_error_t err; + unsigned int i; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + if (flags & ~(GCRY_AC_FLAG_COPY)) + { + err = gcry_error (GPG_ERR_INV_ARG); + goto out; + } + + for (i = 0; i < data->data_n; i++) + if (! strcmp (name, data->data[i].name)) + break; + if (i == data->data_n) + { + err = gcry_error (GPG_ERR_NOT_FOUND); + goto out; + } + + if (flags & GCRY_AC_FLAG_COPY) + { + mpi_return = gcry_mpi_copy (data->data[i].mpi); + if (! mpi_return) + { + err = gcry_error_from_errno (errno); /* FIXME? */ + goto out; + } + } + else + mpi_return = data->data[i].mpi; + + *mpi = mpi_return; + err = 0; + + out: + + return err; +} + +/* Stores in NAME and MPI the named MPI value contained in the data + set DATA with the index IDX. NAME or MPI may be NULL. The + returned MPI value will be released in case gcry_ac_data_set is + used to associate the label NAME with a different MPI value. */ +gcry_error_t +_gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int flags, + unsigned int idx, + const char **name, gcry_mpi_t *mpi) +{ + gcry_error_t err; + gcry_mpi_t mpi_cp; + char *name_cp; + + name_cp = NULL; + mpi_cp = NULL; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + if (flags & ~(GCRY_AC_FLAG_COPY)) + { + err = gcry_error (GPG_ERR_INV_ARG); + goto out; + } + + if (idx >= data->data_n) + { + err = gcry_error (GPG_ERR_INV_ARG); + goto out; + } + + if (flags & GCRY_AC_FLAG_COPY) + { + /* Return copies to the user. */ + if (name) + { + name_cp = gcry_strdup (data->data[idx].name); + if (! name_cp) + { + err = gcry_error_from_errno (errno); + goto out; + } + } + if (mpi) + { + mpi_cp = gcry_mpi_copy (data->data[idx].mpi); + if (! mpi_cp) + { + err = gcry_error_from_errno (errno); + goto out; + } + } + } + + if (name) + *name = name_cp ? name_cp : data->data[idx].name; + if (mpi) + *mpi = mpi_cp ? mpi_cp : data->data[idx].mpi; + err = 0; + + out: + + if (err) + { + gcry_mpi_release (mpi_cp); + gcry_free (name_cp); + } + + return err; +} + +/* Convert the data set DATA into a new S-Expression, which is to be + stored in SEXP, according to the identifiers contained in + IDENTIFIERS. */ +gcry_error_t +_gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp, + const char **identifiers) +{ + gcry_sexp_t sexp_new; + gcry_error_t err; + char *sexp_buffer; + size_t sexp_buffer_n; + size_t identifiers_n; + const char *label; + gcry_mpi_t mpi; + void **arg_list; + size_t data_n; + unsigned int i; + + sexp_buffer_n = 1; + sexp_buffer = NULL; + arg_list = NULL; + err = 0; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + /* Calculate size of S-expression representation. */ + + i = 0; + if (identifiers) + while (identifiers[i]) + { + /* For each identifier, we add "(<IDENTIFIER>)". */ + sexp_buffer_n += 1 + strlen (identifiers[i]) + 1; + i++; + } + identifiers_n = i; + + if (! identifiers_n) + /* If there are NO identifiers, we still add surrounding braces so + that we have a list of named MPI value lists. Otherwise it + wouldn't be too much fun to process these lists. */ + sexp_buffer_n += 2; + + data_n = _gcry_ac_data_length (data); + for (i = 0; i < data_n; i++) + { + err = gcry_ac_data_get_index (data, 0, i, &label, NULL); + if (err) + break; + /* For each MPI we add "(<LABEL> %m)". */ + sexp_buffer_n += 1 + strlen (label) + 4; + } + if (err) + goto out; + + /* Allocate buffer. */ + + sexp_buffer = gcry_malloc (sexp_buffer_n); + if (! sexp_buffer) + { + err = gcry_error_from_errno (errno); + goto out; + } + + /* Fill buffer. */ + + *sexp_buffer = 0; + sexp_buffer_n = 0; + + /* Add identifiers: (<IDENTIFIER0>(<IDENTIFIER1>...)). */ + if (identifiers_n) + { + /* Add nested identifier lists as usual. */ + for (i = 0; i < identifiers_n; i++) + sexp_buffer_n += sprintf (sexp_buffer + sexp_buffer_n, "(%s", + identifiers[i]); + } + else + { + /* Add special list. */ + sexp_buffer_n += sprintf (sexp_buffer + sexp_buffer_n, "("); + } + + /* Add MPI list. */ + arg_list = gcry_calloc (data_n + 1, sizeof (*arg_list)); + if (! arg_list) + { + err = gcry_error_from_errno (errno); + goto out; + } + for (i = 0; i < data_n; i++) + { + err = gcry_ac_data_get_index (data, 0, i, &label, &mpi); + if (err) + break; + sexp_buffer_n += sprintf (sexp_buffer + sexp_buffer_n, + "(%s %%m)", label); + arg_list[i] = &data->data[i].mpi; + } + if (err) + goto out; + + if (identifiers_n) + { + /* Add closing braces for identifier lists as usual. */ + for (i = 0; i < identifiers_n; i++) + sexp_buffer_n += sprintf (sexp_buffer + sexp_buffer_n, ")"); + } + else + { + /* Add closing braces for special list. */ + sexp_buffer_n += sprintf (sexp_buffer + sexp_buffer_n, ")"); + } + + /* Construct. */ + err = gcry_sexp_build_array (&sexp_new, NULL, sexp_buffer, arg_list); + if (err) + goto out; + + *sexp = sexp_new; + + out: + + gcry_free (sexp_buffer); + gcry_free (arg_list); + + return err; +} + +/* Create a new data set, which is to be stored in DATA_SET, from the + S-Expression SEXP, according to the identifiers contained in + IDENTIFIERS. */ +gcry_error_t +_gcry_ac_data_from_sexp (gcry_ac_data_t *data_set, gcry_sexp_t sexp, + const char **identifiers) +{ + gcry_ac_data_t data_set_new; + gcry_error_t err; + gcry_sexp_t sexp_cur; + gcry_sexp_t sexp_tmp; + gcry_mpi_t mpi; + char *string; + const char *data; + size_t data_n; + size_t sexp_n; + unsigned int i; + int skip_name; + + data_set_new = NULL; + sexp_cur = sexp; + sexp_tmp = NULL; + string = NULL; + mpi = NULL; + err = 0; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + /* Process S-expression/identifiers. */ + + if (identifiers) + { + for (i = 0; identifiers[i]; i++) + { + /* Next identifier. Extract first data item from + SEXP_CUR. */ + data = gcry_sexp_nth_data (sexp_cur, 0, &data_n); + + if (! ((data_n == strlen (identifiers[i])) + && (! strncmp (data, identifiers[i], data_n)))) + { + /* Identifier mismatch -> error. */ + err = gcry_error (GPG_ERR_INV_SEXP); + break; + } + + /* Identifier matches. Now we have to distinguish two + cases: + + (i) we are at the last identifier: + leave loop + + (ii) we are not at the last identifier: + extract next element, which is supposed to be a + sublist. */ + + if (! identifiers[i + 1]) + /* Last identifier. */ + break; + else + { + /* Not the last identifier, extract next sublist. */ + + sexp_tmp = gcry_sexp_nth (sexp_cur, 1); + if (! sexp_tmp) + { + /* Missing sublist. */ + err = gcry_error (GPG_ERR_INV_SEXP); + break; + } + + /* Release old SEXP_CUR, in case it is not equal to the + original SEXP. */ + if (sexp_cur != sexp) + gcry_sexp_release (sexp_cur); + + /* Make SEXP_CUR point to the new current sublist. */ + sexp_cur = sexp_tmp; + sexp_tmp = NULL; + } + } + if (err) + goto out; + + if (i) + { + /* We have at least one identifier in the list, this means + the the list of named MPI values is prefixed, this means + that we need to skip the first item (the list name), when + processing the MPI values. */ + skip_name = 1; + } + else + { + /* Since there is no identifiers list, the list of named MPI + values is not prefixed with a list name, therefore the + offset to use is zero. */ + skip_name = 0; + } + } + else + /* Since there is no identifiers list, the list of named MPI + values is not prefixed with a list name, therefore the offset + to use is zero. */ + skip_name = 0; + + /* Create data set from S-expression data. */ + + err = gcry_ac_data_new (&data_set_new); + if (err) + goto out; + + /* Figure out amount of named MPIs in SEXP_CUR. */ + if (sexp_cur) + sexp_n = gcry_sexp_length (sexp_cur) - skip_name; + else + sexp_n = 0; + + /* Extracte the named MPIs sequentially. */ + for (i = 0; i < sexp_n; i++) + { + /* Store next S-Expression pair, which is supposed to consist of + a name and an MPI value, in SEXP_TMP. */ + + sexp_tmp = gcry_sexp_nth (sexp_cur, i + skip_name); + if (! sexp_tmp) + { + err = gcry_error (GPG_ERR_INV_SEXP); + break; + } + + /* Extract name from current S-Expression pair. */ + data = gcry_sexp_nth_data (sexp_tmp, 0, &data_n); + string = gcry_malloc (data_n + 1); + if (! string) + { + err = gcry_error_from_errno (errno); + break; + } + memcpy (string, data, data_n); + string[data_n] = 0; + + /* Extract MPI value. */ + mpi = gcry_sexp_nth_mpi (sexp_tmp, 1, 0); + if (! mpi) + { + err = gcry_error (GPG_ERR_INV_SEXP); /* FIXME? */ + break; + } + + /* Store named MPI in data_set_new. */ + err = gcry_ac_data_set (data_set_new, GCRY_AC_FLAG_DEALLOC, string, mpi); + if (err) + break; + +/* gcry_free (string); */ + string = NULL; +/* gcry_mpi_release (mpi); */ + mpi = NULL; + + gcry_sexp_release (sexp_tmp); + sexp_tmp = NULL; + } + if (err) + goto out; + + *data_set = data_set_new; + + out: + + if (sexp_cur != sexp) + gcry_sexp_release (sexp_cur); + gcry_sexp_release (sexp_tmp); + gcry_mpi_release (mpi); + gcry_free (string); + + if (err) + gcry_ac_data_destroy (data_set_new); + + return err; +} + + +static void +_gcry_ac_data_dump (const char *prefix, gcry_ac_data_t data) +{ + unsigned char *mpi_buffer; + size_t mpi_buffer_n; + unsigned int data_n; + gcry_error_t err; + const char *name; + gcry_mpi_t mpi; + unsigned int i; + + if (! data) + return; + + if (fips_mode ()) + return; + + mpi_buffer = NULL; + + data_n = _gcry_ac_data_length (data); + for (i = 0; i < data_n; i++) + { + err = gcry_ac_data_get_index (data, 0, i, &name, &mpi); + if (err) + { + log_error ("failed to dump data set"); + break; + } + + err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &mpi_buffer, &mpi_buffer_n, mpi); + if (err) + { + log_error ("failed to dump data set"); + break; + } + + log_printf ("%s%s%s: %s\n", + prefix ? prefix : "", + prefix ? ": " : "" + , name, mpi_buffer); + + gcry_free (mpi_buffer); + mpi_buffer = NULL; + } + + gcry_free (mpi_buffer); +} + +/* Dump the named MPI values contained in the data set DATA to + Libgcrypt's logging stream. */ +void +gcry_ac_data_dump (const char *prefix, gcry_ac_data_t data) +{ + _gcry_ac_data_dump (prefix, data); +} + +/* Destroys any values contained in the data set DATA. */ +void +_gcry_ac_data_clear (gcry_ac_data_t data) +{ + ac_data_values_destroy (data); + gcry_free (data->data); + data->data = NULL; + data->data_n = 0; +} + + + +/* + * Implementation of `ac io' objects. + */ + +/* Initialize AC_IO according to MODE, TYPE and the variable list of + arguments AP. The list of variable arguments to specify depends on + the given TYPE. */ +void +_gcry_ac_io_init_va (gcry_ac_io_t *ac_io, + gcry_ac_io_mode_t mode, gcry_ac_io_type_t type, va_list ap) +{ + memset (ac_io, 0, sizeof (*ac_io)); + + if (fips_mode ()) + return; + + gcry_assert ((mode == GCRY_AC_IO_READABLE) || (mode == GCRY_AC_IO_WRITABLE)); + gcry_assert ((type == GCRY_AC_IO_STRING) || (type == GCRY_AC_IO_STRING)); + + ac_io->mode = mode; + ac_io->type = type; + + switch (mode) + { + case GCRY_AC_IO_READABLE: + switch (type) + { + case GCRY_AC_IO_STRING: + ac_io->io.readable.string.data = va_arg (ap, unsigned char *); + ac_io->io.readable.string.data_n = va_arg (ap, size_t); + break; + + case GCRY_AC_IO_CALLBACK: + ac_io->io.readable.callback.cb = va_arg (ap, gcry_ac_data_read_cb_t); + ac_io->io.readable.callback.opaque = va_arg (ap, void *); + break; + } + break; + case GCRY_AC_IO_WRITABLE: + switch (type) + { + case GCRY_AC_IO_STRING: + ac_io->io.writable.string.data = va_arg (ap, unsigned char **); + ac_io->io.writable.string.data_n = va_arg (ap, size_t *); + break; + + case GCRY_AC_IO_CALLBACK: + ac_io->io.writable.callback.cb = va_arg (ap, gcry_ac_data_write_cb_t); + ac_io->io.writable.callback.opaque = va_arg (ap, void *); + break; + } + break; + } +} + +/* Initialize AC_IO according to MODE, TYPE and the variable list of + arguments. The list of variable arguments to specify depends on + the given TYPE. */ +void +_gcry_ac_io_init (gcry_ac_io_t *ac_io, + gcry_ac_io_mode_t mode, gcry_ac_io_type_t type, ...) +{ + va_list ap; + + va_start (ap, type); + _gcry_ac_io_init_va (ac_io, mode, type, ap); + va_end (ap); +} + + +/* Write to the IO object AC_IO BUFFER_N bytes from BUFFER. Return + zero on success or error code. */ +static gcry_error_t +_gcry_ac_io_write (gcry_ac_io_t *ac_io, unsigned char *buffer, size_t buffer_n) +{ + gcry_error_t err; + + gcry_assert (ac_io->mode == GCRY_AC_IO_WRITABLE); + err = 0; + + switch (ac_io->type) + { + case GCRY_AC_IO_STRING: + { + unsigned char *p; + + if (*ac_io->io.writable.string.data) + { + p = gcry_realloc (*ac_io->io.writable.string.data, + *ac_io->io.writable.string.data_n + buffer_n); + if (! p) + err = gcry_error_from_errno (errno); + else + { + if (*ac_io->io.writable.string.data != p) + *ac_io->io.writable.string.data = p; + memcpy (p + *ac_io->io.writable.string.data_n, buffer, buffer_n); + *ac_io->io.writable.string.data_n += buffer_n; + } + } + else + { + if (gcry_is_secure (buffer)) + p = gcry_malloc_secure (buffer_n); + else + p = gcry_malloc (buffer_n); + if (! p) + err = gcry_error_from_errno (errno); + else + { + memcpy (p, buffer, buffer_n); + *ac_io->io.writable.string.data = p; + *ac_io->io.writable.string.data_n = buffer_n; + } + } + } + break; + + case GCRY_AC_IO_CALLBACK: + err = (*ac_io->io.writable.callback.cb) (ac_io->io.writable.callback.opaque, + buffer, buffer_n); + break; + } + + return err; +} + +/* Read *BUFFER_N bytes from the IO object AC_IO into BUFFER; NREAD + bytes have already been read from the object; on success, store the + amount of bytes read in *BUFFER_N; zero bytes read means EOF. + Return zero on success or error code. */ +static gcry_error_t +_gcry_ac_io_read (gcry_ac_io_t *ac_io, + unsigned int nread, unsigned char *buffer, size_t *buffer_n) +{ + gcry_error_t err; + + gcry_assert (ac_io->mode == GCRY_AC_IO_READABLE); + err = 0; + + switch (ac_io->type) + { + case GCRY_AC_IO_STRING: + { + size_t bytes_available; + size_t bytes_to_read; + size_t bytes_wanted; + + bytes_available = ac_io->io.readable.string.data_n - nread; + bytes_wanted = *buffer_n; + + if (bytes_wanted > bytes_available) + bytes_to_read = bytes_available; + else + bytes_to_read = bytes_wanted; + + memcpy (buffer, ac_io->io.readable.string.data + nread, bytes_to_read); + *buffer_n = bytes_to_read; + err = 0; + break; + } + + case GCRY_AC_IO_CALLBACK: + err = (*ac_io->io.readable.callback.cb) + (ac_io->io.readable.callback.opaque, buffer, buffer_n); + break; + } + + return err; +} + +/* Read all data available from the IO object AC_IO into newly + allocated memory, storing an appropriate pointer in *BUFFER and the + amount of bytes read in *BUFFER_N. Return zero on success or error + code. */ +static gcry_error_t +_gcry_ac_io_read_all (gcry_ac_io_t *ac_io, unsigned char **buffer, size_t *buffer_n) +{ + unsigned char *buffer_new; + size_t buffer_new_n; + unsigned char buf[BUFSIZ]; + size_t buf_n; + unsigned char *p; + gcry_error_t err; + + buffer_new = NULL; + buffer_new_n = 0; + + while (1) + { + buf_n = sizeof (buf); + err = _gcry_ac_io_read (ac_io, buffer_new_n, buf, &buf_n); + if (err) + break; + + if (buf_n) + { + p = gcry_realloc (buffer_new, buffer_new_n + buf_n); + if (! p) + { + err = gcry_error_from_errno (errno); + break; + } + + if (buffer_new != p) + buffer_new = p; + + memcpy (buffer_new + buffer_new_n, buf, buf_n); + buffer_new_n += buf_n; + } + else + break; + } + if (err) + goto out; + + *buffer_n = buffer_new_n; + *buffer = buffer_new; + + out: + + if (err) + gcry_free (buffer_new); + + return err; +} + +/* Read data chunks from the IO object AC_IO until EOF, feeding them + to the callback function CB. Return zero on success or error + code. */ +static gcry_error_t +_gcry_ac_io_process (gcry_ac_io_t *ac_io, + gcry_ac_data_write_cb_t cb, void *opaque) +{ + unsigned char buffer[BUFSIZ]; + unsigned int nread; + size_t buffer_n; + gcry_error_t err; + + nread = 0; + + while (1) + { + buffer_n = sizeof (buffer); + err = _gcry_ac_io_read (ac_io, nread, buffer, &buffer_n); + if (err) + break; + if (buffer_n) + { + err = (*cb) (opaque, buffer, buffer_n); + if (err) + break; + nread += buffer_n; + } + else + break; + } + + return err; +} + + + +/* + * Functions for converting data between the native ac and the + * S-expression structure used by the pk interface. + */ + +/* Extract the S-Expression DATA_SEXP into DATA under the control of + TYPE and NAME. This function assumes that S-Expressions are of the + following structure: + + (IDENTIFIER [...] + (ALGORITHM <list of named MPI values>)) */ +static gcry_error_t +ac_data_extract (const char *identifier, const char *algorithm, + gcry_sexp_t sexp, gcry_ac_data_t *data) +{ + gcry_error_t err; + gcry_sexp_t value_sexp; + gcry_sexp_t data_sexp; + size_t data_sexp_n; + gcry_mpi_t value_mpi; + char *value_name; + const char *data_raw; + size_t data_raw_n; + gcry_ac_data_t data_new; + unsigned int i; + + value_sexp = NULL; + data_sexp = NULL; + value_name = NULL; + value_mpi = NULL; + data_new = NULL; + + /* Verify that the S-expression contains the correct identifier. */ + data_raw = gcry_sexp_nth_data (sexp, 0, &data_raw_n); + if ((! data_raw) || strncmp (identifier, data_raw, data_raw_n)) + { + err = gcry_error (GPG_ERR_INV_SEXP); + goto out; + } + + /* Extract inner S-expression. */ + data_sexp = gcry_sexp_find_token (sexp, algorithm, 0); + if (! data_sexp) + { + err = gcry_error (GPG_ERR_INV_SEXP); + goto out; + } + + /* Count data elements. */ + data_sexp_n = gcry_sexp_length (data_sexp); + data_sexp_n--; + + /* Allocate new data set. */ + err = _gcry_ac_data_new (&data_new); + if (err) + goto out; + + /* Iterate through list of data elements and add them to the data + set. */ + for (i = 0; i < data_sexp_n; i++) + { + /* Get the S-expression of the named MPI, that contains the name + and the MPI value. */ + value_sexp = gcry_sexp_nth (data_sexp, i + 1); + if (! value_sexp) + { + err = gcry_error (GPG_ERR_INV_SEXP); + break; + } + + /* Extract the name. */ + data_raw = gcry_sexp_nth_data (value_sexp, 0, &data_raw_n); + if (! data_raw) + { + err = gcry_error (GPG_ERR_INV_SEXP); + break; + } + + /* Extract the MPI value. */ + value_mpi = gcry_sexp_nth_mpi (value_sexp, 1, GCRYMPI_FMT_USG); + if (! value_mpi) + { + err = gcry_error (GPG_ERR_INTERNAL); /* FIXME? */ + break; + } + + /* Duplicate the name. */ + value_name = gcry_malloc (data_raw_n + 1); + if (! value_name) + { + err = gcry_error_from_errno (errno); + break; + } + strncpy (value_name, data_raw, data_raw_n); + value_name[data_raw_n] = 0; + + err = _gcry_ac_data_set (data_new, GCRY_AC_FLAG_DEALLOC, value_name, value_mpi); + if (err) + break; + + gcry_sexp_release (value_sexp); + value_sexp = NULL; + value_name = NULL; + value_mpi = NULL; + } + if (err) + goto out; + + /* Copy out. */ + *data = data_new; + + out: + + /* Deallocate resources. */ + if (err) + { + _gcry_ac_data_destroy (data_new); + gcry_mpi_release (value_mpi); + gcry_free (value_name); + gcry_sexp_release (value_sexp); + } + gcry_sexp_release (data_sexp); + + return err; +} + +/* Construct an S-expression from the DATA and store it in + DATA_SEXP. The S-expression will be of the following structure: + + (IDENTIFIER [(flags [...])] + (ALGORITHM <list of named MPI values>)) */ +static gcry_error_t +ac_data_construct (const char *identifier, int include_flags, + unsigned int flags, const char *algorithm, + gcry_ac_data_t data, gcry_sexp_t *sexp) +{ + unsigned int data_length; + gcry_sexp_t sexp_new; + gcry_error_t err; + size_t sexp_format_n; + char *sexp_format; + void **arg_list; + unsigned int i; + + arg_list = NULL; + sexp_new = NULL; + sexp_format = NULL; + + /* We build a list of arguments to pass to + gcry_sexp_build_array(). */ + data_length = _gcry_ac_data_length (data); + arg_list = gcry_calloc (data_length, sizeof (*arg_list) * 2); + if (! arg_list) + { + err = gcry_error_from_errno (errno); + goto out; + } + + /* Fill list with MPIs. */ + for (i = 0; i < data_length; i++) + { + char **nameaddr = &data->data[i].name; + + arg_list[(i * 2) + 0] = nameaddr; + arg_list[(i * 2) + 1] = &data->data[i].mpi; + } + + /* Calculate size of format string. */ + sexp_format_n = (3 + + (include_flags ? 7 : 0) + + (algorithm ? (2 + strlen (algorithm)) : 0) + + strlen (identifier)); + + for (i = 0; i < data_length; i++) + /* Per-element sizes. */ + sexp_format_n += 6; + + if (include_flags) + /* Add flags. */ + for (i = 0; i < DIM (ac_flags); i++) + if (flags & ac_flags[i].number) + sexp_format_n += strlen (ac_flags[i].string) + 1; + + /* Done. */ + sexp_format = gcry_malloc (sexp_format_n); + if (! sexp_format) + { + err = gcry_error_from_errno (errno); + goto out; + } + + /* Construct the format string. */ + + *sexp_format = 0; + strcat (sexp_format, "("); + strcat (sexp_format, identifier); + if (include_flags) + { + strcat (sexp_format, "(flags"); + for (i = 0; i < DIM (ac_flags); i++) + if (flags & ac_flags[i].number) + { + strcat (sexp_format, " "); + strcat (sexp_format, ac_flags[i].string); + } + strcat (sexp_format, ")"); + } + if (algorithm) + { + strcat (sexp_format, "("); + strcat (sexp_format, algorithm); + } + for (i = 0; i < data_length; i++) + strcat (sexp_format, "(%s%m)"); + if (algorithm) + strcat (sexp_format, ")"); + strcat (sexp_format, ")"); + + /* Create final S-expression. */ + err = gcry_sexp_build_array (&sexp_new, NULL, sexp_format, arg_list); + if (err) + goto out; + + *sexp = sexp_new; + + out: + + /* Deallocate resources. */ + gcry_free (sexp_format); + gcry_free (arg_list); + if (err) + gcry_sexp_release (sexp_new); + + return err; +} + + + +/* + * Handle management. + */ + +/* Creates a new handle for the algorithm ALGORITHM and stores it in + HANDLE. FLAGS is not used yet. */ +gcry_error_t +_gcry_ac_open (gcry_ac_handle_t *handle, + gcry_ac_id_t algorithm, unsigned int flags) +{ + gcry_ac_handle_t handle_new; + const char *algorithm_name; + gcry_module_t module; + gcry_error_t err; + + *handle = NULL; + module = NULL; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + /* Get name. */ + algorithm_name = _gcry_pk_aliased_algo_name (algorithm); + if (! algorithm_name) + { + err = gcry_error (GPG_ERR_PUBKEY_ALGO); + goto out; + } + + /* Acquire reference to the pubkey module. */ + err = _gcry_pk_module_lookup (algorithm, &module); + if (err) + goto out; + + /* Allocate. */ + handle_new = gcry_malloc (sizeof (*handle_new)); + if (! handle_new) + { + err = gcry_error_from_errno (errno); + goto out; + } + + /* Done. */ + handle_new->algorithm = algorithm; + handle_new->algorithm_name = algorithm_name; + handle_new->flags = flags; + handle_new->module = module; + *handle = handle_new; + + out: + + /* Deallocate resources. */ + if (err) + _gcry_pk_module_release (module); + + return err; +} + + +/* Destroys the handle HANDLE. */ +void +_gcry_ac_close (gcry_ac_handle_t handle) +{ + /* Release reference to pubkey module. */ + if (handle) + { + _gcry_pk_module_release (handle->module); + gcry_free (handle); + } +} + + + +/* + * Key management. + */ + +/* Initialize a key from a given data set. */ +/* FIXME/Damn: the argument HANDLE is not only unnecessary, it is + completely WRONG here. */ +gcry_error_t +_gcry_ac_key_init (gcry_ac_key_t *key, gcry_ac_handle_t handle, + gcry_ac_key_type_t type, gcry_ac_data_t data) +{ + gcry_ac_data_t data_new; + gcry_ac_key_t key_new; + gcry_error_t err; + + (void)handle; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + /* Allocate. */ + key_new = gcry_malloc (sizeof (*key_new)); + if (! key_new) + { + err = gcry_error_from_errno (errno); + goto out; + } + + /* Copy data set. */ + err = _gcry_ac_data_copy (&data_new, data); + if (err) + goto out; + + /* Done. */ + key_new->data = data_new; + key_new->type = type; + *key = key_new; + + out: + + if (err) + /* Deallocate resources. */ + gcry_free (key_new); + + return err; +} + + +/* Generates a new key pair via the handle HANDLE of NBITS bits and + stores it in KEY_PAIR. In case non-standard settings are wanted, a + pointer to a structure of type gcry_ac_key_spec_<algorithm>_t, + matching the selected algorithm, can be given as KEY_SPEC. + MISC_DATA is not used yet. */ +gcry_error_t +_gcry_ac_key_pair_generate (gcry_ac_handle_t handle, unsigned int nbits, + void *key_spec, + gcry_ac_key_pair_t *key_pair, + gcry_mpi_t **misc_data) +{ + gcry_sexp_t genkey_sexp_request; + gcry_sexp_t genkey_sexp_reply; + gcry_ac_data_t key_data_secret; + gcry_ac_data_t key_data_public; + gcry_ac_key_pair_t key_pair_new; + gcry_ac_key_t key_secret; + gcry_ac_key_t key_public; + gcry_sexp_t key_sexp; + gcry_error_t err; + char *genkey_format; + size_t genkey_format_n; + void **arg_list; + size_t arg_list_n; + unsigned int i; + unsigned int j; + + (void)misc_data; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + key_data_secret = NULL; + key_data_public = NULL; + key_secret = NULL; + key_public = NULL; + genkey_format = NULL; + arg_list = NULL; + genkey_sexp_request = NULL; + genkey_sexp_reply = NULL; + key_sexp = NULL; + + /* Allocate key pair. */ + key_pair_new = gcry_malloc (sizeof (struct gcry_ac_key_pair)); + if (! key_pair_new) + { + err = gcry_error_from_errno (errno); + goto out; + } + + /* Allocate keys. */ + key_secret = gcry_malloc (sizeof (*key_secret)); + if (! key_secret) + { + err = gcry_error_from_errno (errno); + goto out; + } + key_public = gcry_malloc (sizeof (*key_public)); + if (! key_public) + { + err = gcry_error_from_errno (errno); + goto out; + } + + /* Calculate size of the format string, that is used for creating + the request S-expression. */ + genkey_format_n = 22; + + /* Respect any relevant algorithm specific commands. */ + if (key_spec) + for (i = 0; i < DIM (ac_key_generate_specs); i++) + if (handle->algorithm == ac_key_generate_specs[i].algorithm) + genkey_format_n += 6; + + /* Create format string. */ + genkey_format = gcry_malloc (genkey_format_n); + if (! genkey_format) + { + err = gcry_error_from_errno (errno); + goto out; + } + + /* Fill format string. */ + *genkey_format = 0; + strcat (genkey_format, "(genkey(%s(nbits%d)"); + if (key_spec) + for (i = 0; i < DIM (ac_key_generate_specs); i++) + if (handle->algorithm == ac_key_generate_specs[i].algorithm) + strcat (genkey_format, "(%s%m)"); + strcat (genkey_format, "))"); + + /* Build list of argument pointers, the algorithm name and the nbits + are always needed. */ + arg_list_n = 2; + + /* Now the algorithm specific arguments. */ + if (key_spec) + for (i = 0; i < DIM (ac_key_generate_specs); i++) + if (handle->algorithm == ac_key_generate_specs[i].algorithm) + arg_list_n += 2; + + /* Allocate list. */ + arg_list = gcry_calloc (arg_list_n, sizeof (*arg_list)); + if (! arg_list) + { + err = gcry_error_from_errno (errno); + goto out; + } + + arg_list[0] = (void *) &handle->algorithm_name; + arg_list[1] = (void *) &nbits; + if (key_spec) + for (j = 2, i = 0; i < DIM (ac_key_generate_specs); i++) + if (handle->algorithm == ac_key_generate_specs[i].algorithm) + { + /* Add name of this specification flag and the + according member of the spec strucuture. */ + arg_list[j++] = (void *)(&ac_key_generate_specs[i].name); + arg_list[j++] = (void *) + (((char *) key_spec) + + ac_key_generate_specs[i].offset); + /* FIXME: above seems to suck. */ + } + + /* Construct final request S-expression. */ + err = gcry_sexp_build_array (&genkey_sexp_request, + NULL, genkey_format, arg_list); + if (err) + goto out; + + /* Perform genkey operation. */ + err = gcry_pk_genkey (&genkey_sexp_reply, genkey_sexp_request); + if (err) + goto out; + + key_sexp = gcry_sexp_find_token (genkey_sexp_reply, "private-key", 0); + if (! key_sexp) + { + err = gcry_error (GPG_ERR_INTERNAL); + goto out; + } + err = ac_data_extract ("private-key", handle->algorithm_name, + key_sexp, &key_data_secret); + if (err) + goto out; + + gcry_sexp_release (key_sexp); + key_sexp = gcry_sexp_find_token (genkey_sexp_reply, "public-key", 0); + if (! key_sexp) + { + err = gcry_error (GPG_ERR_INTERNAL); + goto out; + } + err = ac_data_extract ("public-key", handle->algorithm_name, + key_sexp, &key_data_public); + if (err) + goto out; + + /* Done. */ + + key_secret->type = GCRY_AC_KEY_SECRET; + key_secret->data = key_data_secret; + key_public->type = GCRY_AC_KEY_PUBLIC; + key_public->data = key_data_public; + key_pair_new->secret = key_secret; + key_pair_new->public = key_public; + *key_pair = key_pair_new; + + out: + + /* Deallocate resources. */ + + gcry_free (genkey_format); + gcry_free (arg_list); + gcry_sexp_release (genkey_sexp_request); + gcry_sexp_release (genkey_sexp_reply); + gcry_sexp_release (key_sexp); + if (err) + { + _gcry_ac_data_destroy (key_data_secret); + _gcry_ac_data_destroy (key_data_public); + gcry_free (key_secret); + gcry_free (key_public); + gcry_free (key_pair_new); + } + + return err; +} + +/* Returns the key of type WHICH out of the key pair KEY_PAIR. */ +gcry_ac_key_t +_gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair, + gcry_ac_key_type_t which) +{ + gcry_ac_key_t key; + + if (fips_mode ()) + return NULL; + + switch (which) + { + case GCRY_AC_KEY_SECRET: + key = key_pair->secret; + break; + + case GCRY_AC_KEY_PUBLIC: + key = key_pair->public; + break; + + default: + key = NULL; + break; + } + + return key; +} + +/* Destroys the key KEY. */ +void +_gcry_ac_key_destroy (gcry_ac_key_t key) +{ + unsigned int i; + + if (key) + { + if (key->data) + { + for (i = 0; i < key->data->data_n; i++) + { + if (key->data->data[i].mpi) + gcry_mpi_release (key->data->data[i].mpi); + if (key->data->data[i].name) + gcry_free (key->data->data[i].name); + } + gcry_free (key->data->data); + gcry_free (key->data); + } + gcry_free (key); + } +} + +/* Destroys the key pair KEY_PAIR. */ +void +_gcry_ac_key_pair_destroy (gcry_ac_key_pair_t key_pair) +{ + if (key_pair) + { + gcry_ac_key_destroy (key_pair->secret); + gcry_ac_key_destroy (key_pair->public); + gcry_free (key_pair); + } +} + +/* Returns the data set contained in the key KEY. */ +gcry_ac_data_t +_gcry_ac_key_data_get (gcry_ac_key_t key) +{ + if (fips_mode ()) + return NULL; + return key->data; +} + +/* Verifies that the key KEY is sane via HANDLE. */ +gcry_error_t +_gcry_ac_key_test (gcry_ac_handle_t handle, gcry_ac_key_t key) +{ + gcry_sexp_t key_sexp; + gcry_error_t err; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + key_sexp = NULL; + err = ac_data_construct (ac_key_identifiers[key->type], 0, 0, + handle->algorithm_name, key->data, &key_sexp); + if (err) + goto out; + + err = gcry_pk_testkey (key_sexp); + + out: + + gcry_sexp_release (key_sexp); + + return gcry_error (err); +} + +/* Stores the number of bits of the key KEY in NBITS via HANDLE. */ +gcry_error_t +_gcry_ac_key_get_nbits (gcry_ac_handle_t handle, + gcry_ac_key_t key, unsigned int *nbits) +{ + gcry_sexp_t key_sexp; + gcry_error_t err; + unsigned int n; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + key_sexp = NULL; + + err = ac_data_construct (ac_key_identifiers[key->type], + 0, 0, handle->algorithm_name, key->data, &key_sexp); + if (err) + goto out; + + n = gcry_pk_get_nbits (key_sexp); + if (! n) + { + err = gcry_error (GPG_ERR_PUBKEY_ALGO); + goto out; + } + + *nbits = n; + + out: + + gcry_sexp_release (key_sexp); + + return err; +} + +/* Writes the 20 byte long key grip of the key KEY to KEY_GRIP via + HANDLE. */ +gcry_error_t +_gcry_ac_key_get_grip (gcry_ac_handle_t handle, + gcry_ac_key_t key, unsigned char *key_grip) +{ + gcry_sexp_t key_sexp; + gcry_error_t err; + unsigned char *ret; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + key_sexp = NULL; + err = ac_data_construct (ac_key_identifiers[key->type], 0, 0, + handle->algorithm_name, key->data, &key_sexp); + if (err) + goto out; + + ret = gcry_pk_get_keygrip (key_sexp, key_grip); + if (! ret) + { + err = gcry_error (GPG_ERR_INV_OBJ); + goto out; + } + + err = 0; + + out: + + gcry_sexp_release (key_sexp); + + return err; +} + + + + +/* + * Functions performing cryptographic operations. + */ + +/* Encrypts the plain text MPI value DATA_PLAIN with the key public + KEY under the control of the flags FLAGS and stores the resulting + data set into DATA_ENCRYPTED. */ +gcry_error_t +_gcry_ac_data_encrypt (gcry_ac_handle_t handle, + unsigned int flags, + gcry_ac_key_t key, + gcry_mpi_t data_plain, + gcry_ac_data_t *data_encrypted) +{ + gcry_ac_data_t data_encrypted_new; + gcry_ac_data_t data_value; + gcry_sexp_t sexp_request; + gcry_sexp_t sexp_reply; + gcry_sexp_t sexp_key; + gcry_error_t err; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + data_encrypted_new = NULL; + sexp_request = NULL; + sexp_reply = NULL; + data_value = NULL; + sexp_key = NULL; + + if (key->type != GCRY_AC_KEY_PUBLIC) + { + err = gcry_error (GPG_ERR_WRONG_KEY_USAGE); + goto out; + } + + err = ac_data_construct (ac_key_identifiers[key->type], 0, 0, + handle->algorithm_name, key->data, &sexp_key); + if (err) + goto out; + + err = _gcry_ac_data_new (&data_value); + if (err) + goto out; + + err = _gcry_ac_data_set (data_value, 0, "value", data_plain); + if (err) + goto out; + + err = ac_data_construct ("data", 1, flags, handle->algorithm_name, + data_value, &sexp_request); + if (err) + goto out; + + /* FIXME: error vs. errcode? */ + + err = gcry_pk_encrypt (&sexp_reply, sexp_request, sexp_key); + if (err) + goto out; + + /* Extract data. */ + err = ac_data_extract ("enc-val", handle->algorithm_name, + sexp_reply, &data_encrypted_new); + if (err) + goto out; + + *data_encrypted = data_encrypted_new; + + out: + + /* Deallocate resources. */ + + gcry_sexp_release (sexp_request); + gcry_sexp_release (sexp_reply); + gcry_sexp_release (sexp_key); + _gcry_ac_data_destroy (data_value); + + return err; +} + +/* Decrypts the encrypted data contained in the data set + DATA_ENCRYPTED with the secret key KEY under the control of the + flags FLAGS and stores the resulting plain text MPI value in + DATA_PLAIN. */ +gcry_error_t +_gcry_ac_data_decrypt (gcry_ac_handle_t handle, + unsigned int flags, + gcry_ac_key_t key, + gcry_mpi_t *data_plain, + gcry_ac_data_t data_encrypted) +{ + gcry_mpi_t data_decrypted; + gcry_sexp_t sexp_request; + gcry_sexp_t sexp_reply; + gcry_sexp_t sexp_value; + gcry_sexp_t sexp_key; + gcry_error_t err; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + sexp_request = NULL; + sexp_reply = NULL; + sexp_value = NULL; + sexp_key = NULL; + + if (key->type != GCRY_AC_KEY_SECRET) + { + err = gcry_error (GPG_ERR_WRONG_KEY_USAGE); + goto out; + } + + err = ac_data_construct (ac_key_identifiers[key->type], 0, 0, + handle->algorithm_name, key->data, &sexp_key); + if (err) + goto out; + + /* Create S-expression from data. */ + err = ac_data_construct ("enc-val", 1, flags, handle->algorithm_name, + data_encrypted, &sexp_request); + if (err) + goto out; + + /* Decrypt. */ + err = gcry_pk_decrypt (&sexp_reply, sexp_request, sexp_key); + if (err) + goto out; + + /* Extract plain text. */ + sexp_value = gcry_sexp_find_token (sexp_reply, "value", 0); + if (! sexp_value) + { + /* FIXME? */ + err = gcry_error (GPG_ERR_GENERAL); + goto out; + } + + data_decrypted = gcry_sexp_nth_mpi (sexp_value, 1, GCRYMPI_FMT_USG); + if (! data_decrypted) + { + err = gcry_error (GPG_ERR_GENERAL); + goto out; + } + + *data_plain = data_decrypted; + + out: + + /* Deallocate resources. */ + gcry_sexp_release (sexp_request); + gcry_sexp_release (sexp_reply); + gcry_sexp_release (sexp_value); + gcry_sexp_release (sexp_key); + + return gcry_error (err); + +} + +/* Signs the data contained in DATA with the secret key KEY and stores + the resulting signature data set in DATA_SIGNATURE. */ +gcry_error_t +_gcry_ac_data_sign (gcry_ac_handle_t handle, + gcry_ac_key_t key, + gcry_mpi_t data, + gcry_ac_data_t *data_signature) +{ + gcry_ac_data_t data_signed; + gcry_ac_data_t data_value; + gcry_sexp_t sexp_request; + gcry_sexp_t sexp_reply; + gcry_sexp_t sexp_key; + gcry_error_t err; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + data_signed = NULL; + data_value = NULL; + sexp_request = NULL; + sexp_reply = NULL; + sexp_key = NULL; + + if (key->type != GCRY_AC_KEY_SECRET) + { + err = gcry_error (GPG_ERR_WRONG_KEY_USAGE); + goto out; + } + + err = ac_data_construct (ac_key_identifiers[key->type], 0, 0, + handle->algorithm_name, key->data, &sexp_key); + if (err) + goto out; + + err = _gcry_ac_data_new (&data_value); + if (err) + goto out; + + err = _gcry_ac_data_set (data_value, 0, "value", data); + if (err) + goto out; + + /* Create S-expression holding the data. */ + err = ac_data_construct ("data", 1, 0, NULL, data_value, &sexp_request); + if (err) + goto out; + + /* Sign. */ + err = gcry_pk_sign (&sexp_reply, sexp_request, sexp_key); + if (err) + goto out; + + /* Extract data. */ + err = ac_data_extract ("sig-val", handle->algorithm_name, + sexp_reply, &data_signed); + if (err) + goto out; + + /* Done. */ + *data_signature = data_signed; + + out: + + gcry_sexp_release (sexp_request); + gcry_sexp_release (sexp_reply); + gcry_sexp_release (sexp_key); + _gcry_ac_data_destroy (data_value); + + return gcry_error (err); +} + + +/* Verifies that the signature contained in the data set + DATA_SIGNATURE is indeed the result of signing the data contained + in DATA with the secret key belonging to the public key KEY. */ +gcry_error_t +_gcry_ac_data_verify (gcry_ac_handle_t handle, + gcry_ac_key_t key, + gcry_mpi_t data, + gcry_ac_data_t data_signature) +{ + gcry_sexp_t sexp_signature; + gcry_ac_data_t data_value; + gcry_sexp_t sexp_data; + gcry_sexp_t sexp_key; + gcry_error_t err; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + sexp_signature = NULL; + data_value = NULL; + sexp_data = NULL; + sexp_key = NULL; + + err = ac_data_construct ("public-key", 0, 0, + handle->algorithm_name, key->data, &sexp_key); + if (err) + goto out; + + if (key->type != GCRY_AC_KEY_PUBLIC) + { + err = gcry_error (GPG_ERR_WRONG_KEY_USAGE); + goto out; + } + + /* Construct S-expression holding the signature data. */ + err = ac_data_construct ("sig-val", 1, 0, handle->algorithm_name, + data_signature, &sexp_signature); + if (err) + goto out; + + err = _gcry_ac_data_new (&data_value); + if (err) + goto out; + + err = _gcry_ac_data_set (data_value, 0, "value", data); + if (err) + goto out; + + /* Construct S-expression holding the data. */ + err = ac_data_construct ("data", 1, 0, NULL, data_value, &sexp_data); + if (err) + goto out; + + /* Verify signature. */ + err = gcry_pk_verify (sexp_signature, sexp_data, sexp_key); + + out: + + gcry_sexp_release (sexp_signature); + gcry_sexp_release (sexp_data); + gcry_sexp_release (sexp_key); + _gcry_ac_data_destroy (data_value); + + return gcry_error (err); +} + + + + +/* + * Implementation of encoding methods (em). + */ + +/* Type for functions that encode or decode (hence the name) a + message. */ +typedef gcry_error_t (*gcry_ac_em_dencode_t) (unsigned int flags, + void *options, + gcry_ac_io_t *ac_io_read, + gcry_ac_io_t *ac_io_write); + +/* Fill the buffer BUFFER which is BUFFER_N bytes long with non-zero + random bytes of random level LEVEL. */ +static void +em_randomize_nonzero (unsigned char *buffer, size_t buffer_n, + gcry_random_level_t level) +{ + unsigned char *buffer_rand; + unsigned int buffer_rand_n; + unsigned int zeros; + unsigned int i; + unsigned int j; + + for (i = 0; i < buffer_n; i++) + buffer[i] = 0; + + do + { + /* Count zeros. */ + for (i = zeros = 0; i < buffer_n; i++) + if (! buffer[i]) + zeros++; + + if (zeros) + { + /* Get random bytes. */ + buffer_rand_n = zeros + (zeros / 128); + buffer_rand = gcry_random_bytes_secure (buffer_rand_n, level); + + /* Substitute zeros with non-zero random bytes. */ + for (i = j = 0; zeros && (i < buffer_n) && (j < buffer_rand_n); i++) + if (! buffer[i]) + { + while ((j < buffer_rand_n) && (! buffer_rand[j])) + j++; + if (j < buffer_rand_n) + { + buffer[i] = buffer_rand[j++]; + zeros--; + } + else + break; + } + gcry_free (buffer_rand); + } + } + while (zeros); +} + +/* Encode a message according to the Encoding Method for Encryption + `PKCS-V1_5' (EME-PKCS-V1_5). */ +static gcry_error_t +eme_pkcs_v1_5_encode (unsigned int flags, void *opts, + gcry_ac_io_t *ac_io_read, + gcry_ac_io_t *ac_io_write) +{ + gcry_ac_eme_pkcs_v1_5_t *options; + gcry_error_t err; + unsigned char *buffer; + unsigned char *ps; + unsigned char *m; + size_t m_n; + unsigned int ps_n; + unsigned int k; + + (void)flags; + + options = opts; + buffer = NULL; + m = NULL; + + err = _gcry_ac_io_read_all (ac_io_read, &m, &m_n); + if (err) + goto out; + + /* Figure out key length in bytes. */ + k = options->key_size / 8; + + if (m_n > k - 11) + { + /* Key is too short for message. */ + err = gcry_error (GPG_ERR_TOO_SHORT); + goto out; + } + + /* According to this encoding method, the first byte of the encoded + message is zero. This byte will be lost anyway, when the encoded + message is to be converted into an MPI, that's why we skip + it. */ + + /* Allocate buffer. */ + buffer = gcry_malloc (k - 1); + if (! buffer) + { + err = gcry_error_from_errno (errno); + goto out; + } + + /* Generate an octet string PS of length k - mLen - 3 consisting + of pseudorandomly generated nonzero octets. The length of PS + will be at least eight octets. */ + ps_n = k - m_n - 3; + ps = buffer + 1; + em_randomize_nonzero (ps, ps_n, GCRY_STRONG_RANDOM); + + /* Concatenate PS, the message M, and other padding to form an + encoded message EM of length k octets as: + + EM = 0x00 || 0x02 || PS || 0x00 || M. */ + + buffer[0] = 0x02; + buffer[ps_n + 1] = 0x00; + memcpy (buffer + ps_n + 2, m, m_n); + + err = _gcry_ac_io_write (ac_io_write, buffer, k - 1); + + out: + + gcry_free (buffer); + gcry_free (m); + + return err; +} + +/* Decode a message according to the Encoding Method for Encryption + `PKCS-V1_5' (EME-PKCS-V1_5). */ +static gcry_error_t +eme_pkcs_v1_5_decode (unsigned int flags, void *opts, + gcry_ac_io_t *ac_io_read, + gcry_ac_io_t *ac_io_write) +{ + gcry_ac_eme_pkcs_v1_5_t *options; + unsigned char *buffer; + unsigned char *em; + size_t em_n; + gcry_error_t err; + unsigned int i; + unsigned int k; + + (void)flags; + + options = opts; + buffer = NULL; + em = NULL; + + err = _gcry_ac_io_read_all (ac_io_read, &em, &em_n); + if (err) + goto out; + + /* Figure out key size. */ + k = options->key_size / 8; + + /* Search for zero byte. */ + for (i = 0; (i < em_n) && em[i]; i++); + + /* According to this encoding method, the first byte of the encoded + message should be zero. This byte is lost. */ + + if (! ((em_n >= 10) + && (em_n == (k - 1)) + && (em[0] == 0x02) + && (i < em_n) + && ((i - 1) >= 8))) + { + err = gcry_error (GPG_ERR_DECRYPT_FAILED); + goto out; + } + + i++; + buffer = gcry_malloc (em_n - i); + if (! buffer) + { + err = gcry_error_from_errno (errno); + goto out; + } + + memcpy (buffer, em + i, em_n - i); + err = _gcry_ac_io_write (ac_io_write, buffer, em_n - i); + + out: + + gcry_free (buffer); + gcry_free (em); + + return err; +} + +static gcry_error_t +emsa_pkcs_v1_5_encode_data_cb (void *opaque, + unsigned char *buffer, size_t buffer_n) +{ + gcry_md_hd_t md_handle; + + md_handle = opaque; + gcry_md_write (md_handle, buffer, buffer_n); + + return 0; +} + + +/* Encode a message according to the Encoding Method for Signatures + with Appendix `PKCS-V1_5' (EMSA-PKCS-V1_5). */ +static gcry_error_t +emsa_pkcs_v1_5_encode (unsigned int flags, void *opts, + gcry_ac_io_t *ac_io_read, + gcry_ac_io_t *ac_io_write) +{ + gcry_ac_emsa_pkcs_v1_5_t *options; + gcry_error_t err; + gcry_md_hd_t md; + unsigned char *t; + size_t t_n; + unsigned char *h; + size_t h_n; + unsigned char *ps; + size_t ps_n; + unsigned char *buffer; + size_t buffer_n; + unsigned char asn[100]; /* FIXME, always enough? */ + size_t asn_n; + unsigned int i; + + (void)flags; + + options = opts; + buffer = NULL; + md = NULL; + ps = NULL; + t = NULL; + + /* Create hashing handle and get the necessary information. */ + err = gcry_md_open (&md, options->md, 0); + if (err) + goto out; + + asn_n = DIM (asn); + err = gcry_md_algo_info (options->md, GCRYCTL_GET_ASNOID, asn, &asn_n); + if (err) + goto out; + + h_n = gcry_md_get_algo_dlen (options->md); + + err = _gcry_ac_io_process (ac_io_read, emsa_pkcs_v1_5_encode_data_cb, md); + if (err) + goto out; + + h = gcry_md_read (md, 0); + + /* Encode the algorithm ID for the hash function and the hash value + into an ASN.1 value of type DigestInfo with the Distinguished + Encoding Rules (DER), where the type DigestInfo has the syntax: + + DigestInfo ::== SEQUENCE { + digestAlgorithm AlgorithmIdentifier, + digest OCTET STRING + } + + The first field identifies the hash function and the second + contains the hash value. Let T be the DER encoding of the + DigestInfo value and let tLen be the length in octets of T. */ + + t_n = asn_n + h_n; + t = gcry_malloc (t_n); + if (! t) + { + err = gcry_error_from_errno (errno); + goto out; + } + + for (i = 0; i < asn_n; i++) + t[i] = asn[i]; + for (i = 0; i < h_n; i++) + t[asn_n + i] = h[i]; + + /* If emLen < tLen + 11, output "intended encoded message length + too short" and stop. */ + if (options->em_n < t_n + 11) + { + err = gcry_error (GPG_ERR_TOO_SHORT); + goto out; + } + + /* Generate an octet string PS consisting of emLen - tLen - 3 octets + with hexadecimal value 0xFF. The length of PS will be at least 8 + octets. */ + ps_n = options->em_n - t_n - 3; + ps = gcry_malloc (ps_n); + if (! ps) + { + err = gcry_error_from_errno (errno); + goto out; + } + for (i = 0; i < ps_n; i++) + ps[i] = 0xFF; + + /* Concatenate PS, the DER encoding T, and other padding to form the + encoded message EM as: + + EM = 0x00 || 0x01 || PS || 0x00 || T. */ + + buffer_n = ps_n + t_n + 3; + buffer = gcry_malloc (buffer_n); + if (! buffer) + { + err = gcry_error_from_errno (errno); + goto out; + } + + buffer[0] = 0x00; + buffer[1] = 0x01; + for (i = 0; i < ps_n; i++) + buffer[2 + i] = ps[i]; + buffer[2 + ps_n] = 0x00; + for (i = 0; i < t_n; i++) + buffer[3 + ps_n + i] = t[i]; + + err = _gcry_ac_io_write (ac_io_write, buffer, buffer_n); + + out: + + gcry_md_close (md); + + gcry_free (buffer); + gcry_free (ps); + gcry_free (t); + + return err; +} + +/* `Actions' for data_dencode(). */ +typedef enum dencode_action + { + DATA_ENCODE, + DATA_DECODE, + } +dencode_action_t; + +/* Encode or decode a message according to the the encoding method + METHOD; ACTION specifies whether the message that is contained in + BUFFER_IN and of length BUFFER_IN_N should be encoded or decoded. + The resulting message will be stored in a newly allocated buffer in + BUFFER_OUT and BUFFER_OUT_N. */ +static gcry_error_t +ac_data_dencode (gcry_ac_em_t method, dencode_action_t action, + unsigned int flags, void *options, + gcry_ac_io_t *ac_io_read, + gcry_ac_io_t *ac_io_write) +{ + struct + { + gcry_ac_em_t method; + gcry_ac_em_dencode_t encode; + gcry_ac_em_dencode_t decode; + } methods[] = + { + { GCRY_AC_EME_PKCS_V1_5, + eme_pkcs_v1_5_encode, eme_pkcs_v1_5_decode }, + { GCRY_AC_EMSA_PKCS_V1_5, + emsa_pkcs_v1_5_encode, NULL }, + }; + size_t methods_n; + gcry_error_t err; + unsigned int i; + + methods_n = sizeof (methods) / sizeof (*methods); + + for (i = 0; i < methods_n; i++) + if (methods[i].method == method) + break; + if (i == methods_n) + { + err = gcry_error (GPG_ERR_NOT_FOUND); /* FIXME? */ + goto out; + } + + err = 0; + switch (action) + { + case DATA_ENCODE: + if (methods[i].encode) + /* FIXME? */ + err = (*methods[i].encode) (flags, options, ac_io_read, ac_io_write); + break; + + case DATA_DECODE: + if (methods[i].decode) + /* FIXME? */ + err = (*methods[i].decode) (flags, options, ac_io_read, ac_io_write); + break; + + default: + err = gcry_error (GPG_ERR_INV_ARG); + break; + } + + out: + + return err; +} + +/* Encode a message according to the encoding method METHOD. OPTIONS + must be a pointer to a method-specific structure + (gcry_ac_em*_t). */ +gcry_error_t +_gcry_ac_data_encode (gcry_ac_em_t method, + unsigned int flags, void *options, + gcry_ac_io_t *ac_io_read, + gcry_ac_io_t *ac_io_write) +{ + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + return ac_data_dencode (method, DATA_ENCODE, flags, options, + ac_io_read, ac_io_write); +} + +/* Dencode a message according to the encoding method METHOD. OPTIONS + must be a pointer to a method-specific structure + (gcry_ac_em*_t). */ +gcry_error_t +_gcry_ac_data_decode (gcry_ac_em_t method, + unsigned int flags, void *options, + gcry_ac_io_t *ac_io_read, + gcry_ac_io_t *ac_io_write) +{ + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + return ac_data_dencode (method, DATA_DECODE, flags, options, + ac_io_read, ac_io_write); +} + +/* Convert an MPI into an octet string. */ +void +_gcry_ac_mpi_to_os (gcry_mpi_t mpi, unsigned char *os, size_t os_n) +{ + unsigned long digit; + gcry_mpi_t base; + unsigned int i; + unsigned int n; + gcry_mpi_t m; + gcry_mpi_t d; + + if (fips_mode ()) + return; + + base = gcry_mpi_new (0); + gcry_mpi_set_ui (base, 256); + + n = 0; + m = gcry_mpi_copy (mpi); + while (gcry_mpi_cmp_ui (m, 0)) + { + n++; + gcry_mpi_div (m, NULL, m, base, 0); + } + + gcry_mpi_set (m, mpi); + d = gcry_mpi_new (0); + for (i = 0; (i < n) && (i < os_n); i++) + { + gcry_mpi_mod (d, m, base); + _gcry_mpi_get_ui (d, &digit); + gcry_mpi_div (m, NULL, m, base, 0); + os[os_n - i - 1] = (digit & 0xFF); + } + + for (; i < os_n; i++) + os[os_n - i - 1] = 0; + + gcry_mpi_release (base); + gcry_mpi_release (d); + gcry_mpi_release (m); +} + +/* Convert an MPI into an newly allocated octet string. */ +gcry_error_t +_gcry_ac_mpi_to_os_alloc (gcry_mpi_t mpi, unsigned char **os, size_t *os_n) +{ + unsigned char *buffer; + size_t buffer_n; + gcry_error_t err; + unsigned int nbits; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + nbits = gcry_mpi_get_nbits (mpi); + buffer_n = (nbits + 7) / 8; + buffer = gcry_malloc (buffer_n); + if (! buffer) + { + err = gcry_error_from_errno (errno); + goto out; + } + + _gcry_ac_mpi_to_os (mpi, buffer, buffer_n); + *os = buffer; + *os_n = buffer_n; + err = 0; + + out: + + return err; +} + + +/* Convert an octet string into an MPI. */ +void +_gcry_ac_os_to_mpi (gcry_mpi_t mpi, unsigned char *os, size_t os_n) +{ + unsigned int i; + gcry_mpi_t xi; + gcry_mpi_t x; + gcry_mpi_t a; + + if (fips_mode ()) + return; + + a = gcry_mpi_new (0); + gcry_mpi_set_ui (a, 1); + x = gcry_mpi_new (0); + gcry_mpi_set_ui (x, 0); + xi = gcry_mpi_new (0); + + for (i = 0; i < os_n; i++) + { + gcry_mpi_mul_ui (xi, a, os[os_n - i - 1]); + gcry_mpi_add (x, x, xi); + gcry_mpi_mul_ui (a, a, 256); + } + + gcry_mpi_release (xi); + gcry_mpi_release (a); + + gcry_mpi_set (mpi, x); + gcry_mpi_release (x); /* FIXME: correct? */ +} + + + +/* + * Implementation of Encryption Schemes (ES) and Signature Schemes + * with Appendix (SSA). + */ + +/* Schemes consist of two things: encoding methods and cryptographic + primitives. + + Since encoding methods are accessible through a common API with + method-specific options passed as an anonymous struct, schemes have + to provide functions that construct this method-specific structure; + this is what the functions of type `gcry_ac_dencode_prepare_t' are + there for. */ + +typedef gcry_error_t (*gcry_ac_dencode_prepare_t) (gcry_ac_handle_t handle, + gcry_ac_key_t key, + void *opts, + void *opts_em); + +/* The `dencode_prepare' function for ES-PKCS-V1_5. */ +static gcry_error_t +ac_es_dencode_prepare_pkcs_v1_5 (gcry_ac_handle_t handle, gcry_ac_key_t key, + void *opts, void *opts_em) +{ + gcry_ac_eme_pkcs_v1_5_t *options_em; + unsigned int nbits; + gcry_error_t err; + + (void)opts; + + err = _gcry_ac_key_get_nbits (handle, key, &nbits); + if (err) + goto out; + + options_em = opts_em; + options_em->key_size = nbits; + + out: + + return err; +} + +/* The `dencode_prepare' function for SSA-PKCS-V1_5. */ +static gcry_error_t +ac_ssa_dencode_prepare_pkcs_v1_5 (gcry_ac_handle_t handle, gcry_ac_key_t key, + void *opts, void *opts_em) +{ + gcry_ac_emsa_pkcs_v1_5_t *options_em; + gcry_ac_ssa_pkcs_v1_5_t *options; + gcry_error_t err; + unsigned int k; + + options_em = opts_em; + options = opts; + + err = _gcry_ac_key_get_nbits (handle, key, &k); + if (err) + goto out; + + k = (k + 7) / 8; + options_em->md = options->md; + options_em->em_n = k; + + out: + + return err; +} + +/* Type holding the information about each supported + Encryption/Signature Scheme. */ +typedef struct ac_scheme +{ + gcry_ac_scheme_t scheme; + gcry_ac_em_t scheme_encoding; + gcry_ac_dencode_prepare_t dencode_prepare; + size_t options_em_n; +} ac_scheme_t; + +/* List of supported Schemes. */ +static ac_scheme_t ac_schemes[] = + { + { GCRY_AC_ES_PKCS_V1_5, GCRY_AC_EME_PKCS_V1_5, + ac_es_dencode_prepare_pkcs_v1_5, + sizeof (gcry_ac_eme_pkcs_v1_5_t) }, + { GCRY_AC_SSA_PKCS_V1_5, GCRY_AC_EMSA_PKCS_V1_5, + ac_ssa_dencode_prepare_pkcs_v1_5, + sizeof (gcry_ac_emsa_pkcs_v1_5_t) } + }; + +/* Lookup a scheme by it's ID. */ +static ac_scheme_t * +ac_scheme_get (gcry_ac_scheme_t scheme) +{ + ac_scheme_t *ac_scheme; + unsigned int i; + + for (i = 0; i < DIM (ac_schemes); i++) + if (scheme == ac_schemes[i].scheme) + break; + if (i == DIM (ac_schemes)) + ac_scheme = NULL; + else + ac_scheme = ac_schemes + i; + + return ac_scheme; +} + +/* Prepares the encoding/decoding by creating an according option + structure. */ +static gcry_error_t +ac_dencode_prepare (gcry_ac_handle_t handle, gcry_ac_key_t key, void *opts, + ac_scheme_t scheme, void **opts_em) +{ + gcry_error_t err; + void *options_em; + + options_em = gcry_malloc (scheme.options_em_n); + if (! options_em) + { + err = gcry_error_from_errno (errno); + goto out; + } + + err = (*scheme.dencode_prepare) (handle, key, opts, options_em); + if (err) + goto out; + + *opts_em = options_em; + + out: + + if (err) + free (options_em); + + return err; +} + +/* Convert a data set into a single MPI; currently, this is only + supported for data sets containing a single MPI. */ +static gcry_error_t +ac_data_set_to_mpi (gcry_ac_data_t data, gcry_mpi_t *mpi) +{ + gcry_error_t err; + gcry_mpi_t mpi_new; + unsigned int elems; + + elems = _gcry_ac_data_length (data); + + if (elems != 1) + { + /* FIXME: I guess, we should be more flexible in this respect by + allowing the actual encryption/signature schemes to implement + this conversion mechanism. */ + err = gcry_error (GPG_ERR_CONFLICT); + goto out; + } + + err = _gcry_ac_data_get_index (data, GCRY_AC_FLAG_COPY, 0, NULL, &mpi_new); + if (err) + goto out; + + *mpi = mpi_new; + + out: + + return err; +} + +/* Encrypts the plain text message contained in M, which is of size + M_N, with the public key KEY_PUBLIC according to the Encryption + Scheme SCHEME_ID. HANDLE is used for accessing the low-level + cryptographic primitives. If OPTS is not NULL, it has to be an + anonymous structure specific to the chosen scheme (gcry_ac_es_*_t). + The encrypted message will be stored in C and C_N. */ +gcry_error_t +_gcry_ac_data_encrypt_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme_id, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_cipher) +{ + gcry_error_t err; + gcry_ac_io_t io_em; + unsigned char *em; + size_t em_n; + gcry_mpi_t mpi_plain; + gcry_ac_data_t data_encrypted; + gcry_mpi_t mpi_encrypted; + unsigned char *buffer; + size_t buffer_n; + void *opts_em; + ac_scheme_t *scheme; + + (void)flags; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + data_encrypted = NULL; + mpi_encrypted = NULL; + mpi_plain = NULL; + opts_em = NULL; + buffer = NULL; + em = NULL; + + scheme = ac_scheme_get (scheme_id); + if (! scheme) + { + err = gcry_error (GPG_ERR_NO_ENCRYPTION_SCHEME); + goto out; + } + + if (key->type != GCRY_AC_KEY_PUBLIC) + { + err = gcry_error (GPG_ERR_WRONG_KEY_USAGE); + goto out; + } + + err = ac_dencode_prepare (handle, key, opts, *scheme, &opts_em); + if (err) + goto out; + + _gcry_ac_io_init (&io_em, GCRY_AC_IO_WRITABLE, + GCRY_AC_IO_STRING, &em, &em_n); + + err = _gcry_ac_data_encode (scheme->scheme_encoding, 0, opts_em, + io_message, &io_em); + if (err) + goto out; + + mpi_plain = gcry_mpi_snew (0); + gcry_ac_os_to_mpi (mpi_plain, em, em_n); + + err = _gcry_ac_data_encrypt (handle, 0, key, mpi_plain, &data_encrypted); + if (err) + goto out; + + err = ac_data_set_to_mpi (data_encrypted, &mpi_encrypted); + if (err) + goto out; + + err = _gcry_ac_mpi_to_os_alloc (mpi_encrypted, &buffer, &buffer_n); + if (err) + goto out; + + err = _gcry_ac_io_write (io_cipher, buffer, buffer_n); + + out: + + gcry_ac_data_destroy (data_encrypted); + gcry_mpi_release (mpi_encrypted); + gcry_mpi_release (mpi_plain); + gcry_free (opts_em); + gcry_free (buffer); + gcry_free (em); + + return err; +} + +/* Decryptes the cipher message contained in C, which is of size C_N, + with the secret key KEY_SECRET according to the Encryption Scheme + SCHEME_ID. Handle is used for accessing the low-level + cryptographic primitives. If OPTS is not NULL, it has to be an + anonymous structure specific to the chosen scheme (gcry_ac_es_*_t). + The decrypted message will be stored in M and M_N. */ +gcry_error_t +_gcry_ac_data_decrypt_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme_id, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_cipher, + gcry_ac_io_t *io_message) +{ + gcry_ac_io_t io_em; + gcry_error_t err; + gcry_ac_data_t data_encrypted; + unsigned char *em; + size_t em_n; + gcry_mpi_t mpi_encrypted; + gcry_mpi_t mpi_decrypted; + void *opts_em; + ac_scheme_t *scheme; + char *elements_enc; + size_t elements_enc_n; + unsigned char *c; + size_t c_n; + + (void)flags; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + data_encrypted = NULL; + mpi_encrypted = NULL; + mpi_decrypted = NULL; + elements_enc = NULL; + opts_em = NULL; + em = NULL; + c = NULL; + + scheme = ac_scheme_get (scheme_id); + if (! scheme) + { + err = gcry_error (GPG_ERR_NO_ENCRYPTION_SCHEME); + goto out; + } + + if (key->type != GCRY_AC_KEY_SECRET) + { + err = gcry_error (GPG_ERR_WRONG_KEY_USAGE); + goto out; + } + + err = _gcry_ac_io_read_all (io_cipher, &c, &c_n); + if (err) + goto out; + + mpi_encrypted = gcry_mpi_snew (0); + gcry_ac_os_to_mpi (mpi_encrypted, c, c_n); + + err = _gcry_pk_get_elements (handle->algorithm, &elements_enc, NULL); + if (err) + goto out; + + elements_enc_n = strlen (elements_enc); + if (elements_enc_n != 1) + { + /* FIXME? */ + err = gcry_error (GPG_ERR_CONFLICT); + goto out; + } + + err = _gcry_ac_data_new (&data_encrypted); + if (err) + goto out; + + err = _gcry_ac_data_set (data_encrypted, GCRY_AC_FLAG_COPY | GCRY_AC_FLAG_DEALLOC, + elements_enc, mpi_encrypted); + if (err) + goto out; + + err = _gcry_ac_data_decrypt (handle, 0, key, &mpi_decrypted, data_encrypted); + if (err) + goto out; + + err = _gcry_ac_mpi_to_os_alloc (mpi_decrypted, &em, &em_n); + if (err) + goto out; + + err = ac_dencode_prepare (handle, key, opts, *scheme, &opts_em); + if (err) + goto out; + + _gcry_ac_io_init (&io_em, GCRY_AC_IO_READABLE, + GCRY_AC_IO_STRING, em, em_n); + + err = _gcry_ac_data_decode (scheme->scheme_encoding, 0, opts_em, + &io_em, io_message); + if (err) + goto out; + + out: + + _gcry_ac_data_destroy (data_encrypted); + gcry_mpi_release (mpi_encrypted); + gcry_mpi_release (mpi_decrypted); + free (elements_enc); + gcry_free (opts_em); + gcry_free (em); + gcry_free (c); + + return err; +} + + +/* Signs the message contained in M, which is of size M_N, with the + secret key KEY according to the Signature Scheme SCHEME_ID. Handle + is used for accessing the low-level cryptographic primitives. If + OPTS is not NULL, it has to be an anonymous structure specific to + the chosen scheme (gcry_ac_ssa_*_t). The signed message will be + stored in S and S_N. */ +gcry_error_t +_gcry_ac_data_sign_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme_id, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_signature) +{ + gcry_ac_io_t io_em; + gcry_error_t err; + gcry_ac_data_t data_signed; + unsigned char *em; + size_t em_n; + gcry_mpi_t mpi; + void *opts_em; + unsigned char *buffer; + size_t buffer_n; + gcry_mpi_t mpi_signed; + ac_scheme_t *scheme; + + (void)flags; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + data_signed = NULL; + mpi_signed = NULL; + opts_em = NULL; + buffer = NULL; + mpi = NULL; + em = NULL; + + if (key->type != GCRY_AC_KEY_SECRET) + { + err = gcry_error (GPG_ERR_WRONG_KEY_USAGE); + goto out; + } + + scheme = ac_scheme_get (scheme_id); + if (! scheme) + { + /* FIXME: adjust api of scheme_get in respect to err codes. */ + err = gcry_error (GPG_ERR_NO_SIGNATURE_SCHEME); + goto out; + } + + err = ac_dencode_prepare (handle, key, opts, *scheme, &opts_em); + if (err) + goto out; + + _gcry_ac_io_init (&io_em, GCRY_AC_IO_WRITABLE, + GCRY_AC_IO_STRING, &em, &em_n); + + err = _gcry_ac_data_encode (scheme->scheme_encoding, 0, opts_em, + io_message, &io_em); + if (err) + goto out; + + mpi = gcry_mpi_new (0); + _gcry_ac_os_to_mpi (mpi, em, em_n); + + err = _gcry_ac_data_sign (handle, key, mpi, &data_signed); + if (err) + goto out; + + err = ac_data_set_to_mpi (data_signed, &mpi_signed); + if (err) + goto out; + + err = _gcry_ac_mpi_to_os_alloc (mpi_signed, &buffer, &buffer_n); + if (err) + goto out; + + err = _gcry_ac_io_write (io_signature, buffer, buffer_n); + + out: + + _gcry_ac_data_destroy (data_signed); + gcry_mpi_release (mpi_signed); + gcry_mpi_release (mpi); + gcry_free (opts_em); + gcry_free (buffer); + gcry_free (em); + + return err; +} + +/* Verifies that the signature contained in S, which is of length S_N, + is indeed the result of signing the message contained in M, which + is of size M_N, with the secret key belonging to the public key + KEY_PUBLIC. If OPTS is not NULL, it has to be an anonymous + structure (gcry_ac_ssa_*_t) specific to the Signature Scheme, whose + ID is contained in SCHEME_ID. */ +gcry_error_t +_gcry_ac_data_verify_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme_id, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_signature) +{ + gcry_ac_io_t io_em; + gcry_error_t err; + gcry_ac_data_t data_signed; + unsigned char *em; + size_t em_n; + void *opts_em; + gcry_mpi_t mpi_signature; + gcry_mpi_t mpi_data; + ac_scheme_t *scheme; + char *elements_sig; + size_t elements_sig_n; + unsigned char *s; + size_t s_n; + + (void)flags; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + mpi_signature = NULL; + elements_sig = NULL; + data_signed = NULL; + mpi_data = NULL; + opts_em = NULL; + em = NULL; + s = NULL; + + if (key->type != GCRY_AC_KEY_PUBLIC) + { + err = gcry_error (GPG_ERR_WRONG_KEY_USAGE); + goto out; + } + + scheme = ac_scheme_get (scheme_id); + if (! scheme) + { + err = gcry_error (GPG_ERR_NO_SIGNATURE_SCHEME); + goto out; + } + + err = ac_dencode_prepare (handle, key, opts, *scheme, &opts_em); + if (err) + goto out; + + _gcry_ac_io_init (&io_em, GCRY_AC_IO_WRITABLE, + GCRY_AC_IO_STRING, &em, &em_n); + + err = _gcry_ac_data_encode (scheme->scheme_encoding, 0, opts_em, + io_message, &io_em); + if (err) + goto out; + + mpi_data = gcry_mpi_new (0); + _gcry_ac_os_to_mpi (mpi_data, em, em_n); + + err = _gcry_ac_io_read_all (io_signature, &s, &s_n); + if (err) + goto out; + + mpi_signature = gcry_mpi_new (0); + _gcry_ac_os_to_mpi (mpi_signature, s, s_n); + + err = _gcry_pk_get_elements (handle->algorithm, NULL, &elements_sig); + if (err) + goto out; + + elements_sig_n = strlen (elements_sig); + if (elements_sig_n != 1) + { + /* FIXME? */ + err = gcry_error (GPG_ERR_CONFLICT); + goto out; + } + + err = _gcry_ac_data_new (&data_signed); + if (err) + goto out; + + err = _gcry_ac_data_set (data_signed, GCRY_AC_FLAG_COPY | GCRY_AC_FLAG_DEALLOC, + elements_sig, mpi_signature); + if (err) + goto out; + + gcry_mpi_release (mpi_signature); + mpi_signature = NULL; + + err = _gcry_ac_data_verify (handle, key, mpi_data, data_signed); + + out: + + _gcry_ac_data_destroy (data_signed); + gcry_mpi_release (mpi_signature); + gcry_mpi_release (mpi_data); + free (elements_sig); + gcry_free (opts_em); + gcry_free (em); + gcry_free (s); + + return err; +} + + +/* + * General functions. + */ + +gcry_err_code_t +_gcry_ac_init (void) +{ + if (fips_mode ()) + return GPG_ERR_NOT_SUPPORTED; + + return 0; +} diff --git a/grub-core/lib/libgcrypt/cipher/arcfour.c b/grub-core/lib/libgcrypt/cipher/arcfour.c new file mode 100644 index 0000000..6ef07fb --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/arcfour.c @@ -0,0 +1,155 @@ +/* arcfour.c - The arcfour stream cipher + * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * For a description of the algorithm, see: + * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. + * ISBN 0-471-11709-9. Pages 397 ff. + */ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "types.h" +#include "g10lib.h" +#include "cipher.h" + +static const char *selftest(void); + +typedef struct { + int idx_i, idx_j; + byte sbox[256]; +} ARCFOUR_context; + +static void +do_encrypt_stream( ARCFOUR_context *ctx, + byte *outbuf, const byte *inbuf, unsigned int length ) +{ + register int i = ctx->idx_i; + register int j = ctx->idx_j; + register byte *sbox = ctx->sbox; + register int t; + + while ( length-- ) + { + i++; + i = i & 255; /* The and-op seems to be faster than the mod-op. */ + j += sbox[i]; + j &= 255; + t = sbox[i]; sbox[i] = sbox[j]; sbox[j] = t; + *outbuf++ = *inbuf++ ^ sbox[(sbox[i] + sbox[j]) & 255]; + } + + ctx->idx_i = i; + ctx->idx_j = j; +} + +static void +encrypt_stream (void *context, + byte *outbuf, const byte *inbuf, unsigned int length) +{ + ARCFOUR_context *ctx = (ARCFOUR_context *) context; + do_encrypt_stream (ctx, outbuf, inbuf, length ); + _gcry_burn_stack (64); +} + + +static gcry_err_code_t +do_arcfour_setkey (void *context, const byte *key, unsigned int keylen) +{ + static int initialized; + static const char* selftest_failed; + int i, j; + byte karr[256]; + ARCFOUR_context *ctx = (ARCFOUR_context *) context; + + if (!initialized ) + { + initialized = 1; + selftest_failed = selftest(); + if( selftest_failed ) + log_error ("ARCFOUR selftest failed (%s)\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + if( keylen < 40/8 ) /* we want at least 40 bits */ + return GPG_ERR_INV_KEYLEN; + + ctx->idx_i = ctx->idx_j = 0; + for (i=0; i < 256; i++ ) + ctx->sbox[i] = i; + for (i=0; i < 256; i++ ) + karr[i] = key[i%keylen]; + for (i=j=0; i < 256; i++ ) + { + int t; + j = (j + ctx->sbox[i] + karr[i]) % 256; + t = ctx->sbox[i]; + ctx->sbox[i] = ctx->sbox[j]; + ctx->sbox[j] = t; + } + memset( karr, 0, 256 ); + + return GPG_ERR_NO_ERROR; +} + +static gcry_err_code_t +arcfour_setkey ( void *context, const byte *key, unsigned int keylen ) +{ + ARCFOUR_context *ctx = (ARCFOUR_context *) context; + gcry_err_code_t rc = do_arcfour_setkey (ctx, key, keylen ); + _gcry_burn_stack (300); + return rc; +} + + +static const char* +selftest(void) +{ + ARCFOUR_context ctx; + byte scratch[16]; + + /* Test vector from Cryptlib labeled there: "from the + State/Commerce Department". */ + static byte key_1[] = + { 0x61, 0x8A, 0x63, 0xD2, 0xFB }; + static byte plaintext_1[] = + { 0xDC, 0xEE, 0x4C, 0xF9, 0x2C }; + static const byte ciphertext_1[] = + { 0xF1, 0x38, 0x29, 0xC9, 0xDE }; + + arcfour_setkey( &ctx, key_1, sizeof(key_1)); + encrypt_stream( &ctx, scratch, plaintext_1, sizeof(plaintext_1)); + if ( memcmp (scratch, ciphertext_1, sizeof (ciphertext_1))) + return "Arcfour encryption test 1 failed."; + arcfour_setkey( &ctx, key_1, sizeof(key_1)); + encrypt_stream(&ctx, scratch, scratch, sizeof(plaintext_1)); /* decrypt */ + if ( memcmp (scratch, plaintext_1, sizeof (plaintext_1))) + return "Arcfour decryption test 1 failed."; + return NULL; +} + + +gcry_cipher_spec_t _gcry_cipher_spec_arcfour = + { + "ARCFOUR", NULL, NULL, 1, 128, sizeof (ARCFOUR_context), + arcfour_setkey, NULL, NULL, encrypt_stream, encrypt_stream, + }; diff --git a/grub-core/lib/libgcrypt/cipher/bithelp.h b/grub-core/lib/libgcrypt/cipher/bithelp.h new file mode 100644 index 0000000..1505324 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/bithelp.h @@ -0,0 +1,54 @@ +/* bithelp.h - Some bit manipulation helpers + * Copyright (C) 1999, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef G10_BITHELP_H +#define G10_BITHELP_H + + +/**************** + * Rotate the 32 bit unsigned integer X by N bits left/right + */ +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +rol( u32 x, int n) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else +#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +ror(u32 x, int n) +{ + __asm__("rorl %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else +#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) +#endif + + +#endif /*G10_BITHELP_H*/ diff --git a/grub-core/lib/libgcrypt/cipher/blowfish.c b/grub-core/lib/libgcrypt/cipher/blowfish.c new file mode 100644 index 0000000..b4d2b9c --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/blowfish.c @@ -0,0 +1,605 @@ +/* blowfish.c - Blowfish encryption + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * For a description of the algorithm, see: + * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. + * ISBN 0-471-11709-9. Pages 336 ff. + */ + +/* Test values: + * key "abcdefghijklmnopqrstuvwxyz"; + * plain "BLOWFISH" + * cipher 32 4E D0 FE F4 13 A2 03 + * + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "types.h" +#include "g10lib.h" +#include "cipher.h" + +#define BLOWFISH_BLOCKSIZE 8 +#define BLOWFISH_ROUNDS 16 + +typedef struct { + u32 s0[256]; + u32 s1[256]; + u32 s2[256]; + u32 s3[256]; + u32 p[BLOWFISH_ROUNDS+2]; +} BLOWFISH_context; + +static gcry_err_code_t bf_setkey (void *c, const byte *key, unsigned keylen); +static void encrypt_block (void *bc, byte *outbuf, const byte *inbuf); +static void decrypt_block (void *bc, byte *outbuf, const byte *inbuf); + + +/* precomputed S boxes */ +static const u32 ks0[256] = { + 0xD1310BA6,0x98DFB5AC,0x2FFD72DB,0xD01ADFB7,0xB8E1AFED,0x6A267E96, + 0xBA7C9045,0xF12C7F99,0x24A19947,0xB3916CF7,0x0801F2E2,0x858EFC16, + 0x636920D8,0x71574E69,0xA458FEA3,0xF4933D7E,0x0D95748F,0x728EB658, + 0x718BCD58,0x82154AEE,0x7B54A41D,0xC25A59B5,0x9C30D539,0x2AF26013, + 0xC5D1B023,0x286085F0,0xCA417918,0xB8DB38EF,0x8E79DCB0,0x603A180E, + 0x6C9E0E8B,0xB01E8A3E,0xD71577C1,0xBD314B27,0x78AF2FDA,0x55605C60, + 0xE65525F3,0xAA55AB94,0x57489862,0x63E81440,0x55CA396A,0x2AAB10B6, + 0xB4CC5C34,0x1141E8CE,0xA15486AF,0x7C72E993,0xB3EE1411,0x636FBC2A, + 0x2BA9C55D,0x741831F6,0xCE5C3E16,0x9B87931E,0xAFD6BA33,0x6C24CF5C, + 0x7A325381,0x28958677,0x3B8F4898,0x6B4BB9AF,0xC4BFE81B,0x66282193, + 0x61D809CC,0xFB21A991,0x487CAC60,0x5DEC8032,0xEF845D5D,0xE98575B1, + 0xDC262302,0xEB651B88,0x23893E81,0xD396ACC5,0x0F6D6FF3,0x83F44239, + 0x2E0B4482,0xA4842004,0x69C8F04A,0x9E1F9B5E,0x21C66842,0xF6E96C9A, + 0x670C9C61,0xABD388F0,0x6A51A0D2,0xD8542F68,0x960FA728,0xAB5133A3, + 0x6EEF0B6C,0x137A3BE4,0xBA3BF050,0x7EFB2A98,0xA1F1651D,0x39AF0176, + 0x66CA593E,0x82430E88,0x8CEE8619,0x456F9FB4,0x7D84A5C3,0x3B8B5EBE, + 0xE06F75D8,0x85C12073,0x401A449F,0x56C16AA6,0x4ED3AA62,0x363F7706, + 0x1BFEDF72,0x429B023D,0x37D0D724,0xD00A1248,0xDB0FEAD3,0x49F1C09B, + 0x075372C9,0x80991B7B,0x25D479D8,0xF6E8DEF7,0xE3FE501A,0xB6794C3B, + 0x976CE0BD,0x04C006BA,0xC1A94FB6,0x409F60C4,0x5E5C9EC2,0x196A2463, + 0x68FB6FAF,0x3E6C53B5,0x1339B2EB,0x3B52EC6F,0x6DFC511F,0x9B30952C, + 0xCC814544,0xAF5EBD09,0xBEE3D004,0xDE334AFD,0x660F2807,0x192E4BB3, + 0xC0CBA857,0x45C8740F,0xD20B5F39,0xB9D3FBDB,0x5579C0BD,0x1A60320A, + 0xD6A100C6,0x402C7279,0x679F25FE,0xFB1FA3CC,0x8EA5E9F8,0xDB3222F8, + 0x3C7516DF,0xFD616B15,0x2F501EC8,0xAD0552AB,0x323DB5FA,0xFD238760, + 0x53317B48,0x3E00DF82,0x9E5C57BB,0xCA6F8CA0,0x1A87562E,0xDF1769DB, + 0xD542A8F6,0x287EFFC3,0xAC6732C6,0x8C4F5573,0x695B27B0,0xBBCA58C8, + 0xE1FFA35D,0xB8F011A0,0x10FA3D98,0xFD2183B8,0x4AFCB56C,0x2DD1D35B, + 0x9A53E479,0xB6F84565,0xD28E49BC,0x4BFB9790,0xE1DDF2DA,0xA4CB7E33, + 0x62FB1341,0xCEE4C6E8,0xEF20CADA,0x36774C01,0xD07E9EFE,0x2BF11FB4, + 0x95DBDA4D,0xAE909198,0xEAAD8E71,0x6B93D5A0,0xD08ED1D0,0xAFC725E0, + 0x8E3C5B2F,0x8E7594B7,0x8FF6E2FB,0xF2122B64,0x8888B812,0x900DF01C, + 0x4FAD5EA0,0x688FC31C,0xD1CFF191,0xB3A8C1AD,0x2F2F2218,0xBE0E1777, + 0xEA752DFE,0x8B021FA1,0xE5A0CC0F,0xB56F74E8,0x18ACF3D6,0xCE89E299, + 0xB4A84FE0,0xFD13E0B7,0x7CC43B81,0xD2ADA8D9,0x165FA266,0x80957705, + 0x93CC7314,0x211A1477,0xE6AD2065,0x77B5FA86,0xC75442F5,0xFB9D35CF, + 0xEBCDAF0C,0x7B3E89A0,0xD6411BD3,0xAE1E7E49,0x00250E2D,0x2071B35E, + 0x226800BB,0x57B8E0AF,0x2464369B,0xF009B91E,0x5563911D,0x59DFA6AA, + 0x78C14389,0xD95A537F,0x207D5BA2,0x02E5B9C5,0x83260376,0x6295CFA9, + 0x11C81968,0x4E734A41,0xB3472DCA,0x7B14A94A,0x1B510052,0x9A532915, + 0xD60F573F,0xBC9BC6E4,0x2B60A476,0x81E67400,0x08BA6FB5,0x571BE91F, + 0xF296EC6B,0x2A0DD915,0xB6636521,0xE7B9F9B6,0xFF34052E,0xC5855664, + 0x53B02D5D,0xA99F8FA1,0x08BA4799,0x6E85076A }; + +static const u32 ks1[256] = { + 0x4B7A70E9,0xB5B32944,0xDB75092E,0xC4192623,0xAD6EA6B0,0x49A7DF7D, + 0x9CEE60B8,0x8FEDB266,0xECAA8C71,0x699A17FF,0x5664526C,0xC2B19EE1, + 0x193602A5,0x75094C29,0xA0591340,0xE4183A3E,0x3F54989A,0x5B429D65, + 0x6B8FE4D6,0x99F73FD6,0xA1D29C07,0xEFE830F5,0x4D2D38E6,0xF0255DC1, + 0x4CDD2086,0x8470EB26,0x6382E9C6,0x021ECC5E,0x09686B3F,0x3EBAEFC9, + 0x3C971814,0x6B6A70A1,0x687F3584,0x52A0E286,0xB79C5305,0xAA500737, + 0x3E07841C,0x7FDEAE5C,0x8E7D44EC,0x5716F2B8,0xB03ADA37,0xF0500C0D, + 0xF01C1F04,0x0200B3FF,0xAE0CF51A,0x3CB574B2,0x25837A58,0xDC0921BD, + 0xD19113F9,0x7CA92FF6,0x94324773,0x22F54701,0x3AE5E581,0x37C2DADC, + 0xC8B57634,0x9AF3DDA7,0xA9446146,0x0FD0030E,0xECC8C73E,0xA4751E41, + 0xE238CD99,0x3BEA0E2F,0x3280BBA1,0x183EB331,0x4E548B38,0x4F6DB908, + 0x6F420D03,0xF60A04BF,0x2CB81290,0x24977C79,0x5679B072,0xBCAF89AF, + 0xDE9A771F,0xD9930810,0xB38BAE12,0xDCCF3F2E,0x5512721F,0x2E6B7124, + 0x501ADDE6,0x9F84CD87,0x7A584718,0x7408DA17,0xBC9F9ABC,0xE94B7D8C, + 0xEC7AEC3A,0xDB851DFA,0x63094366,0xC464C3D2,0xEF1C1847,0x3215D908, + 0xDD433B37,0x24C2BA16,0x12A14D43,0x2A65C451,0x50940002,0x133AE4DD, + 0x71DFF89E,0x10314E55,0x81AC77D6,0x5F11199B,0x043556F1,0xD7A3C76B, + 0x3C11183B,0x5924A509,0xF28FE6ED,0x97F1FBFA,0x9EBABF2C,0x1E153C6E, + 0x86E34570,0xEAE96FB1,0x860E5E0A,0x5A3E2AB3,0x771FE71C,0x4E3D06FA, + 0x2965DCB9,0x99E71D0F,0x803E89D6,0x5266C825,0x2E4CC978,0x9C10B36A, + 0xC6150EBA,0x94E2EA78,0xA5FC3C53,0x1E0A2DF4,0xF2F74EA7,0x361D2B3D, + 0x1939260F,0x19C27960,0x5223A708,0xF71312B6,0xEBADFE6E,0xEAC31F66, + 0xE3BC4595,0xA67BC883,0xB17F37D1,0x018CFF28,0xC332DDEF,0xBE6C5AA5, + 0x65582185,0x68AB9802,0xEECEA50F,0xDB2F953B,0x2AEF7DAD,0x5B6E2F84, + 0x1521B628,0x29076170,0xECDD4775,0x619F1510,0x13CCA830,0xEB61BD96, + 0x0334FE1E,0xAA0363CF,0xB5735C90,0x4C70A239,0xD59E9E0B,0xCBAADE14, + 0xEECC86BC,0x60622CA7,0x9CAB5CAB,0xB2F3846E,0x648B1EAF,0x19BDF0CA, + 0xA02369B9,0x655ABB50,0x40685A32,0x3C2AB4B3,0x319EE9D5,0xC021B8F7, + 0x9B540B19,0x875FA099,0x95F7997E,0x623D7DA8,0xF837889A,0x97E32D77, + 0x11ED935F,0x16681281,0x0E358829,0xC7E61FD6,0x96DEDFA1,0x7858BA99, + 0x57F584A5,0x1B227263,0x9B83C3FF,0x1AC24696,0xCDB30AEB,0x532E3054, + 0x8FD948E4,0x6DBC3128,0x58EBF2EF,0x34C6FFEA,0xFE28ED61,0xEE7C3C73, + 0x5D4A14D9,0xE864B7E3,0x42105D14,0x203E13E0,0x45EEE2B6,0xA3AAABEA, + 0xDB6C4F15,0xFACB4FD0,0xC742F442,0xEF6ABBB5,0x654F3B1D,0x41CD2105, + 0xD81E799E,0x86854DC7,0xE44B476A,0x3D816250,0xCF62A1F2,0x5B8D2646, + 0xFC8883A0,0xC1C7B6A3,0x7F1524C3,0x69CB7492,0x47848A0B,0x5692B285, + 0x095BBF00,0xAD19489D,0x1462B174,0x23820E00,0x58428D2A,0x0C55F5EA, + 0x1DADF43E,0x233F7061,0x3372F092,0x8D937E41,0xD65FECF1,0x6C223BDB, + 0x7CDE3759,0xCBEE7460,0x4085F2A7,0xCE77326E,0xA6078084,0x19F8509E, + 0xE8EFD855,0x61D99735,0xA969A7AA,0xC50C06C2,0x5A04ABFC,0x800BCADC, + 0x9E447A2E,0xC3453484,0xFDD56705,0x0E1E9EC9,0xDB73DBD3,0x105588CD, + 0x675FDA79,0xE3674340,0xC5C43465,0x713E38D8,0x3D28F89E,0xF16DFF20, + 0x153E21E7,0x8FB03D4A,0xE6E39F2B,0xDB83ADF7 }; + +static const u32 ks2[256] = { + 0xE93D5A68,0x948140F7,0xF64C261C,0x94692934,0x411520F7,0x7602D4F7, + 0xBCF46B2E,0xD4A20068,0xD4082471,0x3320F46A,0x43B7D4B7,0x500061AF, + 0x1E39F62E,0x97244546,0x14214F74,0xBF8B8840,0x4D95FC1D,0x96B591AF, + 0x70F4DDD3,0x66A02F45,0xBFBC09EC,0x03BD9785,0x7FAC6DD0,0x31CB8504, + 0x96EB27B3,0x55FD3941,0xDA2547E6,0xABCA0A9A,0x28507825,0x530429F4, + 0x0A2C86DA,0xE9B66DFB,0x68DC1462,0xD7486900,0x680EC0A4,0x27A18DEE, + 0x4F3FFEA2,0xE887AD8C,0xB58CE006,0x7AF4D6B6,0xAACE1E7C,0xD3375FEC, + 0xCE78A399,0x406B2A42,0x20FE9E35,0xD9F385B9,0xEE39D7AB,0x3B124E8B, + 0x1DC9FAF7,0x4B6D1856,0x26A36631,0xEAE397B2,0x3A6EFA74,0xDD5B4332, + 0x6841E7F7,0xCA7820FB,0xFB0AF54E,0xD8FEB397,0x454056AC,0xBA489527, + 0x55533A3A,0x20838D87,0xFE6BA9B7,0xD096954B,0x55A867BC,0xA1159A58, + 0xCCA92963,0x99E1DB33,0xA62A4A56,0x3F3125F9,0x5EF47E1C,0x9029317C, + 0xFDF8E802,0x04272F70,0x80BB155C,0x05282CE3,0x95C11548,0xE4C66D22, + 0x48C1133F,0xC70F86DC,0x07F9C9EE,0x41041F0F,0x404779A4,0x5D886E17, + 0x325F51EB,0xD59BC0D1,0xF2BCC18F,0x41113564,0x257B7834,0x602A9C60, + 0xDFF8E8A3,0x1F636C1B,0x0E12B4C2,0x02E1329E,0xAF664FD1,0xCAD18115, + 0x6B2395E0,0x333E92E1,0x3B240B62,0xEEBEB922,0x85B2A20E,0xE6BA0D99, + 0xDE720C8C,0x2DA2F728,0xD0127845,0x95B794FD,0x647D0862,0xE7CCF5F0, + 0x5449A36F,0x877D48FA,0xC39DFD27,0xF33E8D1E,0x0A476341,0x992EFF74, + 0x3A6F6EAB,0xF4F8FD37,0xA812DC60,0xA1EBDDF8,0x991BE14C,0xDB6E6B0D, + 0xC67B5510,0x6D672C37,0x2765D43B,0xDCD0E804,0xF1290DC7,0xCC00FFA3, + 0xB5390F92,0x690FED0B,0x667B9FFB,0xCEDB7D9C,0xA091CF0B,0xD9155EA3, + 0xBB132F88,0x515BAD24,0x7B9479BF,0x763BD6EB,0x37392EB3,0xCC115979, + 0x8026E297,0xF42E312D,0x6842ADA7,0xC66A2B3B,0x12754CCC,0x782EF11C, + 0x6A124237,0xB79251E7,0x06A1BBE6,0x4BFB6350,0x1A6B1018,0x11CAEDFA, + 0x3D25BDD8,0xE2E1C3C9,0x44421659,0x0A121386,0xD90CEC6E,0xD5ABEA2A, + 0x64AF674E,0xDA86A85F,0xBEBFE988,0x64E4C3FE,0x9DBC8057,0xF0F7C086, + 0x60787BF8,0x6003604D,0xD1FD8346,0xF6381FB0,0x7745AE04,0xD736FCCC, + 0x83426B33,0xF01EAB71,0xB0804187,0x3C005E5F,0x77A057BE,0xBDE8AE24, + 0x55464299,0xBF582E61,0x4E58F48F,0xF2DDFDA2,0xF474EF38,0x8789BDC2, + 0x5366F9C3,0xC8B38E74,0xB475F255,0x46FCD9B9,0x7AEB2661,0x8B1DDF84, + 0x846A0E79,0x915F95E2,0x466E598E,0x20B45770,0x8CD55591,0xC902DE4C, + 0xB90BACE1,0xBB8205D0,0x11A86248,0x7574A99E,0xB77F19B6,0xE0A9DC09, + 0x662D09A1,0xC4324633,0xE85A1F02,0x09F0BE8C,0x4A99A025,0x1D6EFE10, + 0x1AB93D1D,0x0BA5A4DF,0xA186F20F,0x2868F169,0xDCB7DA83,0x573906FE, + 0xA1E2CE9B,0x4FCD7F52,0x50115E01,0xA70683FA,0xA002B5C4,0x0DE6D027, + 0x9AF88C27,0x773F8641,0xC3604C06,0x61A806B5,0xF0177A28,0xC0F586E0, + 0x006058AA,0x30DC7D62,0x11E69ED7,0x2338EA63,0x53C2DD94,0xC2C21634, + 0xBBCBEE56,0x90BCB6DE,0xEBFC7DA1,0xCE591D76,0x6F05E409,0x4B7C0188, + 0x39720A3D,0x7C927C24,0x86E3725F,0x724D9DB9,0x1AC15BB4,0xD39EB8FC, + 0xED545578,0x08FCA5B5,0xD83D7CD3,0x4DAD0FC4,0x1E50EF5E,0xB161E6F8, + 0xA28514D9,0x6C51133C,0x6FD5C7E7,0x56E14EC4,0x362ABFCE,0xDDC6C837, + 0xD79A3234,0x92638212,0x670EFA8E,0x406000E0 }; + +static const u32 ks3[256] = { + 0x3A39CE37,0xD3FAF5CF,0xABC27737,0x5AC52D1B,0x5CB0679E,0x4FA33742, + 0xD3822740,0x99BC9BBE,0xD5118E9D,0xBF0F7315,0xD62D1C7E,0xC700C47B, + 0xB78C1B6B,0x21A19045,0xB26EB1BE,0x6A366EB4,0x5748AB2F,0xBC946E79, + 0xC6A376D2,0x6549C2C8,0x530FF8EE,0x468DDE7D,0xD5730A1D,0x4CD04DC6, + 0x2939BBDB,0xA9BA4650,0xAC9526E8,0xBE5EE304,0xA1FAD5F0,0x6A2D519A, + 0x63EF8CE2,0x9A86EE22,0xC089C2B8,0x43242EF6,0xA51E03AA,0x9CF2D0A4, + 0x83C061BA,0x9BE96A4D,0x8FE51550,0xBA645BD6,0x2826A2F9,0xA73A3AE1, + 0x4BA99586,0xEF5562E9,0xC72FEFD3,0xF752F7DA,0x3F046F69,0x77FA0A59, + 0x80E4A915,0x87B08601,0x9B09E6AD,0x3B3EE593,0xE990FD5A,0x9E34D797, + 0x2CF0B7D9,0x022B8B51,0x96D5AC3A,0x017DA67D,0xD1CF3ED6,0x7C7D2D28, + 0x1F9F25CF,0xADF2B89B,0x5AD6B472,0x5A88F54C,0xE029AC71,0xE019A5E6, + 0x47B0ACFD,0xED93FA9B,0xE8D3C48D,0x283B57CC,0xF8D56629,0x79132E28, + 0x785F0191,0xED756055,0xF7960E44,0xE3D35E8C,0x15056DD4,0x88F46DBA, + 0x03A16125,0x0564F0BD,0xC3EB9E15,0x3C9057A2,0x97271AEC,0xA93A072A, + 0x1B3F6D9B,0x1E6321F5,0xF59C66FB,0x26DCF319,0x7533D928,0xB155FDF5, + 0x03563482,0x8ABA3CBB,0x28517711,0xC20AD9F8,0xABCC5167,0xCCAD925F, + 0x4DE81751,0x3830DC8E,0x379D5862,0x9320F991,0xEA7A90C2,0xFB3E7BCE, + 0x5121CE64,0x774FBE32,0xA8B6E37E,0xC3293D46,0x48DE5369,0x6413E680, + 0xA2AE0810,0xDD6DB224,0x69852DFD,0x09072166,0xB39A460A,0x6445C0DD, + 0x586CDECF,0x1C20C8AE,0x5BBEF7DD,0x1B588D40,0xCCD2017F,0x6BB4E3BB, + 0xDDA26A7E,0x3A59FF45,0x3E350A44,0xBCB4CDD5,0x72EACEA8,0xFA6484BB, + 0x8D6612AE,0xBF3C6F47,0xD29BE463,0x542F5D9E,0xAEC2771B,0xF64E6370, + 0x740E0D8D,0xE75B1357,0xF8721671,0xAF537D5D,0x4040CB08,0x4EB4E2CC, + 0x34D2466A,0x0115AF84,0xE1B00428,0x95983A1D,0x06B89FB4,0xCE6EA048, + 0x6F3F3B82,0x3520AB82,0x011A1D4B,0x277227F8,0x611560B1,0xE7933FDC, + 0xBB3A792B,0x344525BD,0xA08839E1,0x51CE794B,0x2F32C9B7,0xA01FBAC9, + 0xE01CC87E,0xBCC7D1F6,0xCF0111C3,0xA1E8AAC7,0x1A908749,0xD44FBD9A, + 0xD0DADECB,0xD50ADA38,0x0339C32A,0xC6913667,0x8DF9317C,0xE0B12B4F, + 0xF79E59B7,0x43F5BB3A,0xF2D519FF,0x27D9459C,0xBF97222C,0x15E6FC2A, + 0x0F91FC71,0x9B941525,0xFAE59361,0xCEB69CEB,0xC2A86459,0x12BAA8D1, + 0xB6C1075E,0xE3056A0C,0x10D25065,0xCB03A442,0xE0EC6E0E,0x1698DB3B, + 0x4C98A0BE,0x3278E964,0x9F1F9532,0xE0D392DF,0xD3A0342B,0x8971F21E, + 0x1B0A7441,0x4BA3348C,0xC5BE7120,0xC37632D8,0xDF359F8D,0x9B992F2E, + 0xE60B6F47,0x0FE3F11D,0xE54CDA54,0x1EDAD891,0xCE6279CF,0xCD3E7E6F, + 0x1618B166,0xFD2C1D05,0x848FD2C5,0xF6FB2299,0xF523F357,0xA6327623, + 0x93A83531,0x56CCCD02,0xACF08162,0x5A75EBB5,0x6E163697,0x88D273CC, + 0xDE966292,0x81B949D0,0x4C50901B,0x71C65614,0xE6C6C7BD,0x327A140A, + 0x45E1D006,0xC3F27B9A,0xC9AA53FD,0x62A80F00,0xBB25BFE2,0x35BDD2F6, + 0x71126905,0xB2040222,0xB6CBCF7C,0xCD769C2B,0x53113EC0,0x1640E3D3, + 0x38ABBD60,0x2547ADF0,0xBA38209C,0xF746CE76,0x77AFA1C5,0x20756060, + 0x85CBFE4E,0x8AE88DD8,0x7AAAF9B0,0x4CF9AA7E,0x1948C25C,0x02FB8A8C, + 0x01C36AE4,0xD6EBE1F9,0x90D4F869,0xA65CDEA0,0x3F09252D,0xC208E69F, + 0xB74E6132,0xCE77E25B,0x578FDFE3,0x3AC372E6 }; + +static const u32 ps[BLOWFISH_ROUNDS+2] = { + 0x243F6A88,0x85A308D3,0x13198A2E,0x03707344,0xA4093822,0x299F31D0, + 0x082EFA98,0xEC4E6C89,0x452821E6,0x38D01377,0xBE5466CF,0x34E90C6C, + 0xC0AC29B7,0xC97C50DD,0x3F84D5B5,0xB5470917,0x9216D5D9,0x8979FB1B }; + + + +#if BLOWFISH_ROUNDS != 16 +static inline u32 +function_F( BLOWFISH_context *bc, u32 x ) +{ + u16 a, b, c, d; + +#ifdef WORDS_BIGENDIAN + a = ((byte*)&x)[0]; + b = ((byte*)&x)[1]; + c = ((byte*)&x)[2]; + d = ((byte*)&x)[3]; +#else + a = ((byte*)&x)[3]; + b = ((byte*)&x)[2]; + c = ((byte*)&x)[1]; + d = ((byte*)&x)[0]; +#endif + + return ((bc->s0[a] + bc->s1[b]) ^ bc->s2[c] ) + bc->s3[d]; +} +#endif + +#ifdef WORDS_BIGENDIAN +#define F(x) ((( s0[((byte*)&x)[0]] + s1[((byte*)&x)[1]]) \ + ^ s2[((byte*)&x)[2]]) + s3[((byte*)&x)[3]] ) +#else +#define F(x) ((( s0[((byte*)&x)[3]] + s1[((byte*)&x)[2]]) \ + ^ s2[((byte*)&x)[1]]) + s3[((byte*)&x)[0]] ) +#endif +#define R(l,r,i) do { l ^= p[i]; r ^= F(l); } while(0) + + +static void +do_encrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) +{ +#if BLOWFISH_ROUNDS == 16 + u32 xl, xr, *s0, *s1, *s2, *s3, *p; + + xl = *ret_xl; + xr = *ret_xr; + p = bc->p; + s0 = bc->s0; + s1 = bc->s1; + s2 = bc->s2; + s3 = bc->s3; + + R( xl, xr, 0); + R( xr, xl, 1); + R( xl, xr, 2); + R( xr, xl, 3); + R( xl, xr, 4); + R( xr, xl, 5); + R( xl, xr, 6); + R( xr, xl, 7); + R( xl, xr, 8); + R( xr, xl, 9); + R( xl, xr, 10); + R( xr, xl, 11); + R( xl, xr, 12); + R( xr, xl, 13); + R( xl, xr, 14); + R( xr, xl, 15); + + xl ^= p[BLOWFISH_ROUNDS]; + xr ^= p[BLOWFISH_ROUNDS+1]; + + *ret_xl = xr; + *ret_xr = xl; + +#else + u32 xl, xr, temp, *p; + int i; + + xl = *ret_xl; + xr = *ret_xr; + p = bc->p; + + for(i=0; i < BLOWFISH_ROUNDS; i++ ) + { + xl ^= p[i]; + xr ^= function_F(bc, xl); + temp = xl; + xl = xr; + xr = temp; + } + temp = xl; + xl = xr; + xr = temp; + + xr ^= p[BLOWFISH_ROUNDS]; + xl ^= p[BLOWFISH_ROUNDS+1]; + + *ret_xl = xl; + *ret_xr = xr; +#endif +} + + +static void +decrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) +{ +#if BLOWFISH_ROUNDS == 16 + u32 xl, xr, *s0, *s1, *s2, *s3, *p; + + xl = *ret_xl; + xr = *ret_xr; + p = bc->p; + s0 = bc->s0; + s1 = bc->s1; + s2 = bc->s2; + s3 = bc->s3; + + R( xl, xr, 17); + R( xr, xl, 16); + R( xl, xr, 15); + R( xr, xl, 14); + R( xl, xr, 13); + R( xr, xl, 12); + R( xl, xr, 11); + R( xr, xl, 10); + R( xl, xr, 9); + R( xr, xl, 8); + R( xl, xr, 7); + R( xr, xl, 6); + R( xl, xr, 5); + R( xr, xl, 4); + R( xl, xr, 3); + R( xr, xl, 2); + + xl ^= p[1]; + xr ^= p[0]; + + *ret_xl = xr; + *ret_xr = xl; + +#else + u32 xl, xr, temp, *p; + int i; + + xl = *ret_xl; + xr = *ret_xr; + p = bc->p; + + for (i=BLOWFISH_ROUNDS+1; i > 1; i-- ) + { + xl ^= p[i]; + xr ^= function_F(bc, xl); + temp = xl; + xl = xr; + xr = temp; + } + + temp = xl; + xl = xr; + xr = temp; + + xr ^= p[1]; + xl ^= p[0]; + + *ret_xl = xl; + *ret_xr = xr; +#endif +} + +#undef F +#undef R + +static void +do_encrypt_block ( BLOWFISH_context *bc, byte *outbuf, const byte *inbuf ) +{ + u32 d1, d2; + + d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + do_encrypt( bc, &d1, &d2 ); + outbuf[0] = (d1 >> 24) & 0xff; + outbuf[1] = (d1 >> 16) & 0xff; + outbuf[2] = (d1 >> 8) & 0xff; + outbuf[3] = d1 & 0xff; + outbuf[4] = (d2 >> 24) & 0xff; + outbuf[5] = (d2 >> 16) & 0xff; + outbuf[6] = (d2 >> 8) & 0xff; + outbuf[7] = d2 & 0xff; +} + +static void +encrypt_block (void *context, byte *outbuf, const byte *inbuf) +{ + BLOWFISH_context *bc = (BLOWFISH_context *) context; + do_encrypt_block (bc, outbuf, inbuf); + _gcry_burn_stack (64); +} + + +static void +do_decrypt_block (BLOWFISH_context *bc, byte *outbuf, const byte *inbuf) +{ + u32 d1, d2; + + d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + decrypt( bc, &d1, &d2 ); + outbuf[0] = (d1 >> 24) & 0xff; + outbuf[1] = (d1 >> 16) & 0xff; + outbuf[2] = (d1 >> 8) & 0xff; + outbuf[3] = d1 & 0xff; + outbuf[4] = (d2 >> 24) & 0xff; + outbuf[5] = (d2 >> 16) & 0xff; + outbuf[6] = (d2 >> 8) & 0xff; + outbuf[7] = d2 & 0xff; +} + +static void +decrypt_block (void *context, byte *outbuf, const byte *inbuf) +{ + BLOWFISH_context *bc = (BLOWFISH_context *) context; + do_decrypt_block (bc, outbuf, inbuf); + _gcry_burn_stack (64); +} + + +static const char* +selftest(void) +{ + BLOWFISH_context c; + byte plain[] = "BLOWFISH"; + byte buffer[8]; + byte plain3[] = { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }; + byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 }; + byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 }; + + bf_setkey( (void *) &c, + (const unsigned char*)"abcdefghijklmnopqrstuvwxyz", 26 ); + encrypt_block( (void *) &c, buffer, plain ); + if( memcmp( buffer, "\x32\x4E\xD0\xFE\xF4\x13\xA2\x03", 8 ) ) + return "Blowfish selftest failed (1)."; + decrypt_block( (void *) &c, buffer, buffer ); + if( memcmp( buffer, plain, 8 ) ) + return "Blowfish selftest failed (2)."; + + bf_setkey( (void *) &c, key3, 8 ); + encrypt_block( (void *) &c, buffer, plain3 ); + if( memcmp( buffer, cipher3, 8 ) ) + return "Blowfish selftest failed (3)."; + decrypt_block( (void *) &c, buffer, buffer ); + if( memcmp( buffer, plain3, 8 ) ) + return "Blowfish selftest failed (4)."; + return NULL; +} + + + +static gcry_err_code_t +do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) +{ + int i, j; + u32 data, datal, datar; + static int initialized; + static const char *selftest_failed; + + if( !initialized ) + { + initialized = 1; + selftest_failed = selftest(); + if( selftest_failed ) + log_error ("%s\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + for(i=0; i < BLOWFISH_ROUNDS+2; i++ ) + c->p[i] = ps[i]; + for(i=0; i < 256; i++ ) + { + c->s0[i] = ks0[i]; + c->s1[i] = ks1[i]; + c->s2[i] = ks2[i]; + c->s3[i] = ks3[i]; + } + + for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) + { +#ifdef WORDS_BIGENDIAN + ((byte*)&data)[0] = key[j]; + ((byte*)&data)[1] = key[(j+1)%keylen]; + ((byte*)&data)[2] = key[(j+2)%keylen]; + ((byte*)&data)[3] = key[(j+3)%keylen]; +#else + ((byte*)&data)[3] = key[j]; + ((byte*)&data)[2] = key[(j+1)%keylen]; + ((byte*)&data)[1] = key[(j+2)%keylen]; + ((byte*)&data)[0] = key[(j+3)%keylen]; +#endif + c->p[i] ^= data; + j = (j+4) % keylen; + } + + datal = datar = 0; + for(i=0; i < BLOWFISH_ROUNDS+2; i += 2 ) + { + do_encrypt( c, &datal, &datar ); + c->p[i] = datal; + c->p[i+1] = datar; + } + for(i=0; i < 256; i += 2 ) + { + do_encrypt( c, &datal, &datar ); + c->s0[i] = datal; + c->s0[i+1] = datar; + } + for(i=0; i < 256; i += 2 ) + { + do_encrypt( c, &datal, &datar ); + c->s1[i] = datal; + c->s1[i+1] = datar; + } + for(i=0; i < 256; i += 2 ) + { + do_encrypt( c, &datal, &datar ); + c->s2[i] = datal; + c->s2[i+1] = datar; + } + for(i=0; i < 256; i += 2 ) + { + do_encrypt( c, &datal, &datar ); + c->s3[i] = datal; + c->s3[i+1] = datar; + } + + + /* Check for weak key. A weak key is a key in which a value in + the P-array (here c) occurs more than once per table. */ + for(i=0; i < 255; i++ ) + { + for( j=i+1; j < 256; j++) + { + if( (c->s0[i] == c->s0[j]) || (c->s1[i] == c->s1[j]) || + (c->s2[i] == c->s2[j]) || (c->s3[i] == c->s3[j]) ) + return GPG_ERR_WEAK_KEY; + } + } + + return GPG_ERR_NO_ERROR; +} + + +static gcry_err_code_t +bf_setkey (void *context, const byte *key, unsigned keylen) +{ + BLOWFISH_context *c = (BLOWFISH_context *) context; + gcry_err_code_t rc = do_bf_setkey (c, key, keylen); + _gcry_burn_stack (64); + return rc; +} + + +gcry_cipher_spec_t _gcry_cipher_spec_blowfish = + { + "BLOWFISH", NULL, NULL, BLOWFISH_BLOCKSIZE, 128, + sizeof (BLOWFISH_context), + bf_setkey, encrypt_block, decrypt_block + }; diff --git a/grub-core/lib/libgcrypt/cipher/bufhelp.h b/grub-core/lib/libgcrypt/cipher/bufhelp.h new file mode 100644 index 0000000..df35594 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/bufhelp.h @@ -0,0 +1,432 @@ +/* bufhelp.h - Some buffer manipulation helpers + * Copyright (C) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi> + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef GCRYPT_BUFHELP_H +#define GCRYPT_BUFHELP_H + + +#include "bithelp.h" + + +#undef BUFHELP_FAST_UNALIGNED_ACCESS +#if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \ + defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \ + (defined(__i386__) || defined(__x86_64__) || \ + (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \ + defined(__aarch64__)) +/* These architectures are able of unaligned memory accesses and can + handle those fast. + */ +# define BUFHELP_FAST_UNALIGNED_ACCESS 1 +#endif + + +#ifdef BUFHELP_FAST_UNALIGNED_ACCESS +/* Define type with one-byte alignment on architectures with fast unaligned + memory accesses. + */ +typedef struct bufhelp_int_s +{ + uintptr_t a; +} __attribute__((packed, aligned(1))) bufhelp_int_t; +#else +/* Define type with default alignment for other architectures (unaligned + accessed handled in per byte loops). + */ +typedef struct bufhelp_int_s +{ + uintptr_t a; +} bufhelp_int_t; +#endif + + +/* Optimized function for small buffer copying */ +static inline void +buf_cpy(void *_dst, const void *_src, size_t len) +{ +#if __GNUC__ >= 4 && (defined(__x86_64__) || defined(__i386__)) + /* For AMD64 and i386, memcpy is faster. */ + memcpy(_dst, _src, len); +#else + byte *dst = _dst; + const byte *src = _src; + bufhelp_int_t *ldst; + const bufhelp_int_t *lsrc; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)dst | (uintptr_t)src) & longmask) + goto do_bytes; +#endif + + ldst = (bufhelp_int_t *)(void *)dst; + lsrc = (const bufhelp_int_t *)(const void *)src; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst++)->a = (lsrc++)->a; + + dst = (byte *)ldst; + src = (const byte *)lsrc; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst++ = *src++; +#endif /*__GNUC__ >= 4 && (__x86_64__ || __i386__)*/ +} + + +/* Optimized function for buffer xoring */ +static inline void +buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len) +{ + byte *dst = _dst; + const byte *src1 = _src1; + const byte *src2 = _src2; + bufhelp_int_t *ldst; + const bufhelp_int_t *lsrc1, *lsrc2; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)dst | (uintptr_t)src1 | (uintptr_t)src2) & longmask) + goto do_bytes; +#endif + + ldst = (bufhelp_int_t *)(void *)dst; + lsrc1 = (const bufhelp_int_t *)(const void *)src1; + lsrc2 = (const bufhelp_int_t *)(const void *)src2; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst++)->a = (lsrc1++)->a ^ (lsrc2++)->a; + + dst = (byte *)ldst; + src1 = (const byte *)lsrc1; + src2 = (const byte *)lsrc2; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst++ = *src1++ ^ *src2++; +} + + +/* Optimized function for in-place buffer xoring. */ +static inline void +buf_xor_1(void *_dst, const void *_src, size_t len) +{ + byte *dst = _dst; + const byte *src = _src; + bufhelp_int_t *ldst; + const bufhelp_int_t *lsrc; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)dst | (uintptr_t)src) & longmask) + goto do_bytes; +#endif + + ldst = (bufhelp_int_t *)(void *)dst; + lsrc = (const bufhelp_int_t *)(const void *)src; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst++)->a ^= (lsrc++)->a; + + dst = (byte *)ldst; + src = (const byte *)lsrc; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst++ ^= *src++; +} + + +/* Optimized function for buffer xoring with two destination buffers. Used + mainly by CFB mode encryption. */ +static inline void +buf_xor_2dst(void *_dst1, void *_dst2, const void *_src, size_t len) +{ + byte *dst1 = _dst1; + byte *dst2 = _dst2; + const byte *src = _src; + bufhelp_int_t *ldst1, *ldst2; + const bufhelp_int_t *lsrc; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)src | (uintptr_t)dst1 | (uintptr_t)dst2) & longmask) + goto do_bytes; +#endif + + ldst1 = (bufhelp_int_t *)(void *)dst1; + ldst2 = (bufhelp_int_t *)(void *)dst2; + lsrc = (const bufhelp_int_t *)(const void *)src; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst1++)->a = ((ldst2++)->a ^= (lsrc++)->a); + + dst1 = (byte *)ldst1; + dst2 = (byte *)ldst2; + src = (const byte *)lsrc; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst1++ = (*dst2++ ^= *src++); +} + + +/* Optimized function for combined buffer xoring and copying. Used by mainly + CBC mode decryption. */ +static inline void +buf_xor_n_copy_2(void *_dst_xor, const void *_src_xor, void *_srcdst_cpy, + const void *_src_cpy, size_t len) +{ + byte *dst_xor = _dst_xor; + byte *srcdst_cpy = _srcdst_cpy; + const byte *src_xor = _src_xor; + const byte *src_cpy = _src_cpy; + byte temp; + bufhelp_int_t *ldst_xor, *lsrcdst_cpy; + const bufhelp_int_t *lsrc_cpy, *lsrc_xor; + uintptr_t ltemp; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)src_cpy | (uintptr_t)src_xor | (uintptr_t)dst_xor | + (uintptr_t)srcdst_cpy) & longmask) + goto do_bytes; +#endif + + ldst_xor = (bufhelp_int_t *)(void *)dst_xor; + lsrc_xor = (const bufhelp_int_t *)(void *)src_xor; + lsrcdst_cpy = (bufhelp_int_t *)(void *)srcdst_cpy; + lsrc_cpy = (const bufhelp_int_t *)(const void *)src_cpy; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + { + ltemp = (lsrc_cpy++)->a; + (ldst_xor++)->a = (lsrcdst_cpy)->a ^ (lsrc_xor++)->a; + (lsrcdst_cpy++)->a = ltemp; + } + + dst_xor = (byte *)ldst_xor; + src_xor = (const byte *)lsrc_xor; + srcdst_cpy = (byte *)lsrcdst_cpy; + src_cpy = (const byte *)lsrc_cpy; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + { + temp = *src_cpy++; + *dst_xor++ = *srcdst_cpy ^ *src_xor++; + *srcdst_cpy++ = temp; + } +} + + +/* Optimized function for combined buffer xoring and copying. Used by mainly + CFB mode decryption. */ +static inline void +buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len) +{ + buf_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, len); +} + + +/* Constant-time compare of two buffers. Returns 1 if buffers are equal, + and 0 if buffers differ. */ +static inline int +buf_eq_const(const void *_a, const void *_b, size_t len) +{ + const byte *a = _a; + const byte *b = _b; + size_t diff, i; + + /* Constant-time compare. */ + for (i = 0, diff = 0; i < len; i++) + diff -= !!(a[i] - b[i]); + + return !diff; +} + + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + +/* Functions for loading and storing unaligned u32 values of different + endianness. */ +static inline u32 buf_get_be32(const void *_buf) +{ + const byte *in = _buf; + return ((u32)in[0] << 24) | ((u32)in[1] << 16) | \ + ((u32)in[2] << 8) | (u32)in[3]; +} + +static inline u32 buf_get_le32(const void *_buf) +{ + const byte *in = _buf; + return ((u32)in[3] << 24) | ((u32)in[2] << 16) | \ + ((u32)in[1] << 8) | (u32)in[0]; +} + +static inline void buf_put_be32(void *_buf, u32 val) +{ + byte *out = _buf; + out[0] = val >> 24; + out[1] = val >> 16; + out[2] = val >> 8; + out[3] = val; +} + +static inline void buf_put_le32(void *_buf, u32 val) +{ + byte *out = _buf; + out[3] = val >> 24; + out[2] = val >> 16; + out[1] = val >> 8; + out[0] = val; +} + + +/* Functions for loading and storing unaligned u64 values of different + endianness. */ +static inline u64 buf_get_be64(const void *_buf) +{ + const byte *in = _buf; + return ((u64)in[0] << 56) | ((u64)in[1] << 48) | \ + ((u64)in[2] << 40) | ((u64)in[3] << 32) | \ + ((u64)in[4] << 24) | ((u64)in[5] << 16) | \ + ((u64)in[6] << 8) | (u64)in[7]; +} + +static inline u64 buf_get_le64(const void *_buf) +{ + const byte *in = _buf; + return ((u64)in[7] << 56) | ((u64)in[6] << 48) | \ + ((u64)in[5] << 40) | ((u64)in[4] << 32) | \ + ((u64)in[3] << 24) | ((u64)in[2] << 16) | \ + ((u64)in[1] << 8) | (u64)in[0]; +} + +static inline void buf_put_be64(void *_buf, u64 val) +{ + byte *out = _buf; + out[0] = val >> 56; + out[1] = val >> 48; + out[2] = val >> 40; + out[3] = val >> 32; + out[4] = val >> 24; + out[5] = val >> 16; + out[6] = val >> 8; + out[7] = val; +} + +static inline void buf_put_le64(void *_buf, u64 val) +{ + byte *out = _buf; + out[7] = val >> 56; + out[6] = val >> 48; + out[5] = val >> 40; + out[4] = val >> 32; + out[3] = val >> 24; + out[2] = val >> 16; + out[1] = val >> 8; + out[0] = val; +} + +#else /*BUFHELP_FAST_UNALIGNED_ACCESS*/ + +typedef struct bufhelp_u32_s +{ + u32 a; +} __attribute__((packed, aligned(1))) bufhelp_u32_t; + +/* Functions for loading and storing unaligned u32 values of different + endianness. */ +static inline u32 buf_get_be32(const void *_buf) +{ + return be_bswap32(((const bufhelp_u32_t *)_buf)->a); +} + +static inline u32 buf_get_le32(const void *_buf) +{ + return le_bswap32(((const bufhelp_u32_t *)_buf)->a); +} + +static inline void buf_put_be32(void *_buf, u32 val) +{ + bufhelp_u32_t *out = _buf; + out->a = be_bswap32(val); +} + +static inline void buf_put_le32(void *_buf, u32 val) +{ + bufhelp_u32_t *out = _buf; + out->a = le_bswap32(val); +} + + +typedef struct bufhelp_u64_s +{ + u64 a; +} __attribute__((packed, aligned(1))) bufhelp_u64_t; + +/* Functions for loading and storing unaligned u64 values of different + endianness. */ +static inline u64 buf_get_be64(const void *_buf) +{ + return be_bswap64(((const bufhelp_u64_t *)_buf)->a); +} + +static inline u64 buf_get_le64(const void *_buf) +{ + return le_bswap64(((const bufhelp_u64_t *)_buf)->a); +} + +static inline void buf_put_be64(void *_buf, u64 val) +{ + bufhelp_u64_t *out = _buf; + out->a = be_bswap64(val); +} + +static inline void buf_put_le64(void *_buf, u64 val) +{ + bufhelp_u64_t *out = _buf; + out->a = le_bswap64(val); +} + + +#endif /*BUFHELP_FAST_UNALIGNED_ACCESS*/ + +#endif /*GCRYPT_BUFHELP_H*/ diff --git a/grub-core/lib/libgcrypt/cipher/camellia-glue.c b/grub-core/lib/libgcrypt/cipher/camellia-glue.c new file mode 100644 index 0000000..a263621 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/camellia-glue.c @@ -0,0 +1,253 @@ +/* camellia-glue.c - Glue for the Camellia cipher + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* I put all the libgcrypt-specific stuff in this file to keep the + camellia.c/camellia.h files exactly as provided by NTT. If they + update their code, this should make it easier to bring the changes + in. - dshaw + + There is one small change which needs to be done: Include the + following code at the top of camellia.h: */ +#if 0 + +/* To use Camellia with libraries it is often useful to keep the name + * space of the library clean. The following macro is thus useful: + * + * #define CAMELLIA_EXT_SYM_PREFIX foo_ + * + * This prefixes all external symbols with "foo_". + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#ifdef CAMELLIA_EXT_SYM_PREFIX +#define CAMELLIA_PREFIX1(x,y) x ## y +#define CAMELLIA_PREFIX2(x,y) CAMELLIA_PREFIX1(x,y) +#define CAMELLIA_PREFIX(x) CAMELLIA_PREFIX2(CAMELLIA_EXT_SYM_PREFIX,x) +#define Camellia_Ekeygen CAMELLIA_PREFIX(Camellia_Ekeygen) +#define Camellia_EncryptBlock CAMELLIA_PREFIX(Camellia_EncryptBlock) +#define Camellia_DecryptBlock CAMELLIA_PREFIX(Camellia_DecryptBlock) +#define camellia_decrypt128 CAMELLIA_PREFIX(camellia_decrypt128) +#define camellia_decrypt256 CAMELLIA_PREFIX(camellia_decrypt256) +#define camellia_encrypt128 CAMELLIA_PREFIX(camellia_encrypt128) +#define camellia_encrypt256 CAMELLIA_PREFIX(camellia_encrypt256) +#define camellia_setup128 CAMELLIA_PREFIX(camellia_setup128) +#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) +#define camellia_setup256 CAMELLIA_PREFIX(camellia_setup256) +#endif /*CAMELLIA_EXT_SYM_PREFIX*/ + +#endif /* Code sample. */ + + +#include <config.h> +#include "types.h" +#include "g10lib.h" +#include "cipher.h" +#include "camellia.h" + +typedef struct +{ + int keybitlength; + KEY_TABLE_TYPE keytable; +} CAMELLIA_context; + +static const char *selftest(void); + +static gcry_err_code_t +camellia_setkey(void *c, const byte *key, unsigned keylen) +{ + CAMELLIA_context *ctx=c; + static int initialized=0; + static const char *selftest_failed=NULL; + + if(keylen!=16 && keylen!=24 && keylen!=32) + return GPG_ERR_INV_KEYLEN; + + if(!initialized) + { + initialized=1; + selftest_failed=selftest(); + if(selftest_failed) + log_error("%s\n",selftest_failed); + } + + if(selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + ctx->keybitlength=keylen*8; + Camellia_Ekeygen(ctx->keybitlength,key,ctx->keytable); + _gcry_burn_stack + ((19+34+34)*sizeof(u32)+2*sizeof(void*) /* camellia_setup256 */ + +(4+32)*sizeof(u32)+2*sizeof(void*) /* camellia_setup192 */ + +0+sizeof(int)+2*sizeof(void*) /* Camellia_Ekeygen */ + +3*2*sizeof(void*) /* Function calls. */ + ); + + return 0; +} + +static void +camellia_encrypt(void *c, byte *outbuf, const byte *inbuf) +{ + CAMELLIA_context *ctx=c; + + Camellia_EncryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); + _gcry_burn_stack + (sizeof(int)+2*sizeof(unsigned char *)+sizeof(KEY_TABLE_TYPE) + +4*sizeof(u32) + +2*sizeof(u32*)+4*sizeof(u32) + +2*2*sizeof(void*) /* Function calls. */ + ); +} + +static void +camellia_decrypt(void *c, byte *outbuf, const byte *inbuf) +{ + CAMELLIA_context *ctx=c; + + Camellia_DecryptBlock(ctx->keybitlength,inbuf,ctx->keytable,outbuf); + _gcry_burn_stack + (sizeof(int)+2*sizeof(unsigned char *)+sizeof(KEY_TABLE_TYPE) + +4*sizeof(u32) + +2*sizeof(u32*)+4*sizeof(u32) + +2*2*sizeof(void*) /* Function calls. */ + ); +} + +static const char * +selftest(void) +{ + CAMELLIA_context ctx; + byte scratch[16]; + + /* These test vectors are from RFC-3713 */ + const byte plaintext[]= + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 + }; + const byte key_128[]= + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 + }; + const byte ciphertext_128[]= + { + 0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73, + 0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43 + }; + const byte key_192[]= + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98, + 0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77 + }; + const byte ciphertext_192[]= + { + 0xb4,0x99,0x34,0x01,0xb3,0xe9,0x96,0xf8, + 0x4e,0xe5,0xce,0xe7,0xd7,0x9b,0x09,0xb9 + }; + const byte key_256[]= + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba, + 0x98,0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55, + 0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff + }; + const byte ciphertext_256[]= + { + 0x9a,0xcc,0x23,0x7d,0xff,0x16,0xd7,0x6c, + 0x20,0xef,0x7c,0x91,0x9e,0x3a,0x75,0x09 + }; + + camellia_setkey(&ctx,key_128,sizeof(key_128)); + camellia_encrypt(&ctx,scratch,plaintext); + if(memcmp(scratch,ciphertext_128,sizeof(ciphertext_128))!=0) + return "CAMELLIA-128 test encryption failed."; + camellia_decrypt(&ctx,scratch,scratch); + if(memcmp(scratch,plaintext,sizeof(plaintext))!=0) + return "CAMELLIA-128 test decryption failed."; + + camellia_setkey(&ctx,key_192,sizeof(key_192)); + camellia_encrypt(&ctx,scratch,plaintext); + if(memcmp(scratch,ciphertext_192,sizeof(ciphertext_192))!=0) + return "CAMELLIA-192 test encryption failed."; + camellia_decrypt(&ctx,scratch,scratch); + if(memcmp(scratch,plaintext,sizeof(plaintext))!=0) + return "CAMELLIA-192 test decryption failed."; + + camellia_setkey(&ctx,key_256,sizeof(key_256)); + camellia_encrypt(&ctx,scratch,plaintext); + if(memcmp(scratch,ciphertext_256,sizeof(ciphertext_256))!=0) + return "CAMELLIA-256 test encryption failed."; + camellia_decrypt(&ctx,scratch,scratch); + if(memcmp(scratch,plaintext,sizeof(plaintext))!=0) + return "CAMELLIA-256 test decryption failed."; + + return NULL; +} + +/* These oids are from + <http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications_oid.html>, + retrieved May 1, 2007. */ + +static gcry_cipher_oid_spec_t camellia128_oids[] = + { + {"1.2.392.200011.61.1.1.1.2", GCRY_CIPHER_MODE_CBC}, + {"0.3.4401.5.3.1.9.1", GCRY_CIPHER_MODE_ECB}, + {"0.3.4401.5.3.1.9.3", GCRY_CIPHER_MODE_OFB}, + {"0.3.4401.5.3.1.9.4", GCRY_CIPHER_MODE_CFB}, + { NULL } + }; + +static gcry_cipher_oid_spec_t camellia192_oids[] = + { + {"1.2.392.200011.61.1.1.1.3", GCRY_CIPHER_MODE_CBC}, + {"0.3.4401.5.3.1.9.21", GCRY_CIPHER_MODE_ECB}, + {"0.3.4401.5.3.1.9.23", GCRY_CIPHER_MODE_OFB}, + {"0.3.4401.5.3.1.9.24", GCRY_CIPHER_MODE_CFB}, + { NULL } + }; + +static gcry_cipher_oid_spec_t camellia256_oids[] = + { + {"1.2.392.200011.61.1.1.1.4", GCRY_CIPHER_MODE_CBC}, + {"0.3.4401.5.3.1.9.41", GCRY_CIPHER_MODE_ECB}, + {"0.3.4401.5.3.1.9.43", GCRY_CIPHER_MODE_OFB}, + {"0.3.4401.5.3.1.9.44", GCRY_CIPHER_MODE_CFB}, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_camellia128 = + { + "CAMELLIA128",NULL,camellia128_oids,CAMELLIA_BLOCK_SIZE,128, + sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt + }; + +gcry_cipher_spec_t _gcry_cipher_spec_camellia192 = + { + "CAMELLIA192",NULL,camellia192_oids,CAMELLIA_BLOCK_SIZE,192, + sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt + }; + +gcry_cipher_spec_t _gcry_cipher_spec_camellia256 = + { + "CAMELLIA256",NULL,camellia256_oids,CAMELLIA_BLOCK_SIZE,256, + sizeof(CAMELLIA_context),camellia_setkey,camellia_encrypt,camellia_decrypt + }; diff --git a/grub-core/lib/libgcrypt/cipher/camellia.c b/grub-core/lib/libgcrypt/cipher/camellia.c new file mode 100644 index 0000000..2e28bce --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/camellia.c @@ -0,0 +1,1461 @@ +/* camellia.h ver 1.2.0 + * + * Copyright (C) 2006,2007 + * NTT (Nippon Telegraph and Telephone Corporation). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Algorithm Specification + * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html + */ + +#include <string.h> +#include <stdlib.h> + +#include "camellia.h" + +/* u32 must be 32bit word */ +typedef unsigned int u32; +typedef unsigned char u8; + +/* key constants */ + +#define CAMELLIA_SIGMA1L (0xA09E667FL) +#define CAMELLIA_SIGMA1R (0x3BCC908BL) +#define CAMELLIA_SIGMA2L (0xB67AE858L) +#define CAMELLIA_SIGMA2R (0x4CAA73B2L) +#define CAMELLIA_SIGMA3L (0xC6EF372FL) +#define CAMELLIA_SIGMA3R (0xE94F82BEL) +#define CAMELLIA_SIGMA4L (0x54FF53A5L) +#define CAMELLIA_SIGMA4R (0xF1D36F1CL) +#define CAMELLIA_SIGMA5L (0x10E527FAL) +#define CAMELLIA_SIGMA5R (0xDE682D1DL) +#define CAMELLIA_SIGMA6L (0xB05688C2L) +#define CAMELLIA_SIGMA6R (0xB3E6C1FDL) + +/* + * macros + */ + + +#if defined(_MSC_VER) + +# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +# define GETU32(p) SWAP(*((u32 *)(p))) +# define PUTU32(ct, st) {*((u32 *)(ct)) = SWAP((st));} + +#else /* not MS-VC */ + +# define GETU32(pt) \ + (((u32)(pt)[0] << 24) \ + ^ ((u32)(pt)[1] << 16) \ + ^ ((u32)(pt)[2] << 8) \ + ^ ((u32)(pt)[3])) + +# define PUTU32(ct, st) { \ + (ct)[0] = (u8)((st) >> 24); \ + (ct)[1] = (u8)((st) >> 16); \ + (ct)[2] = (u8)((st) >> 8); \ + (ct)[3] = (u8)(st); } + +#endif + +#define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2]) +#define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1]) + +/* rotation right shift 1byte */ +#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24)) +/* rotation left shift 1bit */ +#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31)) +/* rotation left shift 1byte */ +#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24)) + +#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + ll = (ll << bits) + (lr >> (32 - bits)); \ + lr = (lr << bits) + (rl >> (32 - bits)); \ + rl = (rl << bits) + (rr >> (32 - bits)); \ + rr = (rr << bits) + (w0 >> (32 - bits)); \ + } while(0) + +#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + w1 = lr; \ + ll = (lr << (bits - 32)) + (rl >> (64 - bits)); \ + lr = (rl << (bits - 32)) + (rr >> (64 - bits)); \ + rl = (rr << (bits - 32)) + (w0 >> (64 - bits)); \ + rr = (w0 << (bits - 32)) + (w1 >> (64 - bits)); \ + } while(0) + +#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)]) +#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)]) +#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)]) +#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)]) + +#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + il = xl ^ kl; \ + ir = xr ^ kr; \ + t0 = il >> 16; \ + t1 = ir >> 16; \ + yl = CAMELLIA_SP1110(ir & 0xff) \ + ^ CAMELLIA_SP0222((t1 >> 8) & 0xff) \ + ^ CAMELLIA_SP3033(t1 & 0xff) \ + ^ CAMELLIA_SP4404((ir >> 8) & 0xff); \ + yr = CAMELLIA_SP1110((t0 >> 8) & 0xff) \ + ^ CAMELLIA_SP0222(t0 & 0xff) \ + ^ CAMELLIA_SP3033((il >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(il & 0xff); \ + yl ^= yr; \ + yr = CAMELLIA_RR8(yr); \ + yr ^= yl; \ + } while(0) + + +/* + * for speed up + * + */ +#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \ + do { \ + t0 = kll; \ + t0 &= ll; \ + lr ^= CAMELLIA_RL1(t0); \ + t1 = klr; \ + t1 |= lr; \ + ll ^= t1; \ + \ + t2 = krr; \ + t2 |= rr; \ + rl ^= t2; \ + t3 = krl; \ + t3 &= rl; \ + rr ^= CAMELLIA_RL1(t3); \ + } while(0) + +#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + ir = CAMELLIA_SP1110(xr & 0xff) \ + ^ CAMELLIA_SP0222((xr >> 24) & 0xff) \ + ^ CAMELLIA_SP3033((xr >> 16) & 0xff) \ + ^ CAMELLIA_SP4404((xr >> 8) & 0xff); \ + il = CAMELLIA_SP1110((xl >> 24) & 0xff) \ + ^ CAMELLIA_SP0222((xl >> 16) & 0xff) \ + ^ CAMELLIA_SP3033((xl >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(xl & 0xff); \ + il ^= kl; \ + ir ^= kr; \ + ir ^= il; \ + il = CAMELLIA_RR8(il); \ + il ^= ir; \ + yl ^= ir; \ + yr ^= il; \ + } while(0) + + +static const u32 camellia_sp1110[256] = { + 0x70707000,0x82828200,0x2c2c2c00,0xececec00, + 0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500, + 0xe4e4e400,0x85858500,0x57575700,0x35353500, + 0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100, + 0x23232300,0xefefef00,0x6b6b6b00,0x93939300, + 0x45454500,0x19191900,0xa5a5a500,0x21212100, + 0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00, + 0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00, + 0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00, + 0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00, + 0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00, + 0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00, + 0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00, + 0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00, + 0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600, + 0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00, + 0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600, + 0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00, + 0x74747400,0x12121200,0x2b2b2b00,0x20202000, + 0xf0f0f000,0xb1b1b100,0x84848400,0x99999900, + 0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200, + 0x34343400,0x7e7e7e00,0x76767600,0x05050500, + 0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100, + 0xd1d1d100,0x17171700,0x04040400,0xd7d7d700, + 0x14141400,0x58585800,0x3a3a3a00,0x61616100, + 0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00, + 0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600, + 0x53535300,0x18181800,0xf2f2f200,0x22222200, + 0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200, + 0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100, + 0x24242400,0x08080800,0xe8e8e800,0xa8a8a800, + 0x60606000,0xfcfcfc00,0x69696900,0x50505000, + 0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00, + 0xa1a1a100,0x89898900,0x62626200,0x97979700, + 0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500, + 0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200, + 0x10101000,0xc4c4c400,0x00000000,0x48484800, + 0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00, + 0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00, + 0x09090900,0x3f3f3f00,0xdddddd00,0x94949400, + 0x87878700,0x5c5c5c00,0x83838300,0x02020200, + 0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300, + 0x73737300,0x67676700,0xf6f6f600,0xf3f3f300, + 0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200, + 0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600, + 0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00, + 0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00, + 0x13131300,0xbebebe00,0x63636300,0x2e2e2e00, + 0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00, + 0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00, + 0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600, + 0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900, + 0x78787800,0x98989800,0x06060600,0x6a6a6a00, + 0xe7e7e700,0x46464600,0x71717100,0xbababa00, + 0xd4d4d400,0x25252500,0xababab00,0x42424200, + 0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00, + 0x72727200,0x07070700,0xb9b9b900,0x55555500, + 0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00, + 0x36363600,0x49494900,0x2a2a2a00,0x68686800, + 0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400, + 0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00, + 0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100, + 0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400, + 0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00, +}; + +static const u32 camellia_sp0222[256] = { + 0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9, + 0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb, + 0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a, + 0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282, + 0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727, + 0x008a8a8a,0x00323232,0x004b4b4b,0x00424242, + 0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c, + 0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b, + 0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f, + 0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d, + 0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe, + 0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434, + 0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595, + 0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a, + 0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad, + 0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a, + 0x00171717,0x001a1a1a,0x00353535,0x00cccccc, + 0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a, + 0x00e8e8e8,0x00242424,0x00565656,0x00404040, + 0x00e1e1e1,0x00636363,0x00090909,0x00333333, + 0x00bfbfbf,0x00989898,0x00979797,0x00858585, + 0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a, + 0x00dadada,0x006f6f6f,0x00535353,0x00626262, + 0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf, + 0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2, + 0x00bdbdbd,0x00363636,0x00222222,0x00383838, + 0x00646464,0x001e1e1e,0x00393939,0x002c2c2c, + 0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444, + 0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565, + 0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323, + 0x00484848,0x00101010,0x00d1d1d1,0x00515151, + 0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0, + 0x00555555,0x00a1a1a1,0x00414141,0x00fafafa, + 0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f, + 0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b, + 0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5, + 0x00202020,0x00898989,0x00000000,0x00909090, + 0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7, + 0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5, + 0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929, + 0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404, + 0x009b9b9b,0x00949494,0x00212121,0x00666666, + 0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7, + 0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5, + 0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c, + 0x00919191,0x006e6e6e,0x008d8d8d,0x00767676, + 0x00030303,0x002d2d2d,0x00dedede,0x00969696, + 0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c, + 0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919, + 0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d, + 0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d, + 0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2, + 0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4, + 0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575, + 0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484, + 0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5, + 0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa, + 0x00f1f1f1,0x00dddddd,0x00595959,0x00141414, + 0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0, + 0x00787878,0x00707070,0x00e3e3e3,0x00494949, + 0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6, + 0x00777777,0x00939393,0x00868686,0x00838383, + 0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9, + 0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d, +}; + +static const u32 camellia_sp3033[256] = { + 0x38003838,0x41004141,0x16001616,0x76007676, + 0xd900d9d9,0x93009393,0x60006060,0xf200f2f2, + 0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a, + 0x75007575,0x06000606,0x57005757,0xa000a0a0, + 0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9, + 0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090, + 0xf600f6f6,0x07000707,0xa700a7a7,0x27002727, + 0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede, + 0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7, + 0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767, + 0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf, + 0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d, + 0x53005353,0xf000f0f0,0x9c009c9c,0x65006565, + 0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e, + 0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b, + 0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6, + 0xc500c5c5,0x86008686,0x4d004d4d,0x33003333, + 0xfd00fdfd,0x66006666,0x58005858,0x96009696, + 0x3a003a3a,0x09000909,0x95009595,0x10001010, + 0x78007878,0xd800d8d8,0x42004242,0xcc00cccc, + 0xef00efef,0x26002626,0xe500e5e5,0x61006161, + 0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282, + 0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898, + 0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb, + 0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0, + 0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e, + 0x19001919,0x87008787,0x4e004e4e,0x0b000b0b, + 0xa900a9a9,0x0c000c0c,0x79007979,0x11001111, + 0x7f007f7f,0x22002222,0xe700e7e7,0x59005959, + 0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8, + 0x12001212,0x04000404,0x74007474,0x54005454, + 0x30003030,0x7e007e7e,0xb400b4b4,0x28002828, + 0x55005555,0x68006868,0x50005050,0xbe00bebe, + 0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb, + 0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca, + 0x70007070,0xff00ffff,0x32003232,0x69006969, + 0x08000808,0x62006262,0x00000000,0x24002424, + 0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded, + 0x45004545,0x81008181,0x73007373,0x6d006d6d, + 0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a, + 0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101, + 0xe600e6e6,0x25002525,0x48004848,0x99009999, + 0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9, + 0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171, + 0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313, + 0x64006464,0x9b009b9b,0x63006363,0x9d009d9d, + 0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5, + 0x89008989,0x5f005f5f,0xb100b1b1,0x17001717, + 0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646, + 0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747, + 0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b, + 0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac, + 0x3c003c3c,0x4c004c4c,0x03000303,0x35003535, + 0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d, + 0x6a006a6a,0x92009292,0xd500d5d5,0x21002121, + 0x44004444,0x51005151,0xc600c6c6,0x7d007d7d, + 0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa, + 0x7c007c7c,0x77007777,0x56005656,0x05000505, + 0x1b001b1b,0xa400a4a4,0x15001515,0x34003434, + 0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252, + 0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd, + 0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0, + 0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a, + 0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f, +}; + +static const u32 camellia_sp4404[256] = { + 0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0, + 0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae, + 0x23230023,0x6b6b006b,0x45450045,0xa5a500a5, + 0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092, + 0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f, + 0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b, + 0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d, + 0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c, + 0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0, + 0x74740074,0x2b2b002b,0xf0f000f0,0x84840084, + 0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076, + 0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004, + 0x14140014,0x3a3a003a,0xdede00de,0x11110011, + 0x32320032,0x9c9c009c,0x53530053,0xf2f200f2, + 0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a, + 0x24240024,0xe8e800e8,0x60600060,0x69690069, + 0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062, + 0x54540054,0x1e1e001e,0xe0e000e0,0x64640064, + 0x10100010,0x00000000,0xa3a300a3,0x75750075, + 0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd, + 0x87870087,0x83830083,0xcdcd00cd,0x90900090, + 0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf, + 0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6, + 0x81810081,0x6f6f006f,0x13130013,0x63630063, + 0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc, + 0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4, + 0x78780078,0x06060006,0xe7e700e7,0x71710071, + 0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d, + 0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac, + 0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1, + 0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043, + 0x15150015,0xadad00ad,0x77770077,0x80800080, + 0x82820082,0xecec00ec,0x27270027,0xe5e500e5, + 0x85850085,0x35350035,0x0c0c000c,0x41410041, + 0xefef00ef,0x93930093,0x19190019,0x21210021, + 0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd, + 0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce, + 0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a, + 0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d, + 0x01010001,0xd6d600d6,0x56560056,0x4d4d004d, + 0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d, + 0x12120012,0x20200020,0xb1b100b1,0x99990099, + 0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005, + 0xb7b700b7,0x31310031,0x17170017,0xd7d700d7, + 0x58580058,0x61610061,0x1b1b001b,0x1c1c001c, + 0x0f0f000f,0x16160016,0x18180018,0x22220022, + 0x44440044,0xb2b200b2,0xb5b500b5,0x91910091, + 0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050, + 0xd0d000d0,0x7d7d007d,0x89890089,0x97970097, + 0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2, + 0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db, + 0x03030003,0xdada00da,0x3f3f003f,0x94940094, + 0x5c5c005c,0x02020002,0x4a4a004a,0x33330033, + 0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2, + 0x9b9b009b,0x26260026,0x37370037,0x3b3b003b, + 0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e, + 0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e, + 0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059, + 0x98980098,0x6a6a006a,0x46460046,0xbaba00ba, + 0x25250025,0x42420042,0xa2a200a2,0xfafa00fa, + 0x07070007,0x55550055,0xeeee00ee,0x0a0a000a, + 0x49490049,0x68680068,0x38380038,0xa4a400a4, + 0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1, + 0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e, +}; + + +/** + * Stuff related to the Camellia key schedule + */ +#define subl(x) subL[(x)] +#define subr(x) subR[(x)] + +void camellia_setup128(const unsigned char *key, u32 *subkey) +{ + u32 kll, klr, krl, krr; + u32 il, ir, t0, t1, w0, w1; + u32 kw4l, kw4r, dw, tl, tr; + u32 subL[26]; + u32 subR[26]; + + /** + * k == kll || klr || krl || krr (|| is concatination) + */ + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + /** + * generate KL dependent subkeys + */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(4) = kll; subr(4) = klr; + subl(5) = krl; subr(5) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(10) = kll; subr(10) = klr; + subl(11) = krl; subr(11) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(18) = kll; subr(18) = klr; + subl(19) = krl; subr(19) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + + /* generate KA */ + kll = subl(0); klr = subr(0); + krl = subl(1); krr = subr(1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KA dependent subkeys */ + subl(2) = kll; subr(2) = klr; + subl(3) = krl; subr(3) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(8) = kll; subr(8) = klr; + subl(9) = krl; subr(9) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(12) = kll; subr(12) = klr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(20) = kll; subr(20) = klr; + subl(21) = krl; subr(21) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(24) = kll; subr(24) = klr; + subl(25) = krl; subr(25) = krr; + + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(24) ^= subl(1); subr(24) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(25); kw4r = subr(25); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + CamelliaSubkeyL(23) = subl(22); + CamelliaSubkeyR(23) = subr(22); + CamelliaSubkeyL(24) = subl(24) ^ subl(23); + CamelliaSubkeyR(24) = subr(24) ^ subr(23); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + + return; +} + +void camellia_setup256(const unsigned char *key, u32 *subkey) +{ + u32 kll,klr,krl,krr; /* left half of key */ + u32 krll,krlr,krrl,krrr; /* right half of key */ + u32 il, ir, t0, t1, w0, w1; /* temporary variables */ + u32 kw4l, kw4r, dw, tl, tr; + u32 subL[34]; + u32 subR[34]; + + /** + * key = (kll || klr || krl || krr || krll || krlr || krrl || krrr) + * (|| is concatination) + */ + + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + krll = GETU32(key + 16); + krlr = GETU32(key + 20); + krrl = GETU32(key + 24); + krrr = GETU32(key + 28); + + /* generate KL dependent subkeys */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45); + subl(12) = kll; subr(12) = klr; + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(30) = kll; subr(30) = klr; + subl(31) = krl; subr(31) = krr; + + /* generate KR dependent subkeys */ + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(4) = krll; subr(4) = krlr; + subl(5) = krrl; subr(5) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(8) = krll; subr(8) = krlr; + subl(9) = krrl; subr(9) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(18) = krll; subr(18) = krlr; + subl(19) = krrl; subr(19) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + subl(26) = krll; subr(26) = krlr; + subl(27) = krrl; subr(27) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + + /* generate KA */ + kll = subl(0) ^ krll; klr = subr(0) ^ krlr; + krl = subl(1) ^ krrl; krr = subr(1) ^ krrr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + kll ^= krll; klr ^= krlr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0 ^ krrl; krr ^= w1 ^ krrr; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KB */ + krll ^= kll; krlr ^= klr; + krrl ^= krl; krrr ^= krr; + CAMELLIA_F(krll, krlr, + CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R, + w0, w1, il, ir, t0, t1); + krrl ^= w0; krrr ^= w1; + CAMELLIA_F(krrl, krrr, + CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R, + w0, w1, il, ir, t0, t1); + krll ^= w0; krlr ^= w1; + + /* generate KA dependent subkeys */ + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + subl(24) = klr; subr(24) = krl; + subl(25) = krr; subr(25) = kll; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49); + subl(28) = kll; subr(28) = klr; + subl(29) = krl; subr(29) = krr; + + /* generate KB dependent subkeys */ + subl(2) = krll; subr(2) = krlr; + subl(3) = krrl; subr(3) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(10) = krll; subr(10) = krlr; + subl(11) = krrl; subr(11) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(20) = krll; subr(20) = krlr; + subl(21) = krrl; subr(21) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51); + subl(32) = krll; subr(32) = krlr; + subl(33) = krrl; subr(33) = krrr; + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(1) ^= subr(1) & ~subr(25); + dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw); + subl(27) ^= subl(1); subr(27) ^= subr(1); + subl(29) ^= subl(1); subr(29) ^= subr(1); + subl(31) ^= subl(1); subr(31) ^= subr(1); + subl(32) ^= subl(1); subr(32) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(33); kw4r = subr(33); + subl(30) ^= kw4l; subr(30) ^= kw4r; + subl(28) ^= kw4l; subr(28) ^= kw4r; + subl(26) ^= kw4l; subr(26) ^= kw4r; + kw4l ^= kw4r & ~subr(24); + dw = kw4l & subl(24), kw4r ^= CAMELLIA_RL1(dw); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + tl = subl(26) ^ (subr(26) & ~subr(24)); + dw = tl & subl(24), tr = subr(26) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(23) = subl(22) ^ tl; + CamelliaSubkeyR(23) = subr(22) ^ tr; + CamelliaSubkeyL(24) = subl(24); + CamelliaSubkeyR(24) = subr(24); + CamelliaSubkeyL(25) = subl(25); + CamelliaSubkeyR(25) = subr(25); + tl = subl(23) ^ (subr(23) & ~subr(25)); + dw = tl & subl(25), tr = subr(23) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(26) = tl ^ subl(27); + CamelliaSubkeyR(26) = tr ^ subr(27); + CamelliaSubkeyL(27) = subl(26) ^ subl(28); + CamelliaSubkeyR(27) = subr(26) ^ subr(28); + CamelliaSubkeyL(28) = subl(27) ^ subl(29); + CamelliaSubkeyR(28) = subr(27) ^ subr(29); + CamelliaSubkeyL(29) = subl(28) ^ subl(30); + CamelliaSubkeyR(29) = subr(28) ^ subr(30); + CamelliaSubkeyL(30) = subl(29) ^ subl(31); + CamelliaSubkeyR(30) = subr(29) ^ subr(31); + CamelliaSubkeyL(31) = subl(30); + CamelliaSubkeyR(31) = subr(30); + CamelliaSubkeyL(32) = subl(32) ^ subl(31); + CamelliaSubkeyR(32) = subr(32) ^ subr(31); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + dw = CamelliaSubkeyL(26) ^ CamelliaSubkeyR(26), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(26) = CamelliaSubkeyL(26) ^ dw, CamelliaSubkeyL(26) = dw; + dw = CamelliaSubkeyL(27) ^ CamelliaSubkeyR(27), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(27) = CamelliaSubkeyL(27) ^ dw, CamelliaSubkeyL(27) = dw; + dw = CamelliaSubkeyL(28) ^ CamelliaSubkeyR(28), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(28) = CamelliaSubkeyL(28) ^ dw, CamelliaSubkeyL(28) = dw; + dw = CamelliaSubkeyL(29) ^ CamelliaSubkeyR(29), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(29) = CamelliaSubkeyL(29) ^ dw, CamelliaSubkeyL(29) = dw; + dw = CamelliaSubkeyL(30) ^ CamelliaSubkeyR(30), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw; + dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw; + + return; +} + +void camellia_setup192(const unsigned char *key, u32 *subkey) +{ + unsigned char kk[32]; + u32 krll, krlr, krrl,krrr; + + memcpy(kk, key, 24); + memcpy((unsigned char *)&krll, key+16,4); + memcpy((unsigned char *)&krlr, key+20,4); + krrl = ~krll; + krrr = ~krlr; + memcpy(kk+24, (unsigned char *)&krrl, 4); + memcpy(kk+28, (unsigned char *)&krrr, 4); + camellia_setup256(kk, subkey); + return; +} + + +/** + * Stuff related to camellia encryption/decryption + * + * "io" must be 4byte aligned and big-endian data. + */ +void camellia_encrypt128(const u32 *subkey, u32 *io) +{ + u32 il, ir, t0, t1; + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + /* main iteration */ + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(24); + io[3] ^= CamelliaSubkeyR(24); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +void camellia_decrypt128(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(24); + io[1] ^= CamelliaSubkeyR(24); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/** + * stuff for 192 and 256bit encryption/decryption + */ +void camellia_encrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(32); + io[3] ^= CamelliaSubkeyR(32); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +void camellia_decrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(32); + io[1] ^= CamelliaSubkeyR(32); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/*** + * + * API for compatibility + */ + +void Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, + KEY_TABLE_TYPE keyTable) +{ + switch(keyBitLength) { + case 128: + camellia_setup128(rawKey, keyTable); + break; + case 192: + camellia_setup192(rawKey, keyTable); + break; + case 256: + camellia_setup256(rawKey, keyTable); + break; + default: + break; + } +} + + +void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, + unsigned char *ciphertext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(plaintext); + tmp[1] = GETU32(plaintext + 4); + tmp[2] = GETU32(plaintext + 8); + tmp[3] = GETU32(plaintext + 12); + + switch (keyBitLength) { + case 128: + camellia_encrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_encrypt256(keyTable, tmp); + break; + default: + break; + } + + PUTU32(ciphertext, tmp[0]); + PUTU32(ciphertext + 4, tmp[1]); + PUTU32(ciphertext + 8, tmp[2]); + PUTU32(ciphertext + 12, tmp[3]); +} + +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *ciphertext, + const KEY_TABLE_TYPE keyTable, + unsigned char *plaintext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(ciphertext); + tmp[1] = GETU32(ciphertext + 4); + tmp[2] = GETU32(ciphertext + 8); + tmp[3] = GETU32(ciphertext + 12); + + switch (keyBitLength) { + case 128: + camellia_decrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_decrypt256(keyTable, tmp); + break; + default: + break; + } + PUTU32(plaintext, tmp[0]); + PUTU32(plaintext + 4, tmp[1]); + PUTU32(plaintext + 8, tmp[2]); + PUTU32(plaintext + 12, tmp[3]); +} diff --git a/grub-core/lib/libgcrypt/cipher/camellia.h b/grub-core/lib/libgcrypt/cipher/camellia.h new file mode 100644 index 0000000..cccf786 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/camellia.h @@ -0,0 +1,81 @@ +/* camellia.h ver 1.2.0 + * + * Copyright (C) 2006,2007 + * NTT (Nippon Telegraph and Telephone Corporation). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef HEADER_CAMELLIA_H +#define HEADER_CAMELLIA_H + +/* To use Camellia with libraries it is often useful to keep the name + * space of the library clean. The following macro is thus useful: + * + * #define CAMELLIA_EXT_SYM_PREFIX foo_ + * + * This prefixes all external symbols with "foo_". + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#ifdef CAMELLIA_EXT_SYM_PREFIX +#define CAMELLIA_PREFIX1(x,y) x ## y +#define CAMELLIA_PREFIX2(x,y) CAMELLIA_PREFIX1(x,y) +#define CAMELLIA_PREFIX(x) CAMELLIA_PREFIX2(CAMELLIA_EXT_SYM_PREFIX,x) +#define Camellia_Ekeygen CAMELLIA_PREFIX(Camellia_Ekeygen) +#define Camellia_EncryptBlock CAMELLIA_PREFIX(Camellia_EncryptBlock) +#define Camellia_DecryptBlock CAMELLIA_PREFIX(Camellia_DecryptBlock) +#define camellia_decrypt128 CAMELLIA_PREFIX(camellia_decrypt128) +#define camellia_decrypt256 CAMELLIA_PREFIX(camellia_decrypt256) +#define camellia_encrypt128 CAMELLIA_PREFIX(camellia_encrypt128) +#define camellia_encrypt256 CAMELLIA_PREFIX(camellia_encrypt256) +#define camellia_setup128 CAMELLIA_PREFIX(camellia_setup128) +#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) +#define camellia_setup256 CAMELLIA_PREFIX(camellia_setup256) +#endif /*CAMELLIA_EXT_SYM_PREFIX*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +#define CAMELLIA_BLOCK_SIZE 16 +#define CAMELLIA_TABLE_BYTE_LEN 272 +#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4) + +typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; + + +void Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, + KEY_TABLE_TYPE keyTable); + +void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, + unsigned char *cipherText); + +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *cipherText, + const KEY_TABLE_TYPE keyTable, + unsigned char *plaintext); + + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_CAMELLIA_H */ diff --git a/grub-core/lib/libgcrypt/cipher/cast5.c b/grub-core/lib/libgcrypt/cipher/cast5.c new file mode 100644 index 0000000..9905f5c --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/cast5.c @@ -0,0 +1,620 @@ +/* cast5.c - CAST5 cipher (RFC2144) + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* Test vectors: + * + * 128-bit key = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A + * plaintext = 01 23 45 67 89 AB CD EF + * ciphertext = 23 8B 4F E5 84 7E 44 B2 + * + * 80-bit key = 01 23 45 67 12 34 56 78 23 45 + * = 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00 + * plaintext = 01 23 45 67 89 AB CD EF + * ciphertext = EB 6A 71 1A 2C 02 27 1B + * + * 40-bit key = 01 23 45 67 12 + * = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00 + * plaintext = 01 23 45 67 89 AB CD EF + * ciphertext = 7A C8 16 D1 6E 9B 30 2E + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "g10lib.h" +#include "types.h" +#include "cipher.h" + +#define CAST5_BLOCKSIZE 8 + +typedef struct { + u32 Km[16]; + byte Kr[16]; +} CAST5_context; + +static gcry_err_code_t cast_setkey (void *c, const byte *key, unsigned keylen); +static void encrypt_block (void *c, byte *outbuf, const byte *inbuf); +static void decrypt_block (void *c, byte *outbuf, const byte *inbuf); + + + + +static const u32 s1[256] = { +0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, +0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, +0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, +0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, +0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, +0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, +0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, +0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, +0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, +0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, +0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, +0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, +0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, +0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, +0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, +0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, +0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, +0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, +0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, +0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, +0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, +0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, +0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, +0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, +0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, +0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, +0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, +0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, +0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, +0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, +0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, +0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf +}; +static const u32 s2[256] = { +0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, +0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, +0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, +0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, +0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, +0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, +0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, +0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, +0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, +0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, +0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, +0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, +0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, +0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, +0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, +0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, +0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, +0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, +0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, +0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, +0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, +0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, +0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, +0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, +0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, +0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, +0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, +0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, +0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, +0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, +0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, +0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 +}; +static const u32 s3[256] = { +0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, +0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, +0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, +0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, +0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, +0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, +0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, +0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, +0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, +0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, +0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, +0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, +0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, +0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, +0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, +0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, +0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, +0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, +0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, +0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, +0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, +0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, +0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, +0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, +0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, +0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, +0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, +0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, +0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, +0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, +0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, +0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 +}; +static const u32 s4[256] = { +0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, +0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, +0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, +0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, +0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, +0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, +0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, +0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, +0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, +0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, +0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, +0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, +0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, +0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, +0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, +0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, +0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, +0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, +0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, +0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, +0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, +0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, +0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, +0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, +0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, +0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, +0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, +0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, +0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, +0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, +0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, +0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 +}; +static const u32 s5[256] = { +0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, +0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, +0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, +0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, +0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, +0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, +0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, +0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, +0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, +0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, +0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, +0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, +0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, +0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, +0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, +0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, +0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, +0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, +0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, +0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, +0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, +0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, +0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, +0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, +0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, +0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, +0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, +0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, +0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, +0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, +0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, +0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 +}; +static const u32 s6[256] = { +0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, +0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, +0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, +0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, +0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, +0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, +0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, +0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, +0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, +0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, +0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, +0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, +0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, +0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, +0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, +0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, +0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, +0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, +0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, +0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, +0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, +0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, +0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, +0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, +0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, +0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, +0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, +0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, +0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, +0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, +0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, +0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f +}; +static const u32 s7[256] = { +0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, +0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, +0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, +0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, +0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, +0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, +0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, +0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, +0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, +0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, +0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, +0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, +0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, +0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, +0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, +0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, +0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, +0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, +0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, +0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, +0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, +0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, +0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, +0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, +0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, +0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, +0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, +0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, +0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, +0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, +0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, +0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 +}; +static const u32 s8[256] = { +0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, +0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, +0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, +0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, +0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, +0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, +0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, +0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, +0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, +0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, +0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, +0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, +0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, +0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, +0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, +0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, +0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, +0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, +0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, +0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, +0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, +0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, +0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, +0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, +0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, +0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, +0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, +0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, +0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, +0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, +0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, +0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e +}; + + +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +rol(int n, u32 x) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else +#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + +#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol((r),I)), \ + (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) ) +#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol((r),I)), \ + (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) ) +#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol((r),I)), \ + (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) ) + +static void +do_encrypt_block( CAST5_context *c, byte *outbuf, const byte *inbuf ) +{ + u32 l, r, t; + u32 I; /* used by the Fx macros */ + u32 *Km; + byte *Kr; + + Km = c->Km; + Kr = c->Kr; + + /* (L0,R0) <-- (m1...m64). (Split the plaintext into left and + * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.) + */ + l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + + /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows: + * Li = Ri-1; + * Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2 + * Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1. + * Rounds 2, 5, 8, 11, and 14 use f function Type 2. + * Rounds 3, 6, 9, 12, and 15 use f function Type 3. + */ + + t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); + t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); + t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); + t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); + t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); + t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); + t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); + t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); + t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); + t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); + t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); + t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); + t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); + t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); + t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); + t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); + + /* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and + * concatenate to form the ciphertext.) */ + outbuf[0] = (r >> 24) & 0xff; + outbuf[1] = (r >> 16) & 0xff; + outbuf[2] = (r >> 8) & 0xff; + outbuf[3] = r & 0xff; + outbuf[4] = (l >> 24) & 0xff; + outbuf[5] = (l >> 16) & 0xff; + outbuf[6] = (l >> 8) & 0xff; + outbuf[7] = l & 0xff; +} + +static void +encrypt_block (void *context , byte *outbuf, const byte *inbuf) +{ + CAST5_context *c = (CAST5_context *) context; + do_encrypt_block (c, outbuf, inbuf); + _gcry_burn_stack (20+4*sizeof(void*)); +} + + +static void +do_decrypt_block (CAST5_context *c, byte *outbuf, const byte *inbuf ) +{ + u32 l, r, t; + u32 I; + u32 *Km; + byte *Kr; + + Km = c->Km; + Kr = c->Kr; + + l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; + r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + + t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); + t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); + t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); + t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); + t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); + t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); + t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); + t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); + t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); + t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); + t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); + t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); + t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); + t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); + t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); + t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); + + outbuf[0] = (r >> 24) & 0xff; + outbuf[1] = (r >> 16) & 0xff; + outbuf[2] = (r >> 8) & 0xff; + outbuf[3] = r & 0xff; + outbuf[4] = (l >> 24) & 0xff; + outbuf[5] = (l >> 16) & 0xff; + outbuf[6] = (l >> 8) & 0xff; + outbuf[7] = l & 0xff; +} + +static void +decrypt_block (void *context, byte *outbuf, const byte *inbuf) +{ + CAST5_context *c = (CAST5_context *) context; + do_decrypt_block (c, outbuf, inbuf); + _gcry_burn_stack (20+4*sizeof(void*)); +} + + +static const char* +selftest(void) +{ + CAST5_context c; + byte key[16] = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A }; + byte plain[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; + byte cipher[8]= { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 }; + byte buffer[8]; + + cast_setkey( &c, key, 16 ); + encrypt_block( &c, buffer, plain ); + if( memcmp( buffer, cipher, 8 ) ) + return "1"; + decrypt_block( &c, buffer, buffer ); + if( memcmp( buffer, plain, 8 ) ) + return "2"; + +#if 0 /* full maintenance test */ + { + int i; + byte a0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78, + 0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A }; + byte b0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78, + 0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A }; + byte a1[16] = { 0xEE,0xA9,0xD0,0xA2,0x49,0xFD,0x3B,0xA6, + 0xB3,0x43,0x6F,0xB8,0x9D,0x6D,0xCA,0x92 }; + byte b1[16] = { 0xB2,0xC9,0x5E,0xB0,0x0C,0x31,0xAD,0x71, + 0x80,0xAC,0x05,0xB8,0xE8,0x3D,0x69,0x6E }; + + for(i=0; i < 1000000; i++ ) { + cast_setkey( &c, b0, 16 ); + encrypt_block( &c, a0, a0 ); + encrypt_block( &c, a0+8, a0+8 ); + cast_setkey( &c, a0, 16 ); + encrypt_block( &c, b0, b0 ); + encrypt_block( &c, b0+8, b0+8 ); + } + if( memcmp( a0, a1, 16 ) || memcmp( b0, b1, 16 ) ) + return "3"; + + } +#endif + return NULL; +} + + +static void +key_schedule( u32 *x, u32 *z, u32 *k ) +{ + +#define xi(i) ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff) +#define zi(i) ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff) + + z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)]; + z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)]; + z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)]; + z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)]; + k[0] = s5[zi( 8)]^s6[zi( 9)]^s7[zi( 7)]^s8[zi( 6)]^s5[zi( 2)]; + k[1] = s5[zi(10)]^s6[zi(11)]^s7[zi( 5)]^s8[zi( 4)]^s6[zi( 6)]; + k[2] = s5[zi(12)]^s6[zi(13)]^s7[zi( 3)]^s8[zi( 2)]^s7[zi( 9)]; + k[3] = s5[zi(14)]^s6[zi(15)]^s7[zi( 1)]^s8[zi( 0)]^s8[zi(12)]; + + x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)]; + x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)]; + x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)]; + x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)]; + k[4] = s5[xi( 3)]^s6[xi( 2)]^s7[xi(12)]^s8[xi(13)]^s5[xi( 8)]; + k[5] = s5[xi( 1)]^s6[xi( 0)]^s7[xi(14)]^s8[xi(15)]^s6[xi(13)]; + k[6] = s5[xi( 7)]^s6[xi( 6)]^s7[xi( 8)]^s8[xi( 9)]^s7[xi( 3)]; + k[7] = s5[xi( 5)]^s6[xi( 4)]^s7[xi(10)]^s8[xi(11)]^s8[xi( 7)]; + + z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)]; + z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)]; + z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)]; + z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)]; + k[8] = s5[zi( 3)]^s6[zi( 2)]^s7[zi(12)]^s8[zi(13)]^s5[zi( 9)]; + k[9] = s5[zi( 1)]^s6[zi( 0)]^s7[zi(14)]^s8[zi(15)]^s6[zi(12)]; + k[10]= s5[zi( 7)]^s6[zi( 6)]^s7[zi( 8)]^s8[zi( 9)]^s7[zi( 2)]; + k[11]= s5[zi( 5)]^s6[zi( 4)]^s7[zi(10)]^s8[zi(11)]^s8[zi( 6)]; + + x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)]; + x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)]; + x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)]; + x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)]; + k[12]= s5[xi( 8)]^s6[xi( 9)]^s7[xi( 7)]^s8[xi( 6)]^s5[xi( 3)]; + k[13]= s5[xi(10)]^s6[xi(11)]^s7[xi( 5)]^s8[xi( 4)]^s6[xi( 7)]; + k[14]= s5[xi(12)]^s6[xi(13)]^s7[xi( 3)]^s8[xi( 2)]^s7[xi( 8)]; + k[15]= s5[xi(14)]^s6[xi(15)]^s7[xi( 1)]^s8[xi( 0)]^s8[xi(13)]; + +#undef xi +#undef zi +} + + +static gcry_err_code_t +do_cast_setkey( CAST5_context *c, const byte *key, unsigned keylen ) +{ + static int initialized; + static const char* selftest_failed; + int i; + u32 x[4]; + u32 z[4]; + u32 k[16]; + + if( !initialized ) + { + initialized = 1; + selftest_failed = selftest(); + if( selftest_failed ) + log_error ("CAST5 selftest failed (%s).\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + if( keylen != 16 ) + return GPG_ERR_INV_KEYLEN; + + x[0] = key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3]; + x[1] = key[4] << 24 | key[5] << 16 | key[6] << 8 | key[7]; + x[2] = key[8] << 24 | key[9] << 16 | key[10] << 8 | key[11]; + x[3] = key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15]; + + key_schedule( x, z, k ); + for(i=0; i < 16; i++ ) + c->Km[i] = k[i]; + key_schedule( x, z, k ); + for(i=0; i < 16; i++ ) + c->Kr[i] = k[i] & 0x1f; + + memset(&x,0, sizeof x); + memset(&z,0, sizeof z); + memset(&k,0, sizeof k); + +#undef xi +#undef zi + return GPG_ERR_NO_ERROR; +} + +static gcry_err_code_t +cast_setkey (void *context, const byte *key, unsigned keylen ) +{ + CAST5_context *c = (CAST5_context *) context; + gcry_err_code_t rc = do_cast_setkey (c, key, keylen); + _gcry_burn_stack (96+7*sizeof(void*)); + return rc; +} + + +gcry_cipher_spec_t _gcry_cipher_spec_cast5 = + { + "CAST5", NULL, NULL, CAST5_BLOCKSIZE, 128, sizeof (CAST5_context), + cast_setkey, encrypt_block, decrypt_block + }; diff --git a/grub-core/lib/libgcrypt/cipher/cipher.c b/grub-core/lib/libgcrypt/cipher/cipher.c new file mode 100644 index 0000000..9852d6a --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/cipher.c @@ -0,0 +1,2217 @@ +/* cipher.c - cipher dispatcher + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 + * 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "g10lib.h" +#include "cipher.h" +#include "ath.h" + +#define MAX_BLOCKSIZE 16 +#define TABLE_SIZE 14 +#define CTX_MAGIC_NORMAL 0x24091964 +#define CTX_MAGIC_SECURE 0x46919042 + +/* Try to use 16 byte aligned cipher context for better performance. + We use the aligned attribute, thus it is only possible to implement + this with gcc. */ +#undef NEED_16BYTE_ALIGNED_CONTEXT +#if defined (__GNUC__) +# define NEED_16BYTE_ALIGNED_CONTEXT 1 +#endif + +/* A dummy extraspec so that we do not need to tests the extraspec + field from the module specification against NULL and instead + directly test the respective fields of extraspecs. */ +static cipher_extra_spec_t dummy_extra_spec; + +/* This is the list of the default ciphers, which are included in + libgcrypt. */ +static struct cipher_table_entry +{ + gcry_cipher_spec_t *cipher; + cipher_extra_spec_t *extraspec; + unsigned int algorithm; + int fips_allowed; +} cipher_table[] = + { +#if USE_BLOWFISH + { &_gcry_cipher_spec_blowfish, + &dummy_extra_spec, GCRY_CIPHER_BLOWFISH }, +#endif +#if USE_DES + { &_gcry_cipher_spec_des, + &dummy_extra_spec, GCRY_CIPHER_DES }, + { &_gcry_cipher_spec_tripledes, + &_gcry_cipher_extraspec_tripledes, GCRY_CIPHER_3DES, 1 }, +#endif +#if USE_ARCFOUR + { &_gcry_cipher_spec_arcfour, + &dummy_extra_spec, GCRY_CIPHER_ARCFOUR }, +#endif +#if USE_CAST5 + { &_gcry_cipher_spec_cast5, + &dummy_extra_spec, GCRY_CIPHER_CAST5 }, +#endif +#if USE_AES + { &_gcry_cipher_spec_aes, + &_gcry_cipher_extraspec_aes, GCRY_CIPHER_AES, 1 }, + { &_gcry_cipher_spec_aes192, + &_gcry_cipher_extraspec_aes192, GCRY_CIPHER_AES192, 1 }, + { &_gcry_cipher_spec_aes256, + &_gcry_cipher_extraspec_aes256, GCRY_CIPHER_AES256, 1 }, +#endif +#if USE_TWOFISH + { &_gcry_cipher_spec_twofish, + &dummy_extra_spec, GCRY_CIPHER_TWOFISH }, + { &_gcry_cipher_spec_twofish128, + &dummy_extra_spec, GCRY_CIPHER_TWOFISH128 }, +#endif +#if USE_SERPENT + { &_gcry_cipher_spec_serpent128, + &dummy_extra_spec, GCRY_CIPHER_SERPENT128 }, + { &_gcry_cipher_spec_serpent192, + &dummy_extra_spec, GCRY_CIPHER_SERPENT192 }, + { &_gcry_cipher_spec_serpent256, + &dummy_extra_spec, GCRY_CIPHER_SERPENT256 }, +#endif +#if USE_RFC2268 + { &_gcry_cipher_spec_rfc2268_40, + &dummy_extra_spec, GCRY_CIPHER_RFC2268_40 }, +#endif +#if USE_SEED + { &_gcry_cipher_spec_seed, + &dummy_extra_spec, GCRY_CIPHER_SEED }, +#endif +#if USE_CAMELLIA + { &_gcry_cipher_spec_camellia128, + &dummy_extra_spec, GCRY_CIPHER_CAMELLIA128 }, + { &_gcry_cipher_spec_camellia192, + &dummy_extra_spec, GCRY_CIPHER_CAMELLIA192 }, + { &_gcry_cipher_spec_camellia256, + &dummy_extra_spec, GCRY_CIPHER_CAMELLIA256 }, +#endif +#ifdef USE_IDEA + { &_gcry_cipher_spec_idea, + &dummy_extra_spec, GCRY_CIPHER_IDEA }, +#endif + { NULL } + }; + +/* List of registered ciphers. */ +static gcry_module_t ciphers_registered; + +/* This is the lock protecting CIPHERS_REGISTERED. */ +static ath_mutex_t ciphers_registered_lock = ATH_MUTEX_INITIALIZER; + +/* Flag to check whether the default ciphers have already been + registered. */ +static int default_ciphers_registered; + +/* Convenient macro for registering the default ciphers. */ +#define REGISTER_DEFAULT_CIPHERS \ + do \ + { \ + ath_mutex_lock (&ciphers_registered_lock); \ + if (! default_ciphers_registered) \ + { \ + cipher_register_default (); \ + default_ciphers_registered = 1; \ + } \ + ath_mutex_unlock (&ciphers_registered_lock); \ + } \ + while (0) + + +/* A VIA processor with the Padlock engine as well as the Intel AES_NI + instructions require an alignment of most data on a 16 byte + boundary. Because we trick out the compiler while allocating the + context, the align attribute as used in rijndael.c does not work on + its own. Thus we need to make sure that the entire context + structure is a aligned on that boundary. We achieve this by + defining a new type and use that instead of our usual alignment + type. */ +typedef union +{ + PROPERLY_ALIGNED_TYPE foo; +#ifdef NEED_16BYTE_ALIGNED_CONTEXT + char bar[16] __attribute__ ((aligned (16))); +#endif + char c[1]; +} cipher_context_alignment_t; + + +/* The handle structure. */ +struct gcry_cipher_handle +{ + int magic; + size_t actual_handle_size; /* Allocated size of this handle. */ + size_t handle_offset; /* Offset to the malloced block. */ + gcry_cipher_spec_t *cipher; + cipher_extra_spec_t *extraspec; + gcry_module_t module; + + /* The algorithm id. This is a hack required because the module + interface does not easily allow to retrieve this value. */ + int algo; + + /* A structure with function pointers for bulk operations. Due to + limitations of the module system (we don't want to change the + API) we need to keep these function pointers here. The cipher + open function intializes them and the actual encryption routines + use them if they are not NULL. */ + struct { + void (*cfb_enc)(void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); + void (*cfb_dec)(void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); + void (*cbc_enc)(void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks, int cbc_mac); + void (*cbc_dec)(void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); + void (*ctr_enc)(void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); + } bulk; + + + int mode; + unsigned int flags; + + struct { + unsigned int key:1; /* Set to 1 if a key has been set. */ + unsigned int iv:1; /* Set to 1 if a IV has been set. */ + } marks; + + /* The initialization vector. For best performance we make sure + that it is properly aligned. In particular some implementations + of bulk operations expect an 16 byte aligned IV. */ + union { + cipher_context_alignment_t iv_align; + unsigned char iv[MAX_BLOCKSIZE]; + } u_iv; + + /* The counter for CTR mode. This field is also used by AESWRAP and + thus we can't use the U_IV union. */ + union { + cipher_context_alignment_t iv_align; + unsigned char ctr[MAX_BLOCKSIZE]; + } u_ctr; + + /* Space to save an IV or CTR for chaining operations. */ + unsigned char lastiv[MAX_BLOCKSIZE]; + int unused; /* Number of unused bytes in LASTIV. */ + + /* What follows are two contexts of the cipher in use. The first + one needs to be aligned well enough for the cipher operation + whereas the second one is a copy created by cipher_setkey and + used by cipher_reset. That second copy has no need for proper + aligment because it is only accessed by memcpy. */ + cipher_context_alignment_t context; +}; + + + +/* These dummy functions are used in case a cipher implementation + refuses to provide it's own functions. */ + +static gcry_err_code_t +dummy_setkey (void *c, const unsigned char *key, unsigned int keylen) +{ + (void)c; + (void)key; + (void)keylen; + return GPG_ERR_NO_ERROR; +} + +static void +dummy_encrypt_block (void *c, + unsigned char *outbuf, const unsigned char *inbuf) +{ + (void)c; + (void)outbuf; + (void)inbuf; + BUG(); +} + +static void +dummy_decrypt_block (void *c, + unsigned char *outbuf, const unsigned char *inbuf) +{ + (void)c; + (void)outbuf; + (void)inbuf; + BUG(); +} + +static void +dummy_encrypt_stream (void *c, + unsigned char *outbuf, const unsigned char *inbuf, + unsigned int n) +{ + (void)c; + (void)outbuf; + (void)inbuf; + (void)n; + BUG(); +} + +static void +dummy_decrypt_stream (void *c, + unsigned char *outbuf, const unsigned char *inbuf, + unsigned int n) +{ + (void)c; + (void)outbuf; + (void)inbuf; + (void)n; + BUG(); +} + + +/* Internal function. Register all the ciphers included in + CIPHER_TABLE. Note, that this function gets only used by the macro + REGISTER_DEFAULT_CIPHERS which protects it using a mutex. */ +static void +cipher_register_default (void) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + int i; + + for (i = 0; !err && cipher_table[i].cipher; i++) + { + if (! cipher_table[i].cipher->setkey) + cipher_table[i].cipher->setkey = dummy_setkey; + if (! cipher_table[i].cipher->encrypt) + cipher_table[i].cipher->encrypt = dummy_encrypt_block; + if (! cipher_table[i].cipher->decrypt) + cipher_table[i].cipher->decrypt = dummy_decrypt_block; + if (! cipher_table[i].cipher->stencrypt) + cipher_table[i].cipher->stencrypt = dummy_encrypt_stream; + if (! cipher_table[i].cipher->stdecrypt) + cipher_table[i].cipher->stdecrypt = dummy_decrypt_stream; + + if ( fips_mode () && !cipher_table[i].fips_allowed ) + continue; + + err = _gcry_module_add (&ciphers_registered, + cipher_table[i].algorithm, + (void *) cipher_table[i].cipher, + (void *) cipher_table[i].extraspec, + NULL); + } + + if (err) + BUG (); +} + +/* Internal callback function. Used via _gcry_module_lookup. */ +static int +gcry_cipher_lookup_func_name (void *spec, void *data) +{ + gcry_cipher_spec_t *cipher = (gcry_cipher_spec_t *) spec; + char *name = (char *) data; + const char **aliases = cipher->aliases; + int i, ret = ! stricmp (name, cipher->name); + + if (aliases) + for (i = 0; aliases[i] && (! ret); i++) + ret = ! stricmp (name, aliases[i]); + + return ret; +} + +/* Internal callback function. Used via _gcry_module_lookup. */ +static int +gcry_cipher_lookup_func_oid (void *spec, void *data) +{ + gcry_cipher_spec_t *cipher = (gcry_cipher_spec_t *) spec; + char *oid = (char *) data; + gcry_cipher_oid_spec_t *oid_specs = cipher->oids; + int ret = 0, i; + + if (oid_specs) + for (i = 0; oid_specs[i].oid && (! ret); i++) + if (! stricmp (oid, oid_specs[i].oid)) + ret = 1; + + return ret; +} + +/* Internal function. Lookup a cipher entry by it's name. */ +static gcry_module_t +gcry_cipher_lookup_name (const char *name) +{ + gcry_module_t cipher; + + cipher = _gcry_module_lookup (ciphers_registered, (void *) name, + gcry_cipher_lookup_func_name); + + return cipher; +} + +/* Internal function. Lookup a cipher entry by it's oid. */ +static gcry_module_t +gcry_cipher_lookup_oid (const char *oid) +{ + gcry_module_t cipher; + + cipher = _gcry_module_lookup (ciphers_registered, (void *) oid, + gcry_cipher_lookup_func_oid); + + return cipher; +} + +/* Register a new cipher module whose specification can be found in + CIPHER. On success, a new algorithm ID is stored in ALGORITHM_ID + and a pointer representhing this module is stored in MODULE. */ +gcry_error_t +_gcry_cipher_register (gcry_cipher_spec_t *cipher, + cipher_extra_spec_t *extraspec, + int *algorithm_id, + gcry_module_t *module) +{ + gcry_err_code_t err = 0; + gcry_module_t mod; + + /* We do not support module loading in fips mode. */ + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + ath_mutex_lock (&ciphers_registered_lock); + err = _gcry_module_add (&ciphers_registered, 0, + (void *)cipher, + (void *)(extraspec? extraspec : &dummy_extra_spec), + &mod); + ath_mutex_unlock (&ciphers_registered_lock); + + if (! err) + { + *module = mod; + *algorithm_id = mod->mod_id; + } + + return gcry_error (err); +} + +/* Unregister the cipher identified by MODULE, which must have been + registered with gcry_cipher_register. */ +void +gcry_cipher_unregister (gcry_module_t module) +{ + ath_mutex_lock (&ciphers_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&ciphers_registered_lock); +} + +/* Locate the OID in the oid table and return the index or -1 when not + found. An opitonal "oid." or "OID." prefix in OID is ignored, the + OID is expected to be in standard IETF dotted notation. The + internal algorithm number is returned in ALGORITHM unless it + ispassed as NULL. A pointer to the specification of the module + implementing this algorithm is return in OID_SPEC unless passed as + NULL.*/ +static int +search_oid (const char *oid, int *algorithm, gcry_cipher_oid_spec_t *oid_spec) +{ + gcry_module_t module; + int ret = 0; + + if (oid && ((! strncmp (oid, "oid.", 4)) + || (! strncmp (oid, "OID.", 4)))) + oid += 4; + + module = gcry_cipher_lookup_oid (oid); + if (module) + { + gcry_cipher_spec_t *cipher = module->spec; + int i; + + for (i = 0; cipher->oids[i].oid && !ret; i++) + if (! stricmp (oid, cipher->oids[i].oid)) + { + if (algorithm) + *algorithm = module->mod_id; + if (oid_spec) + *oid_spec = cipher->oids[i]; + ret = 1; + } + _gcry_module_release (module); + } + + return ret; +} + +/* Map STRING to the cipher algorithm identifier. Returns the + algorithm ID of the cipher for the given name or 0 if the name is + not known. It is valid to pass NULL for STRING which results in a + return value of 0. */ +int +gcry_cipher_map_name (const char *string) +{ + gcry_module_t cipher; + int ret, algorithm = 0; + + if (! string) + return 0; + + REGISTER_DEFAULT_CIPHERS; + + /* If the string starts with a digit (optionally prefixed with + either "OID." or "oid."), we first look into our table of ASN.1 + object identifiers to figure out the algorithm */ + + ath_mutex_lock (&ciphers_registered_lock); + + ret = search_oid (string, &algorithm, NULL); + if (! ret) + { + cipher = gcry_cipher_lookup_name (string); + if (cipher) + { + algorithm = cipher->mod_id; + _gcry_module_release (cipher); + } + } + + ath_mutex_unlock (&ciphers_registered_lock); + + return algorithm; +} + + +/* Given a STRING with an OID in dotted decimal notation, this + function returns the cipher mode (GCRY_CIPHER_MODE_*) associated + with that OID or 0 if no mode is known. Passing NULL for string + yields a return value of 0. */ +int +gcry_cipher_mode_from_oid (const char *string) +{ + gcry_cipher_oid_spec_t oid_spec; + int ret = 0, mode = 0; + + if (!string) + return 0; + + ath_mutex_lock (&ciphers_registered_lock); + ret = search_oid (string, NULL, &oid_spec); + if (ret) + mode = oid_spec.mode; + ath_mutex_unlock (&ciphers_registered_lock); + + return mode; +} + + +/* Map the cipher algorithm whose ID is contained in ALGORITHM to a + string representation of the algorithm name. For unknown algorithm + IDs this function returns "?". */ +static const char * +cipher_algo_to_string (int algorithm) +{ + gcry_module_t cipher; + const char *name; + + REGISTER_DEFAULT_CIPHERS; + + ath_mutex_lock (&ciphers_registered_lock); + cipher = _gcry_module_lookup_id (ciphers_registered, algorithm); + if (cipher) + { + name = ((gcry_cipher_spec_t *) cipher->spec)->name; + _gcry_module_release (cipher); + } + else + name = "?"; + ath_mutex_unlock (&ciphers_registered_lock); + + return name; +} + +/* Map the cipher algorithm identifier ALGORITHM to a string + representing this algorithm. This string is the default name as + used by Libgcrypt. An pointer to an empty string is returned for + an unknown algorithm. NULL is never returned. */ +const char * +gcry_cipher_algo_name (int algorithm) +{ + return cipher_algo_to_string (algorithm); +} + + +/* Flag the cipher algorithm with the identifier ALGORITHM as + disabled. There is no error return, the function does nothing for + unknown algorithms. Disabled algorithms are vitually not available + in Libgcrypt. */ +static void +disable_cipher_algo (int algorithm) +{ + gcry_module_t cipher; + + REGISTER_DEFAULT_CIPHERS; + + ath_mutex_lock (&ciphers_registered_lock); + cipher = _gcry_module_lookup_id (ciphers_registered, algorithm); + if (cipher) + { + if (! (cipher->flags & FLAG_MODULE_DISABLED)) + cipher->flags |= FLAG_MODULE_DISABLED; + _gcry_module_release (cipher); + } + ath_mutex_unlock (&ciphers_registered_lock); +} + + +/* Return 0 if the cipher algorithm with identifier ALGORITHM is + available. Returns a basic error code value if it is not + available. */ +static gcry_err_code_t +check_cipher_algo (int algorithm) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_module_t cipher; + + REGISTER_DEFAULT_CIPHERS; + + ath_mutex_lock (&ciphers_registered_lock); + cipher = _gcry_module_lookup_id (ciphers_registered, algorithm); + if (cipher) + { + if (cipher->flags & FLAG_MODULE_DISABLED) + err = GPG_ERR_CIPHER_ALGO; + _gcry_module_release (cipher); + } + else + err = GPG_ERR_CIPHER_ALGO; + ath_mutex_unlock (&ciphers_registered_lock); + + return err; +} + + +/* Return the standard length in bits of the key for the cipher + algorithm with the identifier ALGORITHM. */ +static unsigned int +cipher_get_keylen (int algorithm) +{ + gcry_module_t cipher; + unsigned len = 0; + + REGISTER_DEFAULT_CIPHERS; + + ath_mutex_lock (&ciphers_registered_lock); + cipher = _gcry_module_lookup_id (ciphers_registered, algorithm); + if (cipher) + { + len = ((gcry_cipher_spec_t *) cipher->spec)->keylen; + if (!len) + log_bug ("cipher %d w/o key length\n", algorithm); + _gcry_module_release (cipher); + } + ath_mutex_unlock (&ciphers_registered_lock); + + return len; +} + +/* Return the block length of the cipher algorithm with the identifier + ALGORITHM. This function return 0 for an invalid algorithm. */ +static unsigned int +cipher_get_blocksize (int algorithm) +{ + gcry_module_t cipher; + unsigned len = 0; + + REGISTER_DEFAULT_CIPHERS; + + ath_mutex_lock (&ciphers_registered_lock); + cipher = _gcry_module_lookup_id (ciphers_registered, algorithm); + if (cipher) + { + len = ((gcry_cipher_spec_t *) cipher->spec)->blocksize; + if (! len) + log_bug ("cipher %d w/o blocksize\n", algorithm); + _gcry_module_release (cipher); + } + ath_mutex_unlock (&ciphers_registered_lock); + + return len; +} + + +/* + Open a cipher handle for use with cipher algorithm ALGORITHM, using + the cipher mode MODE (one of the GCRY_CIPHER_MODE_*) and return a + handle in HANDLE. Put NULL into HANDLE and return an error code if + something goes wrong. FLAGS may be used to modify the + operation. The defined flags are: + + GCRY_CIPHER_SECURE: allocate all internal buffers in secure memory. + GCRY_CIPHER_ENABLE_SYNC: Enable the sync operation as used in OpenPGP. + GCRY_CIPHER_CBC_CTS: Enable CTS mode. + GCRY_CIPHER_CBC_MAC: Enable MAC mode. + + Values for these flags may be combined using OR. + */ +gcry_error_t +gcry_cipher_open (gcry_cipher_hd_t *handle, + int algo, int mode, unsigned int flags) +{ + int secure = (flags & GCRY_CIPHER_SECURE); + gcry_cipher_spec_t *cipher = NULL; + cipher_extra_spec_t *extraspec = NULL; + gcry_module_t module = NULL; + gcry_cipher_hd_t h = NULL; + gcry_err_code_t err = 0; + + /* If the application missed to call the random poll function, we do + it here to ensure that it is used once in a while. */ + _gcry_fast_random_poll (); + + REGISTER_DEFAULT_CIPHERS; + + /* Fetch the according module and check whether the cipher is marked + available for use. */ + ath_mutex_lock (&ciphers_registered_lock); + module = _gcry_module_lookup_id (ciphers_registered, algo); + if (module) + { + /* Found module. */ + + if (module->flags & FLAG_MODULE_DISABLED) + { + /* Not available for use. */ + err = GPG_ERR_CIPHER_ALGO; + } + else + { + cipher = (gcry_cipher_spec_t *) module->spec; + extraspec = module->extraspec; + } + } + else + err = GPG_ERR_CIPHER_ALGO; + ath_mutex_unlock (&ciphers_registered_lock); + + /* check flags */ + if ((! err) + && ((flags & ~(0 + | GCRY_CIPHER_SECURE + | GCRY_CIPHER_ENABLE_SYNC + | GCRY_CIPHER_CBC_CTS + | GCRY_CIPHER_CBC_MAC)) + || (flags & GCRY_CIPHER_CBC_CTS & GCRY_CIPHER_CBC_MAC))) + err = GPG_ERR_CIPHER_ALGO; + + /* check that a valid mode has been requested */ + if (! err) + switch (mode) + { + case GCRY_CIPHER_MODE_ECB: + case GCRY_CIPHER_MODE_CBC: + case GCRY_CIPHER_MODE_CFB: + case GCRY_CIPHER_MODE_OFB: + case GCRY_CIPHER_MODE_CTR: + case GCRY_CIPHER_MODE_AESWRAP: + if ((cipher->encrypt == dummy_encrypt_block) + || (cipher->decrypt == dummy_decrypt_block)) + err = GPG_ERR_INV_CIPHER_MODE; + break; + + case GCRY_CIPHER_MODE_STREAM: + if ((cipher->stencrypt == dummy_encrypt_stream) + || (cipher->stdecrypt == dummy_decrypt_stream)) + err = GPG_ERR_INV_CIPHER_MODE; + break; + + case GCRY_CIPHER_MODE_NONE: + /* This mode may be used for debugging. It copies the main + text verbatim to the ciphertext. We do not allow this in + fips mode or if no debug flag has been set. */ + if (fips_mode () || !_gcry_get_debug_flag (0)) + err = GPG_ERR_INV_CIPHER_MODE; + break; + + default: + err = GPG_ERR_INV_CIPHER_MODE; + } + + /* Perform selftest here and mark this with a flag in cipher_table? + No, we should not do this as it takes too long. Further it does + not make sense to exclude algorithms with failing selftests at + runtime: If a selftest fails there is something seriously wrong + with the system and thus we better die immediately. */ + + if (! err) + { + size_t size = (sizeof (*h) + + 2 * cipher->contextsize + - sizeof (cipher_context_alignment_t) +#ifdef NEED_16BYTE_ALIGNED_CONTEXT + + 15 /* Space for leading alignment gap. */ +#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/ + ); + + if (secure) + h = gcry_calloc_secure (1, size); + else + h = gcry_calloc (1, size); + + if (! h) + err = gpg_err_code_from_syserror (); + else + { + size_t off = 0; + +#ifdef NEED_16BYTE_ALIGNED_CONTEXT + if ( ((unsigned long)h & 0x0f) ) + { + /* The malloced block is not aligned on a 16 byte + boundary. Correct for this. */ + off = 16 - ((unsigned long)h & 0x0f); + h = (void*)((char*)h + off); + } +#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/ + + h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL; + h->actual_handle_size = size - off; + h->handle_offset = off; + h->cipher = cipher; + h->extraspec = extraspec; + h->module = module; + h->algo = algo; + h->mode = mode; + h->flags = flags; + + /* Setup bulk encryption routines. */ + switch (algo) + { +#ifdef USE_AES + case GCRY_CIPHER_AES128: + case GCRY_CIPHER_AES192: + case GCRY_CIPHER_AES256: + h->bulk.cfb_enc = _gcry_aes_cfb_enc; + h->bulk.cfb_dec = _gcry_aes_cfb_dec; + h->bulk.cbc_enc = _gcry_aes_cbc_enc; + h->bulk.cbc_dec = _gcry_aes_cbc_dec; + h->bulk.ctr_enc = _gcry_aes_ctr_enc; + break; +#endif /*USE_AES*/ + + default: + break; + } + } + } + + /* Done. */ + + if (err) + { + if (module) + { + /* Release module. */ + ath_mutex_lock (&ciphers_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&ciphers_registered_lock); + } + } + + *handle = err ? NULL : h; + + return gcry_error (err); +} + + +/* Release all resources associated with the cipher handle H. H may be + NULL in which case this is a no-operation. */ +void +gcry_cipher_close (gcry_cipher_hd_t h) +{ + size_t off; + + if (!h) + return; + + if ((h->magic != CTX_MAGIC_SECURE) + && (h->magic != CTX_MAGIC_NORMAL)) + _gcry_fatal_error(GPG_ERR_INTERNAL, + "gcry_cipher_close: already closed/invalid handle"); + else + h->magic = 0; + + /* Release module. */ + ath_mutex_lock (&ciphers_registered_lock); + _gcry_module_release (h->module); + ath_mutex_unlock (&ciphers_registered_lock); + + /* We always want to wipe out the memory even when the context has + been allocated in secure memory. The user might have disabled + secure memory or is using his own implementation which does not + do the wiping. To accomplish this we need to keep track of the + actual size of this structure because we have no way to known + how large the allocated area was when using a standard malloc. */ + off = h->handle_offset; + wipememory (h, h->actual_handle_size); + + gcry_free ((char*)h - off); +} + + +/* Set the key to be used for the encryption context C to KEY with + length KEYLEN. The length should match the required length. */ +static gcry_error_t +cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen) +{ + gcry_err_code_t ret; + + ret = (*c->cipher->setkey) (&c->context.c, key, keylen); + if (!ret) + { + /* Duplicate initial context. */ + memcpy ((void *) ((char *) &c->context.c + c->cipher->contextsize), + (void *) &c->context.c, + c->cipher->contextsize); + c->marks.key = 1; + } + else + c->marks.key = 0; + + return gcry_error (ret); +} + + +/* Set the IV to be used for the encryption context C to IV with + length IVLEN. The length should match the required length. */ +static void +cipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen ) +{ + memset (c->u_iv.iv, 0, c->cipher->blocksize); + if (iv) + { + if (ivlen != c->cipher->blocksize) + { + log_info ("WARNING: cipher_setiv: ivlen=%u blklen=%u\n", + ivlen, (unsigned int)c->cipher->blocksize); + fips_signal_error ("IV length does not match blocklength"); + } + if (ivlen > c->cipher->blocksize) + ivlen = c->cipher->blocksize; + memcpy (c->u_iv.iv, iv, ivlen); + c->marks.iv = 1; + } + else + c->marks.iv = 0; + c->unused = 0; +} + + +/* Reset the cipher context to the initial context. This is basically + the same as an release followed by a new. */ +static void +cipher_reset (gcry_cipher_hd_t c) +{ + memcpy (&c->context.c, + (char *) &c->context.c + c->cipher->contextsize, + c->cipher->contextsize); + memset (&c->marks, 0, sizeof c->marks); + memset (c->u_iv.iv, 0, c->cipher->blocksize); + memset (c->lastiv, 0, c->cipher->blocksize); + memset (c->u_ctr.ctr, 0, c->cipher->blocksize); +} + + + +static gcry_err_code_t +do_ecb_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) +{ + unsigned int blocksize = c->cipher->blocksize; + unsigned int n, nblocks; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + if ((inbuflen % blocksize)) + return GPG_ERR_INV_LENGTH; + + nblocks = inbuflen / c->cipher->blocksize; + + for (n=0; n < nblocks; n++ ) + { + c->cipher->encrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf); + inbuf += blocksize; + outbuf += blocksize; + } + return 0; +} + +static gcry_err_code_t +do_ecb_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) +{ + unsigned int blocksize = c->cipher->blocksize; + unsigned int n, nblocks; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + if ((inbuflen % blocksize)) + return GPG_ERR_INV_LENGTH; + nblocks = inbuflen / c->cipher->blocksize; + + for (n=0; n < nblocks; n++ ) + { + c->cipher->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf ); + inbuf += blocksize; + outbuf += blocksize; + } + + return 0; +} + + +static gcry_err_code_t +do_cbc_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) +{ + unsigned int n; + unsigned char *ivp; + int i; + size_t blocksize = c->cipher->blocksize; + unsigned nblocks = inbuflen / blocksize; + + if (outbuflen < ((c->flags & GCRY_CIPHER_CBC_MAC)? blocksize : inbuflen)) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ((inbuflen % c->cipher->blocksize) + && !(inbuflen > c->cipher->blocksize + && (c->flags & GCRY_CIPHER_CBC_CTS))) + return GPG_ERR_INV_LENGTH; + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) + { + if ((inbuflen % blocksize) == 0) + nblocks--; + } + + if (c->bulk.cbc_enc) + { + c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks, + (c->flags & GCRY_CIPHER_CBC_MAC)); + inbuf += nblocks * blocksize; + if (!(c->flags & GCRY_CIPHER_CBC_MAC)) + outbuf += nblocks * blocksize; + } + else + { + for (n=0; n < nblocks; n++ ) + { + for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) + outbuf[i] = inbuf[i] ^ *ivp++; + c->cipher->encrypt ( &c->context.c, outbuf, outbuf ); + memcpy (c->u_iv.iv, outbuf, blocksize ); + inbuf += blocksize; + if (!(c->flags & GCRY_CIPHER_CBC_MAC)) + outbuf += blocksize; + } + } + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) + { + /* We have to be careful here, since outbuf might be equal to + inbuf. */ + int restbytes; + unsigned char b; + + if ((inbuflen % blocksize) == 0) + restbytes = blocksize; + else + restbytes = inbuflen % blocksize; + + outbuf -= blocksize; + for (ivp = c->u_iv.iv, i = 0; i < restbytes; i++) + { + b = inbuf[i]; + outbuf[blocksize + i] = outbuf[i]; + outbuf[i] = b ^ *ivp++; + } + for (; i < blocksize; i++) + outbuf[i] = 0 ^ *ivp++; + + c->cipher->encrypt (&c->context.c, outbuf, outbuf); + memcpy (c->u_iv.iv, outbuf, blocksize); + } + + return 0; +} + + +static gcry_err_code_t +do_cbc_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) +{ + unsigned int n; + unsigned char *ivp; + int i; + size_t blocksize = c->cipher->blocksize; + unsigned int nblocks = inbuflen / blocksize; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ((inbuflen % c->cipher->blocksize) + && !(inbuflen > c->cipher->blocksize + && (c->flags & GCRY_CIPHER_CBC_CTS))) + return GPG_ERR_INV_LENGTH; + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) + { + nblocks--; + if ((inbuflen % blocksize) == 0) + nblocks--; + memcpy (c->lastiv, c->u_iv.iv, blocksize); + } + + if (c->bulk.cbc_dec) + { + c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); + inbuf += nblocks * blocksize; + outbuf += nblocks * blocksize; + } + else + { + for (n=0; n < nblocks; n++ ) + { + /* Because outbuf and inbuf might be the same, we have to + * save the original ciphertext block. We use LASTIV for + * this here because it is not used otherwise. */ + memcpy (c->lastiv, inbuf, blocksize); + c->cipher->decrypt ( &c->context.c, outbuf, inbuf ); + for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) + outbuf[i] ^= *ivp++; + memcpy(c->u_iv.iv, c->lastiv, blocksize ); + inbuf += c->cipher->blocksize; + outbuf += c->cipher->blocksize; + } + } + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) + { + int restbytes; + + if ((inbuflen % blocksize) == 0) + restbytes = blocksize; + else + restbytes = inbuflen % blocksize; + + memcpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */ + memcpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */ + + c->cipher->decrypt ( &c->context.c, outbuf, inbuf ); + for (ivp=c->u_iv.iv,i=0; i < restbytes; i++ ) + outbuf[i] ^= *ivp++; + + memcpy(outbuf + blocksize, outbuf, restbytes); + for(i=restbytes; i < blocksize; i++) + c->u_iv.iv[i] = outbuf[i]; + c->cipher->decrypt (&c->context.c, outbuf, c->u_iv.iv); + for(ivp=c->lastiv,i=0; i < blocksize; i++ ) + outbuf[i] ^= *ivp++; + /* c->lastiv is now really lastlastiv, does this matter? */ + } + + return 0; +} + + +static gcry_err_code_t +do_cfb_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) +{ + unsigned char *ivp; + size_t blocksize = c->cipher->blocksize; + size_t blocksize_x_2 = blocksize + blocksize; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ( inbuflen <= c->unused ) + { + /* Short enough to be encoded by the remaining XOR mask. */ + /* XOR the input with the IV and store input into IV. */ + for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused; + inbuflen; + inbuflen--, c->unused-- ) + *outbuf++ = (*ivp++ ^= *inbuf++); + return 0; + } + + if ( c->unused ) + { + /* XOR the input with the IV and store input into IV */ + inbuflen -= c->unused; + for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) + *outbuf++ = (*ivp++ ^= *inbuf++); + } + + /* Now we can process complete blocks. We use a loop as long as we + have at least 2 blocks and use conditions for the rest. This + also allows to use a bulk encryption function if available. */ + if (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc) + { + unsigned int nblocks = inbuflen / blocksize; + c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); + outbuf += nblocks * blocksize; + inbuf += nblocks * blocksize; + inbuflen -= nblocks * blocksize; + } + else + { + while ( inbuflen >= blocksize_x_2 ) + { + int i; + /* Encrypt the IV. */ + c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + /* XOR the input with the IV and store input into IV. */ + for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) + *outbuf++ = (*ivp++ ^= *inbuf++); + inbuflen -= blocksize; + } + } + + if ( inbuflen >= blocksize ) + { + int i; + /* Save the current IV and then encrypt the IV. */ + memcpy( c->lastiv, c->u_iv.iv, blocksize ); + c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + /* XOR the input with the IV and store input into IV */ + for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) + *outbuf++ = (*ivp++ ^= *inbuf++); + inbuflen -= blocksize; + } + if ( inbuflen ) + { + /* Save the current IV and then encrypt the IV. */ + memcpy( c->lastiv, c->u_iv.iv, blocksize ); + c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + c->unused = blocksize; + /* Apply the XOR. */ + c->unused -= inbuflen; + for(ivp=c->u_iv.iv; inbuflen; inbuflen-- ) + *outbuf++ = (*ivp++ ^= *inbuf++); + } + return 0; +} + + +static gcry_err_code_t +do_cfb_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) +{ + unsigned char *ivp; + unsigned long temp; + int i; + size_t blocksize = c->cipher->blocksize; + size_t blocksize_x_2 = blocksize + blocksize; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if (inbuflen <= c->unused) + { + /* Short enough to be encoded by the remaining XOR mask. */ + /* XOR the input with the IV and store input into IV. */ + for (ivp=c->u_iv.iv+blocksize - c->unused; + inbuflen; + inbuflen--, c->unused--) + { + temp = *inbuf++; + *outbuf++ = *ivp ^ temp; + *ivp++ = temp; + } + return 0; + } + + if (c->unused) + { + /* XOR the input with the IV and store input into IV. */ + inbuflen -= c->unused; + for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) + { + temp = *inbuf++; + *outbuf++ = *ivp ^ temp; + *ivp++ = temp; + } + } + + /* Now we can process complete blocks. We use a loop as long as we + have at least 2 blocks and use conditions for the rest. This + also allows to use a bulk encryption function if available. */ + if (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec) + { + unsigned int nblocks = inbuflen / blocksize; + c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); + outbuf += nblocks * blocksize; + inbuf += nblocks * blocksize; + inbuflen -= nblocks * blocksize; + } + else + { + while (inbuflen >= blocksize_x_2 ) + { + /* Encrypt the IV. */ + c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + /* XOR the input with the IV and store input into IV. */ + for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) + { + temp = *inbuf++; + *outbuf++ = *ivp ^ temp; + *ivp++ = temp; + } + inbuflen -= blocksize; + } + } + + if (inbuflen >= blocksize ) + { + /* Save the current IV and then encrypt the IV. */ + memcpy ( c->lastiv, c->u_iv.iv, blocksize); + c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + /* XOR the input with the IV and store input into IV */ + for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) + { + temp = *inbuf++; + *outbuf++ = *ivp ^ temp; + *ivp++ = temp; + } + inbuflen -= blocksize; + } + + if (inbuflen) + { + /* Save the current IV and then encrypt the IV. */ + memcpy ( c->lastiv, c->u_iv.iv, blocksize ); + c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + c->unused = blocksize; + /* Apply the XOR. */ + c->unused -= inbuflen; + for (ivp=c->u_iv.iv; inbuflen; inbuflen-- ) + { + temp = *inbuf++; + *outbuf++ = *ivp ^ temp; + *ivp++ = temp; + } + } + return 0; +} + + +static gcry_err_code_t +do_ofb_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) +{ + unsigned char *ivp; + size_t blocksize = c->cipher->blocksize; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ( inbuflen <= c->unused ) + { + /* Short enough to be encoded by the remaining XOR mask. */ + /* XOR the input with the IV */ + for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused; + inbuflen; + inbuflen--, c->unused-- ) + *outbuf++ = (*ivp++ ^ *inbuf++); + return 0; + } + + if( c->unused ) + { + inbuflen -= c->unused; + for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) + *outbuf++ = (*ivp++ ^ *inbuf++); + } + + /* Now we can process complete blocks. */ + while ( inbuflen >= blocksize ) + { + int i; + /* Encrypt the IV (and save the current one). */ + memcpy( c->lastiv, c->u_iv.iv, blocksize ); + c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + + for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) + *outbuf++ = (*ivp++ ^ *inbuf++); + inbuflen -= blocksize; + } + if ( inbuflen ) + { /* process the remaining bytes */ + memcpy( c->lastiv, c->u_iv.iv, blocksize ); + c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + c->unused = blocksize; + c->unused -= inbuflen; + for(ivp=c->u_iv.iv; inbuflen; inbuflen-- ) + *outbuf++ = (*ivp++ ^ *inbuf++); + } + return 0; +} + +static gcry_err_code_t +do_ofb_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) +{ + unsigned char *ivp; + size_t blocksize = c->cipher->blocksize; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if( inbuflen <= c->unused ) + { + /* Short enough to be encoded by the remaining XOR mask. */ + for (ivp=c->u_iv.iv+blocksize - c->unused; inbuflen; inbuflen--,c->unused--) + *outbuf++ = *ivp++ ^ *inbuf++; + return 0; + } + + if ( c->unused ) + { + inbuflen -= c->unused; + for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) + *outbuf++ = *ivp++ ^ *inbuf++; + } + + /* Now we can process complete blocks. */ + while ( inbuflen >= blocksize ) + { + int i; + /* Encrypt the IV (and save the current one). */ + memcpy( c->lastiv, c->u_iv.iv, blocksize ); + c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) + *outbuf++ = *ivp++ ^ *inbuf++; + inbuflen -= blocksize; + } + if ( inbuflen ) + { /* Process the remaining bytes. */ + /* Encrypt the IV (and save the current one). */ + memcpy( c->lastiv, c->u_iv.iv, blocksize ); + c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); + c->unused = blocksize; + c->unused -= inbuflen; + for (ivp=c->u_iv.iv; inbuflen; inbuflen-- ) + *outbuf++ = *ivp++ ^ *inbuf++; + } + return 0; +} + + +static gcry_err_code_t +do_ctr_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) +{ + unsigned int n; + int i; + unsigned int blocksize = c->cipher->blocksize; + unsigned int nblocks; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + /* First process a left over encrypted counter. */ + if (c->unused) + { + gcry_assert (c->unused < blocksize); + i = blocksize - c->unused; + for (n=0; c->unused && n < inbuflen; c->unused--, n++, i++) + { + /* XOR input with encrypted counter and store in output. */ + outbuf[n] = inbuf[n] ^ c->lastiv[i]; + } + inbuf += n; + outbuf += n; + inbuflen -= n; + } + + + /* Use a bulk method if available. */ + nblocks = inbuflen / blocksize; + if (nblocks && c->bulk.ctr_enc) + { + c->bulk.ctr_enc (&c->context.c, c->u_ctr.ctr, outbuf, inbuf, nblocks); + inbuf += nblocks * blocksize; + outbuf += nblocks * blocksize; + inbuflen -= nblocks * blocksize; + } + + /* If we don't have a bulk method use the standard method. We also + use this method for the a remaining partial block. */ + if (inbuflen) + { + unsigned char tmp[MAX_BLOCKSIZE]; + + for (n=0; n < inbuflen; n++) + { + if ((n % blocksize) == 0) + { + c->cipher->encrypt (&c->context.c, tmp, c->u_ctr.ctr); + + for (i = blocksize; i > 0; i--) + { + c->u_ctr.ctr[i-1]++; + if (c->u_ctr.ctr[i-1] != 0) + break; + } + } + + /* XOR input with encrypted counter and store in output. */ + outbuf[n] = inbuf[n] ^ tmp[n % blocksize]; + } + + /* Save the unused bytes of the counter. */ + n %= blocksize; + c->unused = (blocksize - n) % blocksize; + if (c->unused) + memcpy (c->lastiv+n, tmp+n, c->unused); + + wipememory (tmp, sizeof tmp); + } + + return 0; +} + +static gcry_err_code_t +do_ctr_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) +{ + return do_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); +} + + +/* Perform the AES-Wrap algorithm as specified by RFC3394. We + implement this as a mode usable with any cipher algorithm of + blocksize 128. */ +static gcry_err_code_t +do_aeswrap_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen ) +{ + int j, x; + unsigned int n, i; + unsigned char *r, *a, *b; + unsigned char t[8]; + +#if MAX_BLOCKSIZE < 8 +#error Invalid block size +#endif + /* We require a cipher with a 128 bit block length. */ + if (c->cipher->blocksize != 16) + return GPG_ERR_INV_LENGTH; + + /* The output buffer must be able to hold the input data plus one + additional block. */ + if (outbuflen < inbuflen + 8) + return GPG_ERR_BUFFER_TOO_SHORT; + /* Input data must be multiple of 64 bits. */ + if (inbuflen % 8) + return GPG_ERR_INV_ARG; + + n = inbuflen / 8; + + /* We need at least two 64 bit blocks. */ + if (n < 2) + return GPG_ERR_INV_ARG; + + r = outbuf; + a = outbuf; /* We store A directly in OUTBUF. */ + b = c->u_ctr.ctr; /* B is also used to concatenate stuff. */ + + /* If an IV has been set we use that IV as the Alternative Initial + Value; if it has not been set we use the standard value. */ + if (c->marks.iv) + memcpy (a, c->u_iv.iv, 8); + else + memset (a, 0xa6, 8); + + /* Copy the inbuf to the outbuf. */ + memmove (r+8, inbuf, inbuflen); + + memset (t, 0, sizeof t); /* t := 0. */ + + for (j = 0; j <= 5; j++) + { + for (i = 1; i <= n; i++) + { + /* B := AES_k( A | R[i] ) */ + memcpy (b, a, 8); + memcpy (b+8, r+i*8, 8); + c->cipher->encrypt (&c->context.c, b, b); + /* t := t + 1 */ + for (x = 7; x >= 0; x--) + { + t[x]++; + if (t[x]) + break; + } + /* A := MSB_64(B) ^ t */ + for (x=0; x < 8; x++) + a[x] = b[x] ^ t[x]; + /* R[i] := LSB_64(B) */ + memcpy (r+i*8, b+8, 8); + } + } + + return 0; +} + +/* Perform the AES-Unwrap algorithm as specified by RFC3394. We + implement this as a mode usable with any cipher algorithm of + blocksize 128. */ +static gcry_err_code_t +do_aeswrap_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) +{ + int j, x; + unsigned int n, i; + unsigned char *r, *a, *b; + unsigned char t[8]; + +#if MAX_BLOCKSIZE < 8 +#error Invalid block size +#endif + /* We require a cipher with a 128 bit block length. */ + if (c->cipher->blocksize != 16) + return GPG_ERR_INV_LENGTH; + + /* The output buffer must be able to hold the input data minus one + additional block. Fixme: The caller has more restrictive checks + - we may want to fix them for this mode. */ + if (outbuflen + 8 < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + /* Input data must be multiple of 64 bits. */ + if (inbuflen % 8) + return GPG_ERR_INV_ARG; + + n = inbuflen / 8; + + /* We need at least three 64 bit blocks. */ + if (n < 3) + return GPG_ERR_INV_ARG; + + r = outbuf; + a = c->lastiv; /* We use c->LASTIV as buffer for A. */ + b = c->u_ctr.ctr; /* B is also used to concatenate stuff. */ + + /* Copy the inbuf to the outbuf and save A. */ + memcpy (a, inbuf, 8); + memmove (r, inbuf+8, inbuflen-8); + n--; /* Reduce to actual number of data blocks. */ + + /* t := 6 * n */ + i = n * 6; /* The range is valid because: n = inbuflen / 8 - 1. */ + for (x=0; x < 8 && x < sizeof (i); x++) + t[7-x] = i >> (8*x); + for (; x < 8; x++) + t[7-x] = 0; + + for (j = 5; j >= 0; j--) + { + for (i = n; i >= 1; i--) + { + /* B := AES_k^1( (A ^ t)| R[i] ) */ + for (x = 0; x < 8; x++) + b[x] = a[x] ^ t[x]; + memcpy (b+8, r+(i-1)*8, 8); + c->cipher->decrypt (&c->context.c, b, b); + /* t := t - 1 */ + for (x = 7; x >= 0; x--) + { + t[x]--; + if (t[x] != 0xff) + break; + } + /* A := MSB_64(B) */ + memcpy (a, b, 8); + /* R[i] := LSB_64(B) */ + memcpy (r+(i-1)*8, b+8, 8); + } + } + + /* If an IV has been set we compare against this Alternative Initial + Value; if it has not been set we compare against the standard IV. */ + if (c->marks.iv) + j = memcmp (a, c->u_iv.iv, 8); + else + { + for (j=0, x=0; x < 8; x++) + if (a[x] != 0xa6) + { + j=1; + break; + } + } + return j? GPG_ERR_CHECKSUM : 0; +} + + +/**************** + * Encrypt INBUF to OUTBUF with the mode selected at open. + * inbuf and outbuf may overlap or be the same. + * Depending on the mode some constraints apply to INBUFLEN. + */ +static gcry_err_code_t +cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) +{ + gcry_err_code_t rc; + + switch (c->mode) + { + case GCRY_CIPHER_MODE_ECB: + rc = do_ecb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CBC: + rc = do_cbc_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CFB: + rc = do_cfb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_OFB: + rc = do_ofb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CTR: + rc = do_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_AESWRAP: + rc = do_aeswrap_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_STREAM: + c->cipher->stencrypt (&c->context.c, + outbuf, (byte*)/*arggg*/inbuf, inbuflen); + rc = 0; + break; + + case GCRY_CIPHER_MODE_NONE: + if (fips_mode () || !_gcry_get_debug_flag (0)) + { + fips_signal_error ("cipher mode NONE used"); + rc = GPG_ERR_INV_CIPHER_MODE; + } + else + { + if (inbuf != outbuf) + memmove (outbuf, inbuf, inbuflen); + rc = 0; + } + break; + + default: + log_fatal ("cipher_encrypt: invalid mode %d\n", c->mode ); + rc = GPG_ERR_INV_CIPHER_MODE; + break; + } + + return rc; +} + + +/**************** + * Encrypt IN and write it to OUT. If IN is NULL, in-place encryption has + * been requested. + */ +gcry_error_t +gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize, + const void *in, size_t inlen) +{ + gcry_err_code_t err; + + if (!in) /* Caller requested in-place encryption. */ + err = cipher_encrypt (h, out, outsize, out, outsize); + else + err = cipher_encrypt (h, out, outsize, in, inlen); + + /* Failsafe: Make sure that the plaintext will never make it into + OUT if the encryption returned an error. */ + if (err && out) + memset (out, 0x42, outsize); + + return gcry_error (err); +} + + + +/**************** + * Decrypt INBUF to OUTBUF with the mode selected at open. + * inbuf and outbuf may overlap or be the same. + * Depending on the mode some some contraints apply to INBUFLEN. + */ +static gcry_err_code_t +cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) +{ + gcry_err_code_t rc; + + switch (c->mode) + { + case GCRY_CIPHER_MODE_ECB: + rc = do_ecb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CBC: + rc = do_cbc_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CFB: + rc = do_cfb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_OFB: + rc = do_ofb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CTR: + rc = do_ctr_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_AESWRAP: + rc = do_aeswrap_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_STREAM: + c->cipher->stdecrypt (&c->context.c, + outbuf, (byte*)/*arggg*/inbuf, inbuflen); + rc = 0; + break; + + case GCRY_CIPHER_MODE_NONE: + if (fips_mode () || !_gcry_get_debug_flag (0)) + { + fips_signal_error ("cipher mode NONE used"); + rc = GPG_ERR_INV_CIPHER_MODE; + } + else + { + if (inbuf != outbuf) + memmove (outbuf, inbuf, inbuflen); + rc = 0; + } + break; + + default: + log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode ); + rc = GPG_ERR_INV_CIPHER_MODE; + break; + } + + return rc; +} + + +gcry_error_t +gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize, + const void *in, size_t inlen) +{ + gcry_err_code_t err; + + if (!in) /* Caller requested in-place encryption. */ + err = cipher_decrypt (h, out, outsize, out, outsize); + else + err = cipher_decrypt (h, out, outsize, in, inlen); + + return gcry_error (err); +} + + + +/**************** + * Used for PGP's somewhat strange CFB mode. Only works if + * the corresponding flag is set. + */ +static void +cipher_sync (gcry_cipher_hd_t c) +{ + if ((c->flags & GCRY_CIPHER_ENABLE_SYNC) && c->unused) + { + memmove (c->u_iv.iv + c->unused, + c->u_iv.iv, c->cipher->blocksize - c->unused); + memcpy (c->u_iv.iv, + c->lastiv + c->cipher->blocksize - c->unused, c->unused); + c->unused = 0; + } +} + + +gcry_error_t +_gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen) +{ + return cipher_setkey (hd, (void*)key, keylen); +} + + +gcry_error_t +_gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen) +{ + cipher_setiv (hd, iv, ivlen); + return 0; +} + +/* Set counter for CTR mode. (CTR,CTRLEN) must denote a buffer of + block size length, or (NULL,0) to set the CTR to the all-zero + block. */ +gpg_error_t +_gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen) +{ + if (ctr && ctrlen == hd->cipher->blocksize) + { + memcpy (hd->u_ctr.ctr, ctr, hd->cipher->blocksize); + hd->unused = 0; + } + else if (!ctr || !ctrlen) + { + memset (hd->u_ctr.ctr, 0, hd->cipher->blocksize); + hd->unused = 0; + } + else + return gpg_error (GPG_ERR_INV_ARG); + return 0; +} + + +gcry_error_t +gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) +{ + gcry_err_code_t rc = GPG_ERR_NO_ERROR; + + switch (cmd) + { + case GCRYCTL_SET_KEY: /* Deprecated; use gcry_cipher_setkey. */ + rc = cipher_setkey( h, buffer, buflen ); + break; + + case GCRYCTL_SET_IV: /* Deprecated; use gcry_cipher_setiv. */ + cipher_setiv( h, buffer, buflen ); + break; + + case GCRYCTL_RESET: + cipher_reset (h); + break; + + case GCRYCTL_CFB_SYNC: + cipher_sync( h ); + break; + + case GCRYCTL_SET_CBC_CTS: + if (buflen) + if (h->flags & GCRY_CIPHER_CBC_MAC) + rc = GPG_ERR_INV_FLAG; + else + h->flags |= GCRY_CIPHER_CBC_CTS; + else + h->flags &= ~GCRY_CIPHER_CBC_CTS; + break; + + case GCRYCTL_SET_CBC_MAC: + if (buflen) + if (h->flags & GCRY_CIPHER_CBC_CTS) + rc = GPG_ERR_INV_FLAG; + else + h->flags |= GCRY_CIPHER_CBC_MAC; + else + h->flags &= ~GCRY_CIPHER_CBC_MAC; + break; + + case GCRYCTL_DISABLE_ALGO: + /* This command expects NULL for H and BUFFER to point to an + integer with the algo number. */ + if( h || !buffer || buflen != sizeof(int) ) + return gcry_error (GPG_ERR_CIPHER_ALGO); + disable_cipher_algo( *(int*)buffer ); + break; + + case GCRYCTL_SET_CTR: /* Deprecated; use gcry_cipher_setctr. */ + rc = gpg_err_code (_gcry_cipher_setctr (h, buffer, buflen)); + break; + + case 61: /* Disable weak key detection (private). */ + if (h->extraspec->set_extra_info) + rc = h->extraspec->set_extra_info + (&h->context.c, CIPHER_INFO_NO_WEAK_KEY, NULL, 0); + else + rc = GPG_ERR_NOT_SUPPORTED; + break; + + case 62: /* Return current input vector (private). */ + /* This is the input block as used in CFB and OFB mode which has + initially been set as IV. The returned format is: + 1 byte Actual length of the block in bytes. + n byte The block. + If the provided buffer is too short, an error is returned. */ + if (buflen < (1 + h->cipher->blocksize)) + rc = GPG_ERR_TOO_SHORT; + else + { + unsigned char *ivp; + unsigned char *dst = buffer; + int n = h->unused; + + if (!n) + n = h->cipher->blocksize; + gcry_assert (n <= h->cipher->blocksize); + *dst++ = n; + ivp = h->u_iv.iv + h->cipher->blocksize - n; + while (n--) + *dst++ = *ivp++; + } + break; + + default: + rc = GPG_ERR_INV_OP; + } + + return gcry_error (rc); +} + + +/* Return information about the cipher handle H. CMD is the kind of + information requested. BUFFER and NBYTES are reserved for now. + + There are no values for CMD yet defined. + + The function always returns GPG_ERR_INV_OP. + + */ +gcry_error_t +gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + (void)h; + (void)buffer; + (void)nbytes; + + switch (cmd) + { + default: + err = GPG_ERR_INV_OP; + } + + return gcry_error (err); +} + +/* Return information about the given cipher algorithm ALGO. + + WHAT select the kind of information returned: + + GCRYCTL_GET_KEYLEN: + Return the length of the key. If the algorithm ALGO + supports multiple key lengths, the maximum supported key length + is returned. The key length is returned as number of octets. + BUFFER and NBYTES must be zero. + + GCRYCTL_GET_BLKLEN: + Return the blocklength of the algorithm ALGO counted in octets. + BUFFER and NBYTES must be zero. + + GCRYCTL_TEST_ALGO: + Returns 0 if the specified algorithm ALGO is available for use. + BUFFER and NBYTES must be zero. + + Note: Because this function is in most cases used to return an + integer value, we can make it easier for the caller to just look at + the return value. The caller will in all cases consult the value + and thereby detecting whether a error occurred or not (i.e. while + checking the block size) + */ +gcry_error_t +gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + unsigned int ui; + + switch (what) + { + case GCRYCTL_GET_KEYLEN: + if (buffer || (! nbytes)) + err = GPG_ERR_CIPHER_ALGO; + else + { + ui = cipher_get_keylen (algo); + if ((ui > 0) && (ui <= 512)) + *nbytes = (size_t) ui / 8; + else + /* The only reason for an error is an invalid algo. */ + err = GPG_ERR_CIPHER_ALGO; + } + break; + + case GCRYCTL_GET_BLKLEN: + if (buffer || (! nbytes)) + err = GPG_ERR_CIPHER_ALGO; + else + { + ui = cipher_get_blocksize (algo); + if ((ui > 0) && (ui < 10000)) + *nbytes = ui; + else + /* The only reason is an invalid algo or a strange + blocksize. */ + err = GPG_ERR_CIPHER_ALGO; + } + break; + + case GCRYCTL_TEST_ALGO: + if (buffer || nbytes) + err = GPG_ERR_INV_ARG; + else + err = check_cipher_algo (algo); + break; + + default: + err = GPG_ERR_INV_OP; + } + + return gcry_error (err); +} + + +/* This function returns length of the key for algorithm ALGO. If the + algorithm supports multiple key lengths, the maximum supported key + length is returned. On error 0 is returned. The key length is + returned as number of octets. + + This is a convenience functions which should be preferred over + gcry_cipher_algo_info because it allows for proper type + checking. */ +size_t +gcry_cipher_get_algo_keylen (int algo) +{ + size_t n; + + if (gcry_cipher_algo_info (algo, GCRYCTL_GET_KEYLEN, NULL, &n)) + n = 0; + return n; +} + +/* This functions returns the blocklength of the algorithm ALGO + counted in octets. On error 0 is returned. + + This is a convenience functions which should be preferred over + gcry_cipher_algo_info because it allows for proper type + checking. */ +size_t +gcry_cipher_get_algo_blklen (int algo) +{ + size_t n; + + if (gcry_cipher_algo_info( algo, GCRYCTL_GET_BLKLEN, NULL, &n)) + n = 0; + return n; +} + +/* Explicitly initialize this module. */ +gcry_err_code_t +_gcry_cipher_init (void) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + REGISTER_DEFAULT_CIPHERS; + + return err; +} + +/* Get a list consisting of the IDs of the loaded cipher modules. If + LIST is zero, write the number of loaded cipher modules to + LIST_LENGTH and return. If LIST is non-zero, the first + *LIST_LENGTH algorithm IDs are stored in LIST, which must be of + according size. In case there are less cipher modules than + *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */ +gcry_error_t +gcry_cipher_list (int *list, int *list_length) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + ath_mutex_lock (&ciphers_registered_lock); + err = _gcry_module_list (ciphers_registered, list, list_length); + ath_mutex_unlock (&ciphers_registered_lock); + + return err; +} + + +/* Run the selftests for cipher algorithm ALGO with optional reporting + function REPORT. */ +gpg_error_t +_gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report) +{ + gcry_module_t module = NULL; + cipher_extra_spec_t *extraspec = NULL; + gcry_err_code_t ec = 0; + + REGISTER_DEFAULT_CIPHERS; + + ath_mutex_lock (&ciphers_registered_lock); + module = _gcry_module_lookup_id (ciphers_registered, algo); + if (module && !(module->flags & FLAG_MODULE_DISABLED)) + extraspec = module->extraspec; + ath_mutex_unlock (&ciphers_registered_lock); + if (extraspec && extraspec->selftest) + ec = extraspec->selftest (algo, extended, report); + else + { + ec = GPG_ERR_CIPHER_ALGO; + if (report) + report ("cipher", algo, "module", + module && !(module->flags & FLAG_MODULE_DISABLED)? + "no selftest available" : + module? "algorithm disabled" : "algorithm not found"); + } + + if (module) + { + ath_mutex_lock (&ciphers_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&ciphers_registered_lock); + } + return gpg_error (ec); +} diff --git a/grub-core/lib/libgcrypt/cipher/crc.c b/grub-core/lib/libgcrypt/cipher/crc.c new file mode 100644 index 0000000..28454f8 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/crc.c @@ -0,0 +1,793 @@ +/* crc.c - Cyclic redundancy checks. + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "g10lib.h" +#include "cipher.h" + +#include "bithelp.h" +#include "bufhelp.h" + + +typedef struct +{ + u32 CRC; + byte buf[4]; +} +CRC_CONTEXT; + + +/* + * Code generated by universal_crc by Danjel McGougan + * + * CRC parameters used: + * bits: 32 + * poly: 0x04c11db7 + * init: 0xffffffff + * xor: 0xffffffff + * reverse: true + * non-direct: false + * + * CRC of the string "123456789" is 0xcbf43926 + */ + +static const u32 crc32_table[1024] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, + 0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, + 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7, + 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb, + 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf, + 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, + 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a, + 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e, + 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761, + 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, + 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d, + 0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530, + 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034, + 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, + 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6, + 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2, + 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce, + 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, + 0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93, + 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f, + 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b, + 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, + 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c, + 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768, + 0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35, + 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, + 0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539, + 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88, + 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c, + 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, + 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9, + 0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd, + 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1, + 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, + 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, + 0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522, + 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026, + 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, + 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773, + 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277, + 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d, + 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, + 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81, + 0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc, + 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8, + 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, + 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f, + 0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b, + 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27, + 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, + 0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a, + 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876, + 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72, + 0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, + 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685, + 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1, + 0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d, + 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, + 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91, + 0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d, + 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9, + 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, + 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd, + 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9, + 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315, + 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, + 0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399, + 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45, + 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221, + 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, + 0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835, + 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151, + 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d, + 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, + 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1, + 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d, + 0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609, + 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, + 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, + 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9, + 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05, + 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, + 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, + 0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75, + 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711, + 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, + 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5, + 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281, + 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d, + 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, + 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, + 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d, + 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819, + 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, + 0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d, + 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69, + 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5, + 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, + 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9, + 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625, + 0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41, + 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, + 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555, + 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31, + 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed, + 0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, + 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9, + 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701, + 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056, + 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, + 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e, + 0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9, + 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0, + 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, + 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68, + 0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f, + 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018, + 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, + 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3, + 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084, + 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c, + 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, + 0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b, + 0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3, + 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4, + 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, + 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002, + 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755, + 0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72, + 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, + 0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca, + 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5, + 0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82, + 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, + 0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a, + 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d, + 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5, + 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, + 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc, + 0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04, + 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953, + 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, + 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b, + 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc, + 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8, + 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, + 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50, + 0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677, + 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120, + 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, + 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, + 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981, + 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639, + 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, + 0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, + 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6, + 0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1 +}; + +/* CRC32 */ + +static inline u32 +crc32_next (u32 crc, byte data) +{ + return (crc >> 8) ^ crc32_table[(crc & 0xff) ^ data]; +} + +/* + * Process 4 bytes in one go + */ +static inline u32 +crc32_next4 (u32 crc, u32 data) +{ + crc ^= data; + crc = crc32_table[(crc & 0xff) + 0x300] ^ + crc32_table[((crc >> 8) & 0xff) + 0x200] ^ + crc32_table[((crc >> 16) & 0xff) + 0x100] ^ + crc32_table[(crc >> 24) & 0xff]; + return crc; +} + +static void +crc32_init (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + ctx->CRC = 0 ^ 0xffffffffL; +} + +static void +crc32_write (void *context, const void *inbuf_arg, size_t inlen) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + const byte *inbuf = inbuf_arg; + u32 crc; + + if (!inbuf || !inlen) + return; + + crc = ctx->CRC; + + while (inlen >= 16) + { + inlen -= 16; + crc = crc32_next4(crc, buf_get_le32(&inbuf[0])); + crc = crc32_next4(crc, buf_get_le32(&inbuf[4])); + crc = crc32_next4(crc, buf_get_le32(&inbuf[8])); + crc = crc32_next4(crc, buf_get_le32(&inbuf[12])); + inbuf += 16; + } + + while (inlen >= 4) + { + inlen -= 4; + crc = crc32_next4(crc, buf_get_le32(inbuf)); + inbuf += 4; + } + + while (inlen--) + { + crc = crc32_next(crc, *inbuf++); + } + + ctx->CRC = crc; +} + +static byte * +crc32_read (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + return ctx->buf; +} + +static void +crc32_final (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + ctx->CRC ^= 0xffffffffL; + buf_put_be32 (ctx->buf, ctx->CRC); +} + +/* CRC32 a'la RFC 1510 */ +/* CRC of the string "123456789" is 0x2dfd2d88 */ + +static void +crc32rfc1510_init (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + ctx->CRC = 0; +} + +static void +crc32rfc1510_final (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + buf_put_be32(ctx->buf, ctx->CRC); +} + +/* CRC24 a'la RFC 2440 */ +/* + * Code generated by universal_crc by Danjel McGougan + * + * CRC parameters used: + * bits: 24 + * poly: 0x864cfb + * init: 0xb704ce + * xor: 0x000000 + * reverse: false + * non-direct: false + * + * CRC of the string "123456789" is 0x21cf02 + */ + +static const u32 crc24_table[1024] = +{ + 0x00000000, 0x00fb4c86, 0x000dd58a, 0x00f6990c, + 0x00e1e693, 0x001aaa15, 0x00ec3319, 0x00177f9f, + 0x003981a1, 0x00c2cd27, 0x0034542b, 0x00cf18ad, + 0x00d86732, 0x00232bb4, 0x00d5b2b8, 0x002efe3e, + 0x00894ec5, 0x00720243, 0x00849b4f, 0x007fd7c9, + 0x0068a856, 0x0093e4d0, 0x00657ddc, 0x009e315a, + 0x00b0cf64, 0x004b83e2, 0x00bd1aee, 0x00465668, + 0x005129f7, 0x00aa6571, 0x005cfc7d, 0x00a7b0fb, + 0x00e9d10c, 0x00129d8a, 0x00e40486, 0x001f4800, + 0x0008379f, 0x00f37b19, 0x0005e215, 0x00feae93, + 0x00d050ad, 0x002b1c2b, 0x00dd8527, 0x0026c9a1, + 0x0031b63e, 0x00cafab8, 0x003c63b4, 0x00c72f32, + 0x00609fc9, 0x009bd34f, 0x006d4a43, 0x009606c5, + 0x0081795a, 0x007a35dc, 0x008cacd0, 0x0077e056, + 0x00591e68, 0x00a252ee, 0x0054cbe2, 0x00af8764, + 0x00b8f8fb, 0x0043b47d, 0x00b52d71, 0x004e61f7, + 0x00d2a319, 0x0029ef9f, 0x00df7693, 0x00243a15, + 0x0033458a, 0x00c8090c, 0x003e9000, 0x00c5dc86, + 0x00eb22b8, 0x00106e3e, 0x00e6f732, 0x001dbbb4, + 0x000ac42b, 0x00f188ad, 0x000711a1, 0x00fc5d27, + 0x005beddc, 0x00a0a15a, 0x00563856, 0x00ad74d0, + 0x00ba0b4f, 0x004147c9, 0x00b7dec5, 0x004c9243, + 0x00626c7d, 0x009920fb, 0x006fb9f7, 0x0094f571, + 0x00838aee, 0x0078c668, 0x008e5f64, 0x007513e2, + 0x003b7215, 0x00c03e93, 0x0036a79f, 0x00cdeb19, + 0x00da9486, 0x0021d800, 0x00d7410c, 0x002c0d8a, + 0x0002f3b4, 0x00f9bf32, 0x000f263e, 0x00f46ab8, + 0x00e31527, 0x001859a1, 0x00eec0ad, 0x00158c2b, + 0x00b23cd0, 0x00497056, 0x00bfe95a, 0x0044a5dc, + 0x0053da43, 0x00a896c5, 0x005e0fc9, 0x00a5434f, + 0x008bbd71, 0x0070f1f7, 0x008668fb, 0x007d247d, + 0x006a5be2, 0x00911764, 0x00678e68, 0x009cc2ee, + 0x00a44733, 0x005f0bb5, 0x00a992b9, 0x0052de3f, + 0x0045a1a0, 0x00beed26, 0x0048742a, 0x00b338ac, + 0x009dc692, 0x00668a14, 0x00901318, 0x006b5f9e, + 0x007c2001, 0x00876c87, 0x0071f58b, 0x008ab90d, + 0x002d09f6, 0x00d64570, 0x0020dc7c, 0x00db90fa, + 0x00ccef65, 0x0037a3e3, 0x00c13aef, 0x003a7669, + 0x00148857, 0x00efc4d1, 0x00195ddd, 0x00e2115b, + 0x00f56ec4, 0x000e2242, 0x00f8bb4e, 0x0003f7c8, + 0x004d963f, 0x00b6dab9, 0x004043b5, 0x00bb0f33, + 0x00ac70ac, 0x00573c2a, 0x00a1a526, 0x005ae9a0, + 0x0074179e, 0x008f5b18, 0x0079c214, 0x00828e92, + 0x0095f10d, 0x006ebd8b, 0x00982487, 0x00636801, + 0x00c4d8fa, 0x003f947c, 0x00c90d70, 0x003241f6, + 0x00253e69, 0x00de72ef, 0x0028ebe3, 0x00d3a765, + 0x00fd595b, 0x000615dd, 0x00f08cd1, 0x000bc057, + 0x001cbfc8, 0x00e7f34e, 0x00116a42, 0x00ea26c4, + 0x0076e42a, 0x008da8ac, 0x007b31a0, 0x00807d26, + 0x009702b9, 0x006c4e3f, 0x009ad733, 0x00619bb5, + 0x004f658b, 0x00b4290d, 0x0042b001, 0x00b9fc87, + 0x00ae8318, 0x0055cf9e, 0x00a35692, 0x00581a14, + 0x00ffaaef, 0x0004e669, 0x00f27f65, 0x000933e3, + 0x001e4c7c, 0x00e500fa, 0x001399f6, 0x00e8d570, + 0x00c62b4e, 0x003d67c8, 0x00cbfec4, 0x0030b242, + 0x0027cddd, 0x00dc815b, 0x002a1857, 0x00d154d1, + 0x009f3526, 0x006479a0, 0x0092e0ac, 0x0069ac2a, + 0x007ed3b5, 0x00859f33, 0x0073063f, 0x00884ab9, + 0x00a6b487, 0x005df801, 0x00ab610d, 0x00502d8b, + 0x00475214, 0x00bc1e92, 0x004a879e, 0x00b1cb18, + 0x00167be3, 0x00ed3765, 0x001bae69, 0x00e0e2ef, + 0x00f79d70, 0x000cd1f6, 0x00fa48fa, 0x0001047c, + 0x002ffa42, 0x00d4b6c4, 0x00222fc8, 0x00d9634e, + 0x00ce1cd1, 0x00355057, 0x00c3c95b, 0x003885dd, + 0x00000000, 0x00488f66, 0x00901ecd, 0x00d891ab, + 0x00db711c, 0x0093fe7a, 0x004b6fd1, 0x0003e0b7, + 0x00b6e338, 0x00fe6c5e, 0x0026fdf5, 0x006e7293, + 0x006d9224, 0x00251d42, 0x00fd8ce9, 0x00b5038f, + 0x006cc771, 0x00244817, 0x00fcd9bc, 0x00b456da, + 0x00b7b66d, 0x00ff390b, 0x0027a8a0, 0x006f27c6, + 0x00da2449, 0x0092ab2f, 0x004a3a84, 0x0002b5e2, + 0x00015555, 0x0049da33, 0x00914b98, 0x00d9c4fe, + 0x00d88ee3, 0x00900185, 0x0048902e, 0x00001f48, + 0x0003ffff, 0x004b7099, 0x0093e132, 0x00db6e54, + 0x006e6ddb, 0x0026e2bd, 0x00fe7316, 0x00b6fc70, + 0x00b51cc7, 0x00fd93a1, 0x0025020a, 0x006d8d6c, + 0x00b44992, 0x00fcc6f4, 0x0024575f, 0x006cd839, + 0x006f388e, 0x0027b7e8, 0x00ff2643, 0x00b7a925, + 0x0002aaaa, 0x004a25cc, 0x0092b467, 0x00da3b01, + 0x00d9dbb6, 0x009154d0, 0x0049c57b, 0x00014a1d, + 0x004b5141, 0x0003de27, 0x00db4f8c, 0x0093c0ea, + 0x0090205d, 0x00d8af3b, 0x00003e90, 0x0048b1f6, + 0x00fdb279, 0x00b53d1f, 0x006dacb4, 0x002523d2, + 0x0026c365, 0x006e4c03, 0x00b6dda8, 0x00fe52ce, + 0x00279630, 0x006f1956, 0x00b788fd, 0x00ff079b, + 0x00fce72c, 0x00b4684a, 0x006cf9e1, 0x00247687, + 0x00917508, 0x00d9fa6e, 0x00016bc5, 0x0049e4a3, + 0x004a0414, 0x00028b72, 0x00da1ad9, 0x009295bf, + 0x0093dfa2, 0x00db50c4, 0x0003c16f, 0x004b4e09, + 0x0048aebe, 0x000021d8, 0x00d8b073, 0x00903f15, + 0x00253c9a, 0x006db3fc, 0x00b52257, 0x00fdad31, + 0x00fe4d86, 0x00b6c2e0, 0x006e534b, 0x0026dc2d, + 0x00ff18d3, 0x00b797b5, 0x006f061e, 0x00278978, + 0x002469cf, 0x006ce6a9, 0x00b47702, 0x00fcf864, + 0x0049fbeb, 0x0001748d, 0x00d9e526, 0x00916a40, + 0x00928af7, 0x00da0591, 0x0002943a, 0x004a1b5c, + 0x0096a282, 0x00de2de4, 0x0006bc4f, 0x004e3329, + 0x004dd39e, 0x00055cf8, 0x00ddcd53, 0x00954235, + 0x002041ba, 0x0068cedc, 0x00b05f77, 0x00f8d011, + 0x00fb30a6, 0x00b3bfc0, 0x006b2e6b, 0x0023a10d, + 0x00fa65f3, 0x00b2ea95, 0x006a7b3e, 0x0022f458, + 0x002114ef, 0x00699b89, 0x00b10a22, 0x00f98544, + 0x004c86cb, 0x000409ad, 0x00dc9806, 0x00941760, + 0x0097f7d7, 0x00df78b1, 0x0007e91a, 0x004f667c, + 0x004e2c61, 0x0006a307, 0x00de32ac, 0x0096bdca, + 0x00955d7d, 0x00ddd21b, 0x000543b0, 0x004dccd6, + 0x00f8cf59, 0x00b0403f, 0x0068d194, 0x00205ef2, + 0x0023be45, 0x006b3123, 0x00b3a088, 0x00fb2fee, + 0x0022eb10, 0x006a6476, 0x00b2f5dd, 0x00fa7abb, + 0x00f99a0c, 0x00b1156a, 0x006984c1, 0x00210ba7, + 0x00940828, 0x00dc874e, 0x000416e5, 0x004c9983, + 0x004f7934, 0x0007f652, 0x00df67f9, 0x0097e89f, + 0x00ddf3c3, 0x00957ca5, 0x004ded0e, 0x00056268, + 0x000682df, 0x004e0db9, 0x00969c12, 0x00de1374, + 0x006b10fb, 0x00239f9d, 0x00fb0e36, 0x00b38150, + 0x00b061e7, 0x00f8ee81, 0x00207f2a, 0x0068f04c, + 0x00b134b2, 0x00f9bbd4, 0x00212a7f, 0x0069a519, + 0x006a45ae, 0x0022cac8, 0x00fa5b63, 0x00b2d405, + 0x0007d78a, 0x004f58ec, 0x0097c947, 0x00df4621, + 0x00dca696, 0x009429f0, 0x004cb85b, 0x0004373d, + 0x00057d20, 0x004df246, 0x009563ed, 0x00ddec8b, + 0x00de0c3c, 0x0096835a, 0x004e12f1, 0x00069d97, + 0x00b39e18, 0x00fb117e, 0x002380d5, 0x006b0fb3, + 0x0068ef04, 0x00206062, 0x00f8f1c9, 0x00b07eaf, + 0x0069ba51, 0x00213537, 0x00f9a49c, 0x00b12bfa, + 0x00b2cb4d, 0x00fa442b, 0x0022d580, 0x006a5ae6, + 0x00df5969, 0x0097d60f, 0x004f47a4, 0x0007c8c2, + 0x00042875, 0x004ca713, 0x009436b8, 0x00dcb9de, + 0x00000000, 0x00d70983, 0x00555f80, 0x00825603, + 0x0051f286, 0x0086fb05, 0x0004ad06, 0x00d3a485, + 0x0059a88b, 0x008ea108, 0x000cf70b, 0x00dbfe88, + 0x00085a0d, 0x00df538e, 0x005d058d, 0x008a0c0e, + 0x00491c91, 0x009e1512, 0x001c4311, 0x00cb4a92, + 0x0018ee17, 0x00cfe794, 0x004db197, 0x009ab814, + 0x0010b41a, 0x00c7bd99, 0x0045eb9a, 0x0092e219, + 0x0041469c, 0x00964f1f, 0x0014191c, 0x00c3109f, + 0x006974a4, 0x00be7d27, 0x003c2b24, 0x00eb22a7, + 0x00388622, 0x00ef8fa1, 0x006dd9a2, 0x00bad021, + 0x0030dc2f, 0x00e7d5ac, 0x006583af, 0x00b28a2c, + 0x00612ea9, 0x00b6272a, 0x00347129, 0x00e378aa, + 0x00206835, 0x00f761b6, 0x007537b5, 0x00a23e36, + 0x00719ab3, 0x00a69330, 0x0024c533, 0x00f3ccb0, + 0x0079c0be, 0x00aec93d, 0x002c9f3e, 0x00fb96bd, + 0x00283238, 0x00ff3bbb, 0x007d6db8, 0x00aa643b, + 0x0029a4ce, 0x00fead4d, 0x007cfb4e, 0x00abf2cd, + 0x00785648, 0x00af5fcb, 0x002d09c8, 0x00fa004b, + 0x00700c45, 0x00a705c6, 0x002553c5, 0x00f25a46, + 0x0021fec3, 0x00f6f740, 0x0074a143, 0x00a3a8c0, + 0x0060b85f, 0x00b7b1dc, 0x0035e7df, 0x00e2ee5c, + 0x00314ad9, 0x00e6435a, 0x00641559, 0x00b31cda, + 0x003910d4, 0x00ee1957, 0x006c4f54, 0x00bb46d7, + 0x0068e252, 0x00bfebd1, 0x003dbdd2, 0x00eab451, + 0x0040d06a, 0x0097d9e9, 0x00158fea, 0x00c28669, + 0x001122ec, 0x00c62b6f, 0x00447d6c, 0x009374ef, + 0x001978e1, 0x00ce7162, 0x004c2761, 0x009b2ee2, + 0x00488a67, 0x009f83e4, 0x001dd5e7, 0x00cadc64, + 0x0009ccfb, 0x00dec578, 0x005c937b, 0x008b9af8, + 0x00583e7d, 0x008f37fe, 0x000d61fd, 0x00da687e, + 0x00506470, 0x00876df3, 0x00053bf0, 0x00d23273, + 0x000196f6, 0x00d69f75, 0x0054c976, 0x0083c0f5, + 0x00a9041b, 0x007e0d98, 0x00fc5b9b, 0x002b5218, + 0x00f8f69d, 0x002fff1e, 0x00ada91d, 0x007aa09e, + 0x00f0ac90, 0x0027a513, 0x00a5f310, 0x0072fa93, + 0x00a15e16, 0x00765795, 0x00f40196, 0x00230815, + 0x00e0188a, 0x00371109, 0x00b5470a, 0x00624e89, + 0x00b1ea0c, 0x0066e38f, 0x00e4b58c, 0x0033bc0f, + 0x00b9b001, 0x006eb982, 0x00ecef81, 0x003be602, + 0x00e84287, 0x003f4b04, 0x00bd1d07, 0x006a1484, + 0x00c070bf, 0x0017793c, 0x00952f3f, 0x004226bc, + 0x00918239, 0x00468bba, 0x00c4ddb9, 0x0013d43a, + 0x0099d834, 0x004ed1b7, 0x00cc87b4, 0x001b8e37, + 0x00c82ab2, 0x001f2331, 0x009d7532, 0x004a7cb1, + 0x00896c2e, 0x005e65ad, 0x00dc33ae, 0x000b3a2d, + 0x00d89ea8, 0x000f972b, 0x008dc128, 0x005ac8ab, + 0x00d0c4a5, 0x0007cd26, 0x00859b25, 0x005292a6, + 0x00813623, 0x00563fa0, 0x00d469a3, 0x00036020, + 0x0080a0d5, 0x0057a956, 0x00d5ff55, 0x0002f6d6, + 0x00d15253, 0x00065bd0, 0x00840dd3, 0x00530450, + 0x00d9085e, 0x000e01dd, 0x008c57de, 0x005b5e5d, + 0x0088fad8, 0x005ff35b, 0x00dda558, 0x000aacdb, + 0x00c9bc44, 0x001eb5c7, 0x009ce3c4, 0x004bea47, + 0x00984ec2, 0x004f4741, 0x00cd1142, 0x001a18c1, + 0x009014cf, 0x00471d4c, 0x00c54b4f, 0x001242cc, + 0x00c1e649, 0x0016efca, 0x0094b9c9, 0x0043b04a, + 0x00e9d471, 0x003eddf2, 0x00bc8bf1, 0x006b8272, + 0x00b826f7, 0x006f2f74, 0x00ed7977, 0x003a70f4, + 0x00b07cfa, 0x00677579, 0x00e5237a, 0x00322af9, + 0x00e18e7c, 0x003687ff, 0x00b4d1fc, 0x0063d87f, + 0x00a0c8e0, 0x0077c163, 0x00f59760, 0x00229ee3, + 0x00f13a66, 0x002633e5, 0x00a465e6, 0x00736c65, + 0x00f9606b, 0x002e69e8, 0x00ac3feb, 0x007b3668, + 0x00a892ed, 0x007f9b6e, 0x00fdcd6d, 0x002ac4ee, + 0x00000000, 0x00520936, 0x00a4126c, 0x00f61b5a, + 0x004825d8, 0x001a2cee, 0x00ec37b4, 0x00be3e82, + 0x006b0636, 0x00390f00, 0x00cf145a, 0x009d1d6c, + 0x002323ee, 0x00712ad8, 0x00873182, 0x00d538b4, + 0x00d60c6c, 0x0084055a, 0x00721e00, 0x00201736, + 0x009e29b4, 0x00cc2082, 0x003a3bd8, 0x006832ee, + 0x00bd0a5a, 0x00ef036c, 0x00191836, 0x004b1100, + 0x00f52f82, 0x00a726b4, 0x00513dee, 0x000334d8, + 0x00ac19d8, 0x00fe10ee, 0x00080bb4, 0x005a0282, + 0x00e43c00, 0x00b63536, 0x00402e6c, 0x0012275a, + 0x00c71fee, 0x009516d8, 0x00630d82, 0x003104b4, + 0x008f3a36, 0x00dd3300, 0x002b285a, 0x0079216c, + 0x007a15b4, 0x00281c82, 0x00de07d8, 0x008c0eee, + 0x0032306c, 0x0060395a, 0x00962200, 0x00c42b36, + 0x00111382, 0x00431ab4, 0x00b501ee, 0x00e708d8, + 0x0059365a, 0x000b3f6c, 0x00fd2436, 0x00af2d00, + 0x00a37f36, 0x00f17600, 0x00076d5a, 0x0055646c, + 0x00eb5aee, 0x00b953d8, 0x004f4882, 0x001d41b4, + 0x00c87900, 0x009a7036, 0x006c6b6c, 0x003e625a, + 0x00805cd8, 0x00d255ee, 0x00244eb4, 0x00764782, + 0x0075735a, 0x00277a6c, 0x00d16136, 0x00836800, + 0x003d5682, 0x006f5fb4, 0x009944ee, 0x00cb4dd8, + 0x001e756c, 0x004c7c5a, 0x00ba6700, 0x00e86e36, + 0x005650b4, 0x00045982, 0x00f242d8, 0x00a04bee, + 0x000f66ee, 0x005d6fd8, 0x00ab7482, 0x00f97db4, + 0x00474336, 0x00154a00, 0x00e3515a, 0x00b1586c, + 0x006460d8, 0x003669ee, 0x00c072b4, 0x00927b82, + 0x002c4500, 0x007e4c36, 0x0088576c, 0x00da5e5a, + 0x00d96a82, 0x008b63b4, 0x007d78ee, 0x002f71d8, + 0x00914f5a, 0x00c3466c, 0x00355d36, 0x00675400, + 0x00b26cb4, 0x00e06582, 0x00167ed8, 0x004477ee, + 0x00fa496c, 0x00a8405a, 0x005e5b00, 0x000c5236, + 0x0046ff6c, 0x0014f65a, 0x00e2ed00, 0x00b0e436, + 0x000edab4, 0x005cd382, 0x00aac8d8, 0x00f8c1ee, + 0x002df95a, 0x007ff06c, 0x0089eb36, 0x00dbe200, + 0x0065dc82, 0x0037d5b4, 0x00c1ceee, 0x0093c7d8, + 0x0090f300, 0x00c2fa36, 0x0034e16c, 0x0066e85a, + 0x00d8d6d8, 0x008adfee, 0x007cc4b4, 0x002ecd82, + 0x00fbf536, 0x00a9fc00, 0x005fe75a, 0x000dee6c, + 0x00b3d0ee, 0x00e1d9d8, 0x0017c282, 0x0045cbb4, + 0x00eae6b4, 0x00b8ef82, 0x004ef4d8, 0x001cfdee, + 0x00a2c36c, 0x00f0ca5a, 0x0006d100, 0x0054d836, + 0x0081e082, 0x00d3e9b4, 0x0025f2ee, 0x0077fbd8, + 0x00c9c55a, 0x009bcc6c, 0x006dd736, 0x003fde00, + 0x003cead8, 0x006ee3ee, 0x0098f8b4, 0x00caf182, + 0x0074cf00, 0x0026c636, 0x00d0dd6c, 0x0082d45a, + 0x0057ecee, 0x0005e5d8, 0x00f3fe82, 0x00a1f7b4, + 0x001fc936, 0x004dc000, 0x00bbdb5a, 0x00e9d26c, + 0x00e5805a, 0x00b7896c, 0x00419236, 0x00139b00, + 0x00ada582, 0x00ffacb4, 0x0009b7ee, 0x005bbed8, + 0x008e866c, 0x00dc8f5a, 0x002a9400, 0x00789d36, + 0x00c6a3b4, 0x0094aa82, 0x0062b1d8, 0x0030b8ee, + 0x00338c36, 0x00618500, 0x00979e5a, 0x00c5976c, + 0x007ba9ee, 0x0029a0d8, 0x00dfbb82, 0x008db2b4, + 0x00588a00, 0x000a8336, 0x00fc986c, 0x00ae915a, + 0x0010afd8, 0x0042a6ee, 0x00b4bdb4, 0x00e6b482, + 0x00499982, 0x001b90b4, 0x00ed8bee, 0x00bf82d8, + 0x0001bc5a, 0x0053b56c, 0x00a5ae36, 0x00f7a700, + 0x00229fb4, 0x00709682, 0x00868dd8, 0x00d484ee, + 0x006aba6c, 0x0038b35a, 0x00cea800, 0x009ca136, + 0x009f95ee, 0x00cd9cd8, 0x003b8782, 0x00698eb4, + 0x00d7b036, 0x0085b900, 0x0073a25a, 0x0021ab6c, + 0x00f493d8, 0x00a69aee, 0x005081b4, 0x00028882, + 0x00bcb600, 0x00eebf36, 0x0018a46c, 0x004aad5a +}; + +static inline +u32 crc24_init (void) +{ + return 0xce04b7; +} + +static inline +u32 crc24_next (u32 crc, byte data) +{ + return (crc >> 8) ^ crc24_table[(crc & 0xff) ^ data]; +} + +/* + * Process 4 bytes in one go + */ +static inline +u32 crc24_next4 (u32 crc, u32 data) +{ + crc ^= data; + crc = crc24_table[(crc & 0xff) + 0x300] ^ + crc24_table[((crc >> 8) & 0xff) + 0x200] ^ + crc24_table[((crc >> 16) & 0xff) + 0x100] ^ + crc24_table[(crc >> 24) & 0xff]; + return crc; +} + +static inline +u32 crc24_final (u32 crc) +{ + return crc & 0xffffff; +} + +static void +crc24rfc2440_init (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + ctx->CRC = crc24_init(); +} + +static void +crc24rfc2440_write (void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + u32 crc; + + if (!inbuf || !inlen) + return; + + crc = ctx->CRC; + + while (inlen >= 16) + { + inlen -= 16; + crc = crc24_next4(crc, buf_get_le32(&inbuf[0])); + crc = crc24_next4(crc, buf_get_le32(&inbuf[4])); + crc = crc24_next4(crc, buf_get_le32(&inbuf[8])); + crc = crc24_next4(crc, buf_get_le32(&inbuf[12])); + inbuf += 16; + } + + while (inlen >= 4) + { + inlen -= 4; + crc = crc24_next4(crc, buf_get_le32(inbuf)); + inbuf += 4; + } + + while (inlen--) + { + crc = crc24_next(crc, *inbuf++); + } + + ctx->CRC = crc; +} + +static void +crc24rfc2440_final (void *context) +{ + CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + ctx->CRC = crc24_final(ctx->CRC); + buf_put_le32 (ctx->buf, ctx->CRC); +} + +gcry_md_spec_t _gcry_digest_spec_crc32 = + { + "CRC32", NULL, 0, NULL, 4, + crc32_init, crc32_write, crc32_final, crc32_read, + sizeof (CRC_CONTEXT) + }; + +gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510 = + { + "CRC32RFC1510", NULL, 0, NULL, 4, + crc32rfc1510_init, crc32_write, + crc32rfc1510_final, crc32_read, + sizeof (CRC_CONTEXT) + }; + +gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440 = + { + "CRC24RFC2440", NULL, 0, NULL, 3, + crc24rfc2440_init, crc24rfc2440_write, + crc24rfc2440_final, crc32_read, + sizeof (CRC_CONTEXT) + }; diff --git a/grub-core/lib/libgcrypt/cipher/des.c b/grub-core/lib/libgcrypt/cipher/des.c new file mode 100644 index 0000000..96b06ae --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/des.c @@ -0,0 +1,1196 @@ +/* des.c - DES and Triple-DES encryption/decryption Algorithm + * Copyright (C) 1998, 1999, 2001, 2002, 2003, + * 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * For a description of triple encryption, see: + * Bruce Schneier: Applied Cryptography. Second Edition. + * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. + * This implementation is according to the definition of DES in FIPS + * PUB 46-2 from December 1993. + */ + + +/* + * Written by Michael Roth <mroth@nessie.de>, September 1998 + */ + + +/* + * U S A G E + * =========== + * + * For DES or Triple-DES encryption/decryption you must initialize a proper + * encryption context with a key. + * + * A DES key is 64bit wide but only 56bits of the key are used. The remaining + * bits are parity bits and they will _not_ checked in this implementation, but + * simply ignored. + * + * For Triple-DES you could use either two 64bit keys or three 64bit keys. + * The parity bits will _not_ checked, too. + * + * After initializing a context with a key you could use this context to + * encrypt or decrypt data in 64bit blocks in Electronic Codebook Mode. + * + * (In the examples below the slashes at the beginning and ending of comments + * are omited.) + * + * DES Example + * ----------- + * unsigned char key[8]; + * unsigned char plaintext[8]; + * unsigned char ciphertext[8]; + * unsigned char recoverd[8]; + * des_ctx context; + * + * * Fill 'key' and 'plaintext' with some data * + * .... + * + * * Set up the DES encryption context * + * des_setkey(context, key); + * + * * Encrypt the plaintext * + * des_ecb_encrypt(context, plaintext, ciphertext); + * + * * To recover the orginal plaintext from ciphertext use: * + * des_ecb_decrypt(context, ciphertext, recoverd); + * + * + * Triple-DES Example + * ------------------ + * unsigned char key1[8]; + * unsigned char key2[8]; + * unsigned char key3[8]; + * unsigned char plaintext[8]; + * unsigned char ciphertext[8]; + * unsigned char recoverd[8]; + * tripledes_ctx context; + * + * * If you would like to use two 64bit keys, fill 'key1' and'key2' + * then setup the encryption context: * + * tripledes_set2keys(context, key1, key2); + * + * * To use three 64bit keys with Triple-DES use: * + * tripledes_set3keys(context, key1, key2, key3); + * + * * Encrypting plaintext with Triple-DES * + * tripledes_ecb_encrypt(context, plaintext, ciphertext); + * + * * Decrypting ciphertext to recover the plaintext with Triple-DES * + * tripledes_ecb_decrypt(context, ciphertext, recoverd); + * + * + * Selftest + * -------- + * char *error_msg; + * + * * To perform a selftest of this DES/Triple-DES implementation use the + * function selftest(). It will return an error string if there are + * some problems with this library. * + * + * if ( (error_msg = selftest()) ) + * { + * fprintf(stderr, "An error in the DES/Triple-DES implementation occurred: %s\n", error_msg); + * abort(); + * } + */ + + +#include <config.h> +#include <stdio.h> +#include <string.h> /* memcpy, memcmp */ +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + +#if defined(__GNUC__) && defined(__GNU_LIBRARY__) +#define working_memcmp memcmp +#else +/* + * According to the SunOS man page, memcmp returns indeterminate sign + * depending on whether characters are signed or not. + */ +static int +working_memcmp( const char *a, const char *b, size_t n ) +{ + for( ; n; n--, a++, b++ ) + if( *a != *b ) + return (int)(*(byte*)a) - (int)(*(byte*)b); + return 0; +} +#endif + +/* + * Encryption/Decryption context of DES + */ +typedef struct _des_ctx + { + u32 encrypt_subkeys[32]; + u32 decrypt_subkeys[32]; + } +des_ctx[1]; + +/* + * Encryption/Decryption context of Triple-DES + */ +typedef struct _tripledes_ctx + { + u32 encrypt_subkeys[96]; + u32 decrypt_subkeys[96]; + struct { + int no_weak_key; + } flags; + } +tripledes_ctx[1]; + +static void des_key_schedule (const byte *, u32 *); +static int des_setkey (struct _des_ctx *, const byte *); +static int des_ecb_crypt (struct _des_ctx *, const byte *, byte *, int); +static int tripledes_set2keys (struct _tripledes_ctx *, + const byte *, const byte *); +static int tripledes_set3keys (struct _tripledes_ctx *, + const byte *, const byte *, const byte *); +static int tripledes_ecb_crypt (struct _tripledes_ctx *, + const byte *, byte *, int); +static int is_weak_key ( const byte *key ); +static const char *selftest (void); + +static int initialized; + + + + +/* + * The s-box values are permuted according to the 'primitive function P' + * and are rotated one bit to the left. + */ +static u32 sbox1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static u32 sbox2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static u32 sbox3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static u32 sbox4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static u32 sbox5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static u32 sbox6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static u32 sbox7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static u32 sbox8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + + +/* + * These two tables are part of the 'permuted choice 1' function. + * In this implementation several speed improvements are done. + */ +static u32 leftkey_swap[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static u32 rightkey_swap[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + + + +/* + * Numbers of left shifts per round for encryption subkeys. + * To calculate the decryption subkeys we just reverse the + * ordering of the calculated encryption subkeys. So their + * is no need for a decryption rotate tab. + */ +static byte encrypt_rotate_tab[16] = +{ + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + + + +/* + * Table with weak DES keys sorted in ascending order. + * In DES their are 64 known keys which are weak. They are weak + * because they produce only one, two or four different + * subkeys in the subkey scheduling process. + * The keys in this table have all their parity bits cleared. + */ +static byte weak_keys[64][8] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*w*/ + { 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e }, + { 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0 }, + { 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe }, + { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e }, /*sw*/ + { 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00 }, + { 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe }, + { 0x00, 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0 }, + { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0 }, /*sw*/ + { 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe }, + { 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00 }, + { 0x00, 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e }, + { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe }, /*sw*/ + { 0x00, 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0 }, + { 0x00, 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e }, + { 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00 }, + { 0x1e, 0x00, 0x00, 0x1e, 0x0e, 0x00, 0x00, 0x0e }, + { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 }, /*sw*/ + { 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0, 0xfe }, + { 0x1e, 0x00, 0xfe, 0xe0, 0x0e, 0x00, 0xfe, 0xf0 }, + { 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00 }, + { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e }, /*w*/ + { 0x1e, 0x1e, 0xe0, 0xe0, 0x0e, 0x0e, 0xf0, 0xf0 }, + { 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe, 0xfe }, + { 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00, 0xfe }, + { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 }, /*sw*/ + { 0x1e, 0xe0, 0xe0, 0x1e, 0x0e, 0xf0, 0xf0, 0x0e }, + { 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe, 0x00 }, + { 0x1e, 0xfe, 0x00, 0xe0, 0x0e, 0xfe, 0x00, 0xf0 }, + { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, /*sw*/ + { 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0, 0x00 }, + { 0x1e, 0xfe, 0xfe, 0x1e, 0x0e, 0xfe, 0xfe, 0x0e }, + { 0xe0, 0x00, 0x00, 0xe0, 0xf0, 0x00, 0x00, 0xf0 }, + { 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e, 0xfe }, + { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 }, /*sw*/ + { 0xe0, 0x00, 0xfe, 0x1e, 0xf0, 0x00, 0xfe, 0x0e }, + { 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00, 0xfe }, + { 0xe0, 0x1e, 0x1e, 0xe0, 0xf0, 0x0e, 0x0e, 0xf0 }, + { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e }, /*sw*/ + { 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe, 0x00 }, + { 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00 }, + { 0xe0, 0xe0, 0x1e, 0x1e, 0xf0, 0xf0, 0x0e, 0x0e }, + { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 }, /*w*/ + { 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe, 0xfe }, + { 0xe0, 0xfe, 0x00, 0x1e, 0xf0, 0xfe, 0x00, 0x0e }, + { 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e, 0x00 }, + { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe }, /*sw*/ + { 0xe0, 0xfe, 0xfe, 0xe0, 0xf0, 0xfe, 0xfe, 0xf0 }, + { 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe }, + { 0xfe, 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0 }, + { 0xfe, 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e }, + { 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00 }, /*sw*/ + { 0xfe, 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0 }, + { 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe }, + { 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00 }, + { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e }, /*sw*/ + { 0xfe, 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e }, + { 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00 }, + { 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe }, + { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 }, /*sw*/ + { 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00 }, + { 0xfe, 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e }, + { 0xfe, 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0 }, + { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe } /*w*/ +}; +static unsigned char weak_keys_chksum[20] = { + 0xD0, 0xCF, 0x07, 0x38, 0x93, 0x70, 0x8A, 0x83, 0x7D, 0xD7, + 0x8A, 0x36, 0x65, 0x29, 0x6C, 0x1F, 0x7C, 0x3F, 0xD3, 0x41 +}; + + + +/* + * Macro to swap bits across two words. + */ +#define DO_PERMUTATION(a, temp, b, offset, mask) \ + temp = ((a>>offset) ^ b) & mask; \ + b ^= temp; \ + a ^= temp<<offset; + + +/* + * This performs the 'initial permutation' of the data to be encrypted + * or decrypted. Additionally the resulting two words are rotated one bit + * to the left. + */ +#define INITIAL_PERMUTATION(left, temp, right) \ + DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ + DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ + DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ + DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ + right = (right << 1) | (right >> 31); \ + temp = (left ^ right) & 0xaaaaaaaa; \ + right ^= temp; \ + left ^= temp; \ + left = (left << 1) | (left >> 31); + +/* + * The 'inverse initial permutation'. + */ +#define FINAL_PERMUTATION(left, temp, right) \ + left = (left << 31) | (left >> 1); \ + temp = (left ^ right) & 0xaaaaaaaa; \ + left ^= temp; \ + right ^= temp; \ + right = (right << 31) | (right >> 1); \ + DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ + DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ + DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ + DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) + + +/* + * A full DES round including 'expansion function', 'sbox substitution' + * and 'primitive function P' but without swapping the left and right word. + * Please note: The data in 'from' and 'to' is already rotated one bit to + * the left, done in the initial permutation. + */ +#define DES_ROUND(from, to, work, subkey) \ + work = from ^ *subkey++; \ + to ^= sbox8[ work & 0x3f ]; \ + to ^= sbox6[ (work>>8) & 0x3f ]; \ + to ^= sbox4[ (work>>16) & 0x3f ]; \ + to ^= sbox2[ (work>>24) & 0x3f ]; \ + work = ((from << 28) | (from >> 4)) ^ *subkey++; \ + to ^= sbox7[ work & 0x3f ]; \ + to ^= sbox5[ (work>>8) & 0x3f ]; \ + to ^= sbox3[ (work>>16) & 0x3f ]; \ + to ^= sbox1[ (work>>24) & 0x3f ]; + +/* + * Macros to convert 8 bytes from/to 32bit words. + */ +#define READ_64BIT_DATA(data, left, right) \ + left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ + right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; + +#define WRITE_64BIT_DATA(data, left, right) \ + data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ + data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ + data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ + data[6] = (right >> 8) &0xff; data[7] = right &0xff; + +/* + * Handy macros for encryption and decryption of data + */ +#define des_ecb_encrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 0) +#define des_ecb_decrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 1) +#define tripledes_ecb_encrypt(ctx, from, to) tripledes_ecb_crypt(ctx,from,to,0) +#define tripledes_ecb_decrypt(ctx, from, to) tripledes_ecb_crypt(ctx,from,to,1) + + + + + + +/* + * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for + * 16 encryption rounds. + * To calculate subkeys for decryption the caller + * have to reorder the generated subkeys. + * + * rawkey: 8 Bytes of key data + * subkey: Array of at least 32 u32s. Will be filled + * with calculated subkeys. + * + */ +static void +des_key_schedule (const byte * rawkey, u32 * subkey) +{ + u32 left, right, work; + int round; + + READ_64BIT_DATA (rawkey, left, right) + + DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) + DO_PERMUTATION (right, work, left, 0, 0x10101010) + + left = ((leftkey_swap[(left >> 0) & 0xf] << 3) + | (leftkey_swap[(left >> 8) & 0xf] << 2) + | (leftkey_swap[(left >> 16) & 0xf] << 1) + | (leftkey_swap[(left >> 24) & 0xf]) + | (leftkey_swap[(left >> 5) & 0xf] << 7) + | (leftkey_swap[(left >> 13) & 0xf] << 6) + | (leftkey_swap[(left >> 21) & 0xf] << 5) + | (leftkey_swap[(left >> 29) & 0xf] << 4)); + + left &= 0x0fffffff; + + right = ((rightkey_swap[(right >> 1) & 0xf] << 3) + | (rightkey_swap[(right >> 9) & 0xf] << 2) + | (rightkey_swap[(right >> 17) & 0xf] << 1) + | (rightkey_swap[(right >> 25) & 0xf]) + | (rightkey_swap[(right >> 4) & 0xf] << 7) + | (rightkey_swap[(right >> 12) & 0xf] << 6) + | (rightkey_swap[(right >> 20) & 0xf] << 5) + | (rightkey_swap[(right >> 28) & 0xf] << 4)); + + right &= 0x0fffffff; + + for (round = 0; round < 16; ++round) + { + left = ((left << encrypt_rotate_tab[round]) + | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; + right = ((right << encrypt_rotate_tab[round]) + | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; + + *subkey++ = (((left << 4) & 0x24000000) + | ((left << 28) & 0x10000000) + | ((left << 14) & 0x08000000) + | ((left << 18) & 0x02080000) + | ((left << 6) & 0x01000000) + | ((left << 9) & 0x00200000) + | ((left >> 1) & 0x00100000) + | ((left << 10) & 0x00040000) + | ((left << 2) & 0x00020000) + | ((left >> 10) & 0x00010000) + | ((right >> 13) & 0x00002000) + | ((right >> 4) & 0x00001000) + | ((right << 6) & 0x00000800) + | ((right >> 1) & 0x00000400) + | ((right >> 14) & 0x00000200) + | (right & 0x00000100) + | ((right >> 5) & 0x00000020) + | ((right >> 10) & 0x00000010) + | ((right >> 3) & 0x00000008) + | ((right >> 18) & 0x00000004) + | ((right >> 26) & 0x00000002) + | ((right >> 24) & 0x00000001)); + + *subkey++ = (((left << 15) & 0x20000000) + | ((left << 17) & 0x10000000) + | ((left << 10) & 0x08000000) + | ((left << 22) & 0x04000000) + | ((left >> 2) & 0x02000000) + | ((left << 1) & 0x01000000) + | ((left << 16) & 0x00200000) + | ((left << 11) & 0x00100000) + | ((left << 3) & 0x00080000) + | ((left >> 6) & 0x00040000) + | ((left << 15) & 0x00020000) + | ((left >> 4) & 0x00010000) + | ((right >> 2) & 0x00002000) + | ((right << 8) & 0x00001000) + | ((right >> 14) & 0x00000808) + | ((right >> 9) & 0x00000400) + | ((right) & 0x00000200) + | ((right << 7) & 0x00000100) + | ((right >> 7) & 0x00000020) + | ((right >> 3) & 0x00000011) + | ((right << 2) & 0x00000004) + | ((right >> 21) & 0x00000002)); + } +} + + +/* + * Fill a DES context with subkeys calculated from a 64bit key. + * Does not check parity bits, but simply ignore them. + * Does not check for weak keys. + */ +static int +des_setkey (struct _des_ctx *ctx, const byte * key) +{ + static const char *selftest_failed; + int i; + + if (!fips_mode () && !initialized) + { + initialized = 1; + selftest_failed = selftest (); + + if (selftest_failed) + log_error ("%s\n", selftest_failed); + } + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + des_key_schedule (key, ctx->encrypt_subkeys); + _gcry_burn_stack (32); + + for(i=0; i<32; i+=2) + { + ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; + ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; + } + + return 0; +} + + + +/* + * Electronic Codebook Mode DES encryption/decryption of data according + * to 'mode'. + */ +static int +des_ecb_crypt (struct _des_ctx *ctx, const byte * from, byte * to, int mode) +{ + u32 left, right, work; + u32 *keys; + + keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; + + READ_64BIT_DATA (from, left, right) + INITIAL_PERMUTATION (left, work, right) + + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + + FINAL_PERMUTATION (right, work, left) + WRITE_64BIT_DATA (to, right, left) + + return 0; +} + + + +/* + * Fill a Triple-DES context with subkeys calculated from two 64bit keys. + * Does not check the parity bits of the keys, but simply ignore them. + * Does not check for weak keys. + */ +static int +tripledes_set2keys (struct _tripledes_ctx *ctx, + const byte * key1, + const byte * key2) +{ + int i; + + des_key_schedule (key1, ctx->encrypt_subkeys); + des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); + _gcry_burn_stack (32); + + for(i=0; i<32; i+=2) + { + ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; + ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; + + ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i]; + ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i]; + + ctx->encrypt_subkeys[i+64] = ctx->encrypt_subkeys[i]; + ctx->encrypt_subkeys[i+65] = ctx->encrypt_subkeys[i+1]; + + ctx->decrypt_subkeys[i+64] = ctx->decrypt_subkeys[i]; + ctx->decrypt_subkeys[i+65] = ctx->decrypt_subkeys[i+1]; + } + + return 0; +} + + + +/* + * Fill a Triple-DES context with subkeys calculated from three 64bit keys. + * Does not check the parity bits of the keys, but simply ignore them. + * Does not check for weak keys. + */ +static int +tripledes_set3keys (struct _tripledes_ctx *ctx, + const byte * key1, + const byte * key2, + const byte * key3) +{ + static const char *selftest_failed; + int i; + + if (!fips_mode () && !initialized) + { + initialized = 1; + selftest_failed = selftest (); + + if (selftest_failed) + log_error ("%s\n", selftest_failed); + } + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + des_key_schedule (key1, ctx->encrypt_subkeys); + des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); + des_key_schedule (key3, &(ctx->encrypt_subkeys[64])); + _gcry_burn_stack (32); + + for(i=0; i<32; i+=2) + { + ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[94-i]; + ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[95-i]; + + ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i]; + ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i]; + + ctx->decrypt_subkeys[i+64] = ctx->encrypt_subkeys[30-i]; + ctx->decrypt_subkeys[i+65] = ctx->encrypt_subkeys[31-i]; + } + + return 0; +} + + + +/* + * Electronic Codebook Mode Triple-DES encryption/decryption of data + * according to 'mode'. Sometimes this mode is named 'EDE' mode + * (Encryption-Decryption-Encryption). + */ +static int +tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from, + byte * to, int mode) +{ + u32 left, right, work; + u32 *keys; + + keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; + + READ_64BIT_DATA (from, left, right) + INITIAL_PERMUTATION (left, work, right) + + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) + + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) + + FINAL_PERMUTATION (right, work, left) + WRITE_64BIT_DATA (to, right, left) + + return 0; +} + + + + + +/* + * Check whether the 8 byte key is weak. + * Does not check the parity bits of the key but simple ignore them. + */ +static int +is_weak_key ( const byte *key ) +{ + byte work[8]; + int i, left, right, middle, cmp_result; + + /* clear parity bits */ + for(i=0; i<8; ++i) + work[i] = key[i] & 0xfe; + + /* binary search in the weak key table */ + left = 0; + right = 63; + while(left <= right) + { + middle = (left + right) / 2; + + if ( !(cmp_result=working_memcmp(work, weak_keys[middle], 8)) ) + return -1; + + if ( cmp_result > 0 ) + left = middle + 1; + else + right = middle - 1; + } + + return 0; +} + + + +/* + * Performs a selftest of this DES/Triple-DES implementation. + * Returns an string with the error text on failure. + * Returns NULL if all is ok. + */ +static const char * +selftest (void) +{ + /* + * Check if 'u32' is really 32 bits wide. This DES / 3DES implementation + * need this. + */ + if (sizeof (u32) != 4) + return "Wrong word size for DES configured."; + + /* + * DES Maintenance Test + */ + { + int i; + byte key[8] = + {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; + byte input[8] = + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + byte result[8] = + {0x24, 0x6e, 0x9d, 0xb9, 0xc5, 0x50, 0x38, 0x1a}; + byte temp1[8], temp2[8], temp3[8]; + des_ctx des; + + for (i = 0; i < 64; ++i) + { + des_setkey (des, key); + des_ecb_encrypt (des, input, temp1); + des_ecb_encrypt (des, temp1, temp2); + des_setkey (des, temp2); + des_ecb_decrypt (des, temp1, temp3); + memcpy (key, temp3, 8); + memcpy (input, temp1, 8); + } + if (memcmp (temp3, result, 8)) + return "DES maintenance test failed."; + } + + + /* + * Self made Triple-DES test (Does somebody know an official test?) + */ + { + int i; + byte input[8] = + {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}; + byte key1[8] = + {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}; + byte key2[8] = + {0x11, 0x22, 0x33, 0x44, 0xff, 0xaa, 0xcc, 0xdd}; + byte result[8] = + {0x7b, 0x38, 0x3b, 0x23, 0xa2, 0x7d, 0x26, 0xd3}; + + tripledes_ctx des3; + + for (i = 0; i < 16; ++i) + { + tripledes_set2keys (des3, key1, key2); + tripledes_ecb_encrypt (des3, input, key1); + tripledes_ecb_decrypt (des3, input, key2); + tripledes_set3keys (des3, key1, input, key2); + tripledes_ecb_encrypt (des3, input, input); + } + if (memcmp (input, result, 8)) + return "Triple-DES test failed."; + } + + /* + * More Triple-DES test. These are testvectors as used by SSLeay, + * thanks to Jeroen C. van Gelderen. + */ + { + struct { byte key[24]; byte plain[8]; byte cipher[8]; } testdata[] = { + { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, + { 0x95,0xF8,0xA5,0xE5,0xDD,0x31,0xD9,0x00 }, + { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } + }, + + { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, + { 0x9D,0x64,0x55,0x5A,0x9A,0x10,0xB8,0x52, }, + { 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00 } + }, + { { 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E, + 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E, + 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E }, + { 0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A }, + { 0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A } + }, + { { 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6, + 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6, + 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6 }, + { 0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2 }, + { 0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95 } + }, + { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, + 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, + 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, + { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, + { 0x3D,0x12,0x4F,0xE2,0x19,0x8B,0xA3,0x18 } + }, + { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, + 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, + 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, + { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, + { 0xFB,0xAB,0xA1,0xFF,0x9D,0x05,0xE9,0xB1 } + }, + { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, + 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, + 0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10 }, + { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, + { 0x18,0xd7,0x48,0xe5,0x63,0x62,0x05,0x72 } + }, + { { 0x03,0x52,0x02,0x07,0x67,0x20,0x82,0x17, + 0x86,0x02,0x87,0x66,0x59,0x08,0x21,0x98, + 0x64,0x05,0x6A,0xBD,0xFE,0xA9,0x34,0x57 }, + { 0x73,0x71,0x75,0x69,0x67,0x67,0x6C,0x65 }, + { 0xc0,0x7d,0x2a,0x0f,0xa5,0x66,0xfa,0x30 } + }, + { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x80,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0xe6,0xe6,0xdd,0x5b,0x7e,0x72,0x29,0x74 } + }, + { { 0x10,0x46,0x10,0x34,0x89,0x98,0x80,0x20, + 0x91,0x07,0xD0,0x15,0x89,0x19,0x01,0x01, + 0x19,0x07,0x92,0x10,0x98,0x1A,0x01,0x01 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0xe1,0xef,0x62,0xc3,0x32,0xfe,0x82,0x5b } + } + }; + + byte result[8]; + int i; + tripledes_ctx des3; + + for (i=0; i<sizeof(testdata)/sizeof(*testdata); ++i) + { + tripledes_set3keys (des3, testdata[i].key, + testdata[i].key + 8, testdata[i].key + 16); + + tripledes_ecb_encrypt (des3, testdata[i].plain, result); + if (memcmp (testdata[i].cipher, result, 8)) + return "Triple-DES SSLeay test failed on encryption."; + + tripledes_ecb_decrypt (des3, testdata[i].cipher, result); + if (memcmp (testdata[i].plain, result, 8)) + return "Triple-DES SSLeay test failed on decryption.";; + } + } + + /* + * Check the weak key detection. We simply assume that the table + * with weak keys is ok and check every key in the table if it is + * detected... (This test is a little bit stupid). + */ + { + int i; + unsigned char *p; + gcry_md_hd_t h; + + if (_gcry_md_open (&h, GCRY_MD_SHA1, 0)) + return "SHA1 not available"; + + for (i = 0; i < 64; ++i) + _gcry_md_write (h, weak_keys[i], 8); + p = _gcry_md_read (h, GCRY_MD_SHA1); + i = memcmp (p, weak_keys_chksum, 20); + _gcry_md_close (h); + if (i) + return "weak key table defect"; + + for (i = 0; i < 64; ++i) + if (!is_weak_key(weak_keys[i])) + return "DES weak key detection failed"; + } + + return 0; +} + + +static gcry_err_code_t +do_tripledes_setkey ( void *context, const byte *key, unsigned keylen ) +{ + struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; + + if( keylen != 24 ) + return GPG_ERR_INV_KEYLEN; + + tripledes_set3keys ( ctx, key, key+8, key+16); + + if (ctx->flags.no_weak_key) + ; /* Detection has been disabled. */ + else if (is_weak_key (key) || is_weak_key (key+8) || is_weak_key (key+16)) + { + _gcry_burn_stack (64); + return GPG_ERR_WEAK_KEY; + } + _gcry_burn_stack (64); + + return GPG_ERR_NO_ERROR; +} + + +static gcry_err_code_t +do_tripledes_set_extra_info (void *context, int what, + const void *buffer, size_t buflen) +{ + struct _tripledes_ctx *ctx = (struct _tripledes_ctx *)context; + gpg_err_code_t ec = 0; + + (void)buffer; + (void)buflen; + + switch (what) + { + case CIPHER_INFO_NO_WEAK_KEY: + ctx->flags.no_weak_key = 1; + break; + + default: + ec = GPG_ERR_INV_OP; + break; + } + return ec; +} + + +static void +do_tripledes_encrypt( void *context, byte *outbuf, const byte *inbuf ) +{ + struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; + + tripledes_ecb_encrypt ( ctx, inbuf, outbuf ); + _gcry_burn_stack (32); +} + +static void +do_tripledes_decrypt( void *context, byte *outbuf, const byte *inbuf ) +{ + struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; + tripledes_ecb_decrypt ( ctx, inbuf, outbuf ); + _gcry_burn_stack (32); +} + +static gcry_err_code_t +do_des_setkey (void *context, const byte *key, unsigned keylen) +{ + struct _des_ctx *ctx = (struct _des_ctx *) context; + + if (keylen != 8) + return GPG_ERR_INV_KEYLEN; + + des_setkey (ctx, key); + + if (is_weak_key (key)) { + _gcry_burn_stack (64); + return GPG_ERR_WEAK_KEY; + } + _gcry_burn_stack (64); + + return GPG_ERR_NO_ERROR; +} + + +static void +do_des_encrypt( void *context, byte *outbuf, const byte *inbuf ) +{ + struct _des_ctx *ctx = (struct _des_ctx *) context; + + des_ecb_encrypt ( ctx, inbuf, outbuf ); + _gcry_burn_stack (32); +} + +static void +do_des_decrypt( void *context, byte *outbuf, const byte *inbuf ) +{ + struct _des_ctx *ctx = (struct _des_ctx *) context; + + des_ecb_decrypt ( ctx, inbuf, outbuf ); + _gcry_burn_stack (32); +} + + + + +/* + Self-test section. + */ + + +/* Selftest for TripleDES. */ +static gpg_err_code_t +selftest_fips (int extended, selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + + (void)extended; /* No extended tests available. */ + + what = "low-level"; + errtxt = selftest (); + if (errtxt) + goto failed; + + /* The low-level self-tests are quite extensive and thus we can do + without high level tests. This is also justified because we have + no custom block code implementation for 3des but always use the + standard high level block code. */ + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("cipher", GCRY_CIPHER_3DES, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + + +/* Run a full self-test for ALGO and return 0 on success. */ +static gpg_err_code_t +run_selftests (int algo, int extended, selftest_report_func_t report) +{ + gpg_err_code_t ec; + + switch (algo) + { + case GCRY_CIPHER_3DES: + ec = selftest_fips (extended, report); + break; + default: + ec = GPG_ERR_CIPHER_ALGO; + break; + + } + return ec; +} + + + +gcry_cipher_spec_t _gcry_cipher_spec_des = + { + "DES", NULL, NULL, 8, 64, sizeof (struct _des_ctx), + do_des_setkey, do_des_encrypt, do_des_decrypt + }; + +static gcry_cipher_oid_spec_t oids_tripledes[] = + { + { "1.2.840.113549.3.7", GCRY_CIPHER_MODE_CBC }, + /* Teletrust specific OID for 3DES. */ + { "1.3.36.3.1.3.2.1", GCRY_CIPHER_MODE_CBC }, + /* pbeWithSHAAnd3_KeyTripleDES_CBC */ + { "1.2.840.113549.1.12.1.3", GCRY_CIPHER_MODE_CBC }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_tripledes = + { + "3DES", NULL, oids_tripledes, 8, 192, sizeof (struct _tripledes_ctx), + do_tripledes_setkey, do_tripledes_encrypt, do_tripledes_decrypt + }; + +cipher_extra_spec_t _gcry_cipher_extraspec_tripledes = + { + run_selftests, + do_tripledes_set_extra_info + }; diff --git a/grub-core/lib/libgcrypt/cipher/dsa.c b/grub-core/lib/libgcrypt/cipher/dsa.c new file mode 100644 index 0000000..883a815 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/dsa.c @@ -0,0 +1,1193 @@ +/* dsa.c - DSA signature algorithm + * Copyright (C) 1998, 2000, 2001, 2002, 2003, + * 2006, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "g10lib.h" +#include "mpi.h" +#include "cipher.h" + +typedef struct +{ + gcry_mpi_t p; /* prime */ + gcry_mpi_t q; /* group order */ + gcry_mpi_t g; /* group generator */ + gcry_mpi_t y; /* g^x mod p */ +} DSA_public_key; + + +typedef struct +{ + gcry_mpi_t p; /* prime */ + gcry_mpi_t q; /* group order */ + gcry_mpi_t g; /* group generator */ + gcry_mpi_t y; /* g^x mod p */ + gcry_mpi_t x; /* secret exponent */ +} DSA_secret_key; + + +/* A structure used to hold domain parameters. */ +typedef struct +{ + gcry_mpi_t p; /* prime */ + gcry_mpi_t q; /* group order */ + gcry_mpi_t g; /* group generator */ +} dsa_domain_t; + + +/* A sample 1024 bit DSA key used for the selftests. */ +static const char sample_secret_key[] = +"(private-key" +" (dsa" +" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" +" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191" +" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44" +" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)" +" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)" +" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503" +" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E" +" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984" +" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)" +" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46" +" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827" +" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20" +" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)" +" (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))"; +/* A sample 1024 bit DSA key used for the selftests (public only). */ +static const char sample_public_key[] = +"(public-key" +" (dsa" +" (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" +" 96273899DD8B2BB46CD6ECA263FAF04A28903503D59062A8865D2AE8ADFB5191" +" CF36FFB562D0E2F5809801A1F675DAE59698A9E01EFE8D7DCFCA084F4C6F5A44" +" 44D499A06FFAEA5E8EF5E01F2FD20A7B7EF3F6968AFBA1FB8D91F1559D52D8777B#)" +" (q #00EB7B5751D25EBBB7BD59D920315FD840E19AEBF9#)" +" (g #1574363387FDFD1DDF38F4FBE135BB20C7EE4772FB94C337AF86EA8E49666503" +" AE04B6BE81A2F8DD095311E0217ACA698A11E6C5D33CCDAE71498ED35D13991E" +" B02F09AB40BD8F4C5ED8C75DA779D0AE104BC34C960B002377068AB4B5A1F984" +" 3FBA91F537F1B7CAC4D8DD6D89B0D863AF7025D549F9C765D2FC07EE208F8D15#)" +" (y #64B11EF8871BE4AB572AA810D5D3CA11A6CDBC637A8014602C72960DB135BF46" +" A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827" +" 6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20" +" 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)))"; + + + + +static gcry_mpi_t gen_k (gcry_mpi_t q); +static int test_keys (DSA_secret_key *sk, unsigned int qbits); +static int check_secret_key (DSA_secret_key *sk); +static gpg_err_code_t generate (DSA_secret_key *sk, + unsigned int nbits, + unsigned int qbits, + int transient_key, + dsa_domain_t *domain, + gcry_mpi_t **ret_factors); +static void sign (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, + DSA_secret_key *skey); +static int verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, + DSA_public_key *pkey); + +static void (*progress_cb) (void *,const char *, int, int, int ); +static void *progress_cb_data; + + +void +_gcry_register_pk_dsa_progress (void (*cb) (void *, const char *, + int, int, int), + void *cb_data) +{ + progress_cb = cb; + progress_cb_data = cb_data; +} + + +static void +progress (int c) +{ + if (progress_cb) + progress_cb (progress_cb_data, "pk_dsa", c, 0, 0); +} + + +/* + * Generate a random secret exponent k less than q. + */ +static gcry_mpi_t +gen_k( gcry_mpi_t q ) +{ + gcry_mpi_t k = mpi_alloc_secure( mpi_get_nlimbs(q) ); + unsigned int nbits = mpi_get_nbits(q); + unsigned int nbytes = (nbits+7)/8; + char *rndbuf = NULL; + + /* To learn why we don't use mpi_mod to get the requested bit size, + read the paper: "The Insecurity of the Digital Signature + Algorithm with Partially Known Nonces" by Nguyen and Shparlinski. + Journal of Cryptology, New York. Vol 15, nr 3 (2003) */ + + if ( DBG_CIPHER ) + log_debug("choosing a random k "); + for (;;) + { + if( DBG_CIPHER ) + progress('.'); + + if ( !rndbuf || nbits < 32 ) + { + gcry_free(rndbuf); + rndbuf = gcry_random_bytes_secure( (nbits+7)/8, GCRY_STRONG_RANDOM ); + } + else + { /* Change only some of the higher bits. We could improve + this by directly requesting more memory at the first call + to get_random_bytes() and use these extra bytes here. + However the required management code is more complex and + thus we better use this simple method. */ + char *pp = gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM ); + memcpy( rndbuf,pp, 4 ); + gcry_free(pp); + } + _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 ); + + /* Make sure we have the requested number of bits. This code + looks a bit funny but it is easy to understand if you + consider that mpi_set_highbit clears all higher bits. We + don't have a clear_highbit, thus we first set the high bit + and then clear it again. */ + if ( mpi_test_bit( k, nbits-1 ) ) + mpi_set_highbit( k, nbits-1 ); + else + { + mpi_set_highbit( k, nbits-1 ); + mpi_clear_bit( k, nbits-1 ); + } + + if( !(mpi_cmp( k, q ) < 0) ) /* check: k < q */ + { + if( DBG_CIPHER ) + progress('+'); + continue; /* no */ + } + if( !(mpi_cmp_ui( k, 0 ) > 0) ) /* check: k > 0 */ + { + if( DBG_CIPHER ) + progress('-'); + continue; /* no */ + } + break; /* okay */ + } + gcry_free(rndbuf); + if( DBG_CIPHER ) + progress('\n'); + + return k; +} + + +/* Check that a freshly generated key actually works. Returns 0 on success. */ +static int +test_keys (DSA_secret_key *sk, unsigned int qbits) +{ + int result = -1; /* Default to failure. */ + DSA_public_key pk; + gcry_mpi_t data = gcry_mpi_new (qbits); + gcry_mpi_t sig_a = gcry_mpi_new (qbits); + gcry_mpi_t sig_b = gcry_mpi_new (qbits); + + /* Put the relevant parameters into a public key structure. */ + pk.p = sk->p; + pk.q = sk->q; + pk.g = sk->g; + pk.y = sk->y; + + /* Create a random plaintext. */ + gcry_mpi_randomize (data, qbits, GCRY_WEAK_RANDOM); + + /* Sign DATA using the secret key. */ + sign (sig_a, sig_b, data, sk); + + /* Verify the signature using the public key. */ + if ( !verify (sig_a, sig_b, data, &pk) ) + goto leave; /* Signature does not match. */ + + /* Modify the data and check that the signing fails. */ + gcry_mpi_add_ui (data, data, 1); + if ( verify (sig_a, sig_b, data, &pk) ) + goto leave; /* Signature matches but should not. */ + + result = 0; /* The test succeeded. */ + + leave: + gcry_mpi_release (sig_b); + gcry_mpi_release (sig_a); + gcry_mpi_release (data); + return result; +} + + + +/* + Generate a DSA key pair with a key of size NBITS. If transient_key + is true the key is generated using the standard RNG and not the + very secure one. + + Returns: 2 structures filled with all needed values + and an array with the n-1 factors of (p-1) + */ +static gpg_err_code_t +generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, + int transient_key, dsa_domain_t *domain, gcry_mpi_t **ret_factors ) +{ + gcry_mpi_t p; /* the prime */ + gcry_mpi_t q; /* the 160 bit prime factor */ + gcry_mpi_t g; /* the generator */ + gcry_mpi_t y; /* g^x mod p */ + gcry_mpi_t x; /* the secret exponent */ + gcry_mpi_t h, e; /* helper */ + unsigned char *rndbuf; + gcry_random_level_t random_level; + + if (qbits) + ; /* Caller supplied qbits. Use this value. */ + else if ( nbits >= 512 && nbits <= 1024 ) + qbits = 160; + else if ( nbits == 2048 ) + qbits = 224; + else if ( nbits == 3072 ) + qbits = 256; + else if ( nbits == 7680 ) + qbits = 384; + else if ( nbits == 15360 ) + qbits = 512; + else + return GPG_ERR_INV_VALUE; + + if (qbits < 160 || qbits > 512 || (qbits%8) ) + return GPG_ERR_INV_VALUE; + if (nbits < 2*qbits || nbits > 15360) + return GPG_ERR_INV_VALUE; + + if (fips_mode ()) + { + if (nbits < 1024) + return GPG_ERR_INV_VALUE; + if (transient_key) + return GPG_ERR_INV_VALUE; + } + + if (domain->p && domain->q && domain->g) + { + /* Domain parameters are given; use them. */ + p = mpi_copy (domain->p); + q = mpi_copy (domain->q); + g = mpi_copy (domain->g); + gcry_assert (mpi_get_nbits (p) == nbits); + gcry_assert (mpi_get_nbits (q) == qbits); + h = mpi_alloc (0); + e = NULL; + } + else + { + /* Generate new domain parameters. */ + p = _gcry_generate_elg_prime (1, nbits, qbits, NULL, ret_factors); + /* Get q out of factors. */ + q = mpi_copy ((*ret_factors)[0]); + gcry_assert (mpi_get_nbits (q) == qbits); + + /* Find a generator g (h and e are helpers). + e = (p-1)/q */ + e = mpi_alloc (mpi_get_nlimbs (p)); + mpi_sub_ui (e, p, 1); + mpi_fdiv_q (e, e, q); + g = mpi_alloc (mpi_get_nlimbs (p)); + h = mpi_alloc_set_ui (1); /* (We start with 2.) */ + do + { + mpi_add_ui (h, h, 1); + /* g = h^e mod p */ + gcry_mpi_powm (g, h, e, p); + } + while (!mpi_cmp_ui (g, 1)); /* Continue until g != 1. */ + } + + /* Select a random number X with the property: + * 0 < x < q-1 + * This must be a very good random number because this is the secret + * part. The random quality depends on the transient_key flag. */ + random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; + if (DBG_CIPHER) + log_debug("choosing a random x%s", transient_key? " (transient-key)":""); + gcry_assert( qbits >= 160 ); + x = mpi_alloc_secure( mpi_get_nlimbs(q) ); + mpi_sub_ui( h, q, 1 ); /* put q-1 into h */ + rndbuf = NULL; + do + { + if( DBG_CIPHER ) + progress('.'); + if( !rndbuf ) + rndbuf = gcry_random_bytes_secure ((qbits+7)/8, random_level); + else + { /* Change only some of the higher bits (= 2 bytes)*/ + char *r = gcry_random_bytes_secure (2, random_level); + memcpy(rndbuf, r, 2 ); + gcry_free(r); + } + + _gcry_mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 ); + mpi_clear_highbit( x, qbits+1 ); + } + while ( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) ); + gcry_free(rndbuf); + mpi_free( e ); + mpi_free( h ); + + /* y = g^x mod p */ + y = mpi_alloc( mpi_get_nlimbs(p) ); + gcry_mpi_powm( y, g, x, p ); + + if( DBG_CIPHER ) + { + progress('\n'); + log_mpidump("dsa p", p ); + log_mpidump("dsa q", q ); + log_mpidump("dsa g", g ); + log_mpidump("dsa y", y ); + log_mpidump("dsa x", x ); + } + + /* Copy the stuff to the key structures. */ + sk->p = p; + sk->q = q; + sk->g = g; + sk->y = y; + sk->x = x; + + /* Now we can test our keys (this should never fail!). */ + if ( test_keys (sk, qbits) ) + { + gcry_mpi_release (sk->p); sk->p = NULL; + gcry_mpi_release (sk->q); sk->q = NULL; + gcry_mpi_release (sk->g); sk->g = NULL; + gcry_mpi_release (sk->y); sk->y = NULL; + gcry_mpi_release (sk->x); sk->x = NULL; + fips_signal_error ("self-test after key generation failed"); + return GPG_ERR_SELFTEST_FAILED; + } + return 0; +} + + +/* Generate a DSA key pair with a key of size NBITS using the + algorithm given in FIPS-186-3. If USE_FIPS186_2 is true, + FIPS-186-2 is used and thus the length is restricted to 1024/160. + If DERIVEPARMS is not NULL it may contain a seed value. If domain + parameters are specified in DOMAIN, DERIVEPARMS may not be given + and NBITS and QBITS must match the specified domain parameters. */ +static gpg_err_code_t +generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, + gcry_sexp_t deriveparms, int use_fips186_2, + dsa_domain_t *domain, + int *r_counter, void **r_seed, size_t *r_seedlen, + gcry_mpi_t *r_h) +{ + gpg_err_code_t ec; + struct { + gcry_sexp_t sexp; + const void *seed; + size_t seedlen; + } initial_seed = { NULL, NULL, 0 }; + gcry_mpi_t prime_q = NULL; + gcry_mpi_t prime_p = NULL; + gcry_mpi_t value_g = NULL; /* The generator. */ + gcry_mpi_t value_y = NULL; /* g^x mod p */ + gcry_mpi_t value_x = NULL; /* The secret exponent. */ + gcry_mpi_t value_h = NULL; /* Helper. */ + gcry_mpi_t value_e = NULL; /* Helper. */ + + /* Preset return values. */ + *r_counter = 0; + *r_seed = NULL; + *r_seedlen = 0; + *r_h = NULL; + + /* Derive QBITS from NBITS if requested */ + if (!qbits) + { + if (nbits == 1024) + qbits = 160; + else if (nbits == 2048) + qbits = 224; + else if (nbits == 3072) + qbits = 256; + } + + /* Check that QBITS and NBITS match the standard. Note that FIPS + 186-3 uses N for QBITS and L for NBITS. */ + if (nbits == 1024 && qbits == 160) + ; + else if (nbits == 2048 && qbits == 224) + ; + else if (nbits == 2048 && qbits == 256) + ; + else if (nbits == 3072 && qbits == 256) + ; + else + return GPG_ERR_INV_VALUE; + + if (domain->p && domain->q && domain->g) + { + /* Domain parameters are given; use them. */ + prime_p = mpi_copy (domain->p); + prime_q = mpi_copy (domain->q); + value_g = mpi_copy (domain->g); + gcry_assert (mpi_get_nbits (prime_p) == nbits); + gcry_assert (mpi_get_nbits (prime_q) == qbits); + gcry_assert (!deriveparms); + ec = 0; + } + else + { + /* Generate new domain parameters. */ + + /* Get an initial seed value. */ + if (deriveparms) + { + initial_seed.sexp = gcry_sexp_find_token (deriveparms, "seed", 0); + if (initial_seed.sexp) + initial_seed.seed = gcry_sexp_nth_data (initial_seed.sexp, 1, + &initial_seed.seedlen); + } + + /* Fixme: Enable 186-3 after it has been approved and after fixing + the generation function. */ + /* if (use_fips186_2) */ + (void)use_fips186_2; + ec = _gcry_generate_fips186_2_prime (nbits, qbits, + initial_seed.seed, + initial_seed.seedlen, + &prime_q, &prime_p, + r_counter, + r_seed, r_seedlen); + /* else */ + /* ec = _gcry_generate_fips186_3_prime (nbits, qbits, NULL, 0, */ + /* &prime_q, &prime_p, */ + /* r_counter, */ + /* r_seed, r_seedlen, NULL); */ + gcry_sexp_release (initial_seed.sexp); + if (ec) + goto leave; + + /* Find a generator g (h and e are helpers). + e = (p-1)/q */ + value_e = mpi_alloc_like (prime_p); + mpi_sub_ui (value_e, prime_p, 1); + mpi_fdiv_q (value_e, value_e, prime_q ); + value_g = mpi_alloc_like (prime_p); + value_h = mpi_alloc_set_ui (1); + do + { + mpi_add_ui (value_h, value_h, 1); + /* g = h^e mod p */ + mpi_powm (value_g, value_h, value_e, prime_p); + } + while (!mpi_cmp_ui (value_g, 1)); /* Continue until g != 1. */ + } + + + /* Select a random number x with: 0 < x < q */ + value_x = gcry_mpi_snew (qbits); + do + { + if( DBG_CIPHER ) + progress('.'); + gcry_mpi_randomize (value_x, qbits, GCRY_VERY_STRONG_RANDOM); + mpi_clear_highbit (value_x, qbits+1); + } + while (!(mpi_cmp_ui (value_x, 0) > 0 && mpi_cmp (value_x, prime_q) < 0)); + + /* y = g^x mod p */ + value_y = mpi_alloc_like (prime_p); + gcry_mpi_powm (value_y, value_g, value_x, prime_p); + + if (DBG_CIPHER) + { + progress('\n'); + log_mpidump("dsa p", prime_p ); + log_mpidump("dsa q", prime_q ); + log_mpidump("dsa g", value_g ); + log_mpidump("dsa y", value_y ); + log_mpidump("dsa x", value_x ); + log_mpidump("dsa h", value_h ); + } + + /* Copy the stuff to the key structures. */ + sk->p = prime_p; prime_p = NULL; + sk->q = prime_q; prime_q = NULL; + sk->g = value_g; value_g = NULL; + sk->y = value_y; value_y = NULL; + sk->x = value_x; value_x = NULL; + *r_h = value_h; value_h = NULL; + + leave: + gcry_mpi_release (prime_p); + gcry_mpi_release (prime_q); + gcry_mpi_release (value_g); + gcry_mpi_release (value_y); + gcry_mpi_release (value_x); + gcry_mpi_release (value_h); + gcry_mpi_release (value_e); + + /* As a last step test this keys (this should never fail of course). */ + if (!ec && test_keys (sk, qbits) ) + { + gcry_mpi_release (sk->p); sk->p = NULL; + gcry_mpi_release (sk->q); sk->q = NULL; + gcry_mpi_release (sk->g); sk->g = NULL; + gcry_mpi_release (sk->y); sk->y = NULL; + gcry_mpi_release (sk->x); sk->x = NULL; + fips_signal_error ("self-test after key generation failed"); + ec = GPG_ERR_SELFTEST_FAILED; + } + + if (ec) + { + *r_counter = 0; + gcry_free (*r_seed); *r_seed = NULL; + *r_seedlen = 0; + gcry_mpi_release (*r_h); *r_h = NULL; + } + + return ec; +} + + + +/* + Test whether the secret key is valid. + Returns: if this is a valid key. + */ +static int +check_secret_key( DSA_secret_key *sk ) +{ + int rc; + gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs(sk->y) ); + + gcry_mpi_powm( y, sk->g, sk->x, sk->p ); + rc = !mpi_cmp( y, sk->y ); + mpi_free( y ); + return rc; +} + + + +/* + Make a DSA signature from HASH and put it into r and s. + */ +static void +sign(gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t hash, DSA_secret_key *skey ) +{ + gcry_mpi_t k; + gcry_mpi_t kinv; + gcry_mpi_t tmp; + + /* Select a random k with 0 < k < q */ + k = gen_k( skey->q ); + + /* r = (a^k mod p) mod q */ + gcry_mpi_powm( r, skey->g, k, skey->p ); + mpi_fdiv_r( r, r, skey->q ); + + /* kinv = k^(-1) mod q */ + kinv = mpi_alloc( mpi_get_nlimbs(k) ); + mpi_invm(kinv, k, skey->q ); + + /* s = (kinv * ( hash + x * r)) mod q */ + tmp = mpi_alloc( mpi_get_nlimbs(skey->p) ); + mpi_mul( tmp, skey->x, r ); + mpi_add( tmp, tmp, hash ); + mpi_mulm( s , kinv, tmp, skey->q ); + + mpi_free(k); + mpi_free(kinv); + mpi_free(tmp); +} + + +/* + Returns true if the signature composed from R and S is valid. + */ +static int +verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t hash, DSA_public_key *pkey ) +{ + int rc; + gcry_mpi_t w, u1, u2, v; + gcry_mpi_t base[3]; + gcry_mpi_t ex[3]; + + if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) ) + return 0; /* assertion 0 < r < q failed */ + if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) ) + return 0; /* assertion 0 < s < q failed */ + + w = mpi_alloc( mpi_get_nlimbs(pkey->q) ); + u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) ); + u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) ); + v = mpi_alloc( mpi_get_nlimbs(pkey->p) ); + + /* w = s^(-1) mod q */ + mpi_invm( w, s, pkey->q ); + + /* u1 = (hash * w) mod q */ + mpi_mulm( u1, hash, w, pkey->q ); + + /* u2 = r * w mod q */ + mpi_mulm( u2, r, w, pkey->q ); + + /* v = g^u1 * y^u2 mod p mod q */ + base[0] = pkey->g; ex[0] = u1; + base[1] = pkey->y; ex[1] = u2; + base[2] = NULL; ex[2] = NULL; + mpi_mulpowm( v, base, ex, pkey->p ); + mpi_fdiv_r( v, v, pkey->q ); + + rc = !mpi_cmp( v, r ); + + mpi_free(w); + mpi_free(u1); + mpi_free(u2); + mpi_free(v); + + return rc; +} + + +/********************************************* + ************** interface ****************** + *********************************************/ + +static gcry_err_code_t +dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, + const gcry_sexp_t genparms, + gcry_mpi_t *skey, gcry_mpi_t **retfactors, + gcry_sexp_t *r_extrainfo) +{ + gpg_err_code_t ec; + DSA_secret_key sk; + gcry_sexp_t l1; + unsigned int qbits = 0; + gcry_sexp_t deriveparms = NULL; + gcry_sexp_t seedinfo = NULL; + int transient_key = 0; + int use_fips186_2 = 0; + int use_fips186 = 0; + dsa_domain_t domain; + + (void)algo; /* No need to check it. */ + (void)evalue; /* Not required for DSA. */ + + memset (&domain, 0, sizeof domain); + + if (genparms) + { + gcry_sexp_t domainsexp; + + /* Parse the optional qbits element. */ + l1 = gcry_sexp_find_token (genparms, "qbits", 0); + if (l1) + { + char buf[50]; + const char *s; + size_t n; + + s = gcry_sexp_nth_data (l1, 1, &n); + if (!s || n >= DIM (buf) - 1 ) + { + gcry_sexp_release (l1); + return GPG_ERR_INV_OBJ; /* No value or value too large. */ + } + memcpy (buf, s, n); + buf[n] = 0; + qbits = (unsigned int)strtoul (buf, NULL, 0); + gcry_sexp_release (l1); + } + + /* Parse the optional transient-key flag. */ + l1 = gcry_sexp_find_token (genparms, "transient-key", 0); + if (l1) + { + transient_key = 1; + gcry_sexp_release (l1); + } + + /* Get the optional derive parameters. */ + deriveparms = gcry_sexp_find_token (genparms, "derive-parms", 0); + + /* Parse the optional "use-fips186" flags. */ + l1 = gcry_sexp_find_token (genparms, "use-fips186", 0); + if (l1) + { + use_fips186 = 1; + gcry_sexp_release (l1); + } + l1 = gcry_sexp_find_token (genparms, "use-fips186-2", 0); + if (l1) + { + use_fips186_2 = 1; + gcry_sexp_release (l1); + } + + /* Check whether domain parameters are given. */ + domainsexp = gcry_sexp_find_token (genparms, "domain", 0); + if (domainsexp) + { + /* DERIVEPARMS can't be used together with domain + parameters. NBITS abnd QBITS may not be specified + because there values are derived from the domain + parameters. */ + if (deriveparms || qbits || nbits) + { + gcry_sexp_release (domainsexp); + gcry_sexp_release (deriveparms); + return GPG_ERR_INV_VALUE; + } + + /* Put all domain parameters into the domain object. */ + l1 = gcry_sexp_find_token (domainsexp, "p", 0); + domain.p = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l1); + l1 = gcry_sexp_find_token (domainsexp, "q", 0); + domain.q = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l1); + l1 = gcry_sexp_find_token (domainsexp, "g", 0); + domain.g = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l1); + gcry_sexp_release (domainsexp); + + /* Check that all domain parameters are available. */ + if (!domain.p || !domain.q || !domain.g) + { + gcry_mpi_release (domain.p); + gcry_mpi_release (domain.q); + gcry_mpi_release (domain.g); + gcry_sexp_release (deriveparms); + return GPG_ERR_MISSING_VALUE; + } + + /* Get NBITS and QBITS from the domain parameters. */ + nbits = mpi_get_nbits (domain.p); + qbits = mpi_get_nbits (domain.q); + } + } + + if (deriveparms || use_fips186 || use_fips186_2 || fips_mode ()) + { + int counter; + void *seed; + size_t seedlen; + gcry_mpi_t h_value; + + ec = generate_fips186 (&sk, nbits, qbits, deriveparms, use_fips186_2, + &domain, + &counter, &seed, &seedlen, &h_value); + gcry_sexp_release (deriveparms); + if (!ec && h_value) + { + /* Format the seed-values unless domain parameters are used + for which a H_VALUE of NULL is an indication. */ + ec = gpg_err_code (gcry_sexp_build + (&seedinfo, NULL, + "(seed-values(counter %d)(seed %b)(h %m))", + counter, (int)seedlen, seed, h_value)); + if (ec) + { + gcry_mpi_release (sk.p); sk.p = NULL; + gcry_mpi_release (sk.q); sk.q = NULL; + gcry_mpi_release (sk.g); sk.g = NULL; + gcry_mpi_release (sk.y); sk.y = NULL; + gcry_mpi_release (sk.x); sk.x = NULL; + } + gcry_free (seed); + gcry_mpi_release (h_value); + } + } + else + { + ec = generate (&sk, nbits, qbits, transient_key, &domain, retfactors); + } + + gcry_mpi_release (domain.p); + gcry_mpi_release (domain.q); + gcry_mpi_release (domain.g); + + if (!ec) + { + skey[0] = sk.p; + skey[1] = sk.q; + skey[2] = sk.g; + skey[3] = sk.y; + skey[4] = sk.x; + + if (!r_extrainfo) + { + /* Old style interface - return the factors - if any - at + retfactors. */ + } + else if (!*retfactors && !seedinfo) + { + /* No factors and no seedinfo, thus there is nothing to return. */ + *r_extrainfo = NULL; + } + else + { + /* Put the factors into extrainfo and set retfactors to NULL + to make use of the new interface. Note that the factors + are not confidential thus we can store them in standard + memory. */ + int nfactors, i, j; + char *p; + char *format = NULL; + void **arg_list = NULL; + + for (nfactors=0; *retfactors && (*retfactors)[nfactors]; nfactors++) + ; + /* Allocate space for the format string: + "(misc-key-info%S(pm1-factors%m))" + with one "%m" for each factor and construct it. */ + format = gcry_malloc (50 + 2*nfactors); + if (!format) + ec = gpg_err_code_from_syserror (); + else + { + p = stpcpy (format, "(misc-key-info"); + if (seedinfo) + p = stpcpy (p, "%S"); + if (nfactors) + { + p = stpcpy (p, "(pm1-factors"); + for (i=0; i < nfactors; i++) + p = stpcpy (p, "%m"); + p = stpcpy (p, ")"); + } + p = stpcpy (p, ")"); + + /* Allocate space for the list of factors plus one for + an S-expression plus an extra NULL entry for safety + and fill it with the factors. */ + arg_list = gcry_calloc (nfactors+1+1, sizeof *arg_list); + if (!arg_list) + ec = gpg_err_code_from_syserror (); + else + { + i = 0; + if (seedinfo) + arg_list[i++] = &seedinfo; + for (j=0; j < nfactors; j++) + arg_list[i++] = (*retfactors) + j; + arg_list[i] = NULL; + + ec = gpg_err_code (gcry_sexp_build_array + (r_extrainfo, NULL, format, arg_list)); + } + } + + gcry_free (arg_list); + gcry_free (format); + for (i=0; i < nfactors; i++) + { + gcry_mpi_release ((*retfactors)[i]); + (*retfactors)[i] = NULL; + } + gcry_free (*retfactors); + *retfactors = NULL; + if (ec) + { + for (i=0; i < 5; i++) + { + gcry_mpi_release (skey[i]); + skey[i] = NULL; + } + } + } + } + + gcry_sexp_release (seedinfo); + return ec; +} + + +static gcry_err_code_t +dsa_generate (int algo, unsigned int nbits, unsigned long evalue, + gcry_mpi_t *skey, gcry_mpi_t **retfactors) +{ + (void)evalue; + return dsa_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL); +} + + + +static gcry_err_code_t +dsa_check_secret_key (int algo, gcry_mpi_t *skey) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + DSA_secret_key sk; + + (void)algo; + + if ((! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]) || (! skey[4])) + err = GPG_ERR_BAD_MPI; + else + { + sk.p = skey[0]; + sk.q = skey[1]; + sk.g = skey[2]; + sk.y = skey[3]; + sk.x = skey[4]; + if (! check_secret_key (&sk)) + err = GPG_ERR_BAD_SECKEY; + } + + return err; +} + + +static gcry_err_code_t +dsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + DSA_secret_key sk; + + (void)algo; + + if ((! data) + || (! skey[0]) || (! skey[1]) || (! skey[2]) + || (! skey[3]) || (! skey[4])) + err = GPG_ERR_BAD_MPI; + else + { + sk.p = skey[0]; + sk.q = skey[1]; + sk.g = skey[2]; + sk.y = skey[3]; + sk.x = skey[4]; + resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.p)); + resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.p)); + sign (resarr[0], resarr[1], data, &sk); + } + return err; +} + +static gcry_err_code_t +dsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, + int (*cmp) (void *, gcry_mpi_t), void *opaquev) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + DSA_public_key pk; + + (void)algo; + (void)cmp; + (void)opaquev; + + if ((! data[0]) || (! data[1]) || (! hash) + || (! pkey[0]) || (! pkey[1]) || (! pkey[2]) || (! pkey[3])) + err = GPG_ERR_BAD_MPI; + else + { + pk.p = pkey[0]; + pk.q = pkey[1]; + pk.g = pkey[2]; + pk.y = pkey[3]; + if (! verify (data[0], data[1], hash, &pk)) + err = GPG_ERR_BAD_SIGNATURE; + } + return err; +} + + +static unsigned int +dsa_get_nbits (int algo, gcry_mpi_t *pkey) +{ + (void)algo; + + return mpi_get_nbits (pkey[0]); +} + + + +/* + Self-test section. + */ + +static const char * +selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) +{ + static const char sample_data[] = + "(data (flags raw)" + " (value #a0b1c2d3e4f500102030405060708090a1b2c3d4#))"; + static const char sample_data_bad[] = + "(data (flags raw)" + " (value #a0b1c2d3e4f510102030405060708090a1b2c3d4#))"; + + const char *errtxt = NULL; + gcry_error_t err; + gcry_sexp_t data = NULL; + gcry_sexp_t data_bad = NULL; + gcry_sexp_t sig = NULL; + + err = gcry_sexp_sscan (&data, NULL, + sample_data, strlen (sample_data)); + if (!err) + err = gcry_sexp_sscan (&data_bad, NULL, + sample_data_bad, strlen (sample_data_bad)); + if (err) + { + errtxt = "converting data failed"; + goto leave; + } + + err = gcry_pk_sign (&sig, data, skey); + if (err) + { + errtxt = "signing failed"; + goto leave; + } + err = gcry_pk_verify (sig, data, pkey); + if (err) + { + errtxt = "verify failed"; + goto leave; + } + err = gcry_pk_verify (sig, data_bad, pkey); + if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE) + { + errtxt = "bad signature not detected"; + goto leave; + } + + + leave: + gcry_sexp_release (sig); + gcry_sexp_release (data_bad); + gcry_sexp_release (data); + return errtxt; +} + + +static gpg_err_code_t +selftests_dsa (selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + gcry_error_t err; + gcry_sexp_t skey = NULL; + gcry_sexp_t pkey = NULL; + + /* Convert the S-expressions into the internal representation. */ + what = "convert"; + err = gcry_sexp_sscan (&skey, NULL, + sample_secret_key, strlen (sample_secret_key)); + if (!err) + err = gcry_sexp_sscan (&pkey, NULL, + sample_public_key, strlen (sample_public_key)); + if (err) + { + errtxt = gcry_strerror (err); + goto failed; + } + + what = "key consistency"; + err = gcry_pk_testkey (skey); + if (err) + { + errtxt = gcry_strerror (err); + goto failed; + } + + what = "sign"; + errtxt = selftest_sign_1024 (pkey, skey); + if (errtxt) + goto failed; + + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + return 0; /* Succeeded. */ + + failed: + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + if (report) + report ("pubkey", GCRY_PK_DSA, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + +/* Run a full self-test for ALGO and return 0 on success. */ +static gpg_err_code_t +run_selftests (int algo, int extended, selftest_report_func_t report) +{ + gpg_err_code_t ec; + + (void)extended; + + switch (algo) + { + case GCRY_PK_DSA: + ec = selftests_dsa (report); + break; + default: + ec = GPG_ERR_PUBKEY_ALGO; + break; + + } + return ec; +} + + + + +static const char *dsa_names[] = + { + "dsa", + "openpgp-dsa", + NULL, + }; + +gcry_pk_spec_t _gcry_pubkey_spec_dsa = + { + "DSA", dsa_names, + "pqgy", "pqgyx", "", "rs", "pqgy", + GCRY_PK_USAGE_SIGN, + dsa_generate, + dsa_check_secret_key, + NULL, + NULL, + dsa_sign, + dsa_verify, + dsa_get_nbits + }; +pk_extra_spec_t _gcry_pubkey_extraspec_dsa = + { + run_selftests, + dsa_generate_ext + }; diff --git a/grub-core/lib/libgcrypt/cipher/ecc.c b/grub-core/lib/libgcrypt/cipher/ecc.c new file mode 100644 index 0000000..b8487dc --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/ecc.c @@ -0,0 +1,1793 @@ +/* ecc.c - Elliptic Curve Cryptography + Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ + +/* This code is originally based on the Patch 0.1.6 for the gnupg + 1.4.x branch as retrieved on 2007-03-21 from + http://www.calcurco.cat/eccGnuPG/src/gnupg-1.4.6-ecc0.2.0beta1.diff.bz2 + The original authors are: + Written by + Sergi Blanch i Torne <d4372211 at alumnes.eup.udl.es>, + Ramiro Moreno Chiral <ramiro at eup.udl.es> + Maintainers + Sergi Blanch i Torne + Ramiro Moreno Chiral + Mikael Mylnikov (mmr) + For use in Libgcrypt the code has been heavily modified and cleaned + up. In fact there is not much left of the orginally code except for + some variable names and the text book implementaion of the sign and + verification algorithms. The arithmetic functions have entirely + been rewritten and moved to mpi/ec.c. + + ECDH encrypt and decrypt code written by Andrey Jivsov, +*/ + + +/* TODO: + + - If we support point compression we need to uncompress before + computing the keygrip + + - In mpi/ec.c we use mpi_powm for x^2 mod p: Either implement a + special case in mpi_powm or check whether mpi_mulm is faster. + + - Decide whether we should hide the mpi_point_t definition. +*/ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "g10lib.h" +#include "mpi.h" +#include "cipher.h" + +/* Definition of a curve. */ +typedef struct +{ + gcry_mpi_t p; /* Prime specifying the field GF(p). */ + gcry_mpi_t a; /* First coefficient of the Weierstrass equation. */ + gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */ + mpi_point_t G; /* Base point (generator). */ + gcry_mpi_t n; /* Order of G. */ + const char *name; /* Name of curve or NULL. */ +} elliptic_curve_t; + + +typedef struct +{ + elliptic_curve_t E; + mpi_point_t Q; /* Q = [d]G */ +} ECC_public_key; + +typedef struct +{ + elliptic_curve_t E; + mpi_point_t Q; + gcry_mpi_t d; +} ECC_secret_key; + + +/* This tables defines aliases for curve names. */ +static const struct +{ + const char *name; /* Our name. */ + const char *other; /* Other name. */ +} curve_aliases[] = + { + { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID */ + { "NIST P-192", "prime192v1" }, /* X9.62 name. */ + { "NIST P-192", "secp192r1" }, /* SECP name. */ + + { "NIST P-224", "secp224r1" }, + { "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */ + + { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1. */ + { "NIST P-256", "prime256v1" }, + { "NIST P-256", "secp256r1" }, + + { "NIST P-384", "secp384r1" }, + { "NIST P-384", "1.3.132.0.34" }, + + { "NIST P-521", "secp521r1" }, + { "NIST P-521", "1.3.132.0.35" }, + + { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" }, + { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" }, + { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" }, + { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" }, + { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" }, + { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"}, + { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"}, + + { NULL, NULL} + }; + +typedef struct { + const char *desc; /* Description of the curve. */ + unsigned int nbits; /* Number of bits. */ + unsigned int fips:1; /* True if this is a FIPS140-2 approved curve. */ + const char *p; /* Order of the prime field. */ + const char *a, *b; /* The coefficients. */ + const char *n; /* The order of the base point. */ + const char *g_x, *g_y; /* Base point. */ +} ecc_domain_parms_t; + +/* This static table defines all available curves. */ +static const ecc_domain_parms_t domain_parms[] = + { + { + "NIST P-192", 192, 1, + "0xfffffffffffffffffffffffffffffffeffffffffffffffff", + "0xfffffffffffffffffffffffffffffffefffffffffffffffc", + "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", + "0xffffffffffffffffffffffff99def836146bc9b1b4d22831", + + "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", + "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + }, + { + "NIST P-224", 224, 1, + "0xffffffffffffffffffffffffffffffff000000000000000000000001", + "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe", + "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", + "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" , + + "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", + "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" + }, + { + "NIST P-256", 256, 1, + "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc", + "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", + "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + + "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", + "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" + }, + { + "NIST P-384", 384, 1, + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" + "ffffffff0000000000000000ffffffff", + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" + "ffffffff0000000000000000fffffffc", + "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a" + "c656398d8a2ed19d2a85c8edd3ec2aef", + "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf" + "581a0db248b0a77aecec196accc52973", + + "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38" + "5502f25dbf55296c3a545e3872760ab7", + "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0" + "0a60b1ce1d7e819d7a431d7c90ea0e5f" + }, + { + "NIST P-521", 521, 1, + "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc", + "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10" + "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", + "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", + + "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d" + "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", + "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6" + "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650" + }, + + { "brainpoolP160r1", 160, 0, + "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f", + "0x340e7be2a280eb74e2be61bada745d97e8f7c300", + "0x1e589a8595423412134faa2dbdec95c8d8675e58", + "0xe95e4a5f737059dc60df5991d45029409e60fc09", + "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3", + "0x1667cb477a1a8ec338f94741669c976316da6321" + }, + + { "brainpoolP192r1", 192, 0, + "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297", + "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef", + "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9", + "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1", + "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6", + "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f" + }, + + { "brainpoolP224r1", 224, 0, + "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff", + "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43", + "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b", + "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f", + "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d", + "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd" + }, + + { "brainpoolP256r1", 256, 0, + "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377", + "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9", + "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6", + "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7", + "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262", + "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997" + }, + + { "brainpoolP320r1", 320, 0, + "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28" + "fcd412b1f1b32e27", + "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4" + "92f375a97d860eb4", + "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981" + "6f5eb4ac8fb1f1a6", + "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9" + "8691555b44c59311", + "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7" + "10af8d0d39e20611", + "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7" + "d35245d1692e8ee1" + }, + + { "brainpoolP384r1", 384, 0, + "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123" + "acd3a729901d1a71874700133107ec53", + "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f" + "8aa5814a503ad4eb04a8c7dd22ce2826", + "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5" + "7cb4390295dbc9943ab78696fa504c11", + "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7" + "cf3ab6af6b7fc3103b883202e9046565", + "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8" + "e826e03436d646aaef87b2e247d4af1e", + "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928" + "0e4646217791811142820341263c5315" + }, + + { "brainpoolP512r1", 512, 0, + "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871" + "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3", + "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc" + "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca", + "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7" + "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723", + "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870" + "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069", + "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e" + "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822", + "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111" + "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892" + }, + + { NULL, 0, 0, NULL, NULL, NULL, NULL } + }; + + +/* Registered progress function and its callback value. */ +static void (*progress_cb) (void *, const char*, int, int, int); +static void *progress_cb_data; + + +#define point_init(a) _gcry_mpi_ec_point_init ((a)) +#define point_free(a) _gcry_mpi_ec_point_free ((a)) + + + +/* Local prototypes. */ +static gcry_mpi_t gen_k (gcry_mpi_t p, int security_level); +static void test_keys (ECC_secret_key * sk, unsigned int nbits); +static int check_secret_key (ECC_secret_key * sk); +static gpg_err_code_t sign (gcry_mpi_t input, ECC_secret_key *skey, + gcry_mpi_t r, gcry_mpi_t s); +static gpg_err_code_t verify (gcry_mpi_t input, ECC_public_key *pkey, + gcry_mpi_t r, gcry_mpi_t s); + + +static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t * base); + + + + +void +_gcry_register_pk_ecc_progress (void (*cb) (void *, const char *, + int, int, int), + void *cb_data) +{ + progress_cb = cb; + progress_cb_data = cb_data; +} + +/* static void */ +/* progress (int c) */ +/* { */ +/* if (progress_cb) */ +/* progress_cb (progress_cb_data, "pk_ecc", c, 0, 0); */ +/* } */ + + + + +/* Set the value from S into D. */ +static void +point_set (mpi_point_t *d, mpi_point_t *s) +{ + mpi_set (d->x, s->x); + mpi_set (d->y, s->y); + mpi_set (d->z, s->z); +} + + +/* + * Release a curve object. + */ +static void +curve_free (elliptic_curve_t *E) +{ + mpi_free (E->p); E->p = NULL; + mpi_free (E->a); E->a = NULL; + mpi_free (E->b); E->b = NULL; + point_free (&E->G); + mpi_free (E->n); E->n = NULL; +} + + +/* + * Return a copy of a curve object. + */ +static elliptic_curve_t +curve_copy (elliptic_curve_t E) +{ + elliptic_curve_t R; + + R.p = mpi_copy (E.p); + R.a = mpi_copy (E.a); + R.b = mpi_copy (E.b); + point_init (&R.G); + point_set (&R.G, &E.G); + R.n = mpi_copy (E.n); + + return R; +} + + +/* Helper to scan a hex string. */ +static gcry_mpi_t +scanval (const char *string) +{ + gpg_error_t err; + gcry_mpi_t val; + + err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL); + if (err) + log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (err)); + return val; +} + + + + + +/**************** + * Solve the right side of the equation that defines a curve. + */ +static gcry_mpi_t +gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base) +{ + gcry_mpi_t three, x_3, axb, y; + + three = mpi_alloc_set_ui (3); + x_3 = mpi_new (0); + axb = mpi_new (0); + y = mpi_new (0); + + mpi_powm (x_3, x, three, base->p); + mpi_mulm (axb, base->a, x, base->p); + mpi_addm (axb, axb, base->b, base->p); + mpi_addm (y, x_3, axb, base->p); + + mpi_free (x_3); + mpi_free (axb); + mpi_free (three); + return y; /* The quadratic value of the coordinate if it exist. */ +} + + +/* Generate a random secret scalar k with an order of p + + At the beginning this was identical to the code is in elgamal.c. + Later imporved by mmr. Further simplified by wk. */ +static gcry_mpi_t +gen_k (gcry_mpi_t p, int security_level) +{ + gcry_mpi_t k; + unsigned int nbits; + + nbits = mpi_get_nbits (p); + k = mpi_snew (nbits); + if (DBG_CIPHER) + log_debug ("choosing a random k of %u bits at seclevel %d\n", + nbits, security_level); + + gcry_mpi_randomize (k, nbits, security_level); + + mpi_mod (k, k, p); /* k = k mod p */ + + return k; +} + + +/* Generate the crypto system setup. This function takes the NAME of + a curve or the desired number of bits and stores at R_CURVE the + parameters of the named curve or those of a suitable curve. The + chosen number of bits is stored on R_NBITS. */ +static gpg_err_code_t +fill_in_curve (unsigned int nbits, const char *name, + elliptic_curve_t *curve, unsigned int *r_nbits) +{ + int idx, aliasno; + const char *resname = NULL; /* Set to a found curve name. */ + + if (name) + { + /* First check our native curves. */ + for (idx = 0; domain_parms[idx].desc; idx++) + if (!strcmp (name, domain_parms[idx].desc)) + { + resname = domain_parms[idx].desc; + break; + } + /* If not found consult the alias table. */ + if (!domain_parms[idx].desc) + { + for (aliasno = 0; curve_aliases[aliasno].name; aliasno++) + if (!strcmp (name, curve_aliases[aliasno].other)) + break; + if (curve_aliases[aliasno].name) + { + for (idx = 0; domain_parms[idx].desc; idx++) + if (!strcmp (curve_aliases[aliasno].name, + domain_parms[idx].desc)) + { + resname = domain_parms[idx].desc; + break; + } + } + } + } + else + { + for (idx = 0; domain_parms[idx].desc; idx++) + if (nbits == domain_parms[idx].nbits) + break; + } + if (!domain_parms[idx].desc) + return GPG_ERR_INV_VALUE; + + /* In fips mode we only support NIST curves. Note that it is + possible to bypass this check by specifying the curve parameters + directly. */ + if (fips_mode () && !domain_parms[idx].fips ) + return GPG_ERR_NOT_SUPPORTED; + + *r_nbits = domain_parms[idx].nbits; + curve->p = scanval (domain_parms[idx].p); + curve->a = scanval (domain_parms[idx].a); + curve->b = scanval (domain_parms[idx].b); + curve->n = scanval (domain_parms[idx].n); + curve->G.x = scanval (domain_parms[idx].g_x); + curve->G.y = scanval (domain_parms[idx].g_y); + curve->G.z = mpi_alloc_set_ui (1); + curve->name = resname; + + return 0; +} + + +/* + * First obtain the setup. Over the finite field randomize an scalar + * secret value, and calculate the public point. + */ +static gpg_err_code_t +generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, + int transient_key, + gcry_mpi_t g_x, gcry_mpi_t g_y, + gcry_mpi_t q_x, gcry_mpi_t q_y, + const char **r_usedcurve) +{ + gpg_err_code_t err; + elliptic_curve_t E; + gcry_mpi_t d; + mpi_point_t Q; + mpi_ec_t ctx; + gcry_random_level_t random_level; + + *r_usedcurve = NULL; + + err = fill_in_curve (nbits, name, &E, &nbits); + if (err) + return err; + + if (DBG_CIPHER) + { + log_mpidump ("ecgen curve p", E.p); + log_mpidump ("ecgen curve a", E.a); + log_mpidump ("ecgen curve b", E.b); + log_mpidump ("ecgen curve n", E.n); + log_mpidump ("ecgen curve Gx", E.G.x); + log_mpidump ("ecgen curve Gy", E.G.y); + log_mpidump ("ecgen curve Gz", E.G.z); + if (E.name) + log_debug ("ecgen curve used: %s\n", E.name); + } + + random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; + d = gen_k (E.n, random_level); + + /* Compute Q. */ + point_init (&Q); + ctx = _gcry_mpi_ec_init (E.p, E.a); + _gcry_mpi_ec_mul_point (&Q, d, &E.G, ctx); + + /* Copy the stuff to the key structures. */ + sk->E.p = mpi_copy (E.p); + sk->E.a = mpi_copy (E.a); + sk->E.b = mpi_copy (E.b); + point_init (&sk->E.G); + point_set (&sk->E.G, &E.G); + sk->E.n = mpi_copy (E.n); + point_init (&sk->Q); + point_set (&sk->Q, &Q); + sk->d = mpi_copy (d); + /* We also return copies of G and Q in affine coordinates if + requested. */ + if (g_x && g_y) + { + if (_gcry_mpi_ec_get_affine (g_x, g_y, &sk->E.G, ctx)) + log_fatal ("ecgen: Failed to get affine coordinates\n"); + } + if (q_x && q_y) + { + if (_gcry_mpi_ec_get_affine (q_x, q_y, &sk->Q, ctx)) + log_fatal ("ecgen: Failed to get affine coordinates\n"); + } + _gcry_mpi_ec_free (ctx); + + point_free (&Q); + mpi_free (d); + + *r_usedcurve = E.name; + curve_free (&E); + + /* Now we can test our keys (this should never fail!). */ + test_keys (sk, nbits - 64); + + return 0; +} + + +/* + * To verify correct skey it use a random information. + * First, encrypt and decrypt this dummy value, + * test if the information is recuperated. + * Second, test with the sign and verify functions. + */ +static void +test_keys (ECC_secret_key *sk, unsigned int nbits) +{ + ECC_public_key pk; + gcry_mpi_t test = mpi_new (nbits); + mpi_point_t R_; + gcry_mpi_t c = mpi_new (nbits); + gcry_mpi_t out = mpi_new (nbits); + gcry_mpi_t r = mpi_new (nbits); + gcry_mpi_t s = mpi_new (nbits); + + if (DBG_CIPHER) + log_debug ("Testing key.\n"); + + point_init (&R_); + + pk.E = curve_copy (sk->E); + point_init (&pk.Q); + point_set (&pk.Q, &sk->Q); + + gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM); + + if (sign (test, sk, r, s) ) + log_fatal ("ECDSA operation: sign failed\n"); + + if (verify (test, &pk, r, s)) + { + log_fatal ("ECDSA operation: sign, verify failed\n"); + } + + if (DBG_CIPHER) + log_debug ("ECDSA operation: sign, verify ok.\n"); + + point_free (&pk.Q); + curve_free (&pk.E); + + point_free (&R_); + mpi_free (s); + mpi_free (r); + mpi_free (out); + mpi_free (c); + mpi_free (test); +} + + +/* + * To check the validity of the value, recalculate the correspondence + * between the public value and the secret one. + */ +static int +check_secret_key (ECC_secret_key * sk) +{ + int rc = 1; + mpi_point_t Q; + gcry_mpi_t y_2, y2; + mpi_ec_t ctx = NULL; + + point_init (&Q); + + /* ?primarity test of 'p' */ + /* (...) //!! */ + /* G in E(F_p) */ + y_2 = gen_y_2 (sk->E.G.x, &sk->E); /* y^2=x^3+a*x+b */ + y2 = mpi_alloc (0); + mpi_mulm (y2, sk->E.G.y, sk->E.G.y, sk->E.p); /* y^2=y*y */ + if (mpi_cmp (y_2, y2)) + { + if (DBG_CIPHER) + log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n"); + goto leave; + } + /* G != PaI */ + if (!mpi_cmp_ui (sk->E.G.z, 0)) + { + if (DBG_CIPHER) + log_debug ("Bad check: 'G' cannot be Point at Infinity!\n"); + goto leave; + } + + ctx = _gcry_mpi_ec_init (sk->E.p, sk->E.a); + + _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx); + if (mpi_cmp_ui (Q.z, 0)) + { + if (DBG_CIPHER) + log_debug ("check_secret_key: E is not a curve of order n\n"); + goto leave; + } + /* pubkey cannot be PaI */ + if (!mpi_cmp_ui (sk->Q.z, 0)) + { + if (DBG_CIPHER) + log_debug ("Bad check: Q can not be a Point at Infinity!\n"); + goto leave; + } + /* pubkey = [d]G over E */ + _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx); + if ((Q.x == sk->Q.x) && (Q.y == sk->Q.y) && (Q.z == sk->Q.z)) + { + if (DBG_CIPHER) + log_debug + ("Bad check: There is NO correspondence between 'd' and 'Q'!\n"); + goto leave; + } + rc = 0; /* Okay. */ + + leave: + _gcry_mpi_ec_free (ctx); + mpi_free (y2); + mpi_free (y_2); + point_free (&Q); + return rc; +} + + +/* + * Return the signature struct (r,s) from the message hash. The caller + * must have allocated R and S. + */ +static gpg_err_code_t +sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) +{ + gpg_err_code_t err = 0; + gcry_mpi_t k, dr, sum, k_1, x; + mpi_point_t I; + mpi_ec_t ctx; + + if (DBG_CIPHER) + log_mpidump ("ecdsa sign hash ", input ); + + k = NULL; + dr = mpi_alloc (0); + sum = mpi_alloc (0); + k_1 = mpi_alloc (0); + x = mpi_alloc (0); + point_init (&I); + + mpi_set_ui (s, 0); + mpi_set_ui (r, 0); + + ctx = _gcry_mpi_ec_init (skey->E.p, skey->E.a); + + while (!mpi_cmp_ui (s, 0)) /* s == 0 */ + { + while (!mpi_cmp_ui (r, 0)) /* r == 0 */ + { + /* Note, that we are guaranteed to enter this loop at least + once because r has been intialized to 0. We can't use a + do_while because we want to keep the value of R even if S + has to be recomputed. */ + mpi_free (k); + k = gen_k (skey->E.n, GCRY_STRONG_RANDOM); + _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx); + if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx)) + { + if (DBG_CIPHER) + log_debug ("ecc sign: Failed to get affine coordinates\n"); + err = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + mpi_mod (r, x, skey->E.n); /* r = x mod n */ + } + mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n */ + mpi_addm (sum, input, dr, skey->E.n); /* sum = hash + (d*r) mod n */ + mpi_invm (k_1, k, skey->E.n); /* k_1 = k^(-1) mod n */ + mpi_mulm (s, k_1, sum, skey->E.n); /* s = k^(-1)*(hash+(d*r)) mod n */ + } + + if (DBG_CIPHER) + { + log_mpidump ("ecdsa sign result r ", r); + log_mpidump ("ecdsa sign result s ", s); + } + + leave: + _gcry_mpi_ec_free (ctx); + point_free (&I); + mpi_free (x); + mpi_free (k_1); + mpi_free (sum); + mpi_free (dr); + mpi_free (k); + + return err; +} + + +/* + * Check if R and S verifies INPUT. + */ +static gpg_err_code_t +verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) +{ + gpg_err_code_t err = 0; + gcry_mpi_t h, h1, h2, x, y; + mpi_point_t Q, Q1, Q2; + mpi_ec_t ctx; + + if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) ) + return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < r < n failed. */ + if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) ) + return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < s < n failed. */ + + h = mpi_alloc (0); + h1 = mpi_alloc (0); + h2 = mpi_alloc (0); + x = mpi_alloc (0); + y = mpi_alloc (0); + point_init (&Q); + point_init (&Q1); + point_init (&Q2); + + ctx = _gcry_mpi_ec_init (pkey->E.p, pkey->E.a); + + /* h = s^(-1) (mod n) */ + mpi_invm (h, s, pkey->E.n); +/* log_mpidump (" h", h); */ + /* h1 = hash * s^(-1) (mod n) */ + mpi_mulm (h1, input, h, pkey->E.n); +/* log_mpidump (" h1", h1); */ + /* Q1 = [ hash * s^(-1) ]G */ + _gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx); +/* log_mpidump ("Q1.x", Q1.x); */ +/* log_mpidump ("Q1.y", Q1.y); */ +/* log_mpidump ("Q1.z", Q1.z); */ + /* h2 = r * s^(-1) (mod n) */ + mpi_mulm (h2, r, h, pkey->E.n); +/* log_mpidump (" h2", h2); */ + /* Q2 = [ r * s^(-1) ]Q */ + _gcry_mpi_ec_mul_point (&Q2, h2, &pkey->Q, ctx); +/* log_mpidump ("Q2.x", Q2.x); */ +/* log_mpidump ("Q2.y", Q2.y); */ +/* log_mpidump ("Q2.z", Q2.z); */ + /* Q = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */ + _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx); +/* log_mpidump (" Q.x", Q.x); */ +/* log_mpidump (" Q.y", Q.y); */ +/* log_mpidump (" Q.z", Q.z); */ + + if (!mpi_cmp_ui (Q.z, 0)) + { + if (DBG_CIPHER) + log_debug ("ecc verify: Rejected\n"); + err = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx)) + { + if (DBG_CIPHER) + log_debug ("ecc verify: Failed to get affine coordinates\n"); + err = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + mpi_mod (x, x, pkey->E.n); /* x = x mod E_n */ + if (mpi_cmp (x, r)) /* x != r */ + { + if (DBG_CIPHER) + { + log_mpidump (" x", x); + log_mpidump (" y", y); + log_mpidump (" r", r); + log_mpidump (" s", s); + log_debug ("ecc verify: Not verified\n"); + } + err = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + if (DBG_CIPHER) + log_debug ("ecc verify: Accepted\n"); + + leave: + _gcry_mpi_ec_free (ctx); + point_free (&Q2); + point_free (&Q1); + point_free (&Q); + mpi_free (y); + mpi_free (x); + mpi_free (h2); + mpi_free (h1); + mpi_free (h); + return err; +} + + + +/********************************************* + ************** interface ****************** + *********************************************/ +static gcry_mpi_t +ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) +{ + gpg_error_t err; + int pbytes = (mpi_get_nbits (p)+7)/8; + size_t n; + unsigned char *buf, *ptr; + gcry_mpi_t result; + + buf = gcry_xmalloc ( 1 + 2*pbytes ); + *buf = 04; /* Uncompressed point. */ + ptr = buf+1; + err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x); + if (err) + log_fatal ("mpi_print failed: %s\n", gpg_strerror (err)); + if (n < pbytes) + { + memmove (ptr+(pbytes-n), ptr, n); + memset (ptr, 0, (pbytes-n)); + } + ptr += pbytes; + err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y); + if (err) + log_fatal ("mpi_print failed: %s\n", gpg_strerror (err)); + if (n < pbytes) + { + memmove (ptr+(pbytes-n), ptr, n); + memset (ptr, 0, (pbytes-n)); + } + + err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL); + if (err) + log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); + gcry_free (buf); + + return result; +} + + +/* RESULT must have been initialized and is set on success to the + point given by VALUE. */ +static gcry_error_t +os2ec (mpi_point_t *result, gcry_mpi_t value) +{ + gcry_error_t err; + size_t n; + unsigned char *buf; + gcry_mpi_t x, y; + + n = (mpi_get_nbits (value)+7)/8; + buf = gcry_xmalloc (n); + err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, n, &n, value); + if (err) + { + gcry_free (buf); + return err; + } + if (n < 1) + { + gcry_free (buf); + return GPG_ERR_INV_OBJ; + } + if (*buf != 4) + { + gcry_free (buf); + return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */ + } + if ( ((n-1)%2) ) + { + gcry_free (buf); + return GPG_ERR_INV_OBJ; + } + n = (n-1)/2; + err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL); + if (err) + { + gcry_free (buf); + return err; + } + err = gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL); + gcry_free (buf); + if (err) + { + mpi_free (x); + return err; + } + + mpi_set (result->x, x); + mpi_set (result->y, y); + mpi_set_ui (result->z, 1); + + mpi_free (x); + mpi_free (y); + + return 0; +} + + +/* Extended version of ecc_generate. */ +static gcry_err_code_t +ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, + const gcry_sexp_t genparms, + gcry_mpi_t *skey, gcry_mpi_t **retfactors, + gcry_sexp_t *r_extrainfo) +{ + gpg_err_code_t ec; + ECC_secret_key sk; + gcry_mpi_t g_x, g_y, q_x, q_y; + char *curve_name = NULL; + gcry_sexp_t l1; + int transient_key = 0; + const char *usedcurve = NULL; + + (void)algo; + (void)evalue; + + if (genparms) + { + /* Parse the optional "curve" parameter. */ + l1 = gcry_sexp_find_token (genparms, "curve", 0); + if (l1) + { + curve_name = _gcry_sexp_nth_string (l1, 1); + gcry_sexp_release (l1); + if (!curve_name) + return GPG_ERR_INV_OBJ; /* No curve name or value too large. */ + } + + /* Parse the optional transient-key flag. */ + l1 = gcry_sexp_find_token (genparms, "transient-key", 0); + if (l1) + { + transient_key = 1; + gcry_sexp_release (l1); + } + } + + /* NBITS is required if no curve name has been given. */ + if (!nbits && !curve_name) + return GPG_ERR_NO_OBJ; /* No NBITS parameter. */ + + g_x = mpi_new (0); + g_y = mpi_new (0); + q_x = mpi_new (0); + q_y = mpi_new (0); + ec = generate_key (&sk, nbits, curve_name, transient_key, g_x, g_y, q_x, q_y, + &usedcurve); + gcry_free (curve_name); + if (ec) + return ec; + if (usedcurve) /* Fixme: No error return checking. */ + gcry_sexp_build (r_extrainfo, NULL, "(curve %s)", usedcurve); + + skey[0] = sk.E.p; + skey[1] = sk.E.a; + skey[2] = sk.E.b; + skey[3] = ec2os (g_x, g_y, sk.E.p); + skey[4] = sk.E.n; + skey[5] = ec2os (q_x, q_y, sk.E.p); + skey[6] = sk.d; + + mpi_free (g_x); + mpi_free (g_y); + mpi_free (q_x); + mpi_free (q_y); + + point_free (&sk.E.G); + point_free (&sk.Q); + + /* Make an empty list of factors. */ + *retfactors = gcry_calloc ( 1, sizeof **retfactors ); + if (!*retfactors) + return gpg_err_code_from_syserror (); /* Fixme: relase mem? */ + + if (DBG_CIPHER) + { + log_mpidump ("ecgen result p", skey[0]); + log_mpidump ("ecgen result a", skey[1]); + log_mpidump ("ecgen result b", skey[2]); + log_mpidump ("ecgen result G", skey[3]); + log_mpidump ("ecgen result n", skey[4]); + log_mpidump ("ecgen result Q", skey[5]); + log_mpidump ("ecgen result d", skey[6]); + } + + return 0; +} + + +static gcry_err_code_t +ecc_generate (int algo, unsigned int nbits, unsigned long evalue, + gcry_mpi_t *skey, gcry_mpi_t **retfactors) +{ + (void)evalue; + return ecc_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL); +} + + +/* Return the parameters of the curve NAME in an MPI array. */ +static gcry_err_code_t +ecc_get_param (const char *name, gcry_mpi_t *pkey) +{ + gpg_err_code_t err; + unsigned int nbits; + elliptic_curve_t E; + mpi_ec_t ctx; + gcry_mpi_t g_x, g_y; + + err = fill_in_curve (0, name, &E, &nbits); + if (err) + return err; + + g_x = mpi_new (0); + g_y = mpi_new (0); + ctx = _gcry_mpi_ec_init (E.p, E.a); + if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx)) + log_fatal ("ecc get param: Failed to get affine coordinates\n"); + _gcry_mpi_ec_free (ctx); + point_free (&E.G); + + pkey[0] = E.p; + pkey[1] = E.a; + pkey[2] = E.b; + pkey[3] = ec2os (g_x, g_y, E.p); + pkey[4] = E.n; + pkey[5] = NULL; + + mpi_free (g_x); + mpi_free (g_y); + + return 0; +} + + +/* Return the parameters of the curve NAME as an S-expression. */ +static gcry_sexp_t +ecc_get_param_sexp (const char *name) +{ + gcry_mpi_t pkey[6]; + gcry_sexp_t result; + int i; + + if (ecc_get_param (name, pkey)) + return NULL; + + if (gcry_sexp_build (&result, NULL, + "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))", + pkey[0], pkey[1], pkey[2], pkey[3], pkey[4])) + result = NULL; + + for (i=0; pkey[i]; i++) + gcry_mpi_release (pkey[i]); + + return result; +} + + +/* Return the name matching the parameters in PKEY. */ +static const char * +ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits) +{ + gpg_err_code_t err; + elliptic_curve_t E; + int idx; + gcry_mpi_t tmp; + const char *result = NULL; + + if (r_nbits) + *r_nbits = 0; + + if (!pkey) + { + idx = iterator; + if (idx >= 0 && idx < DIM (domain_parms)) + { + result = domain_parms[idx].desc; + if (r_nbits) + *r_nbits = domain_parms[idx].nbits; + } + return result; + } + + if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4]) + return NULL; + + E.p = pkey[0]; + E.a = pkey[1]; + E.b = pkey[2]; + point_init (&E.G); + err = os2ec (&E.G, pkey[3]); + if (err) + { + point_free (&E.G); + return NULL; + } + E.n = pkey[4]; + + for (idx = 0; domain_parms[idx].desc; idx++) + { + tmp = scanval (domain_parms[idx].p); + if (!mpi_cmp (tmp, E.p)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].a); + if (!mpi_cmp (tmp, E.a)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].b); + if (!mpi_cmp (tmp, E.b)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].n); + if (!mpi_cmp (tmp, E.n)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].g_x); + if (!mpi_cmp (tmp, E.G.x)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].g_y); + if (!mpi_cmp (tmp, E.G.y)) + { + result = domain_parms[idx].desc; + if (r_nbits) + *r_nbits = domain_parms[idx].nbits; + break; + } + } + } + } + } + } + mpi_free (tmp); + } + + point_free (&E.G); + + return result; +} + + +static gcry_err_code_t +ecc_check_secret_key (int algo, gcry_mpi_t *skey) +{ + gpg_err_code_t err; + ECC_secret_key sk; + + (void)algo; + + /* FIXME: This check looks a bit fishy: Now long is the array? */ + if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5] + || !skey[6]) + return GPG_ERR_BAD_MPI; + + sk.E.p = skey[0]; + sk.E.a = skey[1]; + sk.E.b = skey[2]; + point_init (&sk.E.G); + err = os2ec (&sk.E.G, skey[3]); + if (err) + { + point_free (&sk.E.G); + return err; + } + sk.E.n = skey[4]; + point_init (&sk.Q); + err = os2ec (&sk.Q, skey[5]); + if (err) + { + point_free (&sk.E.G); + point_free (&sk.Q); + return err; + } + + sk.d = skey[6]; + + if (check_secret_key (&sk)) + { + point_free (&sk.E.G); + point_free (&sk.Q); + return GPG_ERR_BAD_SECKEY; + } + point_free (&sk.E.G); + point_free (&sk.Q); + return 0; +} + + +static gcry_err_code_t +ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) +{ + gpg_err_code_t err; + ECC_secret_key sk; + + (void)algo; + + if (!data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] + || !skey[5] || !skey[6] ) + return GPG_ERR_BAD_MPI; + + sk.E.p = skey[0]; + sk.E.a = skey[1]; + sk.E.b = skey[2]; + point_init (&sk.E.G); + err = os2ec (&sk.E.G, skey[3]); + if (err) + { + point_free (&sk.E.G); + return err; + } + sk.E.n = skey[4]; + point_init (&sk.Q); + err = os2ec (&sk.Q, skey[5]); + if (err) + { + point_free (&sk.E.G); + point_free (&sk.Q); + return err; + } + sk.d = skey[6]; + + resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p)); + resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p)); + err = sign (data, &sk, resarr[0], resarr[1]); + if (err) + { + mpi_free (resarr[0]); + mpi_free (resarr[1]); + resarr[0] = NULL; /* Mark array as released. */ + } + point_free (&sk.E.G); + point_free (&sk.Q); + return err; +} + + +static gcry_err_code_t +ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, + int (*cmp)(void *, gcry_mpi_t), void *opaquev) +{ + gpg_err_code_t err; + ECC_public_key pk; + + (void)algo; + (void)cmp; + (void)opaquev; + + if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] || !pkey[2] + || !pkey[3] || !pkey[4] || !pkey[5] ) + return GPG_ERR_BAD_MPI; + + pk.E.p = pkey[0]; + pk.E.a = pkey[1]; + pk.E.b = pkey[2]; + point_init (&pk.E.G); + err = os2ec (&pk.E.G, pkey[3]); + if (err) + { + point_free (&pk.E.G); + return err; + } + pk.E.n = pkey[4]; + point_init (&pk.Q); + err = os2ec (&pk.Q, pkey[5]); + if (err) + { + point_free (&pk.E.G); + point_free (&pk.Q); + return err; + } + + err = verify (hash, &pk, data[0], data[1]); + + point_free (&pk.E.G); + point_free (&pk.Q); + return err; +} + + +/* ecdh raw is classic 2-round DH protocol published in 1976. + * + * Overview of ecc_encrypt_raw and ecc_decrypt_raw. + * + * As with any PK operation, encrypt version uses a public key and + * decrypt -- private. + * + * Symbols used below: + * G - field generator point + * d - private long-term scalar + * dG - public long-term key + * k - ephemeral scalar + * kG - ephemeral public key + * dkG - shared secret + * + * ecc_encrypt_raw description: + * input: + * data[0] : private scalar (k) + * output: + * result[0] : shared point (kdG) + * result[1] : generated ephemeral public key (kG) + * + * ecc_decrypt_raw description: + * input: + * data[0] : a point kG (ephemeral public key) + * output: + * result[0] : shared point (kdG) + */ +static gcry_err_code_t +ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, + gcry_mpi_t *pkey, int flags) +{ + ECC_public_key pk; + mpi_ec_t ctx; + gcry_mpi_t result[2]; + int err; + + (void)algo; + (void)flags; + + if (!k + || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5]) + return GPG_ERR_BAD_MPI; + + pk.E.p = pkey[0]; + pk.E.a = pkey[1]; + pk.E.b = pkey[2]; + point_init (&pk.E.G); + err = os2ec (&pk.E.G, pkey[3]); + if (err) + { + point_free (&pk.E.G); + return err; + } + pk.E.n = pkey[4]; + point_init (&pk.Q); + err = os2ec (&pk.Q, pkey[5]); + if (err) + { + point_free (&pk.E.G); + point_free (&pk.Q); + return err; + } + + ctx = _gcry_mpi_ec_init (pk.E.p, pk.E.a); + + /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ + { + mpi_point_t R; /* Result that we return. */ + gcry_mpi_t x, y; + + x = mpi_new (0); + y = mpi_new (0); + + point_init (&R); + + /* R = kQ <=> R = kdG */ + _gcry_mpi_ec_mul_point (&R, k, &pk.Q, ctx); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates for kdG\n"); + + result[0] = ec2os (x, y, pk.E.p); + + /* R = kG */ + _gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates for kG\n"); + + result[1] = ec2os (x, y, pk.E.p); + + mpi_free (x); + mpi_free (y); + + point_free (&R); + } + + _gcry_mpi_ec_free (ctx); + point_free (&pk.E.G); + point_free (&pk.Q); + + if (!result[0] || !result[1]) + { + mpi_free (result[0]); + mpi_free (result[1]); + return GPG_ERR_ENOMEM; + } + + /* Success. */ + resarr[0] = result[0]; + resarr[1] = result[1]; + + return 0; +} + +/* input: + * data[0] : a point kG (ephemeral public key) + * output: + * resaddr[0] : shared point kdG + * + * see ecc_encrypt_raw for details. + */ +static gcry_err_code_t +ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, + gcry_mpi_t *skey, int flags) +{ + ECC_secret_key sk; + mpi_point_t R; /* Result that we return. */ + mpi_point_t kG; + mpi_ec_t ctx; + gcry_mpi_t r; + int err; + + (void)algo; + (void)flags; + + *result = NULL; + + if (!data || !data[0] + || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] + || !skey[5] || !skey[6] ) + return GPG_ERR_BAD_MPI; + + point_init (&kG); + err = os2ec (&kG, data[0]); + if (err) + { + point_free (&kG); + return err; + } + + + sk.E.p = skey[0]; + sk.E.a = skey[1]; + sk.E.b = skey[2]; + point_init (&sk.E.G); + err = os2ec (&sk.E.G, skey[3]); + if (err) + { + point_free (&kG); + point_free (&sk.E.G); + return err; + } + sk.E.n = skey[4]; + point_init (&sk.Q); + err = os2ec (&sk.Q, skey[5]); + if (err) + { + point_free (&kG); + point_free (&sk.E.G); + point_free (&sk.Q); + return err; + } + sk.d = skey[6]; + + ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a); + + /* R = dkG */ + point_init (&R); + _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ctx); + + point_free (&kG); + + /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so: */ + { + gcry_mpi_t x, y; + + x = mpi_new (0); + y = mpi_new (0); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates\n"); + + r = ec2os (x, y, sk.E.p); + mpi_free (x); + mpi_free (y); + } + + point_free (&R); + _gcry_mpi_ec_free (ctx); + point_free (&kG); + point_free (&sk.E.G); + point_free (&sk.Q); + + if (!r) + return GPG_ERR_ENOMEM; + + /* Success. */ + + *result = r; + + return 0; +} + + +static unsigned int +ecc_get_nbits (int algo, gcry_mpi_t *pkey) +{ + (void)algo; + + return mpi_get_nbits (pkey[0]); +} + + +/* See rsa.c for a description of this function. */ +static gpg_err_code_t +compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) +{ +#define N_COMPONENTS 6 + static const char names[N_COMPONENTS+1] = "pabgnq"; + gpg_err_code_t ec = 0; + gcry_sexp_t l1; + gcry_mpi_t values[N_COMPONENTS]; + int idx; + + /* Clear the values for easier error cleanup. */ + for (idx=0; idx < N_COMPONENTS; idx++) + values[idx] = NULL; + + /* Fill values with all provided parameters. */ + for (idx=0; idx < N_COMPONENTS; idx++) + { + l1 = gcry_sexp_find_token (keyparam, names+idx, 1); + if (l1) + { + values[idx] = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l1); + if (!values[idx]) + { + ec = GPG_ERR_INV_OBJ; + goto leave; + } + } + } + + /* Check whether a curve parameter is available and use that to fill + in missing values. */ + l1 = gcry_sexp_find_token (keyparam, "curve", 5); + if (l1) + { + char *curve; + gcry_mpi_t tmpvalues[N_COMPONENTS]; + + for (idx = 0; idx < N_COMPONENTS; idx++) + tmpvalues[idx] = NULL; + + curve = _gcry_sexp_nth_string (l1, 1); + gcry_sexp_release (l1); + if (!curve) + { + ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */ + goto leave; + } + ec = ecc_get_param (curve, tmpvalues); + gcry_free (curve); + if (ec) + goto leave; + + for (idx = 0; idx < N_COMPONENTS; idx++) + { + if (!values[idx]) + values[idx] = tmpvalues[idx]; + else + mpi_free (tmpvalues[idx]); + } + } + + /* Check that all parameters are known and normalize all MPIs (that + should not be required but we use an internal function later and + thus we better make 100% sure that they are normalized). */ + for (idx = 0; idx < N_COMPONENTS; idx++) + if (!values[idx]) + { + ec = GPG_ERR_NO_OBJ; + goto leave; + } + else + _gcry_mpi_normalize (values[idx]); + + /* Hash them all. */ + for (idx = 0; idx < N_COMPONENTS; idx++) + { + char buf[30]; + unsigned char *rawmpi; + unsigned int rawmpilen; + + rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL); + if (!rawmpi) + { + ec = gpg_err_code_from_syserror (); + goto leave; + } + snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], rawmpilen); + gcry_md_write (md, buf, strlen (buf)); + gcry_md_write (md, rawmpi, rawmpilen); + gcry_md_write (md, ")", 1); + gcry_free (rawmpi); + } + + leave: + for (idx = 0; idx < N_COMPONENTS; idx++) + _gcry_mpi_release (values[idx]); + + return ec; +#undef N_COMPONENTS +} + + + + + +/* + Self-test section. + */ + + +static gpg_err_code_t +selftests_ecdsa (selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + + what = "low-level"; + errtxt = NULL; /*selftest ();*/ + if (errtxt) + goto failed; + + /* FIXME: need more tests. */ + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("pubkey", GCRY_PK_ECDSA, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + +/* Run a full self-test for ALGO and return 0 on success. */ +static gpg_err_code_t +run_selftests (int algo, int extended, selftest_report_func_t report) +{ + gpg_err_code_t ec; + + (void)extended; + + switch (algo) + { + case GCRY_PK_ECDSA: + ec = selftests_ecdsa (report); + break; + default: + ec = GPG_ERR_PUBKEY_ALGO; + break; + + } + return ec; +} + + + + +static const char *ecdsa_names[] = + { + "ecdsa", + "ecc", + NULL, + }; +static const char *ecdh_names[] = + { + "ecdh", + "ecc", + NULL, + }; + +gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = + { + "ECDSA", ecdsa_names, + "pabgnq", "pabgnqd", "", "rs", "pabgnq", + GCRY_PK_USAGE_SIGN, + ecc_generate, + ecc_check_secret_key, + NULL, + NULL, + ecc_sign, + ecc_verify, + ecc_get_nbits + }; + +gcry_pk_spec_t _gcry_pubkey_spec_ecdh = + { + "ECDH", ecdh_names, + "pabgnq", "pabgnqd", "se", "", "pabgnq", + GCRY_PK_USAGE_ENCR, + ecc_generate, + ecc_check_secret_key, + ecc_encrypt_raw, + ecc_decrypt_raw, + NULL, + NULL, + ecc_get_nbits + }; + + +pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = + { + run_selftests, + ecc_generate_ext, + compute_keygrip, + ecc_get_param, + ecc_get_curve, + ecc_get_param_sexp + }; diff --git a/grub-core/lib/libgcrypt/cipher/elgamal.c b/grub-core/lib/libgcrypt/cipher/elgamal.c new file mode 100644 index 0000000..ce4be85 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/elgamal.c @@ -0,0 +1,845 @@ +/* Elgamal.c - Elgamal Public Key encryption + * Copyright (C) 1998, 2000, 2001, 2002, 2003, + * 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * For a description of the algorithm, see: + * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. + * ISBN 0-471-11709-9. Pages 476 ff. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "g10lib.h" +#include "mpi.h" +#include "cipher.h" + +typedef struct +{ + gcry_mpi_t p; /* prime */ + gcry_mpi_t g; /* group generator */ + gcry_mpi_t y; /* g^x mod p */ +} ELG_public_key; + + +typedef struct +{ + gcry_mpi_t p; /* prime */ + gcry_mpi_t g; /* group generator */ + gcry_mpi_t y; /* g^x mod p */ + gcry_mpi_t x; /* secret exponent */ +} ELG_secret_key; + + +static int test_keys (ELG_secret_key *sk, unsigned int nbits, int nodie); +static gcry_mpi_t gen_k (gcry_mpi_t p, int small_k); +static void generate (ELG_secret_key *sk, unsigned nbits, gcry_mpi_t **factors); +static int check_secret_key (ELG_secret_key *sk); +static void do_encrypt (gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, + ELG_public_key *pkey); +static void decrypt (gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, + ELG_secret_key *skey); +static void sign (gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, + ELG_secret_key *skey); +static int verify (gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, + ELG_public_key *pkey); + + +static void (*progress_cb) (void *, const char *, int, int, int); +static void *progress_cb_data; + +void +_gcry_register_pk_elg_progress (void (*cb) (void *, const char *, + int, int, int), + void *cb_data) +{ + progress_cb = cb; + progress_cb_data = cb_data; +} + + +static void +progress (int c) +{ + if (progress_cb) + progress_cb (progress_cb_data, "pk_elg", c, 0, 0); +} + + +/**************** + * Michael Wiener's table on subgroup sizes to match field sizes. + * (floating around somewhere, probably based on the paper from + * Eurocrypt 96, page 332) + */ +static unsigned int +wiener_map( unsigned int n ) +{ + static struct { unsigned int p_n, q_n; } t[] = + { /* p q attack cost */ + { 512, 119 }, /* 9 x 10^17 */ + { 768, 145 }, /* 6 x 10^21 */ + { 1024, 165 }, /* 7 x 10^24 */ + { 1280, 183 }, /* 3 x 10^27 */ + { 1536, 198 }, /* 7 x 10^29 */ + { 1792, 212 }, /* 9 x 10^31 */ + { 2048, 225 }, /* 8 x 10^33 */ + { 2304, 237 }, /* 5 x 10^35 */ + { 2560, 249 }, /* 3 x 10^37 */ + { 2816, 259 }, /* 1 x 10^39 */ + { 3072, 269 }, /* 3 x 10^40 */ + { 3328, 279 }, /* 8 x 10^41 */ + { 3584, 288 }, /* 2 x 10^43 */ + { 3840, 296 }, /* 4 x 10^44 */ + { 4096, 305 }, /* 7 x 10^45 */ + { 4352, 313 }, /* 1 x 10^47 */ + { 4608, 320 }, /* 2 x 10^48 */ + { 4864, 328 }, /* 2 x 10^49 */ + { 5120, 335 }, /* 3 x 10^50 */ + { 0, 0 } + }; + int i; + + for(i=0; t[i].p_n; i++ ) + { + if( n <= t[i].p_n ) + return t[i].q_n; + } + /* Not in table - use an arbitrary high number. */ + return n / 8 + 200; +} + +static int +test_keys ( ELG_secret_key *sk, unsigned int nbits, int nodie ) +{ + ELG_public_key pk; + gcry_mpi_t test = gcry_mpi_new ( 0 ); + gcry_mpi_t out1_a = gcry_mpi_new ( nbits ); + gcry_mpi_t out1_b = gcry_mpi_new ( nbits ); + gcry_mpi_t out2 = gcry_mpi_new ( nbits ); + int failed = 0; + + pk.p = sk->p; + pk.g = sk->g; + pk.y = sk->y; + + gcry_mpi_randomize ( test, nbits, GCRY_WEAK_RANDOM ); + + do_encrypt ( out1_a, out1_b, test, &pk ); + decrypt ( out2, out1_a, out1_b, sk ); + if ( mpi_cmp( test, out2 ) ) + failed |= 1; + + sign ( out1_a, out1_b, test, sk ); + if ( !verify( out1_a, out1_b, test, &pk ) ) + failed |= 2; + + gcry_mpi_release ( test ); + gcry_mpi_release ( out1_a ); + gcry_mpi_release ( out1_b ); + gcry_mpi_release ( out2 ); + + if (failed && !nodie) + log_fatal ("Elgamal test key for %s %s failed\n", + (failed & 1)? "encrypt+decrypt":"", + (failed & 2)? "sign+verify":""); + if (failed && DBG_CIPHER) + log_debug ("Elgamal test key for %s %s failed\n", + (failed & 1)? "encrypt+decrypt":"", + (failed & 2)? "sign+verify":""); + + return failed; +} + + +/**************** + * Generate a random secret exponent k from prime p, so that k is + * relatively prime to p-1. With SMALL_K set, k will be selected for + * better encryption performance - this must never be used signing! + */ +static gcry_mpi_t +gen_k( gcry_mpi_t p, int small_k ) +{ + gcry_mpi_t k = mpi_alloc_secure( 0 ); + gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(p) ); + gcry_mpi_t p_1 = mpi_copy(p); + unsigned int orig_nbits = mpi_get_nbits(p); + unsigned int nbits, nbytes; + char *rndbuf = NULL; + + if (small_k) + { + /* Using a k much lesser than p is sufficient for encryption and + * it greatly improves the encryption performance. We use + * Wiener's table and add a large safety margin. */ + nbits = wiener_map( orig_nbits ) * 3 / 2; + if( nbits >= orig_nbits ) + BUG(); + } + else + nbits = orig_nbits; + + + nbytes = (nbits+7)/8; + if( DBG_CIPHER ) + log_debug("choosing a random k "); + mpi_sub_ui( p_1, p, 1); + for(;;) + { + if( !rndbuf || nbits < 32 ) + { + gcry_free(rndbuf); + rndbuf = gcry_random_bytes_secure( nbytes, GCRY_STRONG_RANDOM ); + } + else + { + /* Change only some of the higher bits. We could improve + this by directly requesting more memory at the first call + to get_random_bytes() and use this the here maybe it is + easier to do this directly in random.c Anyway, it is + highly inlikely that we will ever reach this code. */ + char *pp = gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM ); + memcpy( rndbuf, pp, 4 ); + gcry_free(pp); + } + _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 ); + + for(;;) + { + if( !(mpi_cmp( k, p_1 ) < 0) ) /* check: k < (p-1) */ + { + if( DBG_CIPHER ) + progress('+'); + break; /* no */ + } + if( !(mpi_cmp_ui( k, 0 ) > 0) ) /* check: k > 0 */ + { + if( DBG_CIPHER ) + progress('-'); + break; /* no */ + } + if (gcry_mpi_gcd( temp, k, p_1 )) + goto found; /* okay, k is relative prime to (p-1) */ + mpi_add_ui( k, k, 1 ); + if( DBG_CIPHER ) + progress('.'); + } + } + found: + gcry_free(rndbuf); + if( DBG_CIPHER ) + progress('\n'); + mpi_free(p_1); + mpi_free(temp); + + return k; +} + +/**************** + * Generate a key pair with a key of size NBITS + * Returns: 2 structures filled with all needed values + * and an array with n-1 factors of (p-1) + */ +static void +generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors ) +{ + gcry_mpi_t p; /* the prime */ + gcry_mpi_t p_min1; + gcry_mpi_t g; + gcry_mpi_t x; /* the secret exponent */ + gcry_mpi_t y; + unsigned int qbits; + unsigned int xbits; + byte *rndbuf; + + p_min1 = gcry_mpi_new ( nbits ); + qbits = wiener_map( nbits ); + if( qbits & 1 ) /* better have a even one */ + qbits++; + g = mpi_alloc(1); + p = _gcry_generate_elg_prime( 0, nbits, qbits, g, ret_factors ); + mpi_sub_ui(p_min1, p, 1); + + + /* Select a random number which has these properties: + * 0 < x < p-1 + * This must be a very good random number because this is the + * secret part. The prime is public and may be shared anyway, + * so a random generator level of 1 is used for the prime. + * + * I don't see a reason to have a x of about the same size + * as the p. It should be sufficient to have one about the size + * of q or the later used k plus a large safety margin. Decryption + * will be much faster with such an x. + */ + xbits = qbits * 3 / 2; + if( xbits >= nbits ) + BUG(); + x = gcry_mpi_snew ( xbits ); + if( DBG_CIPHER ) + log_debug("choosing a random x of size %u", xbits ); + rndbuf = NULL; + do + { + if( DBG_CIPHER ) + progress('.'); + if( rndbuf ) + { /* Change only some of the higher bits */ + if( xbits < 16 ) /* should never happen ... */ + { + gcry_free(rndbuf); + rndbuf = gcry_random_bytes_secure( (xbits+7)/8, + GCRY_VERY_STRONG_RANDOM ); + } + else + { + char *r = gcry_random_bytes_secure( 2, + GCRY_VERY_STRONG_RANDOM ); + memcpy(rndbuf, r, 2 ); + gcry_free(r); + } + } + else + { + rndbuf = gcry_random_bytes_secure( (xbits+7)/8, + GCRY_VERY_STRONG_RANDOM ); + } + _gcry_mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 ); + mpi_clear_highbit( x, xbits+1 ); + } + while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); + gcry_free(rndbuf); + + y = gcry_mpi_new (nbits); + gcry_mpi_powm( y, g, x, p ); + + if( DBG_CIPHER ) + { + progress('\n'); + log_mpidump("elg p= ", p ); + log_mpidump("elg g= ", g ); + log_mpidump("elg y= ", y ); + log_mpidump("elg x= ", x ); + } + + /* Copy the stuff to the key structures */ + sk->p = p; + sk->g = g; + sk->y = y; + sk->x = x; + + gcry_mpi_release ( p_min1 ); + + /* Now we can test our keys (this should never fail!) */ + test_keys ( sk, nbits - 64, 0 ); +} + + +/* Generate a key pair with a key of size NBITS not using a random + value for the secret key but the one given as X. This is useful to + implement a passphrase based decryption for a public key based + encryption. It has appliactions in backup systems. + + Returns: A structure filled with all needed values and an array + with n-1 factors of (p-1). */ +static gcry_err_code_t +generate_using_x (ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t x, + gcry_mpi_t **ret_factors ) +{ + gcry_mpi_t p; /* The prime. */ + gcry_mpi_t p_min1; /* The prime minus 1. */ + gcry_mpi_t g; /* The generator. */ + gcry_mpi_t y; /* g^x mod p. */ + unsigned int qbits; + unsigned int xbits; + + sk->p = NULL; + sk->g = NULL; + sk->y = NULL; + sk->x = NULL; + + /* Do a quick check to see whether X is suitable. */ + xbits = mpi_get_nbits (x); + if ( xbits < 64 || xbits >= nbits ) + return GPG_ERR_INV_VALUE; + + p_min1 = gcry_mpi_new ( nbits ); + qbits = wiener_map ( nbits ); + if ( (qbits & 1) ) /* Better have an even one. */ + qbits++; + g = mpi_alloc (1); + p = _gcry_generate_elg_prime ( 0, nbits, qbits, g, ret_factors ); + mpi_sub_ui (p_min1, p, 1); + + if (DBG_CIPHER) + log_debug ("using a supplied x of size %u", xbits ); + if ( !(mpi_cmp_ui ( x, 0 ) > 0 && mpi_cmp ( x, p_min1 ) <0 ) ) + { + gcry_mpi_release ( p_min1 ); + gcry_mpi_release ( p ); + gcry_mpi_release ( g ); + return GPG_ERR_INV_VALUE; + } + + y = gcry_mpi_new (nbits); + gcry_mpi_powm ( y, g, x, p ); + + if ( DBG_CIPHER ) + { + progress ('\n'); + log_mpidump ("elg p= ", p ); + log_mpidump ("elg g= ", g ); + log_mpidump ("elg y= ", y ); + log_mpidump ("elg x= ", x ); + } + + /* Copy the stuff to the key structures */ + sk->p = p; + sk->g = g; + sk->y = y; + sk->x = gcry_mpi_copy (x); + + gcry_mpi_release ( p_min1 ); + + /* Now we can test our keys. */ + if ( test_keys ( sk, nbits - 64, 1 ) ) + { + gcry_mpi_release ( sk->p ); sk->p = NULL; + gcry_mpi_release ( sk->g ); sk->g = NULL; + gcry_mpi_release ( sk->y ); sk->y = NULL; + gcry_mpi_release ( sk->x ); sk->x = NULL; + return GPG_ERR_BAD_SECKEY; + } + + return 0; +} + + +/**************** + * Test whether the secret key is valid. + * Returns: if this is a valid key. + */ +static int +check_secret_key( ELG_secret_key *sk ) +{ + int rc; + gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs(sk->y) ); + + gcry_mpi_powm( y, sk->g, sk->x, sk->p ); + rc = !mpi_cmp( y, sk->y ); + mpi_free( y ); + return rc; +} + + +static void +do_encrypt(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey ) +{ + gcry_mpi_t k; + + /* Note: maybe we should change the interface, so that it + * is possible to check that input is < p and return an + * error code. + */ + + k = gen_k( pkey->p, 1 ); + gcry_mpi_powm( a, pkey->g, k, pkey->p ); + /* b = (y^k * input) mod p + * = ((y^k mod p) * (input mod p)) mod p + * and because input is < p + * = ((y^k mod p) * input) mod p + */ + gcry_mpi_powm( b, pkey->y, k, pkey->p ); + gcry_mpi_mulm( b, b, input, pkey->p ); +#if 0 + if( DBG_CIPHER ) + { + log_mpidump("elg encrypted y= ", pkey->y); + log_mpidump("elg encrypted p= ", pkey->p); + log_mpidump("elg encrypted k= ", k); + log_mpidump("elg encrypted M= ", input); + log_mpidump("elg encrypted a= ", a); + log_mpidump("elg encrypted b= ", b); + } +#endif + mpi_free(k); +} + + + + +static void +decrypt(gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, ELG_secret_key *skey ) +{ + gcry_mpi_t t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) ); + + /* output = b/(a^x) mod p */ + gcry_mpi_powm( t1, a, skey->x, skey->p ); + mpi_invm( t1, t1, skey->p ); + mpi_mulm( output, b, t1, skey->p ); +#if 0 + if( DBG_CIPHER ) + { + log_mpidump("elg decrypted x= ", skey->x); + log_mpidump("elg decrypted p= ", skey->p); + log_mpidump("elg decrypted a= ", a); + log_mpidump("elg decrypted b= ", b); + log_mpidump("elg decrypted M= ", output); + } +#endif + mpi_free(t1); +} + + +/**************** + * Make an Elgamal signature out of INPUT + */ + +static void +sign(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_secret_key *skey ) +{ + gcry_mpi_t k; + gcry_mpi_t t = mpi_alloc( mpi_get_nlimbs(a) ); + gcry_mpi_t inv = mpi_alloc( mpi_get_nlimbs(a) ); + gcry_mpi_t p_1 = mpi_copy(skey->p); + + /* + * b = (t * inv) mod (p-1) + * b = (t * inv(k,(p-1),(p-1)) mod (p-1) + * b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1) + * + */ + mpi_sub_ui(p_1, p_1, 1); + k = gen_k( skey->p, 0 /* no small K ! */ ); + gcry_mpi_powm( a, skey->g, k, skey->p ); + mpi_mul(t, skey->x, a ); + mpi_subm(t, input, t, p_1 ); + mpi_invm(inv, k, p_1 ); + mpi_mulm(b, t, inv, p_1 ); + +#if 0 + if( DBG_CIPHER ) + { + log_mpidump("elg sign p= ", skey->p); + log_mpidump("elg sign g= ", skey->g); + log_mpidump("elg sign y= ", skey->y); + log_mpidump("elg sign x= ", skey->x); + log_mpidump("elg sign k= ", k); + log_mpidump("elg sign M= ", input); + log_mpidump("elg sign a= ", a); + log_mpidump("elg sign b= ", b); + } +#endif + mpi_free(k); + mpi_free(t); + mpi_free(inv); + mpi_free(p_1); +} + + +/**************** + * Returns true if the signature composed of A and B is valid. + */ +static int +verify(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey ) +{ + int rc; + gcry_mpi_t t1; + gcry_mpi_t t2; + gcry_mpi_t base[4]; + gcry_mpi_t ex[4]; + + if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) ) + return 0; /* assertion 0 < a < p failed */ + + t1 = mpi_alloc( mpi_get_nlimbs(a) ); + t2 = mpi_alloc( mpi_get_nlimbs(a) ); + +#if 0 + /* t1 = (y^a mod p) * (a^b mod p) mod p */ + gcry_mpi_powm( t1, pkey->y, a, pkey->p ); + gcry_mpi_powm( t2, a, b, pkey->p ); + mpi_mulm( t1, t1, t2, pkey->p ); + + /* t2 = g ^ input mod p */ + gcry_mpi_powm( t2, pkey->g, input, pkey->p ); + + rc = !mpi_cmp( t1, t2 ); +#elif 0 + /* t1 = (y^a mod p) * (a^b mod p) mod p */ + base[0] = pkey->y; ex[0] = a; + base[1] = a; ex[1] = b; + base[2] = NULL; ex[2] = NULL; + mpi_mulpowm( t1, base, ex, pkey->p ); + + /* t2 = g ^ input mod p */ + gcry_mpi_powm( t2, pkey->g, input, pkey->p ); + + rc = !mpi_cmp( t1, t2 ); +#else + /* t1 = g ^ - input * y ^ a * a ^ b mod p */ + mpi_invm(t2, pkey->g, pkey->p ); + base[0] = t2 ; ex[0] = input; + base[1] = pkey->y; ex[1] = a; + base[2] = a; ex[2] = b; + base[3] = NULL; ex[3] = NULL; + mpi_mulpowm( t1, base, ex, pkey->p ); + rc = !mpi_cmp_ui( t1, 1 ); + +#endif + + mpi_free(t1); + mpi_free(t2); + return rc; +} + +/********************************************* + ************** interface ****************** + *********************************************/ + +static gpg_err_code_t +elg_generate_ext (int algo, unsigned int nbits, unsigned long evalue, + const gcry_sexp_t genparms, + gcry_mpi_t *skey, gcry_mpi_t **retfactors, + gcry_sexp_t *r_extrainfo) +{ + gpg_err_code_t ec; + ELG_secret_key sk; + gcry_mpi_t xvalue = NULL; + gcry_sexp_t l1; + + (void)algo; + (void)evalue; + (void)r_extrainfo; + + if (genparms) + { + /* Parse the optional xvalue element. */ + l1 = gcry_sexp_find_token (genparms, "xvalue", 0); + if (l1) + { + xvalue = gcry_sexp_nth_mpi (l1, 1, 0); + gcry_sexp_release (l1); + if (!xvalue) + return GPG_ERR_BAD_MPI; + } + } + + if (xvalue) + ec = generate_using_x (&sk, nbits, xvalue, retfactors); + else + { + generate (&sk, nbits, retfactors); + ec = 0; + } + + skey[0] = sk.p; + skey[1] = sk.g; + skey[2] = sk.y; + skey[3] = sk.x; + + return ec; +} + + +static gcry_err_code_t +elg_generate (int algo, unsigned int nbits, unsigned long evalue, + gcry_mpi_t *skey, gcry_mpi_t **retfactors) +{ + ELG_secret_key sk; + + (void)algo; + (void)evalue; + + generate (&sk, nbits, retfactors); + skey[0] = sk.p; + skey[1] = sk.g; + skey[2] = sk.y; + skey[3] = sk.x; + + return GPG_ERR_NO_ERROR; +} + + +static gcry_err_code_t +elg_check_secret_key (int algo, gcry_mpi_t *skey) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + ELG_secret_key sk; + + (void)algo; + + if ((! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3])) + err = GPG_ERR_BAD_MPI; + else + { + sk.p = skey[0]; + sk.g = skey[1]; + sk.y = skey[2]; + sk.x = skey[3]; + + if (! check_secret_key (&sk)) + err = GPG_ERR_BAD_SECKEY; + } + + return err; +} + + +static gcry_err_code_t +elg_encrypt (int algo, gcry_mpi_t *resarr, + gcry_mpi_t data, gcry_mpi_t *pkey, int flags) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + ELG_public_key pk; + + (void)algo; + (void)flags; + + if ((! data) || (! pkey[0]) || (! pkey[1]) || (! pkey[2])) + err = GPG_ERR_BAD_MPI; + else + { + pk.p = pkey[0]; + pk.g = pkey[1]; + pk.y = pkey[2]; + resarr[0] = mpi_alloc (mpi_get_nlimbs (pk.p)); + resarr[1] = mpi_alloc (mpi_get_nlimbs (pk.p)); + do_encrypt (resarr[0], resarr[1], data, &pk); + } + return err; +} + + +static gcry_err_code_t +elg_decrypt (int algo, gcry_mpi_t *result, + gcry_mpi_t *data, gcry_mpi_t *skey, int flags) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + ELG_secret_key sk; + + (void)algo; + (void)flags; + + if ((! data[0]) || (! data[1]) + || (! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3])) + err = GPG_ERR_BAD_MPI; + else + { + sk.p = skey[0]; + sk.g = skey[1]; + sk.y = skey[2]; + sk.x = skey[3]; + *result = mpi_alloc_secure (mpi_get_nlimbs (sk.p)); + decrypt (*result, data[0], data[1], &sk); + } + return err; +} + + +static gcry_err_code_t +elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + ELG_secret_key sk; + + (void)algo; + + if ((! data) + || (! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3])) + err = GPG_ERR_BAD_MPI; + else + { + sk.p = skey[0]; + sk.g = skey[1]; + sk.y = skey[2]; + sk.x = skey[3]; + resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.p)); + resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.p)); + sign (resarr[0], resarr[1], data, &sk); + } + + return err; +} + + +static gcry_err_code_t +elg_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, + int (*cmp) (void *, gcry_mpi_t), void *opaquev) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + ELG_public_key pk; + + (void)algo; + (void)cmp; + (void)opaquev; + + if ((! data[0]) || (! data[1]) || (! hash) + || (! pkey[0]) || (! pkey[1]) || (! pkey[2])) + err = GPG_ERR_BAD_MPI; + else + { + pk.p = pkey[0]; + pk.g = pkey[1]; + pk.y = pkey[2]; + if (! verify (data[0], data[1], hash, &pk)) + err = GPG_ERR_BAD_SIGNATURE; + } + + return err; +} + + +static unsigned int +elg_get_nbits (int algo, gcry_mpi_t *pkey) +{ + (void)algo; + + return mpi_get_nbits (pkey[0]); +} + + +static const char *elg_names[] = + { + "elg", + "openpgp-elg", + "openpgp-elg-sig", + NULL, + }; + + +gcry_pk_spec_t _gcry_pubkey_spec_elg = + { + "ELG", elg_names, + "pgy", "pgyx", "ab", "rs", "pgy", + GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR, + elg_generate, + elg_check_secret_key, + elg_encrypt, + elg_decrypt, + elg_sign, + elg_verify, + elg_get_nbits + }; + +pk_extra_spec_t _gcry_pubkey_extraspec_elg = + { + NULL, + elg_generate_ext, + NULL + }; diff --git a/grub-core/lib/libgcrypt/cipher/hash-common.c b/grub-core/lib/libgcrypt/cipher/hash-common.c new file mode 100644 index 0000000..8c413bc --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/hash-common.c @@ -0,0 +1,93 @@ +/* hash-common.c - Common code for hash algorithms + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif + +#include "g10lib.h" +#include "hash-common.h" + + +/* Run a selftest for hash algorithm ALGO. If the resulting digest + matches EXPECT/EXPECTLEN and everything else is fine as well, + return NULL. If an error occurs, return a static text string + describing the error. + + DATAMODE controls what will be hashed according to this table: + + 0 - Hash the supplied DATA of DATALEN. + 1 - Hash one million times a 'a'. DATA and DATALEN are ignored. + +*/ +const char * +_gcry_hash_selftest_check_one (int algo, + int datamode, const void *data, size_t datalen, + const void *expect, size_t expectlen) +{ + const char *result = NULL; + gcry_error_t err = 0; + gcry_md_hd_t hd; + unsigned char *digest; + + if (_gcry_md_get_algo_dlen (algo) != expectlen) + return "digest size does not match expected size"; + + err = _gcry_md_open (&hd, algo, 0); + if (err) + return "gcry_md_open failed"; + + switch (datamode) + { + case 0: + _gcry_md_write (hd, data, datalen); + break; + + case 1: /* Hash one million times an "a". */ + { + char aaa[1000]; + int i; + + /* Write in odd size chunks so that we test the buffering. */ + memset (aaa, 'a', 1000); + for (i = 0; i < 1000; i++) + _gcry_md_write (hd, aaa, 1000); + } + break; + + default: + result = "invalid DATAMODE"; + } + + if (!result) + { + digest = _gcry_md_read (hd, algo); + + if ( memcmp (digest, expect, expectlen) ) + result = "digest mismatch"; + } + + _gcry_md_close (hd); + + return result; +} diff --git a/grub-core/lib/libgcrypt/cipher/hash-common.h b/grub-core/lib/libgcrypt/cipher/hash-common.h new file mode 100644 index 0000000..fdebef4 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/hash-common.h @@ -0,0 +1,33 @@ +/* hash-common.h - Declarations of common code for hash algorithms. + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GCRY_HASH_COMMON_H +#define GCRY_HASH_COMMON_H + + +const char * _gcry_hash_selftest_check_one +/**/ (int algo, + int datamode, const void *data, size_t datalen, + const void *expect, size_t expectlen); + + + + + +#endif /*GCRY_HASH_COMMON_H*/ diff --git a/grub-core/lib/libgcrypt/cipher/hmac-tests.c b/grub-core/lib/libgcrypt/cipher/hmac-tests.c new file mode 100644 index 0000000..a32ece7 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/hmac-tests.c @@ -0,0 +1,732 @@ +/* hmac-tests.c - HMAC selftests. + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* + Although algorithm self-tests are usually implemented in the module + implementing the algorithm, the case for HMAC is different because + HMAC is implemnetd on a higher level using a special feature of the + gcry_md_ functions. It would be possible to do this also in the + digest algorithm modules, but that would blow up the code too much + and spread the hmac tests over several modules. + + Thus we implement all HMAC tests in this test module and provide a + function to run the tests. +*/ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif + +#include "g10lib.h" +#include "cipher.h" +#include "hmac256.h" + +/* Check one HMAC with digest ALGO using the regualr HAMC + API. (DATA,DATALEN) is the data to be MACed, (KEY,KEYLEN) the key + and (EXPECT,EXPECTLEN) the expected result. Returns NULL on + succdess or a string describing the failure. */ +static const char * +check_one (int algo, + const void *data, size_t datalen, + const void *key, size_t keylen, + const void *expect, size_t expectlen) +{ + gcry_md_hd_t hd; + const unsigned char *digest; + +/* printf ("HMAC algo %d\n", algo); */ + if (_gcry_md_get_algo_dlen (algo) != expectlen) + return "invalid tests data"; + if (_gcry_md_open (&hd, algo, GCRY_MD_FLAG_HMAC)) + return "gcry_md_open failed"; + if (_gcry_md_setkey (hd, key, keylen)) + { + _gcry_md_close (hd); + return "gcry_md_setkey failed"; + } + _gcry_md_write (hd, data, datalen); + digest = _gcry_md_read (hd, algo); + if (!digest) + { + _gcry_md_close (hd); + return "gcry_md_read failed"; + } + if (memcmp (digest, expect, expectlen)) + { +/* int i; */ + +/* fputs (" {", stdout); */ +/* for (i=0; i < expectlen-1; i++) */ +/* { */ +/* if (i && !(i % 8)) */ +/* fputs ("\n ", stdout); */ +/* printf (" 0x%02x,", digest[i]); */ +/* } */ +/* printf (" 0x%02x } },\n", digest[i]); */ + + _gcry_md_close (hd); + return "does not match"; + } + _gcry_md_close (hd); + return NULL; +} + + +static gpg_err_code_t +selftests_sha1 (int extended, selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + unsigned char key[128]; + int i, j; + + what = "FIPS-198a, A.1"; + for (i=0; i < 64; i++) + key[i] = i; + errtxt = check_one (GCRY_MD_SHA1, + "Sample #1", 9, + key, 64, + "\x4f\x4c\xa3\xd5\xd6\x8b\xa7\xcc\x0a\x12" + "\x08\xc9\xc6\x1e\x9c\x5d\xa0\x40\x3c\x0a", 20); + if (errtxt) + goto failed; + + if (extended) + { + what = "FIPS-198a, A.2"; + for (i=0, j=0x30; i < 20; i++) + key[i] = j++; + errtxt = check_one (GCRY_MD_SHA1, + "Sample #2", 9, + key, 20, + "\x09\x22\xd3\x40\x5f\xaa\x3d\x19\x4f\x82" + "\xa4\x58\x30\x73\x7d\x5c\xc6\xc7\x5d\x24", 20); + if (errtxt) + goto failed; + + what = "FIPS-198a, A.3"; + for (i=0, j=0x50; i < 100; i++) + key[i] = j++; + errtxt = check_one (GCRY_MD_SHA1, + "Sample #3", 9, + key, 100, + "\xbc\xf4\x1e\xab\x8b\xb2\xd8\x02\xf3\xd0" + "\x5c\xaf\x7c\xb0\x92\xec\xf8\xd1\xa3\xaa", 20 ); + if (errtxt) + goto failed; + + what = "FIPS-198a, A.4"; + for (i=0, j=0x70; i < 49; i++) + key[i] = j++; + errtxt = check_one (GCRY_MD_SHA1, + "Sample #4", 9, + key, 49, + "\x9e\xa8\x86\xef\xe2\x68\xdb\xec\xce\x42" + "\x0c\x75\x24\xdf\x32\xe0\x75\x1a\x2a\x26", 20 ); + if (errtxt) + goto failed; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("hmac", GCRY_MD_SHA1, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + + +static gpg_err_code_t +selftests_sha224 (int extended, selftest_report_func_t report) +{ + static struct + { + const char * const desc; + const char * const data; + const char * const key; + const char expect[28]; + } tv[] = + { + { "data-28 key-4", + "what do ya want for nothing?", + "Jefe", + { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, + 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f, + 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, + 0x8f, 0xd0, 0x5e, 0x44 } }, + + { "data-9 key-20", + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b", + { 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, + 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f, + 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, + 0x53, 0x68, 0x4b, 0x22 } }, + + { "data-50 key-20", + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa", + { 0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, + 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64, + 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, + 0xec, 0x83, 0x33, 0xea } }, + + { "data-50 key-26", + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19", + { 0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac, + 0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82, 0x62, 0x7c, + 0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d, + 0xe7, 0xaf, 0xec, 0x5a } }, + + { "data-54 key-131", + "Test Using Larger Than Block-Size Key - Hash Key First", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + { 0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad, + 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2, + 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27, + 0x3f, 0xa6, 0x87, 0x0e } }, + + { "data-152 key-131", + "This is a test using a larger than block-size key and a larger " + "than block-size data. The key needs to be hashed before being " + "used by the HMAC algorithm.", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + { 0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02, + 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd, + 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9, + 0xf6, 0xf5, 0x65, 0xd1 } }, + + { NULL } + }; + const char *what; + const char *errtxt; + int tvidx; + + for (tvidx=0; tv[tvidx].desc; tvidx++) + { + what = tv[tvidx].desc; + errtxt = check_one (GCRY_MD_SHA224, + tv[tvidx].data, strlen (tv[tvidx].data), + tv[tvidx].key, strlen (tv[tvidx].key), + tv[tvidx].expect, DIM (tv[tvidx].expect) ); + if (errtxt) + goto failed; + if (!extended) + break; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("hmac", GCRY_MD_SHA224, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + +static gpg_err_code_t +selftests_sha256 (int extended, selftest_report_func_t report) +{ + static struct + { + const char * const desc; + const char * const data; + const char * const key; + const char expect[32]; + } tv[] = + { + { "data-28 key-4", + "what do ya want for nothing?", + "Jefe", + { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, + 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, + 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, + 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 } }, + + { "data-9 key-20", + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b", + { 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, + 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, + 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, + 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 } }, + + { "data-50 key-20", + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa", + { 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, + 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, + 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, + 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe } }, + + { "data-50 key-26", + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19", + { 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, + 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, + 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, + 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b } }, + + { "data-54 key-131", + "Test Using Larger Than Block-Size Key - Hash Key First", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + { 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, + 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, + 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, + 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 } }, + + { "data-152 key-131", + "This is a test using a larger than block-size key and a larger " + "than block-size data. The key needs to be hashed before being " + "used by the HMAC algorithm.", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + { 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, + 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, + 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, + 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2 } }, + + { NULL } + }; + const char *what; + const char *errtxt; + int tvidx; + + for (tvidx=0; tv[tvidx].desc; tvidx++) + { + hmac256_context_t hmachd; + const unsigned char *digest; + size_t dlen; + + what = tv[tvidx].desc; + errtxt = check_one (GCRY_MD_SHA256, + tv[tvidx].data, strlen (tv[tvidx].data), + tv[tvidx].key, strlen (tv[tvidx].key), + tv[tvidx].expect, DIM (tv[tvidx].expect) ); + if (errtxt) + goto failed; + + hmachd = _gcry_hmac256_new (tv[tvidx].key, strlen (tv[tvidx].key)); + if (!hmachd) + { + errtxt = "_gcry_hmac256_new failed"; + goto failed; + } + _gcry_hmac256_update (hmachd, tv[tvidx].data, strlen (tv[tvidx].data)); + digest = _gcry_hmac256_finalize (hmachd, &dlen); + if (!digest) + { + errtxt = "_gcry_hmac256_finalize failed"; + _gcry_hmac256_release (hmachd); + goto failed; + } + if (dlen != DIM (tv[tvidx].expect) + || memcmp (digest, tv[tvidx].expect, DIM (tv[tvidx].expect))) + { + errtxt = "does not match in second implementation"; + _gcry_hmac256_release (hmachd); + goto failed; + } + _gcry_hmac256_release (hmachd); + + if (!extended) + break; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("hmac", GCRY_MD_SHA256, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + +static gpg_err_code_t +selftests_sha384 (int extended, selftest_report_func_t report) +{ + static struct + { + const char * const desc; + const char * const data; + const char * const key; + const char expect[48]; + } tv[] = + { + { "data-28 key-4", + "what do ya want for nothing?", + "Jefe", + { 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, + 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b, + 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47, + 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e, + 0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7, + 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49 } }, + + { "data-9 key-20", + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b", + { 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, + 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f, + 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6, + 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, + 0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f, + 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6 } }, + + { "data-50 key-20", + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa", + { 0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, + 0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f, + 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb, + 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, + 0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9, + 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27 } }, + + { "data-50 key-26", + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19", + { 0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85, + 0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7, + 0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c, + 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e, + 0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79, + 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb } }, + + { "data-54 key-131", + "Test Using Larger Than Block-Size Key - Hash Key First", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + { 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, + 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4, + 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f, + 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6, + 0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82, + 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52 } }, + + { "data-152 key-131", + "This is a test using a larger than block-size key and a larger " + "than block-size data. The key needs to be hashed before being " + "used by the HMAC algorithm.", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + { 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d, + 0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c, + 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a, + 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5, + 0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d, + 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e } }, + + { NULL } + }; + const char *what; + const char *errtxt; + int tvidx; + + for (tvidx=0; tv[tvidx].desc; tvidx++) + { + what = tv[tvidx].desc; + errtxt = check_one (GCRY_MD_SHA384, + tv[tvidx].data, strlen (tv[tvidx].data), + tv[tvidx].key, strlen (tv[tvidx].key), + tv[tvidx].expect, DIM (tv[tvidx].expect) ); + if (errtxt) + goto failed; + if (!extended) + break; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("hmac", GCRY_MD_SHA384, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + +static gpg_err_code_t +selftests_sha512 (int extended, selftest_report_func_t report) +{ + static struct + { + const char * const desc; + const char * const data; + const char * const key; + const char expect[64]; + } tv[] = + { + { "data-28 key-4", + "what do ya want for nothing?", + "Jefe", + { 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, + 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, + 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, + 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, + 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a, + 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, + 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, + 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37 } }, + + { "data-9 key-20", + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b", + { 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, + 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, + 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, + 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, + 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02, + 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4, + 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70, + 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54 } }, + + { "data-50 key-20", + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa", + { 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, + 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9, + 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, + 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, + 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8, + 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07, + 0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26, + 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb } }, + + { "data-50 key-26", + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19", + { 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, + 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, + 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, + 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, + 0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4, + 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63, + 0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d, + 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd } }, + + { "data-54 key-131", + "Test Using Larger Than Block-Size Key - Hash Key First", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + { 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, + 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4, + 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1, + 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52, + 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98, + 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52, + 0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec, + 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98 } }, + + { "data-152 key-131", + "This is a test using a larger than block-size key and a larger " + "than block-size data. The key needs to be hashed before being " + "used by the HMAC algorithm.", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + { 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba, + 0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd, + 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86, + 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44, + 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1, + 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15, + 0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60, + 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58 } }, + + { NULL } + }; + const char *what; + const char *errtxt; + int tvidx; + + for (tvidx=0; tv[tvidx].desc; tvidx++) + { + what = tv[tvidx].desc; + errtxt = check_one (GCRY_MD_SHA512, + tv[tvidx].data, strlen (tv[tvidx].data), + tv[tvidx].key, strlen (tv[tvidx].key), + tv[tvidx].expect, DIM (tv[tvidx].expect) ); + if (errtxt) + goto failed; + if (!extended) + break; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("hmac", GCRY_MD_SHA512, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + + +/* Run a full self-test for ALGO and return 0 on success. */ +static gpg_err_code_t +run_selftests (int algo, int extended, selftest_report_func_t report) +{ + gpg_err_code_t ec; + + switch (algo) + { + case GCRY_MD_SHA1: + ec = selftests_sha1 (extended, report); + break; + case GCRY_MD_SHA224: + ec = selftests_sha224 (extended, report); + break; + case GCRY_MD_SHA256: + ec = selftests_sha256 (extended, report); + break; + case GCRY_MD_SHA384: + ec = selftests_sha384 (extended, report); + break; + case GCRY_MD_SHA512: + ec = selftests_sha512 (extended, report); + break; + default: + ec = GPG_ERR_DIGEST_ALGO; + break; + } + return ec; +} + + + + +/* Run the selftests for HMAC with digest algorithm ALGO with optional + reporting function REPORT. */ +gpg_error_t +_gcry_hmac_selftest (int algo, int extended, selftest_report_func_t report) +{ + gcry_err_code_t ec = 0; + + if (!gcry_md_test_algo (algo)) + { + ec = run_selftests (algo, extended, report); + } + else + { + ec = GPG_ERR_DIGEST_ALGO; + if (report) + report ("hmac", algo, "module", "algorithm not available"); + } + return gpg_error (ec); +} diff --git a/grub-core/lib/libgcrypt/cipher/idea.c b/grub-core/lib/libgcrypt/cipher/idea.c new file mode 100644 index 0000000..3c5578f --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/idea.c @@ -0,0 +1,378 @@ +/* idea.c - IDEA function + * Copyright 1997, 1998, 1999, 2001 Werner Koch (dd9jn) + * Copyright 2013 g10 Code GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * WERNER KOCH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of Werner Koch shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Werner Koch. + * + * Patents on IDEA have expired: + * Europe: EP0482154 on 2011-05-16, + * Japan: JP3225440 on 2011-05-16, + * U.S.: 5,214,703 on 2012-01-07. + */ + +/* + * Please see http://www.noepatents.org/ to learn why software patents + * are bad for society and what you can do to fight them. + * + * The code herein is based on the one from: + * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. + * ISBN 0-471-11709-9. + */ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + + +#define IDEA_KEYSIZE 16 +#define IDEA_BLOCKSIZE 8 +#define IDEA_ROUNDS 8 +#define IDEA_KEYLEN (6*IDEA_ROUNDS+4) + +typedef struct { + u16 ek[IDEA_KEYLEN]; + u16 dk[IDEA_KEYLEN]; + int have_dk; +} IDEA_context; + +static const char *selftest(void); + + +static u16 +mul_inv( u16 x ) +{ + u16 t0, t1; + u16 q, y; + + if( x < 2 ) + return x; + t1 = 0x10001UL / x; + y = 0x10001UL % x; + if( y == 1 ) + return (1-t1) & 0xffff; + + t0 = 1; + do { + q = x / y; + x = x % y; + t0 += q * t1; + if( x == 1 ) + return t0; + q = y / x; + y = y % x; + t1 += q * t0; + } while( y != 1 ); + return (1-t1) & 0xffff; +} + + + +static void +expand_key( const byte *userkey, u16 *ek ) +{ + int i,j; + + for(j=0; j < 8; j++ ) { + ek[j] = (*userkey << 8) + userkey[1]; + userkey += 2; + } + for(i=0; j < IDEA_KEYLEN; j++ ) { + i++; + ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7; + ek += i & 8; + i &= 7; + } +} + + +static void +invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] ) +{ + int i; + u16 t1, t2, t3; + u16 temp[IDEA_KEYLEN]; + u16 *p = temp + IDEA_KEYLEN; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t3; + *--p = t2; + *--p = t1; + + for(i=0; i < IDEA_ROUNDS-1; i++ ) { + t1 = *ek++; + *--p = *ek++; + *--p = t1; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t2; + *--p = t3; + *--p = t1; + } + t1 = *ek++; + *--p = *ek++; + *--p = t1; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t3; + *--p = t2; + *--p = t1; + memcpy(dk, temp, sizeof(temp) ); + memset(temp, 0, sizeof(temp) ); /* burn temp */ +} + + +static void +cipher( byte *outbuf, const byte *inbuf, u16 *key ) +{ + u16 s2, s3; + u16 in[4]; + int r = IDEA_ROUNDS; +#define x1 (in[0]) +#define x2 (in[1]) +#define x3 (in[2]) +#define x4 (in[3]) +#define MUL(x,y) \ + do {u16 _t16; u32 _t32; \ + if( (_t16 = (y)) ) { \ + if( (x = (x)&0xffff) ) { \ + _t32 = (u32)x * _t16; \ + x = _t32 & 0xffff; \ + _t16 = _t32 >> 16; \ + x = ((x)-_t16) + (x<_t16?1:0); \ + } \ + else { \ + x = 1 - _t16; \ + } \ + } \ + else { \ + x = 1 - x; \ + } \ + } while(0) + + memcpy (in, inbuf, sizeof in); +#ifndef WORDS_BIGENDIAN + x1 = (x1>>8) | (x1<<8); + x2 = (x2>>8) | (x2<<8); + x3 = (x3>>8) | (x3<<8); + x4 = (x4>>8) | (x4<<8); +#endif + do { + MUL(x1, *key++); + x2 += *key++; + x3 += *key++; + MUL(x4, *key++ ); + + s3 = x3; + x3 ^= x1; + MUL(x3, *key++); + s2 = x2; + x2 ^=x4; + x2 += x3; + MUL(x2, *key++); + x3 += x2; + + x1 ^= x2; + x4 ^= x3; + + x2 ^= s3; + x3 ^= s2; + } while( --r ); + MUL(x1, *key++); + x3 += *key++; + x2 += *key++; + MUL(x4, *key); + +#ifndef WORDS_BIGENDIAN + x1 = (x1>>8) | (x1<<8); + x2 = (x2>>8) | (x2<<8); + x3 = (x3>>8) | (x3<<8); + x4 = (x4>>8) | (x4<<8); +#endif + memcpy (outbuf+0, &x1, 2); + memcpy (outbuf+2, &x3, 2); + memcpy (outbuf+4, &x2, 2); + memcpy (outbuf+6, &x4, 2); +#undef MUL +#undef x1 +#undef x2 +#undef x3 +#undef x4 +} + + +static int +do_setkey( IDEA_context *c, const byte *key, unsigned int keylen ) +{ + static int initialized = 0; + static const char *selftest_failed = 0; + + if( !initialized ) { + initialized = 1; + selftest_failed = selftest(); + if( selftest_failed ) + log_error( "%s\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + assert(keylen == 16); + c->have_dk = 0; + expand_key( key, c->ek ); + invert_key( c->ek, c->dk ); + return 0; +} + +static gcry_err_code_t +idea_setkey (void *context, const byte *key, unsigned int keylen) +{ + IDEA_context *ctx = context; + int rc = do_setkey (ctx, key, keylen); + _gcry_burn_stack (23+6*sizeof(void*)); + return rc; +} + +static void +encrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) +{ + cipher( outbuf, inbuf, c->ek ); +} + +static void +idea_encrypt (void *context, byte *out, const byte *in) +{ + IDEA_context *ctx = context; + encrypt_block (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + +static void +decrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) +{ + if( !c->have_dk ) { + c->have_dk = 1; + invert_key( c->ek, c->dk ); + } + cipher( outbuf, inbuf, c->dk ); +} + +static void +idea_decrypt (void *context, byte *out, const byte *in) +{ + IDEA_context *ctx = context; + decrypt_block (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + + +static const char * +selftest( void ) +{ +static struct { + byte key[16]; + byte plain[8]; + byte cipher[8]; +} test_vectors[] = { + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 }, + { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x54, 0x0E, 0x5F, 0xEA, 0x18, 0xC2, 0xF8, 0xB1 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x00, 0x19, 0x32, 0x4B, 0x64, 0x7D, 0x96, 0xAF }, + { 0x9F, 0x0A, 0x0A, 0xB6, 0xE1, 0x0C, 0xED, 0x78 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0xF5, 0x20, 0x2D, 0x5B, 0x9C, 0x67, 0x1B, 0x08 }, + { 0xCF, 0x18, 0xFD, 0x73, 0x55, 0xE2, 0xC5, 0xC5 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0xFA, 0xE6, 0xD2, 0xBE, 0xAA, 0x96, 0x82, 0x6E }, + { 0x85, 0xDF, 0x52, 0x00, 0x56, 0x08, 0x19, 0x3D } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x46, 0x50 }, + { 0x2F, 0x7D, 0xE7, 0x50, 0x21, 0x2F, 0xB7, 0x34 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x05, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x23, 0x28 }, + { 0x7B, 0x73, 0x14, 0x92, 0x5D, 0xE5, 0x9C, 0x09 } }, + { { 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x14, + 0x00, 0x19, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x28 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x3E, 0xC0, 0x47, 0x80, 0xBE, 0xFF, 0x6E, 0x20 } }, + { { 0x3A, 0x98, 0x4E, 0x20, 0x00, 0x19, 0x5D, 0xB3, + 0x2E, 0xE5, 0x01, 0xC8, 0xC4, 0x7C, 0xEA, 0x60 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x97, 0xBC, 0xD8, 0x20, 0x07, 0x80, 0xDA, 0x86 } }, + { { 0x00, 0x64, 0x00, 0xC8, 0x01, 0x2C, 0x01, 0x90, + 0x01, 0xF4, 0x02, 0x58, 0x02, 0xBC, 0x03, 0x20 }, + { 0x05, 0x32, 0x0A, 0x64, 0x14, 0xC8, 0x19, 0xFA }, + { 0x65, 0xBE, 0x87, 0xE7, 0xA2, 0x53, 0x8A, 0xED } }, + { { 0x9D, 0x40, 0x75, 0xC1, 0x03, 0xBC, 0x32, 0x2A, + 0xFB, 0x03, 0xE7, 0xBE, 0x6A, 0xB3, 0x00, 0x06 }, + { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, + { 0xF5, 0xDB, 0x1A, 0xC4, 0x5E, 0x5E, 0xF9, 0xF9 } } +}; + IDEA_context c; + byte buffer[8]; + int i; + + for(i=0; i < DIM(test_vectors); i++ ) { + do_setkey( &c, test_vectors[i].key, 16 ); + encrypt_block( &c, buffer, test_vectors[i].plain ); + if( memcmp( buffer, test_vectors[i].cipher, 8 ) ) + return "IDEA test encryption failed."; + decrypt_block( &c, buffer, test_vectors[i].cipher ); + if( memcmp( buffer, test_vectors[i].plain, 8 ) ) + return "IDEA test decryption failed."; + } + + return NULL; +} + + +gcry_cipher_spec_t _gcry_cipher_spec_idea = +{ + "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128, + sizeof (IDEA_context), + idea_setkey, idea_encrypt, idea_decrypt +}; diff --git a/grub-core/lib/libgcrypt/cipher/kdf.c b/grub-core/lib/libgcrypt/cipher/kdf.c new file mode 100644 index 0000000..46e8550 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/kdf.c @@ -0,0 +1,278 @@ +/* kdf.c - Key Derivation Functions + * Copyright (C) 1998, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "g10lib.h" +#include "cipher.h" +#include "ath.h" + + +/* Transform a passphrase into a suitable key of length KEYSIZE and + store this key in the caller provided buffer KEYBUFFER. The caller + must provide an HASHALGO, a valid ALGO and depending on that algo a + SALT of 8 bytes and the number of ITERATIONS. Code taken from + gnupg/agent/protect.c:hash_passphrase. */ +gpg_err_code_t +openpgp_s2k (const void *passphrase, size_t passphraselen, + int algo, int hashalgo, + const void *salt, size_t saltlen, + unsigned long iterations, + size_t keysize, void *keybuffer) +{ + gpg_err_code_t ec; + gcry_md_hd_t md; + char *key = keybuffer; + int pass, i; + int used = 0; + int secmode; + + if ((algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K) + && (!salt || saltlen != 8)) + return GPG_ERR_INV_VALUE; + + secmode = gcry_is_secure (passphrase) || gcry_is_secure (keybuffer); + + ec = gpg_err_code (gcry_md_open (&md, hashalgo, + secmode? GCRY_MD_FLAG_SECURE : 0)); + if (ec) + return ec; + + for (pass=0; used < keysize; pass++) + { + if (pass) + { + gcry_md_reset (md); + for (i=0; i < pass; i++) /* Preset the hash context. */ + gcry_md_putc (md, 0); + } + + if (algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K) + { + int len2 = passphraselen + 8; + unsigned long count = len2; + + if (algo == GCRY_KDF_ITERSALTED_S2K) + { + count = iterations; + if (count < len2) + count = len2; + } + + while (count > len2) + { + gcry_md_write (md, salt, saltlen); + gcry_md_write (md, passphrase, passphraselen); + count -= len2; + } + if (count < saltlen) + gcry_md_write (md, salt, count); + else + { + gcry_md_write (md, salt, saltlen); + count -= saltlen; + gcry_md_write (md, passphrase, count); + } + } + else + gcry_md_write (md, passphrase, passphraselen); + + gcry_md_final (md); + i = gcry_md_get_algo_dlen (hashalgo); + if (i > keysize - used) + i = keysize - used; + memcpy (key+used, gcry_md_read (md, hashalgo), i); + used += i; + } + gcry_md_close (md); + return 0; +} + + +/* Transform a passphrase into a suitable key of length KEYSIZE and + store this key in the caller provided buffer KEYBUFFER. The caller + must provide PRFALGO which indicates the pseudorandom function to + use: This shall be the algorithms id of a hash algorithm; it is + used in HMAC mode. SALT is a salt of length SALTLEN and ITERATIONS + gives the number of iterations. */ +gpg_err_code_t +pkdf2 (const void *passphrase, size_t passphraselen, + int hashalgo, + const void *salt, size_t saltlen, + unsigned long iterations, + size_t keysize, void *keybuffer) +{ + gpg_err_code_t ec; + gcry_md_hd_t md; + int secmode; + unsigned int dklen = keysize; + char *dk = keybuffer; + unsigned int hlen; /* Output length of the digest function. */ + unsigned int l; /* Rounded up number of blocks. */ + unsigned int r; /* Number of octets in the last block. */ + char *sbuf; /* Malloced buffer to concatenate salt and iter + as well as space to hold TBUF and UBUF. */ + char *tbuf; /* Buffer for T; ptr into SBUF, size is HLEN. */ + char *ubuf; /* Buffer for U; ptr into SBUF, size is HLEN. */ + unsigned int lidx; /* Current block number. */ + unsigned long iter; /* Current iteration number. */ + unsigned int i; + + if (!salt || !saltlen || !iterations || !dklen) + return GPG_ERR_INV_VALUE; + + hlen = gcry_md_get_algo_dlen (hashalgo); + if (!hlen) + return GPG_ERR_DIGEST_ALGO; + + secmode = gcry_is_secure (passphrase) || gcry_is_secure (keybuffer); + + /* We ignore step 1 from pksc5v2.1 which demands a check that dklen + is not larger that 0xffffffff * hlen. */ + + /* Step 2 */ + l = ((dklen - 1)/ hlen) + 1; + r = dklen - (l - 1) * hlen; + + /* Setup buffers and prepare a hash context. */ + sbuf = (secmode + ? gcry_malloc_secure (saltlen + 4 + hlen + hlen) + : gcry_malloc (saltlen + 4 + hlen + hlen)); + if (!sbuf) + return gpg_err_code_from_syserror (); + tbuf = sbuf + saltlen + 4; + ubuf = tbuf + hlen; + + ec = gpg_err_code (gcry_md_open (&md, hashalgo, + (GCRY_MD_FLAG_HMAC + | (secmode?GCRY_MD_FLAG_SECURE:0)))); + if (ec) + { + gcry_free (sbuf); + return ec; + } + + /* Step 3 and 4. */ + memcpy (sbuf, salt, saltlen); + for (lidx = 1; lidx <= l; lidx++) + { + for (iter = 0; iter < iterations; iter++) + { + ec = gpg_err_code (gcry_md_setkey (md, passphrase, passphraselen)); + if (ec) + { + gcry_md_close (md); + gcry_free (sbuf); + return ec; + } + if (!iter) /* Compute U_1: */ + { + sbuf[saltlen] = (lidx >> 24); + sbuf[saltlen + 1] = (lidx >> 16); + sbuf[saltlen + 2] = (lidx >> 8); + sbuf[saltlen + 3] = lidx; + gcry_md_write (md, sbuf, saltlen + 4); + memcpy (ubuf, gcry_md_read (md, 0), hlen); + memcpy (tbuf, ubuf, hlen); + } + else /* Compute U_(2..c): */ + { + gcry_md_write (md, ubuf, hlen); + memcpy (ubuf, gcry_md_read (md, 0), hlen); + for (i=0; i < hlen; i++) + tbuf[i] ^= ubuf[i]; + } + } + if (lidx == l) /* Last block. */ + memcpy (dk, tbuf, r); + else + { + memcpy (dk, tbuf, hlen); + dk += hlen; + } + } + + gcry_md_close (md); + gcry_free (sbuf); + return 0; +} + + +/* Derive a key from a passphrase. KEYSIZE gives the requested size + of the keys in octets. KEYBUFFER is a caller provided buffer + filled on success with the derived key. The input passphrase is + taken from (PASSPHRASE,PASSPHRASELEN) which is an arbitrary memory + buffer. ALGO specifies the KDF algorithm to use; these are the + constants GCRY_KDF_*. SUBALGO specifies an algorithm used + internally by the KDF algorithms; this is usually a hash algorithm + but certain KDF algorithm may use it differently. {SALT,SALTLEN} + is a salt as needed by most KDF algorithms. ITERATIONS is a + positive integer parameter to most KDFs. 0 is returned on success, + or an error code on failure. */ +gpg_error_t +gcry_kdf_derive (const void *passphrase, size_t passphraselen, + int algo, int subalgo, + const void *salt, size_t saltlen, + unsigned long iterations, + size_t keysize, void *keybuffer) +{ + gpg_err_code_t ec; + + if (!passphrase || (!passphraselen && algo != GCRY_KDF_PBKDF2)) + { + ec = GPG_ERR_INV_DATA; + goto leave; + } + if (!keybuffer || !keysize) + { + ec = GPG_ERR_INV_VALUE; + goto leave; + } + + + switch (algo) + { + case GCRY_KDF_SIMPLE_S2K: + case GCRY_KDF_SALTED_S2K: + case GCRY_KDF_ITERSALTED_S2K: + ec = openpgp_s2k (passphrase, passphraselen, algo, subalgo, + salt, saltlen, iterations, keysize, keybuffer); + break; + + case GCRY_KDF_PBKDF1: + ec = GPG_ERR_UNSUPPORTED_ALGORITHM; + break; + + case GCRY_KDF_PBKDF2: + ec = pkdf2 (passphrase, passphraselen, subalgo, + salt, saltlen, iterations, keysize, keybuffer); + break; + + default: + ec = GPG_ERR_UNKNOWN_ALGORITHM; + break; + } + + leave: + return gpg_error (ec); +} diff --git a/grub-core/lib/libgcrypt/cipher/md.c b/grub-core/lib/libgcrypt/cipher/md.c new file mode 100644 index 0000000..c3b3a4f --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/md.c @@ -0,0 +1,1383 @@ +/* md.c - message digest dispatcher + * Copyright (C) 1998, 1999, 2002, 2003, 2006, + * 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "g10lib.h" +#include "cipher.h" +#include "ath.h" + +#include "rmd.h" + +/* A dummy extraspec so that we do not need to tests the extraspec + field from the module specification against NULL and instead + directly test the respective fields of extraspecs. */ +static md_extra_spec_t dummy_extra_spec; + + +/* This is the list of the digest implementations included in + libgcrypt. */ +static struct digest_table_entry +{ + gcry_md_spec_t *digest; + md_extra_spec_t *extraspec; + unsigned int algorithm; + int fips_allowed; +} digest_table[] = + { +#if USE_CRC + /* We allow the CRC algorithms even in FIPS mode because they are + actually no cryptographic primitives. */ + { &_gcry_digest_spec_crc32, + &dummy_extra_spec, GCRY_MD_CRC32, 1 }, + { &_gcry_digest_spec_crc32_rfc1510, + &dummy_extra_spec, GCRY_MD_CRC32_RFC1510, 1 }, + { &_gcry_digest_spec_crc24_rfc2440, + &dummy_extra_spec, GCRY_MD_CRC24_RFC2440, 1 }, +#endif +#if USE_MD4 + { &_gcry_digest_spec_md4, + &dummy_extra_spec, GCRY_MD_MD4 }, +#endif +#if USE_MD5 + { &_gcry_digest_spec_md5, + &dummy_extra_spec, GCRY_MD_MD5, 1 }, +#endif +#if USE_RMD160 + { &_gcry_digest_spec_rmd160, + &dummy_extra_spec, GCRY_MD_RMD160 }, +#endif +#if USE_SHA1 + { &_gcry_digest_spec_sha1, + &_gcry_digest_extraspec_sha1, GCRY_MD_SHA1, 1 }, +#endif +#if USE_SHA256 + { &_gcry_digest_spec_sha256, + &_gcry_digest_extraspec_sha256, GCRY_MD_SHA256, 1 }, + { &_gcry_digest_spec_sha224, + &_gcry_digest_extraspec_sha224, GCRY_MD_SHA224, 1 }, +#endif +#if USE_SHA512 + { &_gcry_digest_spec_sha512, + &_gcry_digest_extraspec_sha512, GCRY_MD_SHA512, 1 }, + { &_gcry_digest_spec_sha384, + &_gcry_digest_extraspec_sha384, GCRY_MD_SHA384, 1 }, +#endif +#if USE_TIGER + { &_gcry_digest_spec_tiger, + &dummy_extra_spec, GCRY_MD_TIGER }, + { &_gcry_digest_spec_tiger1, + &dummy_extra_spec, GCRY_MD_TIGER1 }, + { &_gcry_digest_spec_tiger2, + &dummy_extra_spec, GCRY_MD_TIGER2 }, +#endif +#if USE_WHIRLPOOL + { &_gcry_digest_spec_whirlpool, + &dummy_extra_spec, GCRY_MD_WHIRLPOOL }, +#endif + { NULL }, + }; + +/* List of registered digests. */ +static gcry_module_t digests_registered; + +/* This is the lock protecting DIGESTS_REGISTERED. */ +static ath_mutex_t digests_registered_lock = ATH_MUTEX_INITIALIZER; + +/* Flag to check whether the default ciphers have already been + registered. */ +static int default_digests_registered; + +typedef struct gcry_md_list +{ + gcry_md_spec_t *digest; + gcry_module_t module; + struct gcry_md_list *next; + size_t actual_struct_size; /* Allocated size of this structure. */ + PROPERLY_ALIGNED_TYPE context; +} GcryDigestEntry; + +/* this structure is put right after the gcry_md_hd_t buffer, so that + * only one memory block is needed. */ +struct gcry_md_context +{ + int magic; + size_t actual_handle_size; /* Allocated size of this handle. */ + int secure; + FILE *debug; + int finalized; + GcryDigestEntry *list; + byte *macpads; + int macpads_Bsize; /* Blocksize as used for the HMAC pads. */ +}; + + +#define CTX_MAGIC_NORMAL 0x11071961 +#define CTX_MAGIC_SECURE 0x16917011 + +/* Convenient macro for registering the default digests. */ +#define REGISTER_DEFAULT_DIGESTS \ + do \ + { \ + ath_mutex_lock (&digests_registered_lock); \ + if (! default_digests_registered) \ + { \ + md_register_default (); \ + default_digests_registered = 1; \ + } \ + ath_mutex_unlock (&digests_registered_lock); \ + } \ + while (0) + + +static const char * digest_algo_to_string( int algo ); +static gcry_err_code_t check_digest_algo (int algo); +static gcry_err_code_t md_open (gcry_md_hd_t *h, int algo, + int secure, int hmac); +static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algo); +static gcry_err_code_t md_copy (gcry_md_hd_t a, gcry_md_hd_t *b); +static void md_close (gcry_md_hd_t a); +static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen); +static void md_final(gcry_md_hd_t a); +static byte *md_read( gcry_md_hd_t a, int algo ); +static int md_get_algo( gcry_md_hd_t a ); +static int md_digest_length( int algo ); +static const byte *md_asn_oid( int algo, size_t *asnlen, size_t *mdlen ); +static void md_start_debug ( gcry_md_hd_t a, const char *suffix ); +static void md_stop_debug ( gcry_md_hd_t a ); + + + + +/* Internal function. Register all the ciphers included in + CIPHER_TABLE. Returns zero on success or an error code. */ +static void +md_register_default (void) +{ + gcry_err_code_t err = 0; + int i; + + for (i = 0; !err && digest_table[i].digest; i++) + { + if ( fips_mode ()) + { + if (!digest_table[i].fips_allowed) + continue; + if (digest_table[i].algorithm == GCRY_MD_MD5 + && _gcry_enforced_fips_mode () ) + continue; /* Do not register in enforced fips mode. */ + } + + err = _gcry_module_add (&digests_registered, + digest_table[i].algorithm, + (void *) digest_table[i].digest, + (void *) digest_table[i].extraspec, + NULL); + } + + if (err) + BUG (); +} + +/* Internal callback function. */ +static int +gcry_md_lookup_func_name (void *spec, void *data) +{ + gcry_md_spec_t *digest = (gcry_md_spec_t *) spec; + char *name = (char *) data; + + return (! stricmp (digest->name, name)); +} + +/* Internal callback function. Used via _gcry_module_lookup. */ +static int +gcry_md_lookup_func_oid (void *spec, void *data) +{ + gcry_md_spec_t *digest = (gcry_md_spec_t *) spec; + char *oid = (char *) data; + gcry_md_oid_spec_t *oid_specs = digest->oids; + int ret = 0, i; + + if (oid_specs) + { + for (i = 0; oid_specs[i].oidstring && (! ret); i++) + if (! stricmp (oid, oid_specs[i].oidstring)) + ret = 1; + } + + return ret; +} + +/* Internal function. Lookup a digest entry by it's name. */ +static gcry_module_t +gcry_md_lookup_name (const char *name) +{ + gcry_module_t digest; + + digest = _gcry_module_lookup (digests_registered, (void *) name, + gcry_md_lookup_func_name); + + return digest; +} + +/* Internal function. Lookup a cipher entry by it's oid. */ +static gcry_module_t +gcry_md_lookup_oid (const char *oid) +{ + gcry_module_t digest; + + digest = _gcry_module_lookup (digests_registered, (void *) oid, + gcry_md_lookup_func_oid); + + return digest; +} + +/* Register a new digest module whose specification can be found in + DIGEST. On success, a new algorithm ID is stored in ALGORITHM_ID + and a pointer representhing this module is stored in MODULE. */ +gcry_error_t +_gcry_md_register (gcry_md_spec_t *digest, + md_extra_spec_t *extraspec, + unsigned int *algorithm_id, + gcry_module_t *module) +{ + gcry_err_code_t err = 0; + gcry_module_t mod; + + /* We do not support module loading in fips mode. */ + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + ath_mutex_lock (&digests_registered_lock); + err = _gcry_module_add (&digests_registered, 0, + (void *) digest, + (void *)(extraspec? extraspec : &dummy_extra_spec), + &mod); + ath_mutex_unlock (&digests_registered_lock); + + if (! err) + { + *module = mod; + *algorithm_id = mod->mod_id; + } + + return gcry_error (err); +} + +/* Unregister the digest identified by ID, which must have been + registered with gcry_digest_register. */ +void +gcry_md_unregister (gcry_module_t module) +{ + ath_mutex_lock (&digests_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&digests_registered_lock); +} + + +static int +search_oid (const char *oid, int *algorithm, gcry_md_oid_spec_t *oid_spec) +{ + gcry_module_t module; + int ret = 0; + + if (oid && ((! strncmp (oid, "oid.", 4)) + || (! strncmp (oid, "OID.", 4)))) + oid += 4; + + module = gcry_md_lookup_oid (oid); + if (module) + { + gcry_md_spec_t *digest = module->spec; + int i; + + for (i = 0; digest->oids[i].oidstring && !ret; i++) + if (! stricmp (oid, digest->oids[i].oidstring)) + { + if (algorithm) + *algorithm = module->mod_id; + if (oid_spec) + *oid_spec = digest->oids[i]; + ret = 1; + } + _gcry_module_release (module); + } + + return ret; +} + +/**************** + * Map a string to the digest algo + */ +int +gcry_md_map_name (const char *string) +{ + gcry_module_t digest; + int ret, algorithm = 0; + + if (! string) + return 0; + + REGISTER_DEFAULT_DIGESTS; + + /* If the string starts with a digit (optionally prefixed with + either "OID." or "oid."), we first look into our table of ASN.1 + object identifiers to figure out the algorithm */ + + ath_mutex_lock (&digests_registered_lock); + + ret = search_oid (string, &algorithm, NULL); + if (! ret) + { + /* Not found, search a matching digest name. */ + digest = gcry_md_lookup_name (string); + if (digest) + { + algorithm = digest->mod_id; + _gcry_module_release (digest); + } + } + ath_mutex_unlock (&digests_registered_lock); + + return algorithm; +} + + +/**************** + * Map a digest algo to a string + */ +static const char * +digest_algo_to_string (int algorithm) +{ + const char *name = NULL; + gcry_module_t digest; + + REGISTER_DEFAULT_DIGESTS; + + ath_mutex_lock (&digests_registered_lock); + digest = _gcry_module_lookup_id (digests_registered, algorithm); + if (digest) + { + name = ((gcry_md_spec_t *) digest->spec)->name; + _gcry_module_release (digest); + } + ath_mutex_unlock (&digests_registered_lock); + + return name; +} + +/**************** + * This function simply returns the name of the algorithm or some constant + * string when there is no algo. It will never return NULL. + * Use the macro gcry_md_test_algo() to check whether the algorithm + * is valid. + */ +const char * +gcry_md_algo_name (int algorithm) +{ + const char *s = digest_algo_to_string (algorithm); + return s ? s : "?"; +} + + +static gcry_err_code_t +check_digest_algo (int algorithm) +{ + gcry_err_code_t rc = 0; + gcry_module_t digest; + + REGISTER_DEFAULT_DIGESTS; + + ath_mutex_lock (&digests_registered_lock); + digest = _gcry_module_lookup_id (digests_registered, algorithm); + if (digest) + _gcry_module_release (digest); + else + rc = GPG_ERR_DIGEST_ALGO; + ath_mutex_unlock (&digests_registered_lock); + + return rc; +} + + + +/**************** + * Open a message digest handle for use with algorithm ALGO. + * More algorithms may be added by md_enable(). The initial algorithm + * may be 0. + */ +static gcry_err_code_t +md_open (gcry_md_hd_t *h, int algo, int secure, int hmac) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + int bufsize = secure ? 512 : 1024; + struct gcry_md_context *ctx; + gcry_md_hd_t hd; + size_t n; + + /* Allocate a memory area to hold the caller visible buffer with it's + * control information and the data required by this module. Set the + * context pointer at the beginning to this area. + * We have to use this strange scheme because we want to hide the + * internal data but have a variable sized buffer. + * + * +---+------+---........------+-------------+ + * !ctx! bctl ! buffer ! private ! + * +---+------+---........------+-------------+ + * ! ^ + * !---------------------------! + * + * We have to make sure that private is well aligned. + */ + n = sizeof (struct gcry_md_handle) + bufsize; + n = ((n + sizeof (PROPERLY_ALIGNED_TYPE) - 1) + / sizeof (PROPERLY_ALIGNED_TYPE)) * sizeof (PROPERLY_ALIGNED_TYPE); + + /* Allocate and set the Context pointer to the private data */ + if (secure) + hd = gcry_malloc_secure (n + sizeof (struct gcry_md_context)); + else + hd = gcry_malloc (n + sizeof (struct gcry_md_context)); + + if (! hd) + err = gpg_err_code_from_errno (errno); + + if (! err) + { + hd->ctx = ctx = (struct gcry_md_context *) ((char *) hd + n); + /* Setup the globally visible data (bctl in the diagram).*/ + hd->bufsize = n - sizeof (struct gcry_md_handle) + 1; + hd->bufpos = 0; + + /* Initialize the private data. */ + memset (hd->ctx, 0, sizeof *hd->ctx); + ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL; + ctx->actual_handle_size = n + sizeof (struct gcry_md_context); + ctx->secure = secure; + + if (hmac) + { + switch (algo) + { + case GCRY_MD_SHA384: + case GCRY_MD_SHA512: + ctx->macpads_Bsize = 128; + break; + default: + ctx->macpads_Bsize = 64; + break; + } + ctx->macpads = gcry_malloc_secure (2*(ctx->macpads_Bsize)); + if (!ctx->macpads) + { + err = gpg_err_code_from_errno (errno); + md_close (hd); + } + } + } + + if (! err) + { + /* Hmmm, should we really do that? - yes [-wk] */ + _gcry_fast_random_poll (); + + if (algo) + { + err = md_enable (hd, algo); + if (err) + md_close (hd); + } + } + + if (! err) + *h = hd; + + return err; +} + +/* Create a message digest object for algorithm ALGO. FLAGS may be + given as an bitwise OR of the gcry_md_flags values. ALGO may be + given as 0 if the algorithms to be used are later set using + gcry_md_enable. H is guaranteed to be a valid handle or NULL on + error. */ +gcry_error_t +gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_md_hd_t hd; + + if ((flags & ~(GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC))) + err = GPG_ERR_INV_ARG; + else + { + err = md_open (&hd, algo, (flags & GCRY_MD_FLAG_SECURE), + (flags & GCRY_MD_FLAG_HMAC)); + } + + *h = err? NULL : hd; + return gcry_error (err); +} + + + +static gcry_err_code_t +md_enable (gcry_md_hd_t hd, int algorithm) +{ + struct gcry_md_context *h = hd->ctx; + gcry_md_spec_t *digest = NULL; + GcryDigestEntry *entry; + gcry_module_t module; + gcry_err_code_t err = 0; + + for (entry = h->list; entry; entry = entry->next) + if (entry->module->mod_id == algorithm) + return err; /* already enabled */ + + REGISTER_DEFAULT_DIGESTS; + + ath_mutex_lock (&digests_registered_lock); + module = _gcry_module_lookup_id (digests_registered, algorithm); + ath_mutex_unlock (&digests_registered_lock); + if (! module) + { + log_debug ("md_enable: algorithm %d not available\n", algorithm); + err = GPG_ERR_DIGEST_ALGO; + } + else + digest = (gcry_md_spec_t *) module->spec; + + + if (!err && algorithm == GCRY_MD_MD5 && fips_mode ()) + { + _gcry_inactivate_fips_mode ("MD5 used"); + if (_gcry_enforced_fips_mode () ) + { + /* We should never get to here because we do not register + MD5 in enforced fips mode. But better throw an error. */ + err = GPG_ERR_DIGEST_ALGO; + } + } + + if (!err) + { + size_t size = (sizeof (*entry) + + digest->contextsize + - sizeof (entry->context)); + + /* And allocate a new list entry. */ + if (h->secure) + entry = gcry_malloc_secure (size); + else + entry = gcry_malloc (size); + + if (! entry) + err = gpg_err_code_from_errno (errno); + else + { + entry->digest = digest; + entry->module = module; + entry->next = h->list; + entry->actual_struct_size = size; + h->list = entry; + + /* And init this instance. */ + entry->digest->init (&entry->context.c); + } + } + + if (err) + { + if (module) + { + ath_mutex_lock (&digests_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&digests_registered_lock); + } + } + + return err; +} + + +gcry_error_t +gcry_md_enable (gcry_md_hd_t hd, int algorithm) +{ + return gcry_error (md_enable (hd, algorithm)); +} + +static gcry_err_code_t +md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + struct gcry_md_context *a = ahd->ctx; + struct gcry_md_context *b; + GcryDigestEntry *ar, *br; + gcry_md_hd_t bhd; + size_t n; + + if (ahd->bufpos) + md_write (ahd, NULL, 0); + + n = (char *) ahd->ctx - (char *) ahd; + if (a->secure) + bhd = gcry_malloc_secure (n + sizeof (struct gcry_md_context)); + else + bhd = gcry_malloc (n + sizeof (struct gcry_md_context)); + + if (! bhd) + err = gpg_err_code_from_errno (errno); + + if (! err) + { + bhd->ctx = b = (struct gcry_md_context *) ((char *) bhd + n); + /* No need to copy the buffer due to the write above. */ + gcry_assert (ahd->bufsize == (n - sizeof (struct gcry_md_handle) + 1)); + bhd->bufsize = ahd->bufsize; + bhd->bufpos = 0; + gcry_assert (! ahd->bufpos); + memcpy (b, a, sizeof *a); + b->list = NULL; + b->debug = NULL; + if (a->macpads) + { + b->macpads = gcry_malloc_secure (2*(a->macpads_Bsize)); + if (! b->macpads) + { + err = gpg_err_code_from_errno (errno); + md_close (bhd); + } + else + memcpy (b->macpads, a->macpads, (2*(a->macpads_Bsize))); + } + } + + /* Copy the complete list of algorithms. The copied list is + reversed, but that doesn't matter. */ + if (!err) + { + for (ar = a->list; ar; ar = ar->next) + { + if (a->secure) + br = gcry_malloc_secure (sizeof *br + + ar->digest->contextsize + - sizeof(ar->context)); + else + br = gcry_malloc (sizeof *br + + ar->digest->contextsize + - sizeof (ar->context)); + if (!br) + { + err = gpg_err_code_from_errno (errno); + md_close (bhd); + break; + } + + memcpy (br, ar, (sizeof (*br) + ar->digest->contextsize + - sizeof (ar->context))); + br->next = b->list; + b->list = br; + + /* Add a reference to the module. */ + ath_mutex_lock (&digests_registered_lock); + _gcry_module_use (br->module); + ath_mutex_unlock (&digests_registered_lock); + } + } + + if (a->debug && !err) + md_start_debug (bhd, "unknown"); + + if (!err) + *b_hd = bhd; + + return err; +} + +gcry_error_t +gcry_md_copy (gcry_md_hd_t *handle, gcry_md_hd_t hd) +{ + gcry_err_code_t err; + + err = md_copy (hd, handle); + if (err) + *handle = NULL; + return gcry_error (err); +} + +/* + * Reset all contexts and discard any buffered stuff. This may be used + * instead of a md_close(); md_open(). + */ +void +gcry_md_reset (gcry_md_hd_t a) +{ + GcryDigestEntry *r; + + /* Note: We allow this even in fips non operational mode. */ + + a->bufpos = a->ctx->finalized = 0; + + for (r = a->ctx->list; r; r = r->next) + { + memset (r->context.c, 0, r->digest->contextsize); + (*r->digest->init) (&r->context.c); + } + if (a->ctx->macpads) + md_write (a, a->ctx->macpads, a->ctx->macpads_Bsize); /* inner pad */ +} + +static void +md_close (gcry_md_hd_t a) +{ + GcryDigestEntry *r, *r2; + + if (! a) + return; + if (a->ctx->debug) + md_stop_debug (a); + for (r = a->ctx->list; r; r = r2) + { + r2 = r->next; + ath_mutex_lock (&digests_registered_lock); + _gcry_module_release (r->module); + ath_mutex_unlock (&digests_registered_lock); + wipememory (r, r->actual_struct_size); + gcry_free (r); + } + + if (a->ctx->macpads) + { + wipememory (a->ctx->macpads, 2*(a->ctx->macpads_Bsize)); + gcry_free(a->ctx->macpads); + } + + wipememory (a, a->ctx->actual_handle_size); + gcry_free(a); +} + +void +gcry_md_close (gcry_md_hd_t hd) +{ + /* Note: We allow this even in fips non operational mode. */ + md_close (hd); +} + +static void +md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen) +{ + GcryDigestEntry *r; + + if (a->ctx->debug) + { + if (a->bufpos && fwrite (a->buf, a->bufpos, 1, a->ctx->debug) != 1) + BUG(); + if (inlen && fwrite (inbuf, inlen, 1, a->ctx->debug) != 1) + BUG(); + } + + for (r = a->ctx->list; r; r = r->next) + { + if (a->bufpos) + (*r->digest->write) (&r->context.c, a->buf, a->bufpos); + (*r->digest->write) (&r->context.c, inbuf, inlen); + } + a->bufpos = 0; +} + +void +gcry_md_write (gcry_md_hd_t hd, const void *inbuf, size_t inlen) +{ + md_write (hd, inbuf, inlen); +} + +static void +md_final (gcry_md_hd_t a) +{ + GcryDigestEntry *r; + + if (a->ctx->finalized) + return; + + if (a->bufpos) + md_write (a, NULL, 0); + + for (r = a->ctx->list; r; r = r->next) + (*r->digest->final) (&r->context.c); + + a->ctx->finalized = 1; + + if (a->ctx->macpads) + { + /* Finish the hmac. */ + int algo = md_get_algo (a); + byte *p = md_read (a, algo); + size_t dlen = md_digest_length (algo); + gcry_md_hd_t om; + gcry_err_code_t err = md_open (&om, algo, a->ctx->secure, 0); + + if (err) + _gcry_fatal_error (err, NULL); + md_write (om, + (a->ctx->macpads)+(a->ctx->macpads_Bsize), + a->ctx->macpads_Bsize); + md_write (om, p, dlen); + md_final (om); + /* Replace our digest with the mac (they have the same size). */ + memcpy (p, md_read (om, algo), dlen); + md_close (om); + } +} + +static gcry_err_code_t +prepare_macpads (gcry_md_hd_t hd, const unsigned char *key, size_t keylen) +{ + int i; + int algo = md_get_algo (hd); + unsigned char *helpkey = NULL; + unsigned char *ipad, *opad; + + if (!algo) + return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */ + + if ( keylen > hd->ctx->macpads_Bsize ) + { + helpkey = gcry_malloc_secure (md_digest_length (algo)); + if (!helpkey) + return gpg_err_code_from_errno (errno); + gcry_md_hash_buffer (algo, helpkey, key, keylen); + key = helpkey; + keylen = md_digest_length (algo); + gcry_assert ( keylen <= hd->ctx->macpads_Bsize ); + } + + memset ( hd->ctx->macpads, 0, 2*(hd->ctx->macpads_Bsize) ); + ipad = hd->ctx->macpads; + opad = (hd->ctx->macpads)+(hd->ctx->macpads_Bsize); + memcpy ( ipad, key, keylen ); + memcpy ( opad, key, keylen ); + for (i=0; i < hd->ctx->macpads_Bsize; i++ ) + { + ipad[i] ^= 0x36; + opad[i] ^= 0x5c; + } + gcry_free (helpkey); + + return GPG_ERR_NO_ERROR; +} + +gcry_error_t +gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen) +{ + gcry_err_code_t rc = 0; + + switch (cmd) + { + case GCRYCTL_FINALIZE: + md_final (hd); + break; + case GCRYCTL_SET_KEY: + rc = gcry_err_code (gcry_md_setkey (hd, buffer, buflen)); + break; + case GCRYCTL_START_DUMP: + md_start_debug (hd, buffer); + break; + case GCRYCTL_STOP_DUMP: + md_stop_debug ( hd ); + break; + default: + rc = GPG_ERR_INV_OP; + } + return gcry_error (rc); +} + +gcry_error_t +gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen) +{ + gcry_err_code_t rc = GPG_ERR_NO_ERROR; + + if (!hd->ctx->macpads) + rc = GPG_ERR_CONFLICT; + else + { + rc = prepare_macpads (hd, key, keylen); + if (! rc) + gcry_md_reset (hd); + } + + return gcry_error (rc); +} + +/* The new debug interface. If SUFFIX is a string it creates an debug + file for the context HD. IF suffix is NULL, the file is closed and + debugging is stopped. */ +void +gcry_md_debug (gcry_md_hd_t hd, const char *suffix) +{ + if (suffix) + md_start_debug (hd, suffix); + else + md_stop_debug (hd); +} + + + +/**************** + * if ALGO is null get the digest for the used algo (which should be only one) + */ +static byte * +md_read( gcry_md_hd_t a, int algo ) +{ + GcryDigestEntry *r = a->ctx->list; + + if (! algo) + { + /* Return the first algorithm */ + if (r) + { + if (r->next) + log_debug ("more than one algorithm in md_read(0)\n"); + return r->digest->read (&r->context.c); + } + } + else + { + for (r = a->ctx->list; r; r = r->next) + if (r->module->mod_id == algo) + return r->digest->read (&r->context.c); + } + BUG(); + return NULL; +} + +/* + * Read out the complete digest, this function implictly finalizes + * the hash. + */ +byte * +gcry_md_read (gcry_md_hd_t hd, int algo) +{ + /* This function is expected to always return a digest, thus we + can't return an error which we actually should do in + non-operational state. */ + gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0); + return md_read (hd, algo); +} + + +/* + * Read out an intermediate digest. Not yet functional. + */ +gcry_err_code_t +gcry_md_get (gcry_md_hd_t hd, int algo, byte *buffer, int buflen) +{ + (void)hd; + (void)algo; + (void)buffer; + (void)buflen; + + /*md_digest ... */ + fips_signal_error ("unimplemented function called"); + return GPG_ERR_INTERNAL; +} + + +/* + * Shortcut function to hash a buffer with a given algo. The only + * guaranteed supported algorithms are RIPE-MD160 and SHA-1. The + * supplied digest buffer must be large enough to store the resulting + * hash. No error is returned, the function will abort on an invalid + * algo. DISABLED_ALGOS are ignored here. */ +void +gcry_md_hash_buffer (int algo, void *digest, + const void *buffer, size_t length) +{ + if (algo == GCRY_MD_SHA1) + _gcry_sha1_hash_buffer (digest, buffer, length); + else if (algo == GCRY_MD_RMD160 && !fips_mode () ) + _gcry_rmd160_hash_buffer (digest, buffer, length); + else + { + /* For the others we do not have a fast function, so we use the + normal functions. */ + gcry_md_hd_t h; + gpg_err_code_t err; + + if (algo == GCRY_MD_MD5 && fips_mode ()) + { + _gcry_inactivate_fips_mode ("MD5 used"); + if (_gcry_enforced_fips_mode () ) + { + /* We should never get to here because we do not register + MD5 in enforced fips mode. */ + _gcry_fips_noreturn (); + } + } + + err = md_open (&h, algo, 0, 0); + if (err) + log_bug ("gcry_md_open failed for algo %d: %s", + algo, gpg_strerror (gcry_error(err))); + md_write (h, (byte *) buffer, length); + md_final (h); + memcpy (digest, md_read (h, algo), md_digest_length (algo)); + md_close (h); + } +} + +static int +md_get_algo (gcry_md_hd_t a) +{ + GcryDigestEntry *r = a->ctx->list; + + if (r && r->next) + { + fips_signal_error ("possible usage error"); + log_error ("WARNING: more than one algorithm in md_get_algo()\n"); + } + return r ? r->module->mod_id : 0; +} + +int +gcry_md_get_algo (gcry_md_hd_t hd) +{ + return md_get_algo (hd); +} + + +/**************** + * Return the length of the digest + */ +static int +md_digest_length (int algorithm) +{ + gcry_module_t digest; + int mdlen = 0; + + REGISTER_DEFAULT_DIGESTS; + + ath_mutex_lock (&digests_registered_lock); + digest = _gcry_module_lookup_id (digests_registered, algorithm); + if (digest) + { + mdlen = ((gcry_md_spec_t *) digest->spec)->mdlen; + _gcry_module_release (digest); + } + ath_mutex_unlock (&digests_registered_lock); + + return mdlen; +} + +/**************** + * Return the length of the digest in bytes. + * This function will return 0 in case of errors. + */ +unsigned int +gcry_md_get_algo_dlen (int algorithm) +{ + return md_digest_length (algorithm); +} + + +/* Hmmm: add a mode to enumerate the OIDs + * to make g10/sig-check.c more portable */ +static const byte * +md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen) +{ + const byte *asnoid = NULL; + gcry_module_t digest; + + REGISTER_DEFAULT_DIGESTS; + + ath_mutex_lock (&digests_registered_lock); + digest = _gcry_module_lookup_id (digests_registered, algorithm); + if (digest) + { + if (asnlen) + *asnlen = ((gcry_md_spec_t *) digest->spec)->asnlen; + if (mdlen) + *mdlen = ((gcry_md_spec_t *) digest->spec)->mdlen; + asnoid = ((gcry_md_spec_t *) digest->spec)->asnoid; + _gcry_module_release (digest); + } + else + log_bug ("no ASN.1 OID for md algo %d\n", algorithm); + ath_mutex_unlock (&digests_registered_lock); + + return asnoid; +} + + + +/**************** + * Return information about the given cipher algorithm + * WHAT select the kind of information returned: + * GCRYCTL_TEST_ALGO: + * Returns 0 when the specified algorithm is available for use. + * buffer and nbytes must be zero. + * GCRYCTL_GET_ASNOID: + * Return the ASNOID of the algorithm in buffer. if buffer is NULL, only + * the required length is returned. + * + * Note: Because this function is in most cases used to return an + * integer value, we can make it easier for the caller to just look at + * the return value. The caller will in all cases consult the value + * and thereby detecting whether a error occurred or not (i.e. while checking + * the block size) + */ +gcry_error_t +gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + switch (what) + { + case GCRYCTL_TEST_ALGO: + if (buffer || nbytes) + err = GPG_ERR_INV_ARG; + else + err = check_digest_algo (algo); + break; + + case GCRYCTL_GET_ASNOID: + /* We need to check that the algo is available because + md_asn_oid would otherwise raise an assertion. */ + err = check_digest_algo (algo); + if (!err) + { + const char unsigned *asn; + size_t asnlen; + + asn = md_asn_oid (algo, &asnlen, NULL); + if (buffer && (*nbytes >= asnlen)) + { + memcpy (buffer, asn, asnlen); + *nbytes = asnlen; + } + else if (!buffer && nbytes) + *nbytes = asnlen; + else + { + if (buffer) + err = GPG_ERR_TOO_SHORT; + else + err = GPG_ERR_INV_ARG; + } + } + break; + + default: + err = GPG_ERR_INV_OP; + } + + return gcry_error (err); +} + + +static void +md_start_debug ( gcry_md_hd_t md, const char *suffix ) +{ + static int idx=0; + char buf[50]; + + if (fips_mode ()) + return; + + if ( md->ctx->debug ) + { + log_debug("Oops: md debug already started\n"); + return; + } + idx++; + snprintf (buf, DIM(buf)-1, "dbgmd-%05d.%.10s", idx, suffix ); + md->ctx->debug = fopen(buf, "w"); + if ( !md->ctx->debug ) + log_debug("md debug: can't open %s\n", buf ); +} + +static void +md_stop_debug( gcry_md_hd_t md ) +{ + if ( md->ctx->debug ) + { + if ( md->bufpos ) + md_write ( md, NULL, 0 ); + fclose (md->ctx->debug); + md->ctx->debug = NULL; + } + +#ifdef HAVE_U64_TYPEDEF + { /* a kludge to pull in the __muldi3 for Solaris */ + volatile u32 a = (u32)(ulong)md; + volatile u64 b = 42; + volatile u64 c; + c = a * b; + (void)c; + } +#endif +} + + + +/* + * Return information about the digest handle. + * GCRYCTL_IS_SECURE: + * Returns 1 when the handle works on secured memory + * otherwise 0 is returned. There is no error return. + * GCRYCTL_IS_ALGO_ENABLED: + * Returns 1 if the algo is enabled for that handle. + * The algo must be passed as the address of an int. + */ +gcry_error_t +gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + switch (cmd) + { + case GCRYCTL_IS_SECURE: + *nbytes = h->ctx->secure; + break; + + case GCRYCTL_IS_ALGO_ENABLED: + { + GcryDigestEntry *r; + int algo; + + if ( !buffer || (nbytes && (*nbytes != sizeof (int)))) + err = GPG_ERR_INV_ARG; + else + { + algo = *(int*)buffer; + + *nbytes = 0; + for(r=h->ctx->list; r; r = r->next ) { + if (r->module->mod_id == algo) + { + *nbytes = 1; + break; + } + } + } + break; + } + + default: + err = GPG_ERR_INV_OP; + } + + return gcry_error (err); +} + + +/* Explicitly initialize this module. */ +gcry_err_code_t +_gcry_md_init (void) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + REGISTER_DEFAULT_DIGESTS; + + return err; +} + + +int +gcry_md_is_secure (gcry_md_hd_t a) +{ + size_t value; + + if (gcry_md_info (a, GCRYCTL_IS_SECURE, NULL, &value)) + value = 1; /* It seems to be better to assume secure memory on + error. */ + return value; +} + + +int +gcry_md_is_enabled (gcry_md_hd_t a, int algo) +{ + size_t value; + + value = sizeof algo; + if (gcry_md_info (a, GCRYCTL_IS_ALGO_ENABLED, &algo, &value)) + value = 0; + return value; +} + +/* Get a list consisting of the IDs of the loaded message digest + modules. If LIST is zero, write the number of loaded message + digest modules to LIST_LENGTH and return. If LIST is non-zero, the + first *LIST_LENGTH algorithm IDs are stored in LIST, which must be + of according size. In case there are less message digest modules + than *LIST_LENGTH, *LIST_LENGTH is updated to the correct + number. */ +gcry_error_t +gcry_md_list (int *list, int *list_length) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + ath_mutex_lock (&digests_registered_lock); + err = _gcry_module_list (digests_registered, list, list_length); + ath_mutex_unlock (&digests_registered_lock); + + return err; +} + + +/* Run the selftests for digest algorithm ALGO with optional reporting + function REPORT. */ +gpg_error_t +_gcry_md_selftest (int algo, int extended, selftest_report_func_t report) +{ + gcry_module_t module = NULL; + cipher_extra_spec_t *extraspec = NULL; + gcry_err_code_t ec = 0; + + REGISTER_DEFAULT_DIGESTS; + + ath_mutex_lock (&digests_registered_lock); + module = _gcry_module_lookup_id (digests_registered, algo); + if (module && !(module->flags & FLAG_MODULE_DISABLED)) + extraspec = module->extraspec; + ath_mutex_unlock (&digests_registered_lock); + if (extraspec && extraspec->selftest) + ec = extraspec->selftest (algo, extended, report); + else + { + ec = GPG_ERR_DIGEST_ALGO; + if (report) + report ("digest", algo, "module", + module && !(module->flags & FLAG_MODULE_DISABLED)? + "no selftest available" : + module? "algorithm disabled" : "algorithm not found"); + } + + if (module) + { + ath_mutex_lock (&digests_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&digests_registered_lock); + } + return gpg_error (ec); +} diff --git a/grub-core/lib/libgcrypt/cipher/md4.c b/grub-core/lib/libgcrypt/cipher/md4.c new file mode 100644 index 0000000..22fbf8d --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/md4.c @@ -0,0 +1,327 @@ +/* md4.c - MD4 Message-Digest Algorithm + * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Based on md5.c in libgcrypt, but rewritten to compute md4 checksums + * using a public domain md4 implementation with the following comments: + * + * Modified by Wei Dai from Andrew M. Kuchling's md4.c + * The original code and all modifications are in the public domain. + * + * This is the original introductory comment: + * + * md4.c : MD4 hash algorithm. + * + * Part of the Python Cryptography Toolkit, version 1.1 + * + * Distribute and use freely; there are no restrictions on further + * dissemination and usage except those imposed by the laws of your + * country of residence. + * + */ + +/* MD4 test suite: + * MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0 + * MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24 + * MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d + * MD4 ("message digest") = d9130a8164549fe818874806e1c7014b + * MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9 + * MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = + * 043f8582f241db351ce627e153e7f0e4 + * MD4 ("123456789012345678901234567890123456789012345678901234567890123456 + * 78901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "g10lib.h" +#include "cipher.h" + +#include "bithelp.h" + + +typedef struct { + u32 A,B,C,D; /* chaining variables */ + u32 nblocks; + byte buf[64]; + int count; +} MD4_CONTEXT; + + +static void +md4_init( void *context ) +{ + MD4_CONTEXT *ctx = context; + + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->nblocks = 0; + ctx->count = 0; +} + +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + + +/**************** + * transform 64 bytes + */ +static void +transform ( MD4_CONTEXT *ctx, const unsigned char *data ) +{ + u32 in[16]; + register u32 A = ctx->A; + register u32 B = ctx->B; + register u32 C = ctx->C; + register u32 D = ctx->D; + +#ifdef WORDS_BIGENDIAN + { + int i; + byte *p2; + const byte *p1; + for(i=0, p1=data, p2=(byte*)in; i < 16; i++, p2 += 4 ) + { + p2[3] = *p1++; + p2[2] = *p1++; + p2[1] = *p1++; + p2[0] = *p1++; + } + } +#else + memcpy (in, data, 64); +#endif + + /* Round 1. */ +#define function(a,b,c,d,k,s) a=rol(a+F(b,c,d)+in[k],s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 1, 7); + function(C,D,A,B, 2,11); + function(B,C,D,A, 3,19); + function(A,B,C,D, 4, 3); + function(D,A,B,C, 5, 7); + function(C,D,A,B, 6,11); + function(B,C,D,A, 7,19); + function(A,B,C,D, 8, 3); + function(D,A,B,C, 9, 7); + function(C,D,A,B,10,11); + function(B,C,D,A,11,19); + function(A,B,C,D,12, 3); + function(D,A,B,C,13, 7); + function(C,D,A,B,14,11); + function(B,C,D,A,15,19); + +#undef function + + /* Round 2. */ +#define function(a,b,c,d,k,s) a=rol(a+G(b,c,d)+in[k]+0x5a827999,s); + + function(A,B,C,D, 0, 3); + function(D,A,B,C, 4, 5); + function(C,D,A,B, 8, 9); + function(B,C,D,A,12,13); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 5, 5); + function(C,D,A,B, 9, 9); + function(B,C,D,A,13,13); + function(A,B,C,D, 2, 3); + function(D,A,B,C, 6, 5); + function(C,D,A,B,10, 9); + function(B,C,D,A,14,13); + function(A,B,C,D, 3, 3); + function(D,A,B,C, 7, 5); + function(C,D,A,B,11, 9); + function(B,C,D,A,15,13); + +#undef function + + /* Round 3. */ +#define function(a,b,c,d,k,s) a=rol(a+H(b,c,d)+in[k]+0x6ed9eba1,s); + + function(A,B,C,D, 0, 3); + function(D,A,B,C, 8, 9); + function(C,D,A,B, 4,11); + function(B,C,D,A,12,15); + function(A,B,C,D, 2, 3); + function(D,A,B,C,10, 9); + function(C,D,A,B, 6,11); + function(B,C,D,A,14,15); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 9, 9); + function(C,D,A,B, 5,11); + function(B,C,D,A,13,15); + function(A,B,C,D, 3, 3); + function(D,A,B,C,11, 9); + function(C,D,A,B, 7,11); + function(B,C,D,A,15,15); + + + /* Put checksum in context given as argument. */ + ctx->A += A; + ctx->B += B; + ctx->C += C; + ctx->D += D; +} + + + +/* The routine updates the message-digest context to + * account for the presence of each of the characters inBuf[0..inLen-1] + * in the message whose digest is being computed. + */ +static void +md4_write ( void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + MD4_CONTEXT *hd = context; + + if( hd->count == 64 ) /* flush the buffer */ + { + transform( hd, hd->buf ); + _gcry_burn_stack (80+6*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + + if( hd->count ) + { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + md4_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + _gcry_burn_stack (80+6*sizeof(void*)); + + while( inlen >= 64 ) + { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; +} + + + +/* The routine final terminates the message-digest computation and + * ends with the desired message digest in mdContext->digest[0...15]. + * The handle is prepared for a new MD4 cycle. + * Returns 16 bytes representing the digest. + */ + +static void +md4_final( void *context ) +{ + MD4_CONTEXT *hd = context; + u32 t, msb, lsb; + byte *p; + + md4_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) /* enough room */ + { + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else /* need one extra block */ + { + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + md4_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + _gcry_burn_stack (80+6*sizeof(void*)); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ + *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0) +#else /* little endian */ +#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0) +#endif + X(A); + X(B); + X(C); + X(D); +#undef X + +} + +static byte * +md4_read (void *context) +{ + MD4_CONTEXT *hd = context; + return hd->buf; +} + +static byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */ + { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, + 0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 }; + +static gcry_md_oid_spec_t oid_spec_md4[] = + { + /* iso.member-body.us.rsadsi.digestAlgorithm.md4 */ + { "1.2.840.113549.2.4" }, + { NULL }, + }; + +gcry_md_spec_t _gcry_digest_spec_md4 = + { + "MD4", asn, DIM (asn), oid_spec_md4,16, + md4_init, md4_write, md4_final, md4_read, + sizeof (MD4_CONTEXT) + }; diff --git a/grub-core/lib/libgcrypt/cipher/md5.c b/grub-core/lib/libgcrypt/cipher/md5.c new file mode 100644 index 0000000..a98678a --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/md5.c @@ -0,0 +1,355 @@ +/* md5.c - MD5 Message-Digest Algorithm + * Copyright (C) 1995,1996,1998,1999,2001,2002, + * 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * According to the definition of MD5 in RFC 1321 from April 1992. + * NOTE: This is *not* the same file as the one from glibc. + * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. + * heavily modified for GnuPG by Werner Koch <wk@gnupg.org> + */ + +/* Test values: + * "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E + * "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61 + * "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72 + * "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "g10lib.h" +#include "cipher.h" + +#include "bithelp.h" + + +typedef struct { + u32 A,B,C,D; /* chaining variables */ + u32 nblocks; + byte buf[64]; + int count; +} MD5_CONTEXT; + + +static void +md5_init( void *context ) +{ + MD5_CONTEXT *ctx = context; + + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->nblocks = 0; + ctx->count = 0; +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + + +/**************** + * transform n*64 bytes + */ +static void +transform ( MD5_CONTEXT *ctx, const unsigned char *data ) +{ + u32 correct_words[16]; + register u32 A = ctx->A; + register u32 B = ctx->B; + register u32 C = ctx->C; + register u32 D = ctx->D; + u32 *cwp = correct_words; + +#ifdef WORDS_BIGENDIAN + { + int i; + byte *p2; + const byte *p1; + for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) + { + p2[3] = *p1++; + p2[2] = *p1++; + p2[1] = *p1++; + p2[0] = *p1++; + } + } +#else + memcpy( correct_words, data, 64 ); +#endif + + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++) + T; \ + a = rol(a, s); \ + a += b; \ + } \ + while (0) + + /* Before we start, one word about the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + a = rol(a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Put checksum in context given as argument. */ + ctx->A += A; + ctx->B += B; + ctx->C += C; + ctx->D += D; +} + + + +/* The routine updates the message-digest context to + * account for the presence of each of the characters inBuf[0..inLen-1] + * in the message whose digest is being computed. + */ +static void +md5_write( void *context, const void *inbuf_arg , size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + MD5_CONTEXT *hd = context; + + if( hd->count == 64 ) /* flush the buffer */ + { + transform( hd, hd->buf ); + _gcry_burn_stack (80+6*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + + if( hd->count ) + { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + md5_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + _gcry_burn_stack (80+6*sizeof(void*)); + + while( inlen >= 64 ) + { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + +} + + + +/* The routine final terminates the message-digest computation and + * ends with the desired message digest in mdContext->digest[0...15]. + * The handle is prepared for a new MD5 cycle. + * Returns 16 bytes representing the digest. + */ + +static void +md5_final( void *context) +{ + MD5_CONTEXT *hd = context; + u32 t, msb, lsb; + byte *p; + + md5_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) /* enough room */ + { + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else /* need one extra block */ + { + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + md5_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + _gcry_burn_stack (80+6*sizeof(void*)); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ + *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0) +#else /* little endian */ +#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0) +#endif + X(A); + X(B); + X(C); + X(D); +#undef X + +} + +static byte * +md5_read( void *context ) +{ + MD5_CONTEXT *hd = (MD5_CONTEXT *) context; + return hd->buf; +} + +static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */ + { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, + 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; + +static gcry_md_oid_spec_t oid_spec_md5[] = + { + /* iso.member-body.us.rsadsi.pkcs.pkcs-1.4 (md5WithRSAEncryption) */ + { "1.2.840.113549.1.1.4" }, + /* RSADSI digestAlgorithm MD5 */ + { "1.2.840.113549.2.5" }, + { NULL }, + }; + +gcry_md_spec_t _gcry_digest_spec_md5 = + { + "MD5", asn, DIM (asn), oid_spec_md5, 16, + md5_init, md5_write, md5_final, md5_read, + sizeof (MD5_CONTEXT) + }; diff --git a/grub-core/lib/libgcrypt/cipher/primegen.c b/grub-core/lib/libgcrypt/cipher/primegen.c new file mode 100644 index 0000000..b12e79b --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/primegen.c @@ -0,0 +1,1861 @@ +/* primegen.c - prime number generator + * Copyright (C) 1998, 2000, 2001, 2002, 2003 + * 2004, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "g10lib.h" +#include "mpi.h" +#include "cipher.h" +#include "ath.h" + +static gcry_mpi_t gen_prime (unsigned int nbits, int secret, int randomlevel, + int (*extra_check)(void *, gcry_mpi_t), + void *extra_check_arg); +static int check_prime( gcry_mpi_t prime, gcry_mpi_t val_2, int rm_rounds, + gcry_prime_check_func_t cb_func, void *cb_arg ); +static int is_prime (gcry_mpi_t n, int steps, unsigned int *count); +static void m_out_of_n( char *array, int m, int n ); + +static void (*progress_cb) (void *,const char*,int,int, int ); +static void *progress_cb_data; + +/* Note: 2 is not included because it can be tested more easily by + looking at bit 0. The last entry in this list is marked by a zero */ +static ushort small_prime_numbers[] = { + 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, + 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, + 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, + 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, + 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, + 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, + 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, + 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, + 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, + 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, + 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, + 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, + 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, + 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, + 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, + 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, + 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, + 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, + 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, + 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, + 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, + 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, + 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, + 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, + 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, + 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, + 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, + 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, + 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, + 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, + 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, + 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, + 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, + 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, + 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, + 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, + 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, + 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, + 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, + 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, + 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, + 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, + 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, + 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, + 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, + 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, + 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, + 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, + 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, + 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, + 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, + 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, + 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, + 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, + 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, + 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, + 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, + 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, + 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, + 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, + 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, + 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, + 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, + 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, + 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, + 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, + 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, + 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, + 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, + 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, + 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, + 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, + 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, + 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, + 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, + 4957, 4967, 4969, 4973, 4987, 4993, 4999, + 0 +}; +static int no_of_small_prime_numbers = DIM (small_prime_numbers) - 1; + + + +/* An object and a list to build up a global pool of primes. See + save_pool_prime and get_pool_prime. */ +struct primepool_s +{ + struct primepool_s *next; + gcry_mpi_t prime; /* If this is NULL the entry is not used. */ + unsigned int nbits; + gcry_random_level_t randomlevel; +}; +struct primepool_s *primepool; +/* Mutex used to protect access to the primepool. */ +static ath_mutex_t primepool_lock = ATH_MUTEX_INITIALIZER; + + + +/* Save PRIME which has been generated at RANDOMLEVEL for later + use. Needs to be called while primepool_lock is being hold. Note + that PRIME should be considered released after calling this + function. */ +static void +save_pool_prime (gcry_mpi_t prime, gcry_random_level_t randomlevel) +{ + struct primepool_s *item, *item2; + size_t n; + + for (n=0, item = primepool; item; item = item->next, n++) + if (!item->prime) + break; + if (!item && n > 100) + { + /* Remove some of the entries. Our strategy is removing + the last third from the list. */ + int i; + + for (i=0, item2 = primepool; item2; item2 = item2->next) + { + if (i >= n/3*2) + { + gcry_mpi_release (item2->prime); + item2->prime = NULL; + if (!item) + item = item2; + } + } + } + if (!item) + { + item = gcry_calloc (1, sizeof *item); + if (!item) + { + /* Out of memory. Silently giving up. */ + gcry_mpi_release (prime); + return; + } + item->next = primepool; + primepool = item; + } + item->prime = prime; + item->nbits = mpi_get_nbits (prime); + item->randomlevel = randomlevel; +} + + +/* Return a prime for the prime pool or NULL if none has been found. + The prime needs to match NBITS and randomlevel. This function needs + to be called why the primepool_look is being hold. */ +static gcry_mpi_t +get_pool_prime (unsigned int nbits, gcry_random_level_t randomlevel) +{ + struct primepool_s *item; + + for (item = primepool; item; item = item->next) + if (item->prime + && item->nbits == nbits && item->randomlevel == randomlevel) + { + gcry_mpi_t prime = item->prime; + item->prime = NULL; + gcry_assert (nbits == mpi_get_nbits (prime)); + return prime; + } + return NULL; +} + + + + + + +void +_gcry_register_primegen_progress ( void (*cb)(void *,const char*,int,int,int), + void *cb_data ) +{ + progress_cb = cb; + progress_cb_data = cb_data; +} + + +static void +progress( int c ) +{ + if ( progress_cb ) + progress_cb ( progress_cb_data, "primegen", c, 0, 0 ); +} + + +/**************** + * Generate a prime number (stored in secure memory) + */ +gcry_mpi_t +_gcry_generate_secret_prime (unsigned int nbits, + gcry_random_level_t random_level, + int (*extra_check)(void*, gcry_mpi_t), + void *extra_check_arg) +{ + gcry_mpi_t prime; + + prime = gen_prime (nbits, 1, random_level, extra_check, extra_check_arg); + progress('\n'); + return prime; +} + + +/* Generate a prime number which may be public, i.e. not allocated in + secure memory. */ +gcry_mpi_t +_gcry_generate_public_prime (unsigned int nbits, + gcry_random_level_t random_level, + int (*extra_check)(void*, gcry_mpi_t), + void *extra_check_arg) +{ + gcry_mpi_t prime; + + prime = gen_prime (nbits, 0, random_level, extra_check, extra_check_arg); + progress('\n'); + return prime; +} + + +/* Core prime generation function. The algorithm used to generate + practically save primes is due to Lim and Lee as described in the + CRYPTO '97 proceedings (ISBN3540633847) page 260. + + NEED_Q_FACTOR: If true make sure that at least one factor is of + size qbits. This is for example required for DSA. + PRIME_GENERATED: Adresss of a variable where the resulting prime + number will be stored. + PBITS: Requested size of the prime number. At least 48. + QBITS: One factor of the prime needs to be of this size. Maybe 0 + if this is not required. See also MODE. + G: If not NULL an MPI which will receive a generator for the prime + for use with Elgamal. + RET_FACTORS: if not NULL, an array with all factors are stored at + that address. + ALL_FACTORS: If set to true all factors of prime-1 are returned. + RANDOMLEVEL: How strong should the random numers be. + FLAGS: Prime generation bit flags. Currently supported: + GCRY_PRIME_FLAG_SECRET - The prime needs to be kept secret. + CB_FUNC, CB_ARG: Callback to be used for extra checks. + + */ +static gcry_err_code_t +prime_generate_internal (int need_q_factor, + gcry_mpi_t *prime_generated, unsigned int pbits, + unsigned int qbits, gcry_mpi_t g, + gcry_mpi_t **ret_factors, + gcry_random_level_t randomlevel, unsigned int flags, + int all_factors, + gcry_prime_check_func_t cb_func, void *cb_arg) +{ + gcry_err_code_t err = 0; + gcry_mpi_t *factors_new = NULL; /* Factors to return to the + caller. */ + gcry_mpi_t *factors = NULL; /* Current factors. */ + gcry_random_level_t poolrandomlevel; /* Random level used for pool primes. */ + gcry_mpi_t *pool = NULL; /* Pool of primes. */ + int *pool_in_use = NULL; /* Array with currently used POOL elements. */ + unsigned char *perms = NULL; /* Permutations of POOL. */ + gcry_mpi_t q_factor = NULL; /* Used if QBITS is non-zero. */ + unsigned int fbits = 0; /* Length of prime factors. */ + unsigned int n = 0; /* Number of factors. */ + unsigned int m = 0; /* Number of primes in pool. */ + gcry_mpi_t q = NULL; /* First prime factor. */ + gcry_mpi_t prime = NULL; /* Prime candidate. */ + unsigned int nprime = 0; /* Bits of PRIME. */ + unsigned int req_qbits; /* The original QBITS value. */ + gcry_mpi_t val_2; /* For check_prime(). */ + int is_locked = 0; /* Flag to help unlocking the primepool. */ + unsigned int is_secret = (flags & GCRY_PRIME_FLAG_SECRET); + unsigned int count1 = 0, count2 = 0; + unsigned int i = 0, j = 0; + + if (pbits < 48) + return GPG_ERR_INV_ARG; + + /* We won't use a too strong random elvel for the pooled subprimes. */ + poolrandomlevel = (randomlevel > GCRY_STRONG_RANDOM? + GCRY_STRONG_RANDOM : randomlevel); + + + /* If QBITS is not given, assume a reasonable value. */ + if (!qbits) + qbits = pbits / 3; + + req_qbits = qbits; + + /* Find number of needed prime factors N. */ + for (n = 1; (pbits - qbits - 1) / n >= qbits; n++) + ; + n--; + + val_2 = mpi_alloc_set_ui (2); + + if ((! n) || ((need_q_factor) && (n < 2))) + { + err = GPG_ERR_INV_ARG; + goto leave; + } + + if (need_q_factor) + { + n--; /* Need one factor less because we want a specific Q-FACTOR. */ + fbits = (pbits - 2 * req_qbits -1) / n; + qbits = pbits - req_qbits - n * fbits; + } + else + { + fbits = (pbits - req_qbits -1) / n; + qbits = pbits - n * fbits; + } + + if (DBG_CIPHER) + log_debug ("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", + pbits, req_qbits, qbits, fbits, n); + + /* Allocate an integer to old the new prime. */ + prime = gcry_mpi_new (pbits); + + /* Generate first prime factor. */ + q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL); + + /* Generate a specific Q-Factor if requested. */ + if (need_q_factor) + q_factor = gen_prime (req_qbits, is_secret, randomlevel, NULL, NULL); + + /* Allocate an array to hold all factors + 2 for later usage. */ + factors = gcry_calloc (n + 2, sizeof (*factors)); + if (!factors) + { + err = gpg_err_code_from_errno (errno); + goto leave; + } + + /* Allocate an array to track pool usage. */ + pool_in_use = gcry_calloc (n, sizeof *pool_in_use); + if (!pool_in_use) + { + err = gpg_err_code_from_errno (errno); + goto leave; + } + for (i=0; i < n; i++) + pool_in_use[i] = -1; + + /* Make a pool of 3n+5 primes (this is an arbitrary value). We + require at least 30 primes for are useful selection process. + + Fixme: We need to research the best formula for sizing the pool. + */ + m = n * 3 + 5; + if (need_q_factor) /* Need some more in this case. */ + m += 5; + if (m < 30) + m = 30; + pool = gcry_calloc (m , sizeof (*pool)); + if (! pool) + { + err = gpg_err_code_from_errno (errno); + goto leave; + } + + /* Permutate over the pool of primes until we find a prime of the + requested length. */ + do + { + next_try: + for (i=0; i < n; i++) + pool_in_use[i] = -1; + + if (!perms) + { + /* Allocate new primes. This is done right at the beginning + of the loop and if we have later run out of primes. */ + for (i = 0; i < m; i++) + { + mpi_free (pool[i]); + pool[i] = NULL; + } + + /* Init m_out_of_n(). */ + perms = gcry_calloc (1, m); + if (!perms) + { + err = gpg_err_code_from_errno (errno); + goto leave; + } + + if (ath_mutex_lock (&primepool_lock)) + { + err = GPG_ERR_INTERNAL; + goto leave; + } + is_locked = 1; + for (i = 0; i < n; i++) + { + perms[i] = 1; + /* At a maximum we use strong random for the factors. + This saves us a lot of entropy. Given that Q and + possible Q-factor are also used in the final prime + this should be acceptable. We also don't allocate in + secure memory to save on that scare resource too. If + Q has been allocated in secure memory, the final + prime will be saved there anyway. This is because + our MPI routines take care of that. GnuPG has worked + this way ever since. */ + pool[i] = NULL; + if (is_locked) + { + pool[i] = get_pool_prime (fbits, poolrandomlevel); + if (!pool[i]) + { + if (ath_mutex_unlock (&primepool_lock)) + { + err = GPG_ERR_INTERNAL; + goto leave; + } + is_locked = 0; + } + } + if (!pool[i]) + pool[i] = gen_prime (fbits, 0, poolrandomlevel, NULL, NULL); + pool_in_use[i] = i; + factors[i] = pool[i]; + } + if (is_locked && ath_mutex_unlock (&primepool_lock)) + { + err = GPG_ERR_INTERNAL; + goto leave; + } + is_locked = 0; + } + else + { + /* Get next permutation. */ + m_out_of_n ( (char*)perms, n, m); + if (ath_mutex_lock (&primepool_lock)) + { + err = GPG_ERR_INTERNAL; + goto leave; + } + is_locked = 1; + for (i = j = 0; (i < m) && (j < n); i++) + if (perms[i]) + { + /* If the subprime has not yet beed generated do it now. */ + if (!pool[i] && is_locked) + { + pool[i] = get_pool_prime (fbits, poolrandomlevel); + if (!pool[i]) + { + if (ath_mutex_unlock (&primepool_lock)) + { + err = GPG_ERR_INTERNAL; + goto leave; + } + is_locked = 0; + } + } + if (!pool[i]) + pool[i] = gen_prime (fbits, 0, poolrandomlevel, NULL, NULL); + pool_in_use[j] = i; + factors[j++] = pool[i]; + } + if (is_locked && ath_mutex_unlock (&primepool_lock)) + { + err = GPG_ERR_INTERNAL; + goto leave; + } + is_locked = 0; + if (i == n) + { + /* Ran out of permutations: Allocate new primes. */ + gcry_free (perms); + perms = NULL; + progress ('!'); + goto next_try; + } + } + + /* Generate next prime candidate: + p = 2 * q [ * q_factor] * factor_0 * factor_1 * ... * factor_n + 1. + */ + mpi_set (prime, q); + mpi_mul_ui (prime, prime, 2); + if (need_q_factor) + mpi_mul (prime, prime, q_factor); + for(i = 0; i < n; i++) + mpi_mul (prime, prime, factors[i]); + mpi_add_ui (prime, prime, 1); + nprime = mpi_get_nbits (prime); + + if (nprime < pbits) + { + if (++count1 > 20) + { + count1 = 0; + qbits++; + progress('>'); + mpi_free (q); + q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL); + goto next_try; + } + } + else + count1 = 0; + + if (nprime > pbits) + { + if (++count2 > 20) + { + count2 = 0; + qbits--; + progress('<'); + mpi_free (q); + q = gen_prime (qbits, is_secret, randomlevel, NULL, NULL); + goto next_try; + } + } + else + count2 = 0; + } + while (! ((nprime == pbits) && check_prime (prime, val_2, 5, + cb_func, cb_arg))); + + if (DBG_CIPHER) + { + progress ('\n'); + log_mpidump ("prime : ", prime); + log_mpidump ("factor q: ", q); + if (need_q_factor) + log_mpidump ("factor q0: ", q_factor); + for (i = 0; i < n; i++) + log_mpidump ("factor pi: ", factors[i]); + log_debug ("bit sizes: prime=%u, q=%u", + mpi_get_nbits (prime), mpi_get_nbits (q)); + if (need_q_factor) + log_debug (", q0=%u", mpi_get_nbits (q_factor)); + for (i = 0; i < n; i++) + log_debug (", p%d=%u", i, mpi_get_nbits (factors[i])); + progress('\n'); + } + + if (ret_factors) + { + /* Caller wants the factors. */ + factors_new = gcry_calloc (n + 4, sizeof (*factors_new)); + if (! factors_new) + { + err = gpg_err_code_from_errno (errno); + goto leave; + } + + if (all_factors) + { + i = 0; + factors_new[i++] = gcry_mpi_set_ui (NULL, 2); + factors_new[i++] = mpi_copy (q); + if (need_q_factor) + factors_new[i++] = mpi_copy (q_factor); + for(j=0; j < n; j++) + factors_new[i++] = mpi_copy (factors[j]); + } + else + { + i = 0; + if (need_q_factor) + { + factors_new[i++] = mpi_copy (q_factor); + for (; i <= n; i++) + factors_new[i] = mpi_copy (factors[i]); + } + else + for (; i < n; i++ ) + factors_new[i] = mpi_copy (factors[i]); + } + } + + if (g) + { + /* Create a generator (start with 3). */ + gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs (prime)); + gcry_mpi_t b = mpi_alloc (mpi_get_nlimbs (prime)); + gcry_mpi_t pmin1 = mpi_alloc (mpi_get_nlimbs (prime)); + + if (need_q_factor) + err = GPG_ERR_NOT_IMPLEMENTED; + else + { + factors[n] = q; + factors[n + 1] = mpi_alloc_set_ui (2); + mpi_sub_ui (pmin1, prime, 1); + mpi_set_ui (g, 2); + do + { + mpi_add_ui (g, g, 1); + if (DBG_CIPHER) + { + log_debug ("checking g:"); + gcry_mpi_dump (g); + log_printf ("\n"); + } + else + progress('^'); + for (i = 0; i < n + 2; i++) + { + mpi_fdiv_q (tmp, pmin1, factors[i]); + /* No mpi_pow(), but it is okay to use this with mod + prime. */ + gcry_mpi_powm (b, g, tmp, prime); + if (! mpi_cmp_ui (b, 1)) + break; + } + if (DBG_CIPHER) + progress('\n'); + } + while (i < n + 2); + + mpi_free (factors[n+1]); + mpi_free (tmp); + mpi_free (b); + mpi_free (pmin1); + } + } + + if (! DBG_CIPHER) + progress ('\n'); + + + leave: + if (pool) + { + is_locked = !ath_mutex_lock (&primepool_lock); + for(i = 0; i < m; i++) + { + if (pool[i]) + { + for (j=0; j < n; j++) + if (pool_in_use[j] == i) + break; + if (j == n && is_locked) + { + /* This pooled subprime has not been used. */ + save_pool_prime (pool[i], poolrandomlevel); + } + else + mpi_free (pool[i]); + } + } + if (is_locked && ath_mutex_unlock (&primepool_lock)) + err = GPG_ERR_INTERNAL; + is_locked = 0; + gcry_free (pool); + } + gcry_free (pool_in_use); + if (factors) + gcry_free (factors); /* Factors are shallow copies. */ + if (perms) + gcry_free (perms); + + mpi_free (val_2); + mpi_free (q); + mpi_free (q_factor); + + if (! err) + { + *prime_generated = prime; + if (ret_factors) + *ret_factors = factors_new; + } + else + { + if (factors_new) + { + for (i = 0; factors_new[i]; i++) + mpi_free (factors_new[i]); + gcry_free (factors_new); + } + mpi_free (prime); + } + + return err; +} + + +/* Generate a prime used for discrete logarithm algorithms; i.e. this + prime will be public and no strong random is required. */ +gcry_mpi_t +_gcry_generate_elg_prime (int mode, unsigned pbits, unsigned qbits, + gcry_mpi_t g, gcry_mpi_t **ret_factors) +{ + gcry_mpi_t prime = NULL; + + if (prime_generate_internal ((mode == 1), &prime, pbits, qbits, g, + ret_factors, GCRY_WEAK_RANDOM, 0, 0, + NULL, NULL)) + prime = NULL; /* (Should be NULL in the error case anyway.) */ + + return prime; +} + + +static gcry_mpi_t +gen_prime (unsigned int nbits, int secret, int randomlevel, + int (*extra_check)(void *, gcry_mpi_t), void *extra_check_arg) +{ + gcry_mpi_t prime, ptest, pminus1, val_2, val_3, result; + int i; + unsigned int x, step; + unsigned int count1, count2; + int *mods; + +/* if ( DBG_CIPHER ) */ +/* log_debug ("generate a prime of %u bits ", nbits ); */ + + if (nbits < 16) + log_fatal ("can't generate a prime with less than %d bits\n", 16); + + mods = gcry_xcalloc( no_of_small_prime_numbers, sizeof *mods); + /* Make nbits fit into gcry_mpi_t implementation. */ + val_2 = mpi_alloc_set_ui( 2 ); + val_3 = mpi_alloc_set_ui( 3); + prime = secret? gcry_mpi_snew ( nbits ): gcry_mpi_new ( nbits ); + result = mpi_alloc_like( prime ); + pminus1= mpi_alloc_like( prime ); + ptest = mpi_alloc_like( prime ); + count1 = count2 = 0; + for (;;) + { /* try forvever */ + int dotcount=0; + + /* generate a random number */ + gcry_mpi_randomize( prime, nbits, randomlevel ); + + /* Set high order bit to 1, set low order bit to 1. If we are + generating a secret prime we are most probably doing that + for RSA, to make sure that the modulus does have the + requested key size we set the 2 high order bits. */ + mpi_set_highbit (prime, nbits-1); + if (secret) + mpi_set_bit (prime, nbits-2); + mpi_set_bit(prime, 0); + + /* Calculate all remainders. */ + for (i=0; (x = small_prime_numbers[i]); i++ ) + mods[i] = mpi_fdiv_r_ui(NULL, prime, x); + + /* Now try some primes starting with prime. */ + for(step=0; step < 20000; step += 2 ) + { + /* Check against all the small primes we have in mods. */ + count1++; + for (i=0; (x = small_prime_numbers[i]); i++ ) + { + while ( mods[i] + step >= x ) + mods[i] -= x; + if ( !(mods[i] + step) ) + break; + } + if ( x ) + continue; /* Found a multiple of an already known prime. */ + + mpi_add_ui( ptest, prime, step ); + + /* Do a fast Fermat test now. */ + count2++; + mpi_sub_ui( pminus1, ptest, 1); + gcry_mpi_powm( result, val_2, pminus1, ptest ); + if ( !mpi_cmp_ui( result, 1 ) ) + { + /* Not composite, perform stronger tests */ + if (is_prime(ptest, 5, &count2 )) + { + if (!mpi_test_bit( ptest, nbits-1-secret )) + { + progress('\n'); + log_debug ("overflow in prime generation\n"); + break; /* Stop loop, continue with a new prime. */ + } + + if (extra_check && extra_check (extra_check_arg, ptest)) + { + /* The extra check told us that this prime is + not of the caller's taste. */ + progress ('/'); + } + else + { + /* Got it. */ + mpi_free(val_2); + mpi_free(val_3); + mpi_free(result); + mpi_free(pminus1); + mpi_free(prime); + gcry_free(mods); + return ptest; + } + } + } + if (++dotcount == 10 ) + { + progress('.'); + dotcount = 0; + } + } + progress(':'); /* restart with a new random value */ + } +} + +/**************** + * Returns: true if this may be a prime + * RM_ROUNDS gives the number of Rabin-Miller tests to run. + */ +static int +check_prime( gcry_mpi_t prime, gcry_mpi_t val_2, int rm_rounds, + gcry_prime_check_func_t cb_func, void *cb_arg) +{ + int i; + unsigned int x; + unsigned int count=0; + + /* Check against small primes. */ + for (i=0; (x = small_prime_numbers[i]); i++ ) + { + if ( mpi_divisible_ui( prime, x ) ) + return 0; + } + + /* A quick Fermat test. */ + { + gcry_mpi_t result = mpi_alloc_like( prime ); + gcry_mpi_t pminus1 = mpi_alloc_like( prime ); + mpi_sub_ui( pminus1, prime, 1); + gcry_mpi_powm( result, val_2, pminus1, prime ); + mpi_free( pminus1 ); + if ( mpi_cmp_ui( result, 1 ) ) + { + /* Is composite. */ + mpi_free( result ); + progress('.'); + return 0; + } + mpi_free( result ); + } + + if (!cb_func || cb_func (cb_arg, GCRY_PRIME_CHECK_AT_MAYBE_PRIME, prime)) + { + /* Perform stronger tests. */ + if ( is_prime( prime, rm_rounds, &count ) ) + { + if (!cb_func + || cb_func (cb_arg, GCRY_PRIME_CHECK_AT_GOT_PRIME, prime)) + return 1; /* Probably a prime. */ + } + } + progress('.'); + return 0; +} + + +/* + * Return true if n is probably a prime + */ +static int +is_prime (gcry_mpi_t n, int steps, unsigned int *count) +{ + gcry_mpi_t x = mpi_alloc( mpi_get_nlimbs( n ) ); + gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs( n ) ); + gcry_mpi_t z = mpi_alloc( mpi_get_nlimbs( n ) ); + gcry_mpi_t nminus1 = mpi_alloc( mpi_get_nlimbs( n ) ); + gcry_mpi_t a2 = mpi_alloc_set_ui( 2 ); + gcry_mpi_t q; + unsigned i, j, k; + int rc = 0; + unsigned nbits = mpi_get_nbits( n ); + + if (steps < 5) /* Make sure that we do at least 5 rounds. */ + steps = 5; + + mpi_sub_ui( nminus1, n, 1 ); + + /* Find q and k, so that n = 1 + 2^k * q . */ + q = mpi_copy ( nminus1 ); + k = mpi_trailing_zeros ( q ); + mpi_tdiv_q_2exp (q, q, k); + + for (i=0 ; i < steps; i++ ) + { + ++*count; + if( !i ) + { + mpi_set_ui( x, 2 ); + } + else + { + gcry_mpi_randomize( x, nbits, GCRY_WEAK_RANDOM ); + + /* Make sure that the number is smaller than the prime and + keep the randomness of the high bit. */ + if ( mpi_test_bit ( x, nbits-2) ) + { + mpi_set_highbit ( x, nbits-2); /* Clear all higher bits. */ + } + else + { + mpi_set_highbit( x, nbits-2 ); + mpi_clear_bit( x, nbits-2 ); + } + gcry_assert (mpi_cmp (x, nminus1) < 0 && mpi_cmp_ui (x, 1) > 0); + } + gcry_mpi_powm ( y, x, q, n); + if ( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) ) + { + for ( j=1; j < k && mpi_cmp( y, nminus1 ); j++ ) + { + gcry_mpi_powm(y, y, a2, n); + if( !mpi_cmp_ui( y, 1 ) ) + goto leave; /* Not a prime. */ + } + if (mpi_cmp( y, nminus1 ) ) + goto leave; /* Not a prime. */ + } + progress('+'); + } + rc = 1; /* May be a prime. */ + + leave: + mpi_free( x ); + mpi_free( y ); + mpi_free( z ); + mpi_free( nminus1 ); + mpi_free( q ); + mpi_free( a2 ); + + return rc; +} + + +/* Given ARRAY of size N with M elements set to true produce a + modified array with the next permutation of M elements. Note, that + ARRAY is used in a one-bit-per-byte approach. To detected the last + permutation it is useful to initialize the array with the first M + element set to true and use this test: + m_out_of_n (array, m, n); + for (i = j = 0; i < n && j < m; i++) + if (array[i]) + j++; + if (j == m) + goto ready; + + This code is based on the algorithm 452 from the "Collected + Algorithms From ACM, Volume II" by C. N. Liu and D. T. Tang. +*/ +static void +m_out_of_n ( char *array, int m, int n ) +{ + int i=0, i1=0, j=0, jp=0, j1=0, k1=0, k2=0; + + if( !m || m >= n ) + return; + + /* Need to handle this simple case separately. */ + if( m == 1 ) + { + for (i=0; i < n; i++ ) + { + if ( array[i] ) + { + array[i++] = 0; + if( i >= n ) + i = 0; + array[i] = 1; + return; + } + } + BUG(); + } + + + for (j=1; j < n; j++ ) + { + if ( array[n-1] == array[n-j-1]) + continue; + j1 = j; + break; + } + + if ( (m & 1) ) + { + /* M is odd. */ + if( array[n-1] ) + { + if( j1 & 1 ) + { + k1 = n - j1; + k2 = k1+2; + if( k2 > n ) + k2 = n; + goto leave; + } + goto scan; + } + k2 = n - j1 - 1; + if( k2 == 0 ) + { + k1 = i; + k2 = n - j1; + } + else if( array[k2] && array[k2-1] ) + k1 = n; + else + k1 = k2 + 1; + } + else + { + /* M is even. */ + if( !array[n-1] ) + { + k1 = n - j1; + k2 = k1 + 1; + goto leave; + } + + if( !(j1 & 1) ) + { + k1 = n - j1; + k2 = k1+2; + if( k2 > n ) + k2 = n; + goto leave; + } + scan: + jp = n - j1 - 1; + for (i=1; i <= jp; i++ ) + { + i1 = jp + 2 - i; + if( array[i1-1] ) + { + if( array[i1-2] ) + { + k1 = i1 - 1; + k2 = n - j1; + } + else + { + k1 = i1 - 1; + k2 = n + 1 - j1; + } + goto leave; + } + } + k1 = 1; + k2 = n + 1 - m; + } + leave: + /* Now complement the two selected bits. */ + array[k1-1] = !array[k1-1]; + array[k2-1] = !array[k2-1]; +} + + +/* Generate a new prime number of PRIME_BITS bits and store it in + PRIME. If FACTOR_BITS is non-zero, one of the prime factors of + (prime - 1) / 2 must be FACTOR_BITS bits long. If FACTORS is + non-zero, allocate a new, NULL-terminated array holding the prime + factors and store it in FACTORS. FLAGS might be used to influence + the prime number generation process. */ +gcry_error_t +gcry_prime_generate (gcry_mpi_t *prime, unsigned int prime_bits, + unsigned int factor_bits, gcry_mpi_t **factors, + gcry_prime_check_func_t cb_func, void *cb_arg, + gcry_random_level_t random_level, + unsigned int flags) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_mpi_t *factors_generated = NULL; + gcry_mpi_t prime_generated = NULL; + unsigned int mode = 0; + + if (!prime) + return gpg_error (GPG_ERR_INV_ARG); + *prime = NULL; + + if (flags & GCRY_PRIME_FLAG_SPECIAL_FACTOR) + mode = 1; + + /* Generate. */ + err = prime_generate_internal ((mode==1), &prime_generated, prime_bits, + factor_bits, NULL, + factors? &factors_generated : NULL, + random_level, flags, 1, + cb_func, cb_arg); + + if (! err) + if (cb_func) + { + /* Additional check. */ + if ( !cb_func (cb_arg, GCRY_PRIME_CHECK_AT_FINISH, prime_generated)) + { + /* Failed, deallocate resources. */ + unsigned int i; + + mpi_free (prime_generated); + if (factors) + { + for (i = 0; factors_generated[i]; i++) + mpi_free (factors_generated[i]); + gcry_free (factors_generated); + } + err = GPG_ERR_GENERAL; + } + } + + if (! err) + { + if (factors) + *factors = factors_generated; + *prime = prime_generated; + } + + return gcry_error (err); +} + +/* Check whether the number X is prime. */ +gcry_error_t +gcry_prime_check (gcry_mpi_t x, unsigned int flags) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_mpi_t val_2 = mpi_alloc_set_ui (2); /* Used by the Fermat test. */ + + (void)flags; + + /* We use 64 rounds because the prime we are going to test is not + guaranteed to be a random one. */ + if (! check_prime (x, val_2, 64, NULL, NULL)) + err = GPG_ERR_NO_PRIME; + + mpi_free (val_2); + + return gcry_error (err); +} + +/* Find a generator for PRIME where the factorization of (prime-1) is + in the NULL terminated array FACTORS. Return the generator as a + newly allocated MPI in R_G. If START_G is not NULL, use this as s + atart for the search. Returns 0 on success.*/ +gcry_error_t +gcry_prime_group_generator (gcry_mpi_t *r_g, + gcry_mpi_t prime, gcry_mpi_t *factors, + gcry_mpi_t start_g) +{ + gcry_mpi_t tmp = gcry_mpi_new (0); + gcry_mpi_t b = gcry_mpi_new (0); + gcry_mpi_t pmin1 = gcry_mpi_new (0); + gcry_mpi_t g = start_g? gcry_mpi_copy (start_g) : gcry_mpi_set_ui (NULL, 3); + int first = 1; + int i, n; + + if (!factors || !r_g || !prime) + return gpg_error (GPG_ERR_INV_ARG); + *r_g = NULL; + + for (n=0; factors[n]; n++) + ; + if (n < 2) + return gpg_error (GPG_ERR_INV_ARG); + + /* Extra sanity check - usually disabled. */ +/* mpi_set (tmp, factors[0]); */ +/* for(i = 1; i < n; i++) */ +/* mpi_mul (tmp, tmp, factors[i]); */ +/* mpi_add_ui (tmp, tmp, 1); */ +/* if (mpi_cmp (prime, tmp)) */ +/* return gpg_error (GPG_ERR_INV_ARG); */ + + gcry_mpi_sub_ui (pmin1, prime, 1); + do + { + if (first) + first = 0; + else + gcry_mpi_add_ui (g, g, 1); + + if (DBG_CIPHER) + { + log_debug ("checking g:"); + gcry_mpi_dump (g); + log_debug ("\n"); + } + else + progress('^'); + + for (i = 0; i < n; i++) + { + mpi_fdiv_q (tmp, pmin1, factors[i]); + gcry_mpi_powm (b, g, tmp, prime); + if (! mpi_cmp_ui (b, 1)) + break; + } + if (DBG_CIPHER) + progress('\n'); + } + while (i < n); + + gcry_mpi_release (tmp); + gcry_mpi_release (b); + gcry_mpi_release (pmin1); + *r_g = g; + + return 0; +} + +/* Convenience function to release the factors array. */ +void +gcry_prime_release_factors (gcry_mpi_t *factors) +{ + if (factors) + { + int i; + + for (i=0; factors[i]; i++) + mpi_free (factors[i]); + gcry_free (factors); + } +} + + + +/* Helper for _gcry_derive_x931_prime. */ +static gcry_mpi_t +find_x931_prime (const gcry_mpi_t pfirst) +{ + gcry_mpi_t val_2 = mpi_alloc_set_ui (2); + gcry_mpi_t prime; + + prime = gcry_mpi_copy (pfirst); + /* If P is even add 1. */ + mpi_set_bit (prime, 0); + + /* We use 64 Rabin-Miller rounds which is better and thus + sufficient. We do not have a Lucas test implementaion thus we + can't do it in the X9.31 preferred way of running a few + Rabin-Miller followed by one Lucas test. */ + while ( !check_prime (prime, val_2, 64, NULL, NULL) ) + mpi_add_ui (prime, prime, 2); + + mpi_free (val_2); + + return prime; +} + + +/* Generate a prime using the algorithm from X9.31 appendix B.4. + + This function requires that the provided public exponent E is odd. + XP, XP1 and XP2 are the seed values. All values are mandatory. + + On success the prime is returned. If R_P1 or R_P2 are given the + internal values P1 and P2 are saved at these addresses. On error + NULL is returned. */ +gcry_mpi_t +_gcry_derive_x931_prime (const gcry_mpi_t xp, + const gcry_mpi_t xp1, const gcry_mpi_t xp2, + const gcry_mpi_t e, + gcry_mpi_t *r_p1, gcry_mpi_t *r_p2) +{ + gcry_mpi_t p1, p2, p1p2, yp0; + + if (!xp || !xp1 || !xp2) + return NULL; + if (!e || !mpi_test_bit (e, 0)) + return NULL; /* We support only odd values for E. */ + + p1 = find_x931_prime (xp1); + p2 = find_x931_prime (xp2); + p1p2 = mpi_alloc_like (xp); + mpi_mul (p1p2, p1, p2); + + { + gcry_mpi_t r1, tmp; + + /* r1 = (p2^{-1} mod p1)p2 - (p1^{-1} mod p2) */ + tmp = mpi_alloc_like (p1); + mpi_invm (tmp, p2, p1); + mpi_mul (tmp, tmp, p2); + r1 = tmp; + + tmp = mpi_alloc_like (p2); + mpi_invm (tmp, p1, p2); + mpi_mul (tmp, tmp, p1); + mpi_sub (r1, r1, tmp); + + /* Fixup a negative value. */ + if (mpi_is_neg (r1)) + mpi_add (r1, r1, p1p2); + + /* yp0 = xp + (r1 - xp mod p1*p2) */ + yp0 = tmp; tmp = NULL; + mpi_subm (yp0, r1, xp, p1p2); + mpi_add (yp0, yp0, xp); + mpi_free (r1); + + /* Fixup a negative value. */ + if (mpi_cmp (yp0, xp) < 0 ) + mpi_add (yp0, yp0, p1p2); + } + + /* yp0 is now the first integer greater than xp with p1 being a + large prime factor of yp0-1 and p2 a large prime factor of yp0+1. */ + + /* Note that the first example from X9.31 (D.1.1) which uses + (Xq1 #1A5CF72EE770DE50CB09ACCEA9#) + (Xq2 #134E4CAA16D2350A21D775C404#) + (Xq #CC1092495D867E64065DEE3E7955F2EBC7D47A2D + 7C9953388F97DDDC3E1CA19C35CA659EDC2FC325 + 6D29C2627479C086A699A49C4C9CEE7EF7BD1B34 + 321DE34A#)))) + returns an yp0 of + #CC1092495D867E64065DEE3E7955F2EBC7D47A2D + 7C9953388F97DDDC3E1CA19C35CA659EDC2FC4E3 + BF20CB896EE37E098A906313271422162CB6C642 + 75C1201F# + and not + #CC1092495D867E64065DEE3E7955F2EBC7D47A2D + 7C9953388F97DDDC3E1CA19C35CA659EDC2FC2E6 + C88FE299D52D78BE405A97E01FD71DD7819ECB91 + FA85A076# + as stated in the standard. This seems to be a bug in X9.31. + */ + + { + gcry_mpi_t val_2 = mpi_alloc_set_ui (2); + gcry_mpi_t gcdtmp = mpi_alloc_like (yp0); + int gcdres; + + mpi_sub_ui (p1p2, p1p2, 1); /* Adjust for loop body. */ + mpi_sub_ui (yp0, yp0, 1); /* Ditto. */ + for (;;) + { + gcdres = gcry_mpi_gcd (gcdtmp, e, yp0); + mpi_add_ui (yp0, yp0, 1); + if (!gcdres) + progress ('/'); /* gcd (e, yp0-1) != 1 */ + else if (check_prime (yp0, val_2, 64, NULL, NULL)) + break; /* Found. */ + /* We add p1p2-1 because yp0 is incremented after the gcd test. */ + mpi_add (yp0, yp0, p1p2); + } + mpi_free (gcdtmp); + mpi_free (val_2); + } + + mpi_free (p1p2); + + progress('\n'); + if (r_p1) + *r_p1 = p1; + else + mpi_free (p1); + if (r_p2) + *r_p2 = p2; + else + mpi_free (p2); + return yp0; +} + + + +/* Generate the two prime used for DSA using the algorithm specified + in FIPS 186-2. PBITS is the desired length of the prime P and a + QBITS the length of the prime Q. If SEED is not supplied and + SEEDLEN is 0 the function generates an appropriate SEED. On + success the generated primes are stored at R_Q and R_P, the counter + value is stored at R_COUNTER and the seed actually used for + generation is stored at R_SEED and R_SEEDVALUE. */ +gpg_err_code_t +_gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, + const void *seed, size_t seedlen, + gcry_mpi_t *r_q, gcry_mpi_t *r_p, + int *r_counter, + void **r_seed, size_t *r_seedlen) +{ + gpg_err_code_t ec; + unsigned char seed_help_buffer[160/8]; /* Used to hold a generated SEED. */ + unsigned char *seed_plus; /* Malloced buffer to hold SEED+x. */ + unsigned char digest[160/8]; /* Helper buffer for SHA-1 digest. */ + gcry_mpi_t val_2 = NULL; /* Helper for the prime test. */ + gcry_mpi_t tmpval = NULL; /* Helper variable. */ + int i; + + unsigned char value_u[160/8]; + int value_n, value_b, value_k; + int counter; + gcry_mpi_t value_w = NULL; + gcry_mpi_t value_x = NULL; + gcry_mpi_t prime_q = NULL; + gcry_mpi_t prime_p = NULL; + + /* FIPS 186-2 allows only for 1024/160 bit. */ + if (pbits != 1024 || qbits != 160) + return GPG_ERR_INV_KEYLEN; + + if (!seed && !seedlen) + ; /* No seed value given: We are asked to generate it. */ + else if (!seed || seedlen < qbits/8) + return GPG_ERR_INV_ARG; + + /* Allocate a buffer to later compute SEED+some_increment. */ + seed_plus = gcry_malloc (seedlen < 20? 20:seedlen); + if (!seed_plus) + { + ec = gpg_err_code_from_syserror (); + goto leave; + } + + val_2 = mpi_alloc_set_ui (2); + value_n = (pbits - 1) / qbits; + value_b = (pbits - 1) - value_n * qbits; + value_w = gcry_mpi_new (pbits); + value_x = gcry_mpi_new (pbits); + + restart: + /* Generate Q. */ + for (;;) + { + /* Step 1: Generate a (new) seed unless one has been supplied. */ + if (!seed) + { + seedlen = sizeof seed_help_buffer; + gcry_create_nonce (seed_help_buffer, seedlen); + seed = seed_help_buffer; + } + + /* Step 2: U = sha1(seed) ^ sha1((seed+1) mod 2^{qbits}) */ + memcpy (seed_plus, seed, seedlen); + for (i=seedlen-1; i >= 0; i--) + { + seed_plus[i]++; + if (seed_plus[i]) + break; + } + gcry_md_hash_buffer (GCRY_MD_SHA1, value_u, seed, seedlen); + gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen); + for (i=0; i < sizeof value_u; i++) + value_u[i] ^= digest[i]; + + /* Step 3: Form q from U */ + gcry_mpi_release (prime_q); prime_q = NULL; + ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, + value_u, sizeof value_u, NULL)); + if (ec) + goto leave; + mpi_set_highbit (prime_q, qbits-1 ); + mpi_set_bit (prime_q, 0); + + /* Step 4: Test whether Q is prime using 64 round of Rabin-Miller. */ + if (check_prime (prime_q, val_2, 64, NULL, NULL)) + break; /* Yes, Q is prime. */ + + /* Step 5. */ + seed = NULL; /* Force a new seed at Step 1. */ + } + + /* Step 6. Note that we do no use an explicit offset but increment + SEED_PLUS accordingly. SEED_PLUS is currently SEED+1. */ + counter = 0; + + /* Generate P. */ + prime_p = gcry_mpi_new (pbits); + for (;;) + { + /* Step 7: For k = 0,...n let + V_k = sha1(seed+offset+k) mod 2^{qbits} + Step 8: W = V_0 + V_1*2^160 + + ... + + V_{n-1}*2^{(n-1)*160} + + (V_{n} mod 2^b)*2^{n*160} + */ + mpi_set_ui (value_w, 0); + for (value_k=0; value_k <= value_n; value_k++) + { + /* There is no need to have an explicit offset variable: In + the first round we shall have an offset of 2, this is + achieved by using SEED_PLUS which is already at SEED+1, + thus we just need to increment it once again. The + requirement for the next round is to update offset by N, + which we implictly did at the end of this loop, and then + to add one; this one is the same as in the first round. */ + for (i=seedlen-1; i >= 0; i--) + { + seed_plus[i]++; + if (seed_plus[i]) + break; + } + gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen); + + gcry_mpi_release (tmpval); tmpval = NULL; + ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG, + digest, sizeof digest, NULL)); + if (ec) + goto leave; + if (value_k == value_n) + mpi_clear_highbit (tmpval, value_b); /* (V_n mod 2^b) */ + mpi_lshift (tmpval, tmpval, value_k*qbits); + mpi_add (value_w, value_w, tmpval); + } + + /* Step 8 continued: X = W + 2^{L-1} */ + mpi_set_ui (value_x, 0); + mpi_set_highbit (value_x, pbits-1); + mpi_add (value_x, value_x, value_w); + + /* Step 9: c = X mod 2q, p = X - (c - 1) */ + mpi_mul_2exp (tmpval, prime_q, 1); + mpi_mod (tmpval, value_x, tmpval); + mpi_sub_ui (tmpval, tmpval, 1); + mpi_sub (prime_p, value_x, tmpval); + + /* Step 10: If p < 2^{L-1} skip the primality test. */ + /* Step 11 and 12: Primality test. */ + if (mpi_get_nbits (prime_p) >= pbits-1 + && check_prime (prime_p, val_2, 64, NULL, NULL) ) + break; /* Yes, P is prime, continue with Step 15. */ + + /* Step 13: counter = counter + 1, offset = offset + n + 1. */ + counter++; + + /* Step 14: If counter >= 2^12 goto Step 1. */ + if (counter >= 4096) + goto restart; + } + + /* Step 15: Save p, q, counter and seed. */ +/* log_debug ("fips186-2 pbits p=%u q=%u counter=%d\n", */ +/* mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter); */ +/* log_printhex("fips186-2 seed:", seed, seedlen); */ +/* log_mpidump ("fips186-2 prime p", prime_p); */ +/* log_mpidump ("fips186-2 prime q", prime_q); */ + if (r_q) + { + *r_q = prime_q; + prime_q = NULL; + } + if (r_p) + { + *r_p = prime_p; + prime_p = NULL; + } + if (r_counter) + *r_counter = counter; + if (r_seed && r_seedlen) + { + memcpy (seed_plus, seed, seedlen); + *r_seed = seed_plus; + seed_plus = NULL; + *r_seedlen = seedlen; + } + + + leave: + gcry_mpi_release (tmpval); + gcry_mpi_release (value_x); + gcry_mpi_release (value_w); + gcry_mpi_release (prime_p); + gcry_mpi_release (prime_q); + gcry_free (seed_plus); + gcry_mpi_release (val_2); + return ec; +} + + + +/* WARNING: The code below has not yet been tested! However, it is + not yet used. We need to wait for FIPS 186-3 final and for test + vectors. + + Generate the two prime used for DSA using the algorithm specified + in FIPS 186-3, A.1.1.2. PBITS is the desired length of the prime P + and a QBITS the length of the prime Q. If SEED is not supplied and + SEEDLEN is 0 the function generates an appropriate SEED. On + success the generated primes are stored at R_Q and R_P, the counter + value is stored at R_COUNTER and the seed actually used for + generation is stored at R_SEED and R_SEEDVALUE. The hash algorithm + used is stored at R_HASHALGO. + + Note that this function is very similar to the fips186_2 code. Due + to the minor differences, other buffer sizes and for documentarion, + we use a separate function. +*/ +gpg_err_code_t +_gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, + const void *seed, size_t seedlen, + gcry_mpi_t *r_q, gcry_mpi_t *r_p, + int *r_counter, + void **r_seed, size_t *r_seedlen, + int *r_hashalgo) +{ + gpg_err_code_t ec; + unsigned char seed_help_buffer[256/8]; /* Used to hold a generated SEED. */ + unsigned char *seed_plus; /* Malloced buffer to hold SEED+x. */ + unsigned char digest[256/8]; /* Helper buffer for SHA-1 digest. */ + gcry_mpi_t val_2 = NULL; /* Helper for the prime test. */ + gcry_mpi_t tmpval = NULL; /* Helper variable. */ + int hashalgo; /* The id of the Approved Hash Function. */ + int i; + + unsigned char value_u[256/8]; + int value_n, value_b, value_j; + int counter; + gcry_mpi_t value_w = NULL; + gcry_mpi_t value_x = NULL; + gcry_mpi_t prime_q = NULL; + gcry_mpi_t prime_p = NULL; + + gcry_assert (sizeof seed_help_buffer == sizeof digest + && sizeof seed_help_buffer == sizeof value_u); + + /* Step 1: Check the requested prime lengths. */ + /* Note that due to the size of our buffers QBITS is limited to 256. */ + if (pbits == 1024 && qbits == 160) + hashalgo = GCRY_MD_SHA1; + else if (pbits == 2048 && qbits == 224) + hashalgo = GCRY_MD_SHA224; + else if (pbits == 2048 && qbits == 256) + hashalgo = GCRY_MD_SHA256; + else if (pbits == 3072 && qbits == 256) + hashalgo = GCRY_MD_SHA256; + else + return GPG_ERR_INV_KEYLEN; + + /* Also check that the hash algorithm is available. */ + ec = gpg_err_code (gcry_md_test_algo (hashalgo)); + if (ec) + return ec; + gcry_assert (qbits/8 <= sizeof digest); + gcry_assert (gcry_md_get_algo_dlen (hashalgo) == qbits/8); + + + /* Step 2: Check seedlen. */ + if (!seed && !seedlen) + ; /* No seed value given: We are asked to generate it. */ + else if (!seed || seedlen < qbits/8) + return GPG_ERR_INV_ARG; + + /* Allocate a buffer to later compute SEED+some_increment and a few + helper variables. */ + seed_plus = gcry_malloc (seedlen < sizeof seed_help_buffer? + sizeof seed_help_buffer : seedlen); + if (!seed_plus) + { + ec = gpg_err_code_from_syserror (); + goto leave; + } + val_2 = mpi_alloc_set_ui (2); + value_w = gcry_mpi_new (pbits); + value_x = gcry_mpi_new (pbits); + + /* Step 3: n = \lceil L / outlen \rceil - 1 */ + value_n = (pbits + qbits - 1) / qbits - 1; + /* Step 4: b = L - 1 - (n * outlen) */ + value_b = pbits - 1 - (value_n * qbits); + + restart: + /* Generate Q. */ + for (;;) + { + /* Step 5: Generate a (new) seed unless one has been supplied. */ + if (!seed) + { + seedlen = qbits/8; + gcry_assert (seedlen <= sizeof seed_help_buffer); + gcry_create_nonce (seed_help_buffer, seedlen); + seed = seed_help_buffer; + } + + /* Step 6: U = hash(seed) */ + gcry_md_hash_buffer (hashalgo, value_u, seed, seedlen); + + /* Step 7: q = 2^{N-1} + U + 1 - (U mod 2) */ + if ( !(value_u[qbits/8-1] & 0x01) ) + { + for (i=qbits/8-1; i >= 0; i--) + { + value_u[i]++; + if (value_u[i]) + break; + } + } + gcry_mpi_release (prime_q); prime_q = NULL; + ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, + value_u, sizeof value_u, NULL)); + if (ec) + goto leave; + mpi_set_highbit (prime_q, qbits-1 ); + + /* Step 8: Test whether Q is prime using 64 round of Rabin-Miller. + According to table C.1 this is sufficient for all + supported prime sizes (i.e. up 3072/256). */ + if (check_prime (prime_q, val_2, 64, NULL, NULL)) + break; /* Yes, Q is prime. */ + + /* Step 8. */ + seed = NULL; /* Force a new seed at Step 5. */ + } + + /* Step 11. Note that we do no use an explicit offset but increment + SEED_PLUS accordingly. */ + memcpy (seed_plus, seed, seedlen); + counter = 0; + + /* Generate P. */ + prime_p = gcry_mpi_new (pbits); + for (;;) + { + /* Step 11.1: For j = 0,...n let + V_j = hash(seed+offset+j) + Step 11.2: W = V_0 + V_1*2^outlen + + ... + + V_{n-1}*2^{(n-1)*outlen} + + (V_{n} mod 2^b)*2^{n*outlen} + */ + mpi_set_ui (value_w, 0); + for (value_j=0; value_j <= value_n; value_j++) + { + /* There is no need to have an explicit offset variable: In + the first round we shall have an offset of 1 and a j of + 0. This is achieved by incrementing SEED_PLUS here. For + the next round offset is implicitly updated by using + SEED_PLUS again. */ + for (i=seedlen-1; i >= 0; i--) + { + seed_plus[i]++; + if (seed_plus[i]) + break; + } + gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen); + + gcry_mpi_release (tmpval); tmpval = NULL; + ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG, + digest, sizeof digest, NULL)); + if (ec) + goto leave; + if (value_j == value_n) + mpi_clear_highbit (tmpval, value_b); /* (V_n mod 2^b) */ + mpi_lshift (tmpval, tmpval, value_j*qbits); + mpi_add (value_w, value_w, tmpval); + } + + /* Step 11.3: X = W + 2^{L-1} */ + mpi_set_ui (value_x, 0); + mpi_set_highbit (value_x, pbits-1); + mpi_add (value_x, value_x, value_w); + + /* Step 11.4: c = X mod 2q */ + mpi_mul_2exp (tmpval, prime_q, 1); + mpi_mod (tmpval, value_x, tmpval); + + /* Step 11.5: p = X - (c - 1) */ + mpi_sub_ui (tmpval, tmpval, 1); + mpi_sub (prime_p, value_x, tmpval); + + /* Step 11.6: If p < 2^{L-1} skip the primality test. */ + /* Step 11.7 and 11.8: Primality test. */ + if (mpi_get_nbits (prime_p) >= pbits-1 + && check_prime (prime_p, val_2, 64, NULL, NULL) ) + break; /* Yes, P is prime, continue with Step 15. */ + + /* Step 11.9: counter = counter + 1, offset = offset + n + 1. + If counter >= 4L goto Step 5. */ + counter++; + if (counter >= 4*pbits) + goto restart; + } + + /* Step 12: Save p, q, counter and seed. */ + log_debug ("fips186-3 pbits p=%u q=%u counter=%d\n", + mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter); + log_printhex("fips186-3 seed:", seed, seedlen); + log_mpidump ("fips186-3 prime p", prime_p); + log_mpidump ("fips186-3 prime q", prime_q); + if (r_q) + { + *r_q = prime_q; + prime_q = NULL; + } + if (r_p) + { + *r_p = prime_p; + prime_p = NULL; + } + if (r_counter) + *r_counter = counter; + if (r_seed && r_seedlen) + { + memcpy (seed_plus, seed, seedlen); + *r_seed = seed_plus; + seed_plus = NULL; + *r_seedlen = seedlen; + } + if (r_hashalgo) + *r_hashalgo = hashalgo; + + leave: + gcry_mpi_release (tmpval); + gcry_mpi_release (value_x); + gcry_mpi_release (value_w); + gcry_mpi_release (prime_p); + gcry_mpi_release (prime_q); + gcry_free (seed_plus); + gcry_mpi_release (val_2); + return ec; +} diff --git a/grub-core/lib/libgcrypt/cipher/pubkey.c b/grub-core/lib/libgcrypt/cipher/pubkey.c new file mode 100644 index 0000000..ca087ad --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/pubkey.c @@ -0,0 +1,4212 @@ +/* pubkey.c - pubkey dispatcher + * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005, + * 2007, 2008, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "g10lib.h" +#include "mpi.h" +#include "cipher.h" +#include "ath.h" + + +static gcry_err_code_t pubkey_decrypt (int algo, gcry_mpi_t *result, + gcry_mpi_t *data, gcry_mpi_t *skey, + int flags); +static gcry_err_code_t pubkey_sign (int algo, gcry_mpi_t *resarr, + gcry_mpi_t hash, gcry_mpi_t *skey); +static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash, + gcry_mpi_t *data, gcry_mpi_t *pkey, + int (*cmp) (void *, gcry_mpi_t), + void *opaque); + + +/* A dummy extraspec so that we do not need to tests the extraspec + field from the module specification against NULL and instead + directly test the respective fields of extraspecs. */ +static pk_extra_spec_t dummy_extra_spec; + + +/* This is the list of the default public-key ciphers included in + libgcrypt. FIPS_ALLOWED indicated whether the algorithm is used in + FIPS mode. */ +static struct pubkey_table_entry +{ + gcry_pk_spec_t *pubkey; + pk_extra_spec_t *extraspec; + unsigned int algorithm; + int fips_allowed; +} pubkey_table[] = + { +#if USE_RSA + { &_gcry_pubkey_spec_rsa, + &_gcry_pubkey_extraspec_rsa, GCRY_PK_RSA, 1}, +#endif +#if USE_ELGAMAL + { &_gcry_pubkey_spec_elg, + &_gcry_pubkey_extraspec_elg, GCRY_PK_ELG }, + { &_gcry_pubkey_spec_elg, + &_gcry_pubkey_extraspec_elg, GCRY_PK_ELG_E }, +#endif +#if USE_DSA + { &_gcry_pubkey_spec_dsa, + &_gcry_pubkey_extraspec_dsa, GCRY_PK_DSA, 1 }, +#endif +#if USE_ECC + { &_gcry_pubkey_spec_ecdsa, + &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDSA, 0 }, + { &_gcry_pubkey_spec_ecdh, + &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDH, 0 }, +#endif + { NULL, 0 }, + }; + +/* List of registered ciphers. */ +static gcry_module_t pubkeys_registered; + +/* This is the lock protecting PUBKEYS_REGISTERED. */ +static ath_mutex_t pubkeys_registered_lock = ATH_MUTEX_INITIALIZER;; + +/* Flag to check whether the default pubkeys have already been + registered. */ +static int default_pubkeys_registered; + +/* Convenient macro for registering the default digests. */ +#define REGISTER_DEFAULT_PUBKEYS \ + do \ + { \ + ath_mutex_lock (&pubkeys_registered_lock); \ + if (! default_pubkeys_registered) \ + { \ + pk_register_default (); \ + default_pubkeys_registered = 1; \ + } \ + ath_mutex_unlock (&pubkeys_registered_lock); \ + } \ + while (0) + +/* These dummy functions are used in case a cipher implementation + refuses to provide it's own functions. */ + +static gcry_err_code_t +dummy_generate (int algorithm, unsigned int nbits, unsigned long dummy, + gcry_mpi_t *skey, gcry_mpi_t **retfactors) +{ + (void)algorithm; + (void)nbits; + (void)dummy; + (void)skey; + (void)retfactors; + fips_signal_error ("using dummy public key function"); + return GPG_ERR_NOT_IMPLEMENTED; +} + +static gcry_err_code_t +dummy_check_secret_key (int algorithm, gcry_mpi_t *skey) +{ + (void)algorithm; + (void)skey; + fips_signal_error ("using dummy public key function"); + return GPG_ERR_NOT_IMPLEMENTED; +} + +static gcry_err_code_t +dummy_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, + gcry_mpi_t *pkey, int flags) +{ + (void)algorithm; + (void)resarr; + (void)data; + (void)pkey; + (void)flags; + fips_signal_error ("using dummy public key function"); + return GPG_ERR_NOT_IMPLEMENTED; +} + +static gcry_err_code_t +dummy_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, + gcry_mpi_t *skey, int flags) +{ + (void)algorithm; + (void)result; + (void)data; + (void)skey; + (void)flags; + fips_signal_error ("using dummy public key function"); + return GPG_ERR_NOT_IMPLEMENTED; +} + +static gcry_err_code_t +dummy_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, + gcry_mpi_t *skey) +{ + (void)algorithm; + (void)resarr; + (void)data; + (void)skey; + fips_signal_error ("using dummy public key function"); + return GPG_ERR_NOT_IMPLEMENTED; +} + +static gcry_err_code_t +dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, + gcry_mpi_t *pkey, + int (*cmp) (void *, gcry_mpi_t), void *opaquev) +{ + (void)algorithm; + (void)hash; + (void)data; + (void)pkey; + (void)cmp; + (void)opaquev; + fips_signal_error ("using dummy public key function"); + return GPG_ERR_NOT_IMPLEMENTED; +} + +static unsigned +dummy_get_nbits (int algorithm, gcry_mpi_t *pkey) +{ + (void)algorithm; + (void)pkey; + fips_signal_error ("using dummy public key function"); + return 0; +} + +/* Internal function. Register all the pubkeys included in + PUBKEY_TABLE. Returns zero on success or an error code. */ +static void +pk_register_default (void) +{ + gcry_err_code_t err = 0; + int i; + + for (i = 0; (! err) && pubkey_table[i].pubkey; i++) + { +#define pubkey_use_dummy(func) \ + if (! pubkey_table[i].pubkey->func) \ + pubkey_table[i].pubkey->func = dummy_##func; + + pubkey_use_dummy (generate); + pubkey_use_dummy (check_secret_key); + pubkey_use_dummy (encrypt); + pubkey_use_dummy (decrypt); + pubkey_use_dummy (sign); + pubkey_use_dummy (verify); + pubkey_use_dummy (get_nbits); +#undef pubkey_use_dummy + + err = _gcry_module_add (&pubkeys_registered, + pubkey_table[i].algorithm, + (void *) pubkey_table[i].pubkey, + (void *) pubkey_table[i].extraspec, + NULL); + } + + if (err) + BUG (); +} + +/* Internal callback function. Used via _gcry_module_lookup. */ +static int +gcry_pk_lookup_func_name (void *spec, void *data) +{ + gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) spec; + char *name = (char *) data; + const char **aliases = pubkey->aliases; + int ret = stricmp (name, pubkey->name); + + while (ret && *aliases) + ret = stricmp (name, *aliases++); + + return ! ret; +} + +/* Internal function. Lookup a pubkey entry by it's name. */ +static gcry_module_t +gcry_pk_lookup_name (const char *name) +{ + gcry_module_t pubkey; + + pubkey = _gcry_module_lookup (pubkeys_registered, (void *) name, + gcry_pk_lookup_func_name); + + return pubkey; +} + +/* Register a new pubkey module whose specification can be found in + PUBKEY. On success, a new algorithm ID is stored in ALGORITHM_ID + and a pointer representhing this module is stored in MODULE. */ +gcry_error_t +_gcry_pk_register (gcry_pk_spec_t *pubkey, + pk_extra_spec_t *extraspec, + unsigned int *algorithm_id, + gcry_module_t *module) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_module_t mod; + + /* We do not support module loading in fips mode. */ + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + ath_mutex_lock (&pubkeys_registered_lock); + err = _gcry_module_add (&pubkeys_registered, 0, + (void *) pubkey, + (void *)(extraspec? extraspec : &dummy_extra_spec), + &mod); + ath_mutex_unlock (&pubkeys_registered_lock); + + if (! err) + { + *module = mod; + *algorithm_id = mod->mod_id; + } + + return err; +} + +/* Unregister the pubkey identified by ID, which must have been + registered with gcry_pk_register. */ +void +gcry_pk_unregister (gcry_module_t module) +{ + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); +} + +static void +release_mpi_array (gcry_mpi_t *array) +{ + for (; *array; array++) + { + mpi_free(*array); + *array = NULL; + } +} + +/**************** + * Map a string to the pubkey algo + */ +int +gcry_pk_map_name (const char *string) +{ + gcry_module_t pubkey; + int algorithm = 0; + + if (!string) + return 0; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + pubkey = gcry_pk_lookup_name (string); + if (pubkey) + { + algorithm = pubkey->mod_id; + _gcry_module_release (pubkey); + } + ath_mutex_unlock (&pubkeys_registered_lock); + + return algorithm; +} + + +/* Map the public key algorithm whose ID is contained in ALGORITHM to + a string representation of the algorithm name. For unknown + algorithm IDs this functions returns "?". */ +const char * +gcry_pk_algo_name (int algorithm) +{ + gcry_module_t pubkey; + const char *name; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (pubkey) + { + name = ((gcry_pk_spec_t *) pubkey->spec)->name; + _gcry_module_release (pubkey); + } + else + name = "?"; + ath_mutex_unlock (&pubkeys_registered_lock); + + return name; +} + + +/* A special version of gcry_pk_algo name to return the first aliased + name of the algorithm. This is required to adhere to the spki + specs where the algorithm names are lowercase. */ +const char * +_gcry_pk_aliased_algo_name (int algorithm) +{ + const char *name = NULL; + gcry_module_t module; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + module = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (module) + { + gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) module->spec; + + name = pubkey->aliases? *pubkey->aliases : NULL; + if (!name || !*name) + name = pubkey->name; + _gcry_module_release (module); + } + ath_mutex_unlock (&pubkeys_registered_lock); + + return name; +} + + +static void +disable_pubkey_algo (int algorithm) +{ + gcry_module_t pubkey; + + ath_mutex_lock (&pubkeys_registered_lock); + pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (pubkey) + { + if (! (pubkey-> flags & FLAG_MODULE_DISABLED)) + pubkey->flags |= FLAG_MODULE_DISABLED; + _gcry_module_release (pubkey); + } + ath_mutex_unlock (&pubkeys_registered_lock); +} + + +/**************** + * A USE of 0 means: don't care. + */ +static gcry_err_code_t +check_pubkey_algo (int algorithm, unsigned use) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_pk_spec_t *pubkey; + gcry_module_t module; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + module = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (module) + { + pubkey = (gcry_pk_spec_t *) module->spec; + + if (((use & GCRY_PK_USAGE_SIGN) + && (! (pubkey->use & GCRY_PK_USAGE_SIGN))) + || ((use & GCRY_PK_USAGE_ENCR) + && (! (pubkey->use & GCRY_PK_USAGE_ENCR)))) + err = GPG_ERR_WRONG_PUBKEY_ALGO; + else if (module->flags & FLAG_MODULE_DISABLED) + err = GPG_ERR_PUBKEY_ALGO; + _gcry_module_release (module); + } + else + err = GPG_ERR_PUBKEY_ALGO; + ath_mutex_unlock (&pubkeys_registered_lock); + + return err; +} + + +/**************** + * Return the number of public key material numbers + */ +static int +pubkey_get_npkey (int algorithm) +{ + gcry_module_t pubkey; + int npkey = 0; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (pubkey) + { + npkey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_pkey); + _gcry_module_release (pubkey); + } + ath_mutex_unlock (&pubkeys_registered_lock); + + return npkey; +} + +/**************** + * Return the number of secret key material numbers + */ +static int +pubkey_get_nskey (int algorithm) +{ + gcry_module_t pubkey; + int nskey = 0; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (pubkey) + { + nskey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_skey); + _gcry_module_release (pubkey); + } + ath_mutex_unlock (&pubkeys_registered_lock); + + return nskey; +} + +/**************** + * Return the number of signature material numbers + */ +static int +pubkey_get_nsig (int algorithm) +{ + gcry_module_t pubkey; + int nsig = 0; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (pubkey) + { + nsig = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_sig); + _gcry_module_release (pubkey); + } + ath_mutex_unlock (&pubkeys_registered_lock); + + return nsig; +} + +/**************** + * Return the number of encryption material numbers + */ +static int +pubkey_get_nenc (int algorithm) +{ + gcry_module_t pubkey; + int nenc = 0; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (pubkey) + { + nenc = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_enc); + _gcry_module_release (pubkey); + } + ath_mutex_unlock (&pubkeys_registered_lock); + + return nenc; +} + + +/* Generate a new public key with algorithm ALGORITHM of size NBITS + and return it at SKEY. USE_E depends on the ALGORITHM. GENPARMS + is passed to the algorithm module if it features an extended + generation function. RETFACTOR is used by some algorithms to + return certain additional information which are in general not + required. + + The function returns the error code number or 0 on success. */ +static gcry_err_code_t +pubkey_generate (int algorithm, + unsigned int nbits, + unsigned long use_e, + gcry_sexp_t genparms, + gcry_mpi_t *skey, gcry_mpi_t **retfactors, + gcry_sexp_t *r_extrainfo) +{ + gcry_err_code_t ec = GPG_ERR_PUBKEY_ALGO; + gcry_module_t pubkey; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (pubkey) + { + pk_extra_spec_t *extraspec = pubkey->extraspec; + + if (extraspec && extraspec->ext_generate) + { + /* Use the extended generate function. */ + ec = extraspec->ext_generate + (algorithm, nbits, use_e, genparms, skey, retfactors, r_extrainfo); + } + else + { + /* Use the standard generate function. */ + ec = ((gcry_pk_spec_t *) pubkey->spec)->generate + (algorithm, nbits, use_e, skey, retfactors); + } + _gcry_module_release (pubkey); + } + ath_mutex_unlock (&pubkeys_registered_lock); + + return ec; +} + + +static gcry_err_code_t +pubkey_check_secret_key (int algorithm, gcry_mpi_t *skey) +{ + gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO; + gcry_module_t pubkey; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (pubkey) + { + err = ((gcry_pk_spec_t *) pubkey->spec)->check_secret_key + (algorithm, skey); + _gcry_module_release (pubkey); + } + ath_mutex_unlock (&pubkeys_registered_lock); + + return err; +} + + +/**************** + * This is the interface to the public key encryption. Encrypt DATA + * with PKEY and put it into RESARR which should be an array of MPIs + * of size PUBKEY_MAX_NENC (or less if the algorithm allows this - + * check with pubkey_get_nenc() ) + */ +static gcry_err_code_t +pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, + gcry_mpi_t *pkey, int flags) +{ + gcry_pk_spec_t *pubkey; + gcry_module_t module; + gcry_err_code_t rc; + int i; + + /* Note: In fips mode DBG_CIPHER will enver evaluate to true but as + an extra failsafe protection we explicitly test for fips mode + here. */ + if (DBG_CIPHER && !fips_mode ()) + { + log_debug ("pubkey_encrypt: algo=%d\n", algorithm); + for(i = 0; i < pubkey_get_npkey (algorithm); i++) + log_mpidump (" pkey:", pkey[i]); + log_mpidump (" data:", data); + } + + ath_mutex_lock (&pubkeys_registered_lock); + module = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (module) + { + pubkey = (gcry_pk_spec_t *) module->spec; + rc = pubkey->encrypt (algorithm, resarr, data, pkey, flags); + _gcry_module_release (module); + goto ready; + } + rc = GPG_ERR_PUBKEY_ALGO; + + ready: + ath_mutex_unlock (&pubkeys_registered_lock); + + if (!rc && DBG_CIPHER && !fips_mode ()) + { + for(i = 0; i < pubkey_get_nenc (algorithm); i++) + log_mpidump(" encr:", resarr[i] ); + } + return rc; +} + + +/**************** + * This is the interface to the public key decryption. + * ALGO gives the algorithm to use and this implicitly determines + * the size of the arrays. + * result is a pointer to a mpi variable which will receive a + * newly allocated mpi or NULL in case of an error. + */ +static gcry_err_code_t +pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, + gcry_mpi_t *skey, int flags) +{ + gcry_pk_spec_t *pubkey; + gcry_module_t module; + gcry_err_code_t rc; + int i; + + *result = NULL; /* so the caller can always do a mpi_free */ + if (DBG_CIPHER && !fips_mode ()) + { + log_debug ("pubkey_decrypt: algo=%d\n", algorithm); + for(i = 0; i < pubkey_get_nskey (algorithm); i++) + log_mpidump (" skey:", skey[i]); + for(i = 0; i < pubkey_get_nenc (algorithm); i++) + log_mpidump (" data:", data[i]); + } + + ath_mutex_lock (&pubkeys_registered_lock); + module = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (module) + { + pubkey = (gcry_pk_spec_t *) module->spec; + rc = pubkey->decrypt (algorithm, result, data, skey, flags); + _gcry_module_release (module); + goto ready; + } + + rc = GPG_ERR_PUBKEY_ALGO; + + ready: + ath_mutex_unlock (&pubkeys_registered_lock); + + if (!rc && DBG_CIPHER && !fips_mode ()) + log_mpidump (" plain:", *result); + + return rc; +} + + +/**************** + * This is the interface to the public key signing. + * Sign data with skey and put the result into resarr which + * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the + * algorithm allows this - check with pubkey_get_nsig() ) + */ +static gcry_err_code_t +pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, + gcry_mpi_t *skey) +{ + gcry_pk_spec_t *pubkey; + gcry_module_t module; + gcry_err_code_t rc; + int i; + + if (DBG_CIPHER && !fips_mode ()) + { + log_debug ("pubkey_sign: algo=%d\n", algorithm); + for(i = 0; i < pubkey_get_nskey (algorithm); i++) + log_mpidump (" skey:", skey[i]); + log_mpidump(" data:", data ); + } + + ath_mutex_lock (&pubkeys_registered_lock); + module = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (module) + { + pubkey = (gcry_pk_spec_t *) module->spec; + rc = pubkey->sign (algorithm, resarr, data, skey); + _gcry_module_release (module); + goto ready; + } + + rc = GPG_ERR_PUBKEY_ALGO; + + ready: + ath_mutex_unlock (&pubkeys_registered_lock); + + if (!rc && DBG_CIPHER && !fips_mode ()) + for (i = 0; i < pubkey_get_nsig (algorithm); i++) + log_mpidump (" sig:", resarr[i]); + + return rc; +} + +/**************** + * Verify a public key signature. + * Return 0 if the signature is good + */ +static gcry_err_code_t +pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, + gcry_mpi_t *pkey, + int (*cmp)(void *, gcry_mpi_t), void *opaquev) +{ + gcry_pk_spec_t *pubkey; + gcry_module_t module; + gcry_err_code_t rc; + int i; + + if (DBG_CIPHER && !fips_mode ()) + { + log_debug ("pubkey_verify: algo=%d\n", algorithm); + for (i = 0; i < pubkey_get_npkey (algorithm); i++) + log_mpidump (" pkey", pkey[i]); + for (i = 0; i < pubkey_get_nsig (algorithm); i++) + log_mpidump (" sig", data[i]); + log_mpidump (" hash", hash); + } + + ath_mutex_lock (&pubkeys_registered_lock); + module = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (module) + { + pubkey = (gcry_pk_spec_t *) module->spec; + rc = pubkey->verify (algorithm, hash, data, pkey, cmp, opaquev); + _gcry_module_release (module); + goto ready; + } + + rc = GPG_ERR_PUBKEY_ALGO; + + ready: + ath_mutex_unlock (&pubkeys_registered_lock); + return rc; +} + + +/* Turn VALUE into an octet string and store it in an allocated buffer + at R_FRAME or - if R_RAME is NULL - copy it into the caller + provided buffer SPACE; either SPACE or R_FRAME may be used. If + SPACE if not NULL, the caller must provide a buffer of at least + NBYTES. If the resulting octet string is shorter than NBYTES pad + it to the left with zeroes. If VALUE does not fit into NBYTES + return an error code. */ +static gpg_err_code_t +octet_string_from_mpi (unsigned char **r_frame, void *space, + gcry_mpi_t value, size_t nbytes) +{ + gpg_err_code_t rc; + size_t nframe, noff, n; + unsigned char *frame; + + if (!r_frame == !space) + return GPG_ERR_INV_ARG; /* Only one may be used. */ + + if (r_frame) + *r_frame = NULL; + + rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG, + NULL, 0, &nframe, value)); + if (rc) + return rc; + if (nframe > nbytes) + return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES. */ + + noff = (nframe < nbytes)? nbytes - nframe : 0; + n = nframe + noff; + if (space) + frame = space; + else + { + frame = mpi_is_secure (value)? gcry_malloc_secure (n) : gcry_malloc (n); + if (!frame) + { + rc = gpg_err_code_from_syserror (); + return rc; + } + } + if (noff) + memset (frame, 0, noff); + nframe += noff; + rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG, + frame+noff, nframe-noff, NULL, value)); + if (rc) + { + gcry_free (frame); + return rc; + } + + if (r_frame) + *r_frame = frame; + return 0; +} + + +/* Encode {VALUE,VALUELEN} for an NBITS keys using the pkcs#1 block + type 2 padding. On sucess the result is stored as a new MPI at + R_RESULT. On error the value at R_RESULT is undefined. + + If {RANDOM_OVERRIDE, RANDOM_OVERRIDE_LEN} is given it is used as + the seed instead of using a random string for it. This feature is + only useful for regression tests. Note that this value may not + contain zero bytes. + + We encode the value in this way: + + 0 2 RND(n bytes) 0 VALUE + + 0 is a marker we unfortunately can't encode because we return an + MPI which strips all leading zeroes. + 2 is the block type. + RND are non-zero random bytes. + + (Note that OpenPGP includes the cipher algorithm and a checksum in + VALUE; the caller needs to prepare the value accordingly.) + */ +static gcry_err_code_t +pkcs1_encode_for_encryption (gcry_mpi_t *r_result, unsigned int nbits, + const unsigned char *value, size_t valuelen, + const unsigned char *random_override, + size_t random_override_len) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + unsigned char *frame = NULL; + size_t nframe = (nbits+7) / 8; + int i; + size_t n; + unsigned char *p; + + if (valuelen + 7 > nframe || !nframe) + { + /* Can't encode a VALUELEN value in a NFRAME bytes frame. */ + return GPG_ERR_TOO_SHORT; /* The key is too short. */ + } + + if ( !(frame = gcry_malloc_secure (nframe))) + return gpg_err_code_from_syserror (); + + n = 0; + frame[n++] = 0; + frame[n++] = 2; /* block type */ + i = nframe - 3 - valuelen; + gcry_assert (i > 0); + + if (random_override) + { + int j; + + if (random_override_len != i) + { + gcry_free (frame); + return GPG_ERR_INV_ARG; + } + /* Check that random does not include a zero byte. */ + for (j=0; j < random_override_len; j++) + if (!random_override[j]) + { + gcry_free (frame); + return GPG_ERR_INV_ARG; + } + memcpy (frame + n, random_override, random_override_len); + n += random_override_len; + } + else + { + p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); + /* Replace zero bytes by new values. */ + for (;;) + { + int j, k; + unsigned char *pp; + + /* Count the zero bytes. */ + for (j=k=0; j < i; j++) + { + if (!p[j]) + k++; + } + if (!k) + break; /* Okay: no (more) zero bytes. */ + + k += k/128 + 3; /* Better get some more. */ + pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); + for (j=0; j < i && k; ) + { + if (!p[j]) + p[j] = pp[--k]; + if (p[j]) + j++; + } + gcry_free (pp); + } + memcpy (frame+n, p, i); + n += i; + gcry_free (p); + } + + frame[n++] = 0; + memcpy (frame+n, value, valuelen); + n += valuelen; + gcry_assert (n == nframe); + + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, n, &nframe); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("PKCS#1 block type 2 encoded data", *r_result); + gcry_free (frame); + + return rc; +} + + +/* Decode a plaintext in VALUE assuming pkcs#1 block type 2 padding. + NBITS is the size of the secret key. On success the result is + stored as a newly allocated buffer at R_RESULT and its valid length at + R_RESULTLEN. On error NULL is stored at R_RESULT. */ +static gcry_err_code_t +pkcs1_decode_for_encryption (unsigned char **r_result, size_t *r_resultlen, + unsigned int nbits, gcry_mpi_t value) +{ + gcry_error_t err; + unsigned char *frame = NULL; + size_t nframe = (nbits+7) / 8; + size_t n; + + *r_result = NULL; + + if ( !(frame = gcry_malloc_secure (nframe))) + return gpg_err_code_from_syserror (); + + err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &n, value); + if (err) + { + gcry_free (frame); + return gcry_err_code (err); + } + + nframe = n; /* Set NFRAME to the actual length. */ + + /* FRAME = 0x00 || 0x02 || PS || 0x00 || M + + pkcs#1 requires that the first byte is zero. Our MPIs usually + strip leading zero bytes; thus we are not able to detect them. + However due to the way gcry_mpi_print is implemented we may see + leading zero bytes nevertheless. We handle this by making the + first zero byte optional. */ + if (nframe < 4) + { + gcry_free (frame); + return GPG_ERR_ENCODING_PROBLEM; /* Too short. */ + } + n = 0; + if (!frame[0]) + n++; + if (frame[n++] != 0x02) + { + gcry_free (frame); + return GPG_ERR_ENCODING_PROBLEM; /* Wrong block type. */ + } + + /* Skip the non-zero random bytes and the terminating zero byte. */ + for (; n < nframe && frame[n] != 0x00; n++) + ; + if (n+1 >= nframe) + { + gcry_free (frame); + return GPG_ERR_ENCODING_PROBLEM; /* No zero byte. */ + } + n++; /* Skip the zero byte. */ + + /* To avoid an extra allocation we reuse the frame buffer. The only + caller of this function will anyway free the result soon. */ + memmove (frame, frame + n, nframe - n); + *r_result = frame; + *r_resultlen = nframe - n; + + if (DBG_CIPHER) + log_printhex ("value extracted from PKCS#1 block type 2 encoded data:", + *r_result, *r_resultlen); + + return 0; +} + + +/* Encode {VALUE,VALUELEN} for an NBITS keys and hash algorith ALGO + using the pkcs#1 block type 1 padding. On success the result is + stored as a new MPI at R_RESULT. On error the value at R_RESULT is + undefined. + + We encode the value in this way: + + 0 1 PAD(n bytes) 0 ASN(asnlen bytes) VALUE(valuelen bytes) + + 0 is a marker we unfortunately can't encode because we return an + MPI which strips all leading zeroes. + 1 is the block type. + PAD consists of 0xff bytes. + 0 marks the end of the padding. + ASN is the DER encoding of the hash algorithm; along with the VALUE + it yields a valid DER encoding. + + (Note that PGP prior to version 2.3 encoded the message digest as: + 0 1 MD(16 bytes) 0 PAD(n bytes) 1 + The MD is always 16 bytes here because it's always MD5. GnuPG + does not not support pre-v2.3 signatures, but I'm including this + comment so the information is easily found if needed.) +*/ +static gcry_err_code_t +pkcs1_encode_for_signature (gcry_mpi_t *r_result, unsigned int nbits, + const unsigned char *value, size_t valuelen, + int algo) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + byte asn[100]; + byte *frame = NULL; + size_t nframe = (nbits+7) / 8; + int i; + size_t n; + size_t asnlen, dlen; + + asnlen = DIM(asn); + dlen = gcry_md_get_algo_dlen (algo); + + if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) + { + /* We don't have yet all of the above algorithms. */ + return GPG_ERR_NOT_IMPLEMENTED; + } + + if ( valuelen != dlen ) + { + /* Hash value does not match the length of digest for + the given algorithm. */ + return GPG_ERR_CONFLICT; + } + + if ( !dlen || dlen + asnlen + 4 > nframe) + { + /* Can't encode an DLEN byte digest MD into an NFRAME byte + frame. */ + return GPG_ERR_TOO_SHORT; + } + + if ( !(frame = gcry_malloc (nframe)) ) + return gpg_err_code_from_syserror (); + + /* Assemble the pkcs#1 block type 1. */ + n = 0; + frame[n++] = 0; + frame[n++] = 1; /* block type */ + i = nframe - valuelen - asnlen - 3 ; + gcry_assert (i > 1); + memset (frame+n, 0xff, i ); + n += i; + frame[n++] = 0; + memcpy (frame+n, asn, asnlen); + n += asnlen; + memcpy (frame+n, value, valuelen ); + n += valuelen; + gcry_assert (n == nframe); + + /* Convert it into an MPI. */ + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, n, &nframe); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("PKCS#1 block type 1 encoded data", *r_result); + gcry_free (frame); + + return rc; +} + + +/* Mask generation function for OAEP. See RFC-3447 B.2.1. */ +static gcry_err_code_t +mgf1 (unsigned char *output, size_t outlen, unsigned char *seed, size_t seedlen, + int algo) +{ + size_t dlen, nbytes, n; + int idx; + gcry_md_hd_t hd; + gcry_error_t err; + + err = gcry_md_open (&hd, algo, 0); + if (err) + return gpg_err_code (err); + + dlen = gcry_md_get_algo_dlen (algo); + + /* We skip step 1 which would be assert(OUTLEN <= 2^32). The loop + in step 3 is merged with step 4 by concatenating no more octets + than what would fit into OUTPUT. The ceiling for the counter IDX + is implemented indirectly. */ + nbytes = 0; /* Step 2. */ + idx = 0; + while ( nbytes < outlen ) + { + unsigned char c[4], *digest; + + if (idx) + gcry_md_reset (hd); + + c[0] = (idx >> 24) & 0xFF; + c[1] = (idx >> 16) & 0xFF; + c[2] = (idx >> 8) & 0xFF; + c[3] = idx & 0xFF; + idx++; + + gcry_md_write (hd, seed, seedlen); + gcry_md_write (hd, c, 4); + digest = gcry_md_read (hd, 0); + + n = (outlen - nbytes < dlen)? (outlen - nbytes) : dlen; + memcpy (output+nbytes, digest, n); + nbytes += n; + } + + gcry_md_close (hd); + return GPG_ERR_NO_ERROR; +} + + +/* RFC-3447 (pkcs#1 v2.1) OAEP encoding. NBITS is the length of the + key measured in bits. ALGO is the hash function; it must be a + valid and usable algorithm. {VALUE,VALUELEN} is the message to + encrypt. {LABEL,LABELLEN} is the optional label to be associated + with the message, if LABEL is NULL the default is to use the empty + string as label. On success the encoded ciphertext is returned at + R_RESULT. + + If {RANDOM_OVERRIDE, RANDOM_OVERRIDE_LEN} is given it is used as + the seed instead of using a random string for it. This feature is + only useful for regression tests. + + Here is figure 1 from the RFC depicting the process: + + +----------+---------+-------+ + DB = | lHash | PS | M | + +----------+---------+-------+ + | + +----------+ V + | seed |--> MGF ---> xor + +----------+ | + | | + +--+ V | + |00| xor <----- MGF <-----| + +--+ | | + | | | + V V V + +--+----------+----------------------------+ + EM = |00|maskedSeed| maskedDB | + +--+----------+----------------------------+ + */ +static gcry_err_code_t +oaep_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo, + const unsigned char *value, size_t valuelen, + const unsigned char *label, size_t labellen, + const void *random_override, size_t random_override_len) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + unsigned char *frame = NULL; + size_t nframe = (nbits+7) / 8; + unsigned char *p; + size_t hlen; + size_t n; + + *r_result = NULL; + + /* Set defaults for LABEL. */ + if (!label || !labellen) + { + label = (const unsigned char*)""; + labellen = 0; + } + + hlen = gcry_md_get_algo_dlen (algo); + + /* We skip step 1a which would be to check that LABELLEN is not + greater than 2^61-1. See rfc-3447 7.1.1. */ + + /* Step 1b. Note that the obsolete rfc-2437 uses the check: + valuelen > nframe - 2 * hlen - 1 . */ + if (valuelen > nframe - 2 * hlen - 2 || !nframe) + { + /* Can't encode a VALUELEN value in a NFRAME bytes frame. */ + return GPG_ERR_TOO_SHORT; /* The key is too short. */ + } + + /* Allocate the frame. */ + frame = gcry_calloc_secure (1, nframe); + if (!frame) + return gpg_err_code_from_syserror (); + + /* Step 2a: Compute the hash of the label. We store it in the frame + where later the maskedDB will commence. */ + gcry_md_hash_buffer (algo, frame + 1 + hlen, label, labellen); + + /* Step 2b: Set octet string to zero. */ + /* This has already been done while allocating FRAME. */ + + /* Step 2c: Create DB by concatenating lHash, PS, 0x01 and M. */ + n = nframe - valuelen - 1; + frame[n] = 0x01; + memcpy (frame + n + 1, value, valuelen); + + /* Step 3d: Generate seed. We store it where the maskedSeed will go + later. */ + if (random_override) + { + if (random_override_len != hlen) + { + gcry_free (frame); + return GPG_ERR_INV_ARG; + } + memcpy (frame + 1, random_override, hlen); + } + else + gcry_randomize (frame + 1, hlen, GCRY_STRONG_RANDOM); + + /* Step 2e and 2f: Create maskedDB. */ + { + unsigned char *dmask; + + dmask = gcry_malloc_secure (nframe - hlen - 1); + if (!dmask) + { + rc = gpg_err_code_from_syserror (); + gcry_free (frame); + return rc; + } + rc = mgf1 (dmask, nframe - hlen - 1, frame+1, hlen, algo); + if (rc) + { + gcry_free (dmask); + gcry_free (frame); + return rc; + } + for (n = 1 + hlen, p = dmask; n < nframe; n++) + frame[n] ^= *p++; + gcry_free (dmask); + } + + /* Step 2g and 2h: Create maskedSeed. */ + { + unsigned char *smask; + + smask = gcry_malloc_secure (hlen); + if (!smask) + { + rc = gpg_err_code_from_syserror (); + gcry_free (frame); + return rc; + } + rc = mgf1 (smask, hlen, frame + 1 + hlen, nframe - hlen - 1, algo); + if (rc) + { + gcry_free (smask); + gcry_free (frame); + return rc; + } + for (n = 1, p = smask; n < 1 + hlen; n++) + frame[n] ^= *p++; + gcry_free (smask); + } + + /* Step 2i: Concatenate 0x00, maskedSeed and maskedDB. */ + /* This has already been done by using in-place operations. */ + + /* Convert the stuff into an MPI as expected by the caller. */ + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, nframe, NULL); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("OAEP encoded data", *r_result); + gcry_free (frame); + + return rc; +} + + +/* RFC-3447 (pkcs#1 v2.1) OAEP decoding. NBITS is the length of the + key measured in bits. ALGO is the hash function; it must be a + valid and usable algorithm. VALUE is the raw decrypted message + {LABEL,LABELLEN} is the optional label to be associated with the + message, if LABEL is NULL the default is to use the empty string as + label. On success the plaintext is returned as a newly allocated + buffer at R_RESULT; its valid length is stored at R_RESULTLEN. On + error NULL is stored at R_RESULT. */ +static gcry_err_code_t +oaep_decode (unsigned char **r_result, size_t *r_resultlen, + unsigned int nbits, int algo, + gcry_mpi_t value, const unsigned char *label, size_t labellen) +{ + gcry_err_code_t rc; + unsigned char *frame = NULL; /* Encoded messages (EM). */ + unsigned char *masked_seed; /* Points into FRAME. */ + unsigned char *masked_db; /* Points into FRAME. */ + unsigned char *seed = NULL; /* Allocated space for the seed and DB. */ + unsigned char *db; /* Points into SEED. */ + unsigned char *lhash = NULL; /* Hash of the label. */ + size_t nframe; /* Length of the ciphertext (EM). */ + size_t hlen; /* Length of the hash digest. */ + size_t db_len; /* Length of DB and masked_db. */ + size_t nkey = (nbits+7)/8; /* Length of the key in bytes. */ + int failed = 0; /* Error indicator. */ + size_t n; + + *r_result = NULL; + + /* This code is implemented as described by rfc-3447 7.1.2. */ + + /* Set defaults for LABEL. */ + if (!label || !labellen) + { + label = (const unsigned char*)""; + labellen = 0; + } + + /* Get the length of the digest. */ + hlen = gcry_md_get_algo_dlen (algo); + + /* Hash the label right away. */ + lhash = gcry_malloc (hlen); + if (!lhash) + return gpg_err_code_from_syserror (); + gcry_md_hash_buffer (algo, lhash, label, labellen); + + /* Turn the MPI into an octet string. If the octet string is + shorter than the key we pad it to the left with zeroes. This may + happen due to the leading zero in OAEP frames and due to the + following random octets (seed^mask) which may have leading zero + bytes. This all is needed to cope with our leading zeroes + suppressing MPI implementation. The code implictly implements + Step 1b (bail out if NFRAME != N). */ + rc = octet_string_from_mpi (&frame, NULL, value, nkey); + if (rc) + { + gcry_free (lhash); + return GPG_ERR_ENCODING_PROBLEM; + } + nframe = nkey; + + /* Step 1c: Check that the key is long enough. */ + if ( nframe < 2 * hlen + 2 ) + { + gcry_free (frame); + gcry_free (lhash); + return GPG_ERR_ENCODING_PROBLEM; + } + + /* Step 2 has already been done by the caller and the + gcry_mpi_aprint above. */ + + /* Allocate space for SEED and DB. */ + seed = gcry_malloc_secure (nframe - 1); + if (!seed) + { + rc = gpg_err_code_from_syserror (); + gcry_free (frame); + gcry_free (lhash); + return rc; + } + db = seed + hlen; + + /* To avoid choosen ciphertext attacks from now on we make sure to + run all code even in the error case; this avoids possible timing + attacks as described by Manger. */ + + /* Step 3a: Hash the label. */ + /* This has already been done. */ + + /* Step 3b: Separate the encoded message. */ + masked_seed = frame + 1; + masked_db = frame + 1 + hlen; + db_len = nframe - 1 - hlen; + + /* Step 3c and 3d: seed = maskedSeed ^ mgf(maskedDB, hlen). */ + if (mgf1 (seed, hlen, masked_db, db_len, algo)) + failed = 1; + for (n = 0; n < hlen; n++) + seed[n] ^= masked_seed[n]; + + /* Step 3e and 3f: db = maskedDB ^ mgf(seed, db_len). */ + if (mgf1 (db, db_len, seed, hlen, algo)) + failed = 1; + for (n = 0; n < db_len; n++) + db[n] ^= masked_db[n]; + + /* Step 3g: Check lhash, an possible empty padding string terminated + by 0x01 and the first byte of EM being 0. */ + if (memcmp (lhash, db, hlen)) + failed = 1; + for (n = hlen; n < db_len; n++) + if (db[n] == 0x01) + break; + if (n == db_len) + failed = 1; + if (frame[0]) + failed = 1; + + gcry_free (lhash); + gcry_free (frame); + if (failed) + { + gcry_free (seed); + return GPG_ERR_ENCODING_PROBLEM; + } + + /* Step 4: Output M. */ + /* To avoid an extra allocation we reuse the seed buffer. The only + caller of this function will anyway free the result soon. */ + n++; + memmove (seed, db + n, db_len - n); + *r_result = seed; + *r_resultlen = db_len - n; + seed = NULL; + + if (DBG_CIPHER) + log_printhex ("value extracted from OAEP encoded data:", + *r_result, *r_resultlen); + + return 0; +} + + +/* RFC-3447 (pkcs#1 v2.1) PSS encoding. Encode {VALUE,VALUELEN} for + an NBITS key. Note that VALUE is already the mHash from the + picture below. ALGO is a valid hash algorithm and SALTLEN is the + length of salt to be used. On success the result is stored as a + new MPI at R_RESULT. On error the value at R_RESULT is undefined. + + If {RANDOM_OVERRIDE, RANDOM_OVERRIDE_LEN} is given it is used as + the salt instead of using a random string for the salt. This + feature is only useful for regression tests. + + Here is figure 2 from the RFC (errata 595 applied) depicting the + process: + + +-----------+ + | M | + +-----------+ + | + V + Hash + | + V + +--------+----------+----------+ + M' = |Padding1| mHash | salt | + +--------+----------+----------+ + | + +--------+----------+ V + DB = |Padding2| salt | Hash + +--------+----------+ | + | | + V | +----+ + xor <--- MGF <---| |0xbc| + | | +----+ + | | | + V V V + +-------------------+----------+----+ + EM = | maskedDB | H |0xbc| + +-------------------+----------+----+ + + */ +static gcry_err_code_t +pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo, + const unsigned char *value, size_t valuelen, int saltlen, + const void *random_override, size_t random_override_len) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + size_t hlen; /* Length of the hash digest. */ + unsigned char *em = NULL; /* Encoded message. */ + size_t emlen = (nbits+7)/8; /* Length in bytes of EM. */ + unsigned char *h; /* Points into EM. */ + unsigned char *buf = NULL; /* Help buffer. */ + size_t buflen; /* Length of BUF. */ + unsigned char *mhash; /* Points into BUF. */ + unsigned char *salt; /* Points into BUF. */ + unsigned char *dbmask; /* Points into BUF. */ + unsigned char *p; + size_t n; + + /* This code is implemented as described by rfc-3447 9.1.1. */ + + /* Get the length of the digest. */ + hlen = gcry_md_get_algo_dlen (algo); + gcry_assert (hlen); /* We expect a valid ALGO here. */ + + /* Allocate a help buffer and setup some pointers. */ + buflen = 8 + hlen + saltlen + (emlen - hlen - 1); + buf = gcry_malloc (buflen); + if (!buf) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + mhash = buf + 8; + salt = mhash + hlen; + dbmask= salt + saltlen; + + /* Step 2: That would be: mHash = Hash(M) but our input is already + mHash thus we do only a consistency check and copy to MHASH. */ + if (valuelen != hlen) + { + rc = GPG_ERR_INV_LENGTH; + goto leave; + } + memcpy (mhash, value, hlen); + + /* Step 3: Check length constraints. */ + if (emlen < hlen + saltlen + 2) + { + rc = GPG_ERR_TOO_SHORT; + goto leave; + } + + /* Allocate space for EM. */ + em = gcry_malloc (emlen); + if (!em) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + h = em + emlen - 1 - hlen; + + /* Step 4: Create a salt. */ + if (saltlen) + { + if (random_override) + { + if (random_override_len != saltlen) + { + rc = GPG_ERR_INV_ARG; + goto leave; + } + memcpy (salt, random_override, saltlen); + } + else + gcry_randomize (salt, saltlen, GCRY_STRONG_RANDOM); + } + + /* Step 5 and 6: M' = Hash(Padding1 || mHash || salt). */ + memset (buf, 0, 8); /* Padding. */ + gcry_md_hash_buffer (algo, h, buf, 8 + hlen + saltlen); + + /* Step 7 and 8: DB = PS || 0x01 || salt. */ + /* Note that we use EM to store DB and later Xor in-place. */ + p = em + emlen - 1 - hlen - saltlen - 1; + memset (em, 0, p - em); + *p++ = 0x01; + memcpy (p, salt, saltlen); + + /* Step 9: dbmask = MGF(H, emlen - hlen - 1). */ + mgf1 (dbmask, emlen - hlen - 1, h, hlen, algo); + + /* Step 10: maskedDB = DB ^ dbMask */ + for (n = 0, p = dbmask; n < emlen - hlen - 1; n++, p++) + em[n] ^= *p; + + /* Step 11: Set the leftmost bits to zero. */ + em[0] &= 0xFF >> (8 * emlen - nbits); + + /* Step 12: EM = maskedDB || H || 0xbc. */ + em[emlen-1] = 0xbc; + + /* Convert EM into an MPI. */ + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, em, emlen, NULL); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("PSS encoded data", *r_result); + + leave: + if (em) + { + wipememory (em, emlen); + gcry_free (em); + } + if (buf) + { + wipememory (buf, buflen); + gcry_free (buf); + } + return rc; +} + + +/* Verify a signature assuming PSS padding. VALUE is the hash of the + message (mHash) encoded as an MPI; its length must match the digest + length of ALGO. ENCODED is the output of the RSA public key + function (EM). NBITS is the size of the public key. ALGO is the + hash algorithm and SALTLEN is the length of the used salt. The + function returns 0 on success or on error code. */ +static gcry_err_code_t +pss_verify (gcry_mpi_t value, gcry_mpi_t encoded, unsigned int nbits, int algo, + size_t saltlen) +{ + gcry_err_code_t rc = 0; + size_t hlen; /* Length of the hash digest. */ + unsigned char *em = NULL; /* Encoded message. */ + size_t emlen = (nbits+7)/8; /* Length in bytes of EM. */ + unsigned char *salt; /* Points into EM. */ + unsigned char *h; /* Points into EM. */ + unsigned char *buf = NULL; /* Help buffer. */ + size_t buflen; /* Length of BUF. */ + unsigned char *dbmask; /* Points into BUF. */ + unsigned char *mhash; /* Points into BUF. */ + unsigned char *p; + size_t n; + + /* This code is implemented as described by rfc-3447 9.1.2. */ + + /* Get the length of the digest. */ + hlen = gcry_md_get_algo_dlen (algo); + gcry_assert (hlen); /* We expect a valid ALGO here. */ + + /* Allocate a help buffer and setup some pointers. + This buffer is used for two purposes: + +------------------------------+-------+ + 1. | dbmask | mHash | + +------------------------------+-------+ + emlen - hlen - 1 hlen + + +----------+-------+---------+-+-------+ + 2. | padding1 | mHash | salt | | mHash | + +----------+-------+---------+-+-------+ + 8 hlen saltlen hlen + */ + buflen = 8 + hlen + saltlen; + if (buflen < emlen - hlen - 1) + buflen = emlen - hlen - 1; + buflen += hlen; + buf = gcry_malloc (buflen); + if (!buf) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + dbmask = buf; + mhash = buf + buflen - hlen; + + /* Step 2: That would be: mHash = Hash(M) but our input is already + mHash thus we only need to convert VALUE into MHASH. */ + rc = octet_string_from_mpi (NULL, mhash, value, hlen); + if (rc) + goto leave; + + /* Convert the signature into an octet string. */ + rc = octet_string_from_mpi (&em, NULL, encoded, emlen); + if (rc) + goto leave; + + /* Step 3: Check length of EM. Because we internally use MPI + functions we can't do this properly; EMLEN is always the length + of the key because octet_string_from_mpi needs to left pad the + result with zero to cope with the fact that our MPIs suppress all + leading zeroes. Thus what we test here are merely the digest and + salt lengths to the key. */ + if (emlen < hlen + saltlen + 2) + { + rc = GPG_ERR_TOO_SHORT; /* For the hash and saltlen. */ + goto leave; + } + + /* Step 4: Check last octet. */ + if (em[emlen - 1] != 0xbc) + { + rc = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + + /* Step 5: Split EM. */ + h = em + emlen - 1 - hlen; + + /* Step 6: Check the leftmost bits. */ + if ((em[0] & ~(0xFF >> (8 * emlen - nbits)))) + { + rc = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + + /* Step 7: dbmask = MGF(H, emlen - hlen - 1). */ + mgf1 (dbmask, emlen - hlen - 1, h, hlen, algo); + + /* Step 8: maskedDB = DB ^ dbMask. */ + for (n = 0, p = dbmask; n < emlen - hlen - 1; n++, p++) + em[n] ^= *p; + + /* Step 9: Set leftmost bits in DB to zero. */ + em[0] &= 0xFF >> (8 * emlen - nbits); + + /* Step 10: Check the padding of DB. */ + for (n = 0; n < emlen - hlen - saltlen - 2 && !em[n]; n++) + ; + if (n != emlen - hlen - saltlen - 2 || em[n++] != 1) + { + rc = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + + /* Step 11: Extract salt from DB. */ + salt = em + n; + + /* Step 12: M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt */ + memset (buf, 0, 8); + memcpy (buf+8, mhash, hlen); + memcpy (buf+8+hlen, salt, saltlen); + + /* Step 13: H' = Hash(M'). */ + gcry_md_hash_buffer (algo, buf, buf, 8 + hlen + saltlen); + + /* Step 14: Check H == H'. */ + rc = memcmp (h, buf, hlen) ? GPG_ERR_BAD_SIGNATURE : GPG_ERR_NO_ERROR; + + leave: + if (em) + { + wipememory (em, emlen); + gcry_free (em); + } + if (buf) + { + wipememory (buf, buflen); + gcry_free (buf); + } + return rc; +} + + +/* Callback for the pubkey algorithm code to verify PSS signatures. + OPAQUE is the data provided by the actual caller. The meaning of + TMP depends on the actual algorithm (but there is only RSA); now + for RSA it is the output of running the public key function on the + input. */ +static int +pss_verify_cmp (void *opaque, gcry_mpi_t tmp) +{ + struct pk_encoding_ctx *ctx = opaque; + gcry_mpi_t hash = ctx->verify_arg; + + return pss_verify (hash, tmp, ctx->nbits - 1, ctx->hash_algo, ctx->saltlen); +} + + +/* Internal function. */ +static gcry_err_code_t +sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names, + gcry_mpi_t *elements, const char *algo_name) +{ + gcry_err_code_t err = 0; + int i, idx; + const char *name; + gcry_sexp_t list; + + for (name = element_names, idx = 0; *name && !err; name++, idx++) + { + list = gcry_sexp_find_token (key_sexp, name, 1); + if (!list) + elements[idx] = NULL; + else + { + elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (list); + if (!elements[idx]) + err = GPG_ERR_INV_OBJ; + } + } + + if (!err) + { + /* Check that all elements are available. */ + for (name = element_names, idx = 0; *name; name++, idx++) + if (!elements[idx]) + break; + if (*name) + { + err = GPG_ERR_NO_OBJ; + /* Some are missing. Before bailing out we test for + optional parameters. */ + if (algo_name && !strcmp (algo_name, "RSA") + && !strcmp (element_names, "nedpqu") ) + { + /* This is RSA. Test whether we got N, E and D and that + the optional P, Q and U are all missing. */ + if (elements[0] && elements[1] && elements[2] + && !elements[3] && !elements[4] && !elements[5]) + err = 0; + } + } + } + + + if (err) + { + for (i = 0; i < idx; i++) + if (elements[i]) + gcry_free (elements[i]); + } + return err; +} + + +/* Internal function used for ecc. Note, that this function makes use + of its intimate knowledge about the ECC parameters from ecc.c. */ +static gcry_err_code_t +sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, + gcry_mpi_t *elements, pk_extra_spec_t *extraspec) + +{ + gcry_err_code_t err = 0; + int idx; + const char *name; + gcry_sexp_t list; + + /* Clear the array for easier error cleanup. */ + for (name = element_names, idx = 0; *name; name++, idx++) + elements[idx] = NULL; + gcry_assert (idx >= 5); /* We know that ECC has at least 5 elements + (params only) or 6 (full public key). */ + if (idx == 5) + elements[5] = NULL; /* Extra clear for the params only case. */ + + + /* Init the array with the available curve parameters. */ + for (name = element_names, idx = 0; *name && !err; name++, idx++) + { + list = gcry_sexp_find_token (key_sexp, name, 1); + if (!list) + elements[idx] = NULL; + else + { + elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (list); + if (!elements[idx]) + { + err = GPG_ERR_INV_OBJ; + goto leave; + } + } + } + + /* Check whether a curve parameter has been given and then fill any + missing elements. */ + list = gcry_sexp_find_token (key_sexp, "curve", 5); + if (list) + { + if (extraspec->get_param) + { + char *curve; + gcry_mpi_t params[6]; + + for (idx = 0; idx < DIM(params); idx++) + params[idx] = NULL; + + curve = _gcry_sexp_nth_string (list, 1); + gcry_sexp_release (list); + if (!curve) + { + /* No curve name given (or out of core). */ + err = GPG_ERR_INV_OBJ; + goto leave; + } + err = extraspec->get_param (curve, params); + gcry_free (curve); + if (err) + goto leave; + + for (idx = 0; idx < DIM(params); idx++) + { + if (!elements[idx]) + elements[idx] = params[idx]; + else + mpi_free (params[idx]); + } + } + else + { + gcry_sexp_release (list); + err = GPG_ERR_INV_OBJ; /* "curve" given but ECC not supported. */ + goto leave; + } + } + + /* Check that all parameters are known. */ + for (name = element_names, idx = 0; *name; name++, idx++) + if (!elements[idx]) + { + err = GPG_ERR_NO_OBJ; + goto leave; + } + + leave: + if (err) + { + for (name = element_names, idx = 0; *name; name++, idx++) + if (elements[idx]) + gcry_free (elements[idx]); + } + return err; +} + + + +/**************** + * Convert a S-Exp with either a private or a public key to our + * internal format. Currently we do only support the following + * algorithms: + * dsa + * rsa + * openpgp-dsa + * openpgp-rsa + * openpgp-elg + * openpgp-elg-sig + * ecdsa + * ecdh + * Provide a SE with the first element be either "private-key" or + * or "public-key". It is followed by a list with its first element + * be one of the above algorithm identifiers and the remaning + * elements are pairs with parameter-id and value. + * NOTE: we look through the list to find a list beginning with + * "private-key" or "public-key" - the first one found is used. + * + * If OVERRIDE_ELEMS is not NULL those elems override the parameter + * specification taken from the module. This ise used by + * gcry_pk_get_curve. + * + * Returns: A pointer to an allocated array of MPIs if the return value is + * zero; the caller has to release this array. + * + * Example of a DSA public key: + * (private-key + * (dsa + * (p <mpi>) + * (g <mpi>) + * (y <mpi>) + * (x <mpi>) + * ) + * ) + * The <mpi> are expected to be in GCRYMPI_FMT_USG + */ +static gcry_err_code_t +sexp_to_key (gcry_sexp_t sexp, int want_private, const char *override_elems, + gcry_mpi_t **retarray, gcry_module_t *retalgo) +{ + gcry_err_code_t err = 0; + gcry_sexp_t list, l2; + char *name; + const char *elems; + gcry_mpi_t *array; + gcry_module_t module; + gcry_pk_spec_t *pubkey; + pk_extra_spec_t *extraspec; + int is_ecc; + + /* Check that the first element is valid. */ + list = gcry_sexp_find_token (sexp, + want_private? "private-key":"public-key", 0); + if (!list) + return GPG_ERR_INV_OBJ; /* Does not contain a key object. */ + + l2 = gcry_sexp_cadr( list ); + gcry_sexp_release ( list ); + list = l2; + name = _gcry_sexp_nth_string (list, 0); + if (!name) + { + gcry_sexp_release ( list ); + return GPG_ERR_INV_OBJ; /* Invalid structure of object. */ + } + + ath_mutex_lock (&pubkeys_registered_lock); + module = gcry_pk_lookup_name (name); + ath_mutex_unlock (&pubkeys_registered_lock); + + /* Fixme: We should make sure that an ECC key is always named "ecc" + and not "ecdsa". "ecdsa" should be used for the signature + itself. We need a function to test whether an algorithm given + with a key is compatible with an application of the key (signing, + encryption). For RSA this is easy, but ECC is the first + algorithm which has many flavours. */ + is_ecc = ( !strcmp (name, "ecdsa") + || !strcmp (name, "ecdh") + || !strcmp (name, "ecc") ); + gcry_free (name); + + if (!module) + { + gcry_sexp_release (list); + return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ + } + else + { + pubkey = (gcry_pk_spec_t *) module->spec; + extraspec = module->extraspec; + } + + if (override_elems) + elems = override_elems; + else if (want_private) + elems = pubkey->elements_skey; + else + elems = pubkey->elements_pkey; + array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); + if (!array) + err = gpg_err_code_from_syserror (); + if (!err) + { + if (is_ecc) + err = sexp_elements_extract_ecc (list, elems, array, extraspec); + else + err = sexp_elements_extract (list, elems, array, pubkey->name); + } + + gcry_sexp_release (list); + + if (err) + { + gcry_free (array); + + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + } + else + { + *retarray = array; + *retalgo = module; + } + + return err; +} + + +static gcry_err_code_t +sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, + gcry_module_t *retalgo) +{ + gcry_err_code_t err = 0; + gcry_sexp_t list, l2; + char *name; + const char *elems; + gcry_mpi_t *array; + gcry_module_t module; + gcry_pk_spec_t *pubkey; + + /* Check that the first element is valid. */ + list = gcry_sexp_find_token( sexp, "sig-val" , 0 ); + if (!list) + return GPG_ERR_INV_OBJ; /* Does not contain a signature value object. */ + + l2 = gcry_sexp_nth (list, 1); + if (!l2) + { + gcry_sexp_release (list); + return GPG_ERR_NO_OBJ; /* No cadr for the sig object. */ + } + name = _gcry_sexp_nth_string (l2, 0); + if (!name) + { + gcry_sexp_release (list); + gcry_sexp_release (l2); + return GPG_ERR_INV_OBJ; /* Invalid structure of object. */ + } + else if (!strcmp (name, "flags")) + { + /* Skip flags, since they are not used but here just for the + sake of consistent S-expressions. */ + gcry_free (name); + gcry_sexp_release (l2); + l2 = gcry_sexp_nth (list, 2); + if (!l2) + { + gcry_sexp_release (list); + return GPG_ERR_INV_OBJ; + } + name = _gcry_sexp_nth_string (l2, 0); + } + + ath_mutex_lock (&pubkeys_registered_lock); + module = gcry_pk_lookup_name (name); + ath_mutex_unlock (&pubkeys_registered_lock); + gcry_free (name); + name = NULL; + + if (!module) + { + gcry_sexp_release (l2); + gcry_sexp_release (list); + return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ + } + else + pubkey = (gcry_pk_spec_t *) module->spec; + + elems = pubkey->elements_sig; + array = gcry_calloc (strlen (elems) + 1 , sizeof *array ); + if (!array) + err = gpg_err_code_from_syserror (); + + if (!err) + err = sexp_elements_extract (list, elems, array, NULL); + + gcry_sexp_release (l2); + gcry_sexp_release (list); + + if (err) + { + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + + gcry_free (array); + } + else + { + *retarray = array; + *retalgo = module; + } + + return err; +} + +static inline int +get_hash_algo (const char *s, size_t n) +{ + static const struct { const char *name; int algo; } hashnames[] = { + { "sha1", GCRY_MD_SHA1 }, + { "md5", GCRY_MD_MD5 }, + { "sha256", GCRY_MD_SHA256 }, + { "ripemd160", GCRY_MD_RMD160 }, + { "rmd160", GCRY_MD_RMD160 }, + { "sha384", GCRY_MD_SHA384 }, + { "sha512", GCRY_MD_SHA512 }, + { "sha224", GCRY_MD_SHA224 }, + { "md2", GCRY_MD_MD2 }, + { "md4", GCRY_MD_MD4 }, + { "tiger", GCRY_MD_TIGER }, + { "haval", GCRY_MD_HAVAL }, + { NULL, 0 } + }; + int algo; + int i; + + for (i=0; hashnames[i].name; i++) + { + if ( strlen (hashnames[i].name) == n + && !memcmp (hashnames[i].name, s, n)) + break; + } + if (hashnames[i].name) + algo = hashnames[i].algo; + else + { + /* In case of not listed or dynamically allocated hash + algorithm we fall back to this somewhat slower + method. Further, it also allows to use OIDs as + algorithm names. */ + char *tmpname; + + tmpname = gcry_malloc (n+1); + if (!tmpname) + algo = 0; /* Out of core - silently give up. */ + else + { + memcpy (tmpname, s, n); + tmpname[n] = 0; + algo = gcry_md_map_name (tmpname); + gcry_free (tmpname); + } + } + return algo; +} + + +/**************** + * Take sexp and return an array of MPI as used for our internal decrypt + * function. + * s_data = (enc-val + * [(flags [raw, pkcs1, oaep, no-blinding])] + * [(hash-algo <algo>)] + * [(label <label>)] + * (<algo> + * (<param_name1> <mpi>) + * ... + * (<param_namen> <mpi>) + * )) + * HASH-ALGO and LABEL are specific to OAEP. + * RET_MODERN is set to true when at least an empty flags list has been found. + * CTX is used to return encoding information; it may be NULL in which + * case raw encoding is used. + */ +static gcry_err_code_t +sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo, + int *ret_modern, int *flags, struct pk_encoding_ctx *ctx) +{ + gcry_err_code_t err = 0; + gcry_sexp_t list = NULL, l2 = NULL; + gcry_pk_spec_t *pubkey = NULL; + gcry_module_t module = NULL; + char *name = NULL; + size_t n; + int parsed_flags = 0; + const char *elems; + gcry_mpi_t *array = NULL; + + *ret_modern = 0; + + /* Check that the first element is valid. */ + list = gcry_sexp_find_token (sexp, "enc-val" , 0); + if (!list) + { + err = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object. */ + goto leave; + } + + l2 = gcry_sexp_nth (list, 1); + if (!l2) + { + err = GPG_ERR_NO_OBJ; /* No cdr for the data object. */ + goto leave; + } + + /* Extract identifier of sublist. */ + name = _gcry_sexp_nth_string (l2, 0); + if (!name) + { + err = GPG_ERR_INV_OBJ; /* Invalid structure of object. */ + goto leave; + } + + if (!strcmp (name, "flags")) + { + /* There is a flags element - process it. */ + const char *s; + int i; + + *ret_modern = 1; + for (i = gcry_sexp_length (l2) - 1; i > 0; i--) + { + s = gcry_sexp_nth_data (l2, i, &n); + if (! s) + ; /* Not a data element - ignore. */ + else if (n == 3 && !memcmp (s, "raw", 3) + && ctx->encoding == PUBKEY_ENC_UNKNOWN) + ctx->encoding = PUBKEY_ENC_RAW; + else if (n == 5 && !memcmp (s, "pkcs1", 5) + && ctx->encoding == PUBKEY_ENC_UNKNOWN) + ctx->encoding = PUBKEY_ENC_PKCS1; + else if (n == 4 && !memcmp (s, "oaep", 4) + && ctx->encoding == PUBKEY_ENC_UNKNOWN) + ctx->encoding = PUBKEY_ENC_OAEP; + else if (n == 3 && !memcmp (s, "pss", 3) + && ctx->encoding == PUBKEY_ENC_UNKNOWN) + { + err = GPG_ERR_CONFLICT; + goto leave; + } + else if (n == 11 && ! memcmp (s, "no-blinding", 11)) + parsed_flags |= PUBKEY_FLAG_NO_BLINDING; + else + { + err = GPG_ERR_INV_FLAG; + goto leave; + } + } + gcry_sexp_release (l2); + + /* Get the OAEP parameters HASH-ALGO and LABEL, if any. */ + if (ctx->encoding == PUBKEY_ENC_OAEP) + { + /* Get HASH-ALGO. */ + l2 = gcry_sexp_find_token (list, "hash-algo", 0); + if (l2) + { + s = gcry_sexp_nth_data (l2, 1, &n); + if (!s) + err = GPG_ERR_NO_OBJ; + else + { + ctx->hash_algo = get_hash_algo (s, n); + if (!ctx->hash_algo) + err = GPG_ERR_DIGEST_ALGO; + } + gcry_sexp_release (l2); + if (err) + goto leave; + } + + /* Get LABEL. */ + l2 = gcry_sexp_find_token (list, "label", 0); + if (l2) + { + s = gcry_sexp_nth_data (l2, 1, &n); + if (!s) + err = GPG_ERR_NO_OBJ; + else if (n > 0) + { + ctx->label = gcry_malloc (n); + if (!ctx->label) + err = gpg_err_code_from_syserror (); + else + { + memcpy (ctx->label, s, n); + ctx->labellen = n; + } + } + gcry_sexp_release (l2); + if (err) + goto leave; + } + } + + /* Get the next which has the actual data - skip HASH-ALGO and LABEL. */ + for (i = 2; (l2 = gcry_sexp_nth (list, i)) != NULL; i++) + { + s = gcry_sexp_nth_data (l2, 0, &n); + if (!(n == 9 && !memcmp (s, "hash-algo", 9)) + && !(n == 5 && !memcmp (s, "label", 5)) + && !(n == 15 && !memcmp (s, "random-override", 15))) + break; + gcry_sexp_release (l2); + } + + if (!l2) + { + err = GPG_ERR_NO_OBJ; /* No cdr for the data object. */ + goto leave; + } + + /* Extract sublist identifier. */ + gcry_free (name); + name = _gcry_sexp_nth_string (l2, 0); + if (!name) + { + err = GPG_ERR_INV_OBJ; /* Invalid structure of object. */ + goto leave; + } + + gcry_sexp_release (list); + list = l2; + l2 = NULL; + } + + ath_mutex_lock (&pubkeys_registered_lock); + module = gcry_pk_lookup_name (name); + ath_mutex_unlock (&pubkeys_registered_lock); + + if (!module) + { + err = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ + goto leave; + } + pubkey = (gcry_pk_spec_t *) module->spec; + + elems = pubkey->elements_enc; + array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); + if (!array) + { + err = gpg_err_code_from_syserror (); + goto leave; + } + + err = sexp_elements_extract (list, elems, array, NULL); + + leave: + gcry_sexp_release (list); + gcry_sexp_release (l2); + gcry_free (name); + + if (err) + { + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + gcry_free (array); + gcry_free (ctx->label); + ctx->label = NULL; + } + else + { + *retarray = array; + *retalgo = module; + *flags = parsed_flags; + } + + return err; +} + +/* Take the hash value and convert into an MPI, suitable for + passing to the low level functions. We currently support the + old style way of passing just a MPI and the modern interface which + allows to pass flags so that we can choose between raw and pkcs1 + padding - may be more padding options later. + + (<mpi>) + or + (data + [(flags [raw, pkcs1, oaep, pss, no-blinding])] + [(hash <algo> <value>)] + [(value <text>)] + [(hash-algo <algo>)] + [(label <label>)] + [(salt-length <length>)] + [(random-override <data>)] + ) + + Either the VALUE or the HASH element must be present for use + with signatures. VALUE is used for encryption. + + HASH-ALGO and LABEL are specific to OAEP. + + SALT-LENGTH is for PSS. + + RANDOM-OVERRIDE is used to replace random nonces for regression + testing. */ +static gcry_err_code_t +sexp_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, + struct pk_encoding_ctx *ctx) +{ + gcry_err_code_t rc = 0; + gcry_sexp_t ldata, lhash, lvalue; + int i; + size_t n; + const char *s; + int unknown_flag=0; + int parsed_flags = 0; + + *ret_mpi = NULL; + ldata = gcry_sexp_find_token (input, "data", 0); + if (!ldata) + { /* assume old style */ + *ret_mpi = gcry_sexp_nth_mpi (input, 0, 0); + return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ; + } + + /* see whether there is a flags object */ + { + gcry_sexp_t lflags = gcry_sexp_find_token (ldata, "flags", 0); + if (lflags) + { /* parse the flags list. */ + for (i=gcry_sexp_length (lflags)-1; i > 0; i--) + { + s = gcry_sexp_nth_data (lflags, i, &n); + if (!s) + ; /* not a data element*/ + else if ( n == 3 && !memcmp (s, "raw", 3) + && ctx->encoding == PUBKEY_ENC_UNKNOWN) + ctx->encoding = PUBKEY_ENC_RAW; + else if ( n == 5 && !memcmp (s, "pkcs1", 5) + && ctx->encoding == PUBKEY_ENC_UNKNOWN) + ctx->encoding = PUBKEY_ENC_PKCS1; + else if ( n == 4 && !memcmp (s, "oaep", 4) + && ctx->encoding == PUBKEY_ENC_UNKNOWN) + ctx->encoding = PUBKEY_ENC_OAEP; + else if ( n == 3 && !memcmp (s, "pss", 3) + && ctx->encoding == PUBKEY_ENC_UNKNOWN) + ctx->encoding = PUBKEY_ENC_PSS; + else if (n == 11 && ! memcmp (s, "no-blinding", 11)) + parsed_flags |= PUBKEY_FLAG_NO_BLINDING; + else + unknown_flag = 1; + } + gcry_sexp_release (lflags); + } + } + + if (ctx->encoding == PUBKEY_ENC_UNKNOWN) + ctx->encoding = PUBKEY_ENC_RAW; /* default to raw */ + + /* Get HASH or MPI */ + lhash = gcry_sexp_find_token (ldata, "hash", 0); + lvalue = lhash? NULL : gcry_sexp_find_token (ldata, "value", 0); + + if (!(!lhash ^ !lvalue)) + rc = GPG_ERR_INV_OBJ; /* none or both given */ + else if (unknown_flag) + rc = GPG_ERR_INV_FLAG; + else if (ctx->encoding == PUBKEY_ENC_RAW && lvalue) + { + *ret_mpi = gcry_sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_USG); + if (!*ret_mpi) + rc = GPG_ERR_INV_OBJ; + } + else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lvalue + && ctx->op == PUBKEY_OP_ENCRYPT) + { + const void * value; + size_t valuelen; + gcry_sexp_t list; + void *random_override = NULL; + size_t random_override_len = 0; + + if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen ) + rc = GPG_ERR_INV_OBJ; + else + { + /* Get optional RANDOM-OVERRIDE. */ + list = gcry_sexp_find_token (ldata, "random-override", 0); + if (list) + { + s = gcry_sexp_nth_data (list, 1, &n); + if (!s) + rc = GPG_ERR_NO_OBJ; + else if (n > 0) + { + random_override = gcry_malloc (n); + if (!random_override) + rc = gpg_err_code_from_syserror (); + else + { + memcpy (random_override, s, n); + random_override_len = n; + } + } + gcry_sexp_release (list); + if (rc) + goto leave; + } + + rc = pkcs1_encode_for_encryption (ret_mpi, ctx->nbits, + value, valuelen, + random_override, + random_override_len); + gcry_free (random_override); + } + } + else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lhash + && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY)) + { + if (gcry_sexp_length (lhash) != 3) + rc = GPG_ERR_INV_OBJ; + else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n ) + rc = GPG_ERR_INV_OBJ; + else + { + const void * value; + size_t valuelen; + + ctx->hash_algo = get_hash_algo (s, n); + + if (!ctx->hash_algo) + rc = GPG_ERR_DIGEST_ALGO; + else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen)) + || !valuelen ) + rc = GPG_ERR_INV_OBJ; + else + rc = pkcs1_encode_for_signature (ret_mpi, ctx->nbits, + value, valuelen, + ctx->hash_algo); + } + } + else if (ctx->encoding == PUBKEY_ENC_OAEP && lvalue + && ctx->op == PUBKEY_OP_ENCRYPT) + { + const void * value; + size_t valuelen; + + if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen ) + rc = GPG_ERR_INV_OBJ; + else + { + gcry_sexp_t list; + void *random_override = NULL; + size_t random_override_len = 0; + + /* Get HASH-ALGO. */ + list = gcry_sexp_find_token (ldata, "hash-algo", 0); + if (list) + { + s = gcry_sexp_nth_data (list, 1, &n); + if (!s) + rc = GPG_ERR_NO_OBJ; + else + { + ctx->hash_algo = get_hash_algo (s, n); + if (!ctx->hash_algo) + rc = GPG_ERR_DIGEST_ALGO; + } + gcry_sexp_release (list); + if (rc) + goto leave; + } + + /* Get LABEL. */ + list = gcry_sexp_find_token (ldata, "label", 0); + if (list) + { + s = gcry_sexp_nth_data (list, 1, &n); + if (!s) + rc = GPG_ERR_NO_OBJ; + else if (n > 0) + { + ctx->label = gcry_malloc (n); + if (!ctx->label) + rc = gpg_err_code_from_syserror (); + else + { + memcpy (ctx->label, s, n); + ctx->labellen = n; + } + } + gcry_sexp_release (list); + if (rc) + goto leave; + } + /* Get optional RANDOM-OVERRIDE. */ + list = gcry_sexp_find_token (ldata, "random-override", 0); + if (list) + { + s = gcry_sexp_nth_data (list, 1, &n); + if (!s) + rc = GPG_ERR_NO_OBJ; + else if (n > 0) + { + random_override = gcry_malloc (n); + if (!random_override) + rc = gpg_err_code_from_syserror (); + else + { + memcpy (random_override, s, n); + random_override_len = n; + } + } + gcry_sexp_release (list); + if (rc) + goto leave; + } + + rc = oaep_encode (ret_mpi, ctx->nbits, ctx->hash_algo, + value, valuelen, + ctx->label, ctx->labellen, + random_override, random_override_len); + + gcry_free (random_override); + } + } + else if (ctx->encoding == PUBKEY_ENC_PSS && lhash + && ctx->op == PUBKEY_OP_SIGN) + { + if (gcry_sexp_length (lhash) != 3) + rc = GPG_ERR_INV_OBJ; + else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n ) + rc = GPG_ERR_INV_OBJ; + else + { + const void * value; + size_t valuelen; + void *random_override = NULL; + size_t random_override_len = 0; + + ctx->hash_algo = get_hash_algo (s, n); + + if (!ctx->hash_algo) + rc = GPG_ERR_DIGEST_ALGO; + else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen)) + || !valuelen ) + rc = GPG_ERR_INV_OBJ; + else + { + gcry_sexp_t list; + + /* Get SALT-LENGTH. */ + list = gcry_sexp_find_token (ldata, "salt-length", 0); + if (list) + { + s = gcry_sexp_nth_data (list, 1, &n); + if (!s) + { + rc = GPG_ERR_NO_OBJ; + goto leave; + } + ctx->saltlen = (unsigned int)strtoul (s, NULL, 10); + gcry_sexp_release (list); + } + + /* Get optional RANDOM-OVERRIDE. */ + list = gcry_sexp_find_token (ldata, "random-override", 0); + if (list) + { + s = gcry_sexp_nth_data (list, 1, &n); + if (!s) + rc = GPG_ERR_NO_OBJ; + else if (n > 0) + { + random_override = gcry_malloc (n); + if (!random_override) + rc = gpg_err_code_from_syserror (); + else + { + memcpy (random_override, s, n); + random_override_len = n; + } + } + gcry_sexp_release (list); + if (rc) + goto leave; + } + + /* Encode the data. (NBITS-1 is due to 8.1.1, step 1.) */ + rc = pss_encode (ret_mpi, ctx->nbits - 1, ctx->hash_algo, + value, valuelen, ctx->saltlen, + random_override, random_override_len); + + gcry_free (random_override); + } + } + } + else if (ctx->encoding == PUBKEY_ENC_PSS && lhash + && ctx->op == PUBKEY_OP_VERIFY) + { + if (gcry_sexp_length (lhash) != 3) + rc = GPG_ERR_INV_OBJ; + else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n ) + rc = GPG_ERR_INV_OBJ; + else + { + ctx->hash_algo = get_hash_algo (s, n); + + if (!ctx->hash_algo) + rc = GPG_ERR_DIGEST_ALGO; + else + { + *ret_mpi = gcry_sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_USG); + if (!*ret_mpi) + rc = GPG_ERR_INV_OBJ; + ctx->verify_cmp = pss_verify_cmp; + ctx->verify_arg = *ret_mpi; + } + } + } + else + rc = GPG_ERR_CONFLICT; + + leave: + gcry_sexp_release (ldata); + gcry_sexp_release (lhash); + gcry_sexp_release (lvalue); + + if (!rc) + ctx->flags = parsed_flags; + else + { + gcry_free (ctx->label); + ctx->label = NULL; + } + + return rc; +} + +static void +init_encoding_ctx (struct pk_encoding_ctx *ctx, enum pk_operation op, + unsigned int nbits) +{ + ctx->op = op; + ctx->nbits = nbits; + ctx->encoding = PUBKEY_ENC_UNKNOWN; + ctx->flags = 0; + ctx->hash_algo = GCRY_MD_SHA1; + ctx->label = NULL; + ctx->labellen = 0; + ctx->saltlen = 20; + ctx->verify_cmp = NULL; + ctx->verify_arg = NULL; +} + + +/* + Do a PK encrypt operation + + Caller has to provide a public key as the SEXP pkey and data as a + SEXP with just one MPI in it. Alternatively S_DATA might be a + complex S-Expression, similar to the one used for signature + verification. This provides a flag which allows to handle PKCS#1 + block type 2 padding. The function returns a sexp which may be + passed to to pk_decrypt. + + Returns: 0 or an errorcode. + + s_data = See comment for sexp_data_to_mpi + s_pkey = <key-as-defined-in-sexp_to_key> + r_ciph = (enc-val + (<algo> + (<param_name1> <mpi>) + ... + (<param_namen> <mpi>) + )) + +*/ +gcry_error_t +gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) +{ + gcry_mpi_t *pkey = NULL, data = NULL, *ciph = NULL; + const char *algo_name, *algo_elems; + struct pk_encoding_ctx ctx; + gcry_err_code_t rc; + gcry_pk_spec_t *pubkey = NULL; + gcry_module_t module = NULL; + + *r_ciph = NULL; + + REGISTER_DEFAULT_PUBKEYS; + + /* Get the key. */ + rc = sexp_to_key (s_pkey, 0, NULL, &pkey, &module); + if (rc) + goto leave; + + gcry_assert (module); + pubkey = (gcry_pk_spec_t *) module->spec; + + /* If aliases for the algorithm name exists, take the first one + instead of the regular name to adhere to SPKI conventions. We + assume that the first alias name is the lowercase version of the + regular one. This change is required for compatibility with + 1.1.12 generated S-expressions. */ + algo_name = pubkey->aliases? *pubkey->aliases : NULL; + if (!algo_name || !*algo_name) + algo_name = pubkey->name; + + algo_elems = pubkey->elements_enc; + + /* Get the stuff we want to encrypt. */ + init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, gcry_pk_get_nbits (s_pkey)); + rc = sexp_data_to_mpi (s_data, &data, &ctx); + if (rc) + goto leave; + + /* Now we can encrypt DATA to CIPH. */ + ciph = gcry_calloc (strlen (algo_elems) + 1, sizeof (*ciph)); + if (!ciph) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + rc = pubkey_encrypt (module->mod_id, ciph, data, pkey, ctx.flags); + mpi_free (data); + data = NULL; + if (rc) + goto leave; + + /* We did it. Now build the return list */ + if (ctx.encoding == PUBKEY_ENC_OAEP + || ctx.encoding == PUBKEY_ENC_PKCS1) + { + /* We need to make sure to return the correct length to avoid + problems with missing leading zeroes. We know that this + encoding does only make sense with RSA thus we don't need to + build the S-expression on the fly. */ + unsigned char *em; + size_t emlen = (ctx.nbits+7)/8; + + rc = octet_string_from_mpi (&em, NULL, ciph[0], emlen); + if (rc) + goto leave; + rc = gcry_err_code (gcry_sexp_build (r_ciph, NULL, + "(enc-val(%s(a%b)))", + algo_name, (int)emlen, em)); + gcry_free (em); + if (rc) + goto leave; + } + else + { + char *string, *p; + int i; + size_t nelem = strlen (algo_elems); + size_t needed = 19 + strlen (algo_name) + (nelem * 5); + void **arg_list; + + /* Build the string. */ + string = p = gcry_malloc (needed); + if (!string) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + p = stpcpy ( p, "(enc-val(" ); + p = stpcpy ( p, algo_name ); + for (i=0; algo_elems[i]; i++ ) + { + *p++ = '('; + *p++ = algo_elems[i]; + p = stpcpy ( p, "%m)" ); + } + strcpy ( p, "))" ); + + /* And now the ugly part: We don't have a function to pass an + * array to a format string, so we have to do it this way :-(. */ + /* FIXME: There is now such a format specifier, so we can + change the code to be more clear. */ + arg_list = calloc (nelem, sizeof *arg_list); + if (!arg_list) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + + for (i = 0; i < nelem; i++) + arg_list[i] = ciph + i; + + rc = gcry_sexp_build_array (r_ciph, NULL, string, arg_list); + free (arg_list); + if (rc) + BUG (); + gcry_free (string); + } + + leave: + if (pkey) + { + release_mpi_array (pkey); + gcry_free (pkey); + } + + if (ciph) + { + release_mpi_array (ciph); + gcry_free (ciph); + } + + if (module) + { + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + } + + gcry_free (ctx.label); + + return gcry_error (rc); +} + +/* + Do a PK decrypt operation + + Caller has to provide a secret key as the SEXP skey and data in a + format as created by gcry_pk_encrypt. For historic reasons the + function returns simply an MPI as an S-expression part; this is + deprecated and the new method should be used which returns a real + S-expressionl this is selected by adding at least an empty flags + list to S_DATA. + + Returns: 0 or an errorcode. + + s_data = (enc-val + [(flags [raw, pkcs1, oaep])] + (<algo> + (<param_name1> <mpi>) + ... + (<param_namen> <mpi>) + )) + s_skey = <key-as-defined-in-sexp_to_key> + r_plain= Either an incomplete S-expression without the parentheses + or if the flags list is used (even if empty) a real S-expression: + (value PLAIN). In raw mode (or no flags given) the returned value + is to be interpreted as a signed MPI, thus it may have an extra + leading zero octet even if not included in the original data. + With pkcs1 or oaep decoding enabled the returned value is a + verbatim octet string. + */ +gcry_error_t +gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) +{ + gcry_mpi_t *skey = NULL, *data = NULL, plain = NULL; + unsigned char *unpad = NULL; + size_t unpadlen = 0; + int modern, flags; + struct pk_encoding_ctx ctx; + gcry_err_code_t rc; + gcry_module_t module_enc = NULL, module_key = NULL; + + *r_plain = NULL; + ctx.label = NULL; + + REGISTER_DEFAULT_PUBKEYS; + + rc = sexp_to_key (s_skey, 1, NULL, &skey, &module_key); + if (rc) + goto leave; + + init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, gcry_pk_get_nbits (s_skey)); + rc = sexp_to_enc (s_data, &data, &module_enc, &modern, &flags, &ctx); + if (rc) + goto leave; + + if (module_key->mod_id != module_enc->mod_id) + { + rc = GPG_ERR_CONFLICT; /* Key algo does not match data algo. */ + goto leave; + } + + rc = pubkey_decrypt (module_key->mod_id, &plain, data, skey, flags); + if (rc) + goto leave; + + /* Do un-padding if necessary. */ + switch (ctx.encoding) + { + case PUBKEY_ENC_PKCS1: + rc = pkcs1_decode_for_encryption (&unpad, &unpadlen, + gcry_pk_get_nbits (s_skey), plain); + mpi_free (plain); + plain = NULL; + if (!rc) + rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", + (int)unpadlen, unpad)); + break; + + case PUBKEY_ENC_OAEP: + rc = oaep_decode (&unpad, &unpadlen, + gcry_pk_get_nbits (s_skey), ctx.hash_algo, + plain, ctx.label, ctx.labellen); + mpi_free (plain); + plain = NULL; + if (!rc) + rc = gcry_err_code (gcry_sexp_build (r_plain, NULL, "(value %b)", + (int)unpadlen, unpad)); + break; + + default: + /* Raw format. For backward compatibility we need to assume a + signed mpi by using the sexp format string "%m". */ + rc = gcry_err_code (gcry_sexp_build + (r_plain, NULL, modern? "(value %m)" : "%m", plain)); + break; + } + + leave: + gcry_free (unpad); + + if (skey) + { + release_mpi_array (skey); + gcry_free (skey); + } + + mpi_free (plain); + + if (data) + { + release_mpi_array (data); + gcry_free (data); + } + + if (module_key || module_enc) + { + ath_mutex_lock (&pubkeys_registered_lock); + if (module_key) + _gcry_module_release (module_key); + if (module_enc) + _gcry_module_release (module_enc); + ath_mutex_unlock (&pubkeys_registered_lock); + } + + gcry_free (ctx.label); + + return gcry_error (rc); +} + + + +/* + Create a signature. + + Caller has to provide a secret key as the SEXP skey and data + expressed as a SEXP list hash with only one element which should + instantly be available as a MPI. Alternatively the structure given + below may be used for S_HASH, it provides the abiliy to pass flags + to the operation; the flags defined by now are "pkcs1" which does + PKCS#1 block type 1 style padding and "pss" for PSS encoding. + + Returns: 0 or an errorcode. + In case of 0 the function returns a new SEXP with the + signature value; the structure of this signature depends on the + other arguments but is always suitable to be passed to + gcry_pk_verify + + s_hash = See comment for sexp_data_to_mpi + + s_skey = <key-as-defined-in-sexp_to_key> + r_sig = (sig-val + (<algo> + (<param_name1> <mpi>) + ... + (<param_namen> <mpi>)) + [(hash algo)]) + + Note that (hash algo) in R_SIG is not used. +*/ +gcry_error_t +gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey) +{ + gcry_mpi_t *skey = NULL, hash = NULL, *result = NULL; + gcry_pk_spec_t *pubkey = NULL; + gcry_module_t module = NULL; + const char *algo_name, *algo_elems; + struct pk_encoding_ctx ctx; + int i; + gcry_err_code_t rc; + + *r_sig = NULL; + + REGISTER_DEFAULT_PUBKEYS; + + rc = sexp_to_key (s_skey, 1, NULL, &skey, &module); + if (rc) + goto leave; + + gcry_assert (module); + pubkey = (gcry_pk_spec_t *) module->spec; + algo_name = pubkey->aliases? *pubkey->aliases : NULL; + if (!algo_name || !*algo_name) + algo_name = pubkey->name; + + algo_elems = pubkey->elements_sig; + + /* Get the stuff we want to sign. Note that pk_get_nbits does also + work on a private key. */ + init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, gcry_pk_get_nbits (s_skey)); + rc = sexp_data_to_mpi (s_hash, &hash, &ctx); + if (rc) + goto leave; + + result = gcry_calloc (strlen (algo_elems) + 1, sizeof (*result)); + if (!result) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + rc = pubkey_sign (module->mod_id, result, hash, skey); + if (rc) + goto leave; + + if (ctx.encoding == PUBKEY_ENC_PSS + || ctx.encoding == PUBKEY_ENC_PKCS1) + { + /* We need to make sure to return the correct length to avoid + problems with missing leading zeroes. We know that this + encoding does only make sense with RSA thus we don't need to + build the S-expression on the fly. */ + unsigned char *em; + size_t emlen = (ctx.nbits+7)/8; + + rc = octet_string_from_mpi (&em, NULL, result[0], emlen); + if (rc) + goto leave; + rc = gcry_err_code (gcry_sexp_build (r_sig, NULL, + "(sig-val(%s(s%b)))", + algo_name, (int)emlen, em)); + gcry_free (em); + if (rc) + goto leave; + } + else + { + /* General purpose output encoding. Do it on the fly. */ + char *string, *p; + size_t nelem, needed = strlen (algo_name) + 20; + void **arg_list; + + nelem = strlen (algo_elems); + + /* Count elements, so that we can allocate enough space. */ + needed += 10 * nelem; + + /* Build the string. */ + string = p = gcry_malloc (needed); + if (!string) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + p = stpcpy (p, "(sig-val("); + p = stpcpy (p, algo_name); + for (i = 0; algo_elems[i]; i++) + { + *p++ = '('; + *p++ = algo_elems[i]; + p = stpcpy (p, "%M)"); + } + strcpy (p, "))"); + + arg_list = calloc (nelem, sizeof *arg_list); + if (!arg_list) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + + for (i = 0; i < nelem; i++) + arg_list[i] = result + i; + + rc = gcry_sexp_build_array (r_sig, NULL, string, arg_list); + free (arg_list); + if (rc) + BUG (); + gcry_free (string); + } + + leave: + if (skey) + { + release_mpi_array (skey); + gcry_free (skey); + } + + if (hash) + mpi_free (hash); + + if (result) + { + release_mpi_array (result); + gcry_free (result); + } + + return gcry_error (rc); +} + + +/* + Verify a signature. + + Caller has to supply the public key pkey, the signature sig and his + hashvalue data. Public key has to be a standard public key given + as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data + must be an S-Exp like the one in sign too. */ +gcry_error_t +gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) +{ + gcry_module_t module_key = NULL, module_sig = NULL; + gcry_mpi_t *pkey = NULL, hash = NULL, *sig = NULL; + struct pk_encoding_ctx ctx; + gcry_err_code_t rc; + + REGISTER_DEFAULT_PUBKEYS; + + rc = sexp_to_key (s_pkey, 0, NULL, &pkey, &module_key); + if (rc) + goto leave; + + rc = sexp_to_sig (s_sig, &sig, &module_sig); + if (rc) + goto leave; + + /* Fixme: Check that the algorithm of S_SIG is compatible to the one + of S_PKEY. */ + + if (module_key->mod_id != module_sig->mod_id) + { + rc = GPG_ERR_CONFLICT; + goto leave; + } + + /* Get the stuff we want to verify. */ + init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY, gcry_pk_get_nbits (s_pkey)); + rc = sexp_data_to_mpi (s_hash, &hash, &ctx); + if (rc) + goto leave; + + rc = pubkey_verify (module_key->mod_id, hash, sig, pkey, + ctx.verify_cmp, &ctx); + + leave: + if (pkey) + { + release_mpi_array (pkey); + gcry_free (pkey); + } + if (sig) + { + release_mpi_array (sig); + gcry_free (sig); + } + if (hash) + mpi_free (hash); + + if (module_key || module_sig) + { + ath_mutex_lock (&pubkeys_registered_lock); + if (module_key) + _gcry_module_release (module_key); + if (module_sig) + _gcry_module_release (module_sig); + ath_mutex_unlock (&pubkeys_registered_lock); + } + + return gcry_error (rc); +} + + +/* + Test a key. + + This may be used either for a public or a secret key to see whether + the internal structure is okay. + + Returns: 0 or an errorcode. + + s_key = <key-as-defined-in-sexp_to_key> */ +gcry_error_t +gcry_pk_testkey (gcry_sexp_t s_key) +{ + gcry_module_t module = NULL; + gcry_mpi_t *key = NULL; + gcry_err_code_t rc; + + REGISTER_DEFAULT_PUBKEYS; + + /* Note we currently support only secret key checking. */ + rc = sexp_to_key (s_key, 1, NULL, &key, &module); + if (! rc) + { + rc = pubkey_check_secret_key (module->mod_id, key); + release_mpi_array (key); + gcry_free (key); + } + return gcry_error (rc); +} + + +/* + Create a public key pair and return it in r_key. + How the key is created depends on s_parms: + (genkey + (algo + (parameter_name_1 ....) + .... + (parameter_name_n ....) + )) + The key is returned in a format depending on the + algorithm. Both, private and secret keys are returned + and optionally some additional informatin. + For elgamal we return this structure: + (key-data + (public-key + (elg + (p <mpi>) + (g <mpi>) + (y <mpi>) + ) + ) + (private-key + (elg + (p <mpi>) + (g <mpi>) + (y <mpi>) + (x <mpi>) + ) + ) + (misc-key-info + (pm1-factors n1 n2 ... nn) + )) + */ +gcry_error_t +gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) +{ + gcry_pk_spec_t *pubkey = NULL; + gcry_module_t module = NULL; + gcry_sexp_t list = NULL; + gcry_sexp_t l2 = NULL; + gcry_sexp_t l3 = NULL; + char *name = NULL; + size_t n; + gcry_err_code_t rc = GPG_ERR_NO_ERROR; + int i, j; + const char *algo_name = NULL; + int algo; + const char *sec_elems = NULL, *pub_elems = NULL; + gcry_mpi_t skey[12]; + gcry_mpi_t *factors = NULL; + gcry_sexp_t extrainfo = NULL; + unsigned int nbits = 0; + unsigned long use_e = 0; + + skey[0] = NULL; + *r_key = NULL; + + REGISTER_DEFAULT_PUBKEYS; + + list = gcry_sexp_find_token (s_parms, "genkey", 0); + if (!list) + { + rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */ + goto leave; + } + + l2 = gcry_sexp_cadr (list); + gcry_sexp_release (list); + list = l2; + l2 = NULL; + if (! list) + { + rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */ + goto leave; + } + + name = _gcry_sexp_nth_string (list, 0); + if (!name) + { + rc = GPG_ERR_INV_OBJ; /* Algo string missing. */ + goto leave; + } + + ath_mutex_lock (&pubkeys_registered_lock); + module = gcry_pk_lookup_name (name); + ath_mutex_unlock (&pubkeys_registered_lock); + gcry_free (name); + name = NULL; + if (!module) + { + rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ + goto leave; + } + + pubkey = (gcry_pk_spec_t *) module->spec; + algo = module->mod_id; + algo_name = pubkey->aliases? *pubkey->aliases : NULL; + if (!algo_name || !*algo_name) + algo_name = pubkey->name; + pub_elems = pubkey->elements_pkey; + sec_elems = pubkey->elements_skey; + if (strlen (sec_elems) >= DIM(skey)) + BUG (); + + /* Handle the optional rsa-use-e element. Actually this belong into + the algorithm module but we have this parameter in the public + module API, so we need to parse it right here. */ + l2 = gcry_sexp_find_token (list, "rsa-use-e", 0); + if (l2) + { + char buf[50]; + const char *s; + + s = gcry_sexp_nth_data (l2, 1, &n); + if ( !s || n >= DIM (buf) - 1 ) + { + rc = GPG_ERR_INV_OBJ; /* No value or value too large. */ + goto leave; + } + memcpy (buf, s, n); + buf[n] = 0; + use_e = strtoul (buf, NULL, 0); + gcry_sexp_release (l2); + l2 = NULL; + } + else + use_e = 65537; /* Not given, use the value generated by old versions. */ + + + /* Get the "nbits" parameter. */ + l2 = gcry_sexp_find_token (list, "nbits", 0); + if (l2) + { + char buf[50]; + const char *s; + + s = gcry_sexp_nth_data (l2, 1, &n); + if (!s || n >= DIM (buf) - 1 ) + { + rc = GPG_ERR_INV_OBJ; /* NBITS given without a cdr. */ + goto leave; + } + memcpy (buf, s, n); + buf[n] = 0; + nbits = (unsigned int)strtoul (buf, NULL, 0); + gcry_sexp_release (l2); l2 = NULL; + } + else + nbits = 0; + + /* Pass control to the algorithm module. */ + rc = pubkey_generate (module->mod_id, nbits, use_e, list, skey, + &factors, &extrainfo); + gcry_sexp_release (list); list = NULL; + if (rc) + goto leave; + + /* Key generation succeeded: Build an S-expression. */ + { + char *string, *p; + size_t nelem=0, nelem_cp = 0, needed=0; + gcry_mpi_t mpis[30]; + int percent_s_idx = -1; + + /* Estimate size of format string. */ + nelem = strlen (pub_elems) + strlen (sec_elems); + if (factors) + { + for (i = 0; factors[i]; i++) + nelem++; + } + nelem_cp = nelem; + + needed += nelem * 10; + /* (+5 is for EXTRAINFO ("%S")). */ + needed += 2 * strlen (algo_name) + 300 + 5; + if (nelem > DIM (mpis)) + BUG (); + + /* Build the string. */ + nelem = 0; + string = p = gcry_malloc (needed); + if (!string) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + p = stpcpy (p, "(key-data"); + p = stpcpy (p, "(public-key("); + p = stpcpy (p, algo_name); + for(i = 0; pub_elems[i]; i++) + { + *p++ = '('; + *p++ = pub_elems[i]; + p = stpcpy (p, "%m)"); + mpis[nelem++] = skey[i]; + } + if (extrainfo && (algo == GCRY_PK_ECDSA || algo == GCRY_PK_ECDH)) + { + /* Very ugly hack to insert the used curve parameter into the + list of public key parameters. */ + percent_s_idx = nelem; + p = stpcpy (p, "%S"); + } + p = stpcpy (p, "))"); + p = stpcpy (p, "(private-key("); + p = stpcpy (p, algo_name); + for (i = 0; sec_elems[i]; i++) + { + *p++ = '('; + *p++ = sec_elems[i]; + p = stpcpy (p, "%m)"); + mpis[nelem++] = skey[i]; + } + p = stpcpy (p, "))"); + + /* Hack to make release_mpi_array() work. */ + skey[i] = NULL; + + if (extrainfo && percent_s_idx == -1) + { + /* If we have extrainfo we should not have any factors. */ + p = stpcpy (p, "%S"); + } + else if (factors && factors[0]) + { + p = stpcpy (p, "(misc-key-info(pm1-factors"); + for(i = 0; factors[i]; i++) + { + p = stpcpy (p, "%m"); + mpis[nelem++] = factors[i]; + } + p = stpcpy (p, "))"); + } + strcpy (p, ")"); + gcry_assert (p - string < needed); + + while (nelem < DIM (mpis)) + mpis[nelem++] = NULL; + + { + int elem_n = strlen (pub_elems) + strlen (sec_elems); + void **arg_list; + + /* Allocate one extra for EXTRAINFO ("%S"). */ + arg_list = gcry_calloc (nelem_cp+1, sizeof *arg_list); + if (!arg_list) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + for (i = j = 0; i < elem_n; i++) + { + if (i == percent_s_idx) + arg_list[j++] = &extrainfo; + arg_list[j++] = mpis + i; + } + if (extrainfo && percent_s_idx == -1) + arg_list[j] = &extrainfo; + else if (factors && factors[0]) + { + for (; i < nelem_cp; i++) + arg_list[j++] = factors + i - elem_n; + } + rc = gcry_sexp_build_array (r_key, NULL, string, arg_list); + gcry_free (arg_list); + if (rc) + BUG (); + gcry_assert (DIM (mpis) == 30); /* Reminder to make sure that + the array gets increased if + new parameters are added. */ + } + gcry_free (string); + } + + leave: + gcry_free (name); + gcry_sexp_release (extrainfo); + release_mpi_array (skey); + /* Don't free SKEY itself, it is an stack allocated array. */ + + if (factors) + { + release_mpi_array ( factors ); + gcry_free (factors); + } + + gcry_sexp_release (l3); + gcry_sexp_release (l2); + gcry_sexp_release (list); + + if (module) + { + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + } + + return gcry_error (rc); +} + + +/* + Get the number of nbits from the public key. + + Hmmm: Should we have really this function or is it better to have a + more general function to retrieve different properties of the key? */ +unsigned int +gcry_pk_get_nbits (gcry_sexp_t key) +{ + gcry_module_t module = NULL; + gcry_pk_spec_t *pubkey; + gcry_mpi_t *keyarr = NULL; + unsigned int nbits = 0; + gcry_err_code_t rc; + + REGISTER_DEFAULT_PUBKEYS; + + rc = sexp_to_key (key, 0, NULL, &keyarr, &module); + if (rc == GPG_ERR_INV_OBJ) + rc = sexp_to_key (key, 1, NULL, &keyarr, &module); + if (rc) + return 0; /* Error - 0 is a suitable indication for that. */ + + pubkey = (gcry_pk_spec_t *) module->spec; + nbits = (*pubkey->get_nbits) (module->mod_id, keyarr); + + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + + release_mpi_array (keyarr); + gcry_free (keyarr); + + return nbits; +} + + +/* Return the so called KEYGRIP which is the SHA-1 hash of the public + key parameters expressed in a way depending on the algorithm. + + ARRAY must either be 20 bytes long or NULL; in the latter case a + newly allocated array of that size is returned, otherwise ARRAY or + NULL is returned to indicate an error which is most likely an + unknown algorithm. The function accepts public or secret keys. */ +unsigned char * +gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) +{ + gcry_sexp_t list = NULL, l2 = NULL; + gcry_pk_spec_t *pubkey = NULL; + gcry_module_t module = NULL; + pk_extra_spec_t *extraspec; + const char *s; + char *name = NULL; + int idx; + const char *elems; + gcry_md_hd_t md = NULL; + int okay = 0; + + REGISTER_DEFAULT_PUBKEYS; + + /* Check that the first element is valid. */ + list = gcry_sexp_find_token (key, "public-key", 0); + if (! list) + list = gcry_sexp_find_token (key, "private-key", 0); + if (! list) + list = gcry_sexp_find_token (key, "protected-private-key", 0); + if (! list) + list = gcry_sexp_find_token (key, "shadowed-private-key", 0); + if (! list) + return NULL; /* No public- or private-key object. */ + + l2 = gcry_sexp_cadr (list); + gcry_sexp_release (list); + list = l2; + l2 = NULL; + + name = _gcry_sexp_nth_string (list, 0); + if (!name) + goto fail; /* Invalid structure of object. */ + + ath_mutex_lock (&pubkeys_registered_lock); + module = gcry_pk_lookup_name (name); + ath_mutex_unlock (&pubkeys_registered_lock); + + if (!module) + goto fail; /* Unknown algorithm. */ + + pubkey = (gcry_pk_spec_t *) module->spec; + extraspec = module->extraspec; + + elems = pubkey->elements_grip; + if (!elems) + goto fail; /* No grip parameter. */ + + if (gcry_md_open (&md, GCRY_MD_SHA1, 0)) + goto fail; + + if (extraspec && extraspec->comp_keygrip) + { + /* Module specific method to compute a keygrip. */ + if (extraspec->comp_keygrip (md, list)) + goto fail; + } + else + { + /* Generic method to compute a keygrip. */ + for (idx = 0, s = elems; *s; s++, idx++) + { + const char *data; + size_t datalen; + char buf[30]; + + l2 = gcry_sexp_find_token (list, s, 1); + if (! l2) + goto fail; + data = gcry_sexp_nth_data (l2, 1, &datalen); + if (! data) + goto fail; + + snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen); + gcry_md_write (md, buf, strlen (buf)); + gcry_md_write (md, data, datalen); + gcry_sexp_release (l2); + l2 = NULL; + gcry_md_write (md, ")", 1); + } + } + + if (!array) + { + array = gcry_malloc (20); + if (! array) + goto fail; + } + + memcpy (array, gcry_md_read (md, GCRY_MD_SHA1), 20); + okay = 1; + + fail: + gcry_free (name); + gcry_sexp_release (l2); + gcry_md_close (md); + gcry_sexp_release (list); + return okay? array : NULL; +} + + + +const char * +gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits) +{ + gcry_mpi_t *pkey = NULL; + gcry_sexp_t list = NULL; + gcry_sexp_t l2; + gcry_module_t module = NULL; + pk_extra_spec_t *extraspec; + char *name = NULL; + const char *result = NULL; + int want_private = 1; + + if (r_nbits) + *r_nbits = 0; + + REGISTER_DEFAULT_PUBKEYS; + + if (key) + { + iterator = 0; + + /* Check that the first element is valid. */ + list = gcry_sexp_find_token (key, "public-key", 0); + if (list) + want_private = 0; + if (!list) + list = gcry_sexp_find_token (key, "private-key", 0); + if (!list) + return NULL; /* No public- or private-key object. */ + + l2 = gcry_sexp_cadr (list); + gcry_sexp_release (list); + list = l2; + l2 = NULL; + + name = _gcry_sexp_nth_string (list, 0); + if (!name) + goto leave; /* Invalid structure of object. */ + + /* Get the key. We pass the names of the parameters for + override_elems; this allows to call this function without the + actual public key parameter. */ + if (sexp_to_key (key, want_private, "pabgn", &pkey, &module)) + goto leave; + } + else + { + ath_mutex_lock (&pubkeys_registered_lock); + module = gcry_pk_lookup_name ("ecc"); + ath_mutex_unlock (&pubkeys_registered_lock); + if (!module) + goto leave; + } + + extraspec = module->extraspec; + if (!extraspec || !extraspec->get_curve) + goto leave; + + result = extraspec->get_curve (pkey, iterator, r_nbits); + + leave: + if (pkey) + { + release_mpi_array (pkey); + gcry_free (pkey); + } + if (module) + { + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + } + gcry_free (name); + gcry_sexp_release (list); + return result; +} + + + +gcry_sexp_t +gcry_pk_get_param (int algo, const char *name) +{ + gcry_module_t module = NULL; + pk_extra_spec_t *extraspec; + gcry_sexp_t result = NULL; + + if (algo != GCRY_PK_ECDSA && algo != GCRY_PK_ECDH) + return NULL; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + module = gcry_pk_lookup_name ("ecc"); + ath_mutex_unlock (&pubkeys_registered_lock); + if (module) + { + extraspec = module->extraspec; + if (extraspec && extraspec->get_curve_param) + result = extraspec->get_curve_param (name); + + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + } + return result; +} + + + +gcry_error_t +gcry_pk_ctl (int cmd, void *buffer, size_t buflen) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + REGISTER_DEFAULT_PUBKEYS; + + switch (cmd) + { + case GCRYCTL_DISABLE_ALGO: + /* This one expects a buffer pointing to an integer with the + algo number. */ + if ((! buffer) || (buflen != sizeof (int))) + err = GPG_ERR_INV_ARG; + else + disable_pubkey_algo (*((int *) buffer)); + break; + + default: + err = GPG_ERR_INV_OP; + } + + return gcry_error (err); +} + + +/* Return information about the given algorithm + + WHAT selects the kind of information returned: + + GCRYCTL_TEST_ALGO: + Returns 0 when the specified algorithm is available for use. + Buffer must be NULL, nbytes may have the address of a variable + with the required usage of the algorithm. It may be 0 for don't + care or a combination of the GCRY_PK_USAGE_xxx flags; + + GCRYCTL_GET_ALGO_USAGE: + Return the usage flags for the given algo. An invalid algo + returns 0. Disabled algos are ignored here because we + only want to know whether the algo is at all capable of + the usage. + + Note: Because this function is in most cases used to return an + integer value, we can make it easier for the caller to just look at + the return value. The caller will in all cases consult the value + and thereby detecting whether a error occurred or not (i.e. while + checking the block size) */ +gcry_error_t +gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + switch (what) + { + case GCRYCTL_TEST_ALGO: + { + int use = nbytes ? *nbytes : 0; + if (buffer) + err = GPG_ERR_INV_ARG; + else if (check_pubkey_algo (algorithm, use)) + err = GPG_ERR_PUBKEY_ALGO; + break; + } + + case GCRYCTL_GET_ALGO_USAGE: + { + gcry_module_t pubkey; + int use = 0; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (pubkey) + { + use = ((gcry_pk_spec_t *) pubkey->spec)->use; + _gcry_module_release (pubkey); + } + ath_mutex_unlock (&pubkeys_registered_lock); + + /* FIXME? */ + *nbytes = use; + + break; + } + + case GCRYCTL_GET_ALGO_NPKEY: + { + /* FIXME? */ + int npkey = pubkey_get_npkey (algorithm); + *nbytes = npkey; + break; + } + case GCRYCTL_GET_ALGO_NSKEY: + { + /* FIXME? */ + int nskey = pubkey_get_nskey (algorithm); + *nbytes = nskey; + break; + } + case GCRYCTL_GET_ALGO_NSIGN: + { + /* FIXME? */ + int nsign = pubkey_get_nsig (algorithm); + *nbytes = nsign; + break; + } + case GCRYCTL_GET_ALGO_NENCR: + { + /* FIXME? */ + int nencr = pubkey_get_nenc (algorithm); + *nbytes = nencr; + break; + } + + default: + err = GPG_ERR_INV_OP; + } + + return gcry_error (err); +} + + +/* Explicitly initialize this module. */ +gcry_err_code_t +_gcry_pk_init (void) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + REGISTER_DEFAULT_PUBKEYS; + + return err; +} + + +gcry_err_code_t +_gcry_pk_module_lookup (int algorithm, gcry_module_t *module) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_module_t pubkey; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm); + if (pubkey) + *module = pubkey; + else + err = GPG_ERR_PUBKEY_ALGO; + ath_mutex_unlock (&pubkeys_registered_lock); + + return err; +} + + +void +_gcry_pk_module_release (gcry_module_t module) +{ + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); +} + +/* Get a list consisting of the IDs of the loaded pubkey modules. If + LIST is zero, write the number of loaded pubkey modules to + LIST_LENGTH and return. If LIST is non-zero, the first + *LIST_LENGTH algorithm IDs are stored in LIST, which must be of + according size. In case there are less pubkey modules than + *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */ +gcry_error_t +gcry_pk_list (int *list, int *list_length) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + ath_mutex_lock (&pubkeys_registered_lock); + err = _gcry_module_list (pubkeys_registered, list, list_length); + ath_mutex_unlock (&pubkeys_registered_lock); + + return err; +} + + +/* Run the selftests for pubkey algorithm ALGO with optional reporting + function REPORT. */ +gpg_error_t +_gcry_pk_selftest (int algo, int extended, selftest_report_func_t report) +{ + gcry_module_t module = NULL; + pk_extra_spec_t *extraspec = NULL; + gcry_err_code_t ec = 0; + + REGISTER_DEFAULT_PUBKEYS; + + ath_mutex_lock (&pubkeys_registered_lock); + module = _gcry_module_lookup_id (pubkeys_registered, algo); + if (module && !(module->flags & FLAG_MODULE_DISABLED)) + extraspec = module->extraspec; + ath_mutex_unlock (&pubkeys_registered_lock); + if (extraspec && extraspec->selftest) + ec = extraspec->selftest (algo, extended, report); + else + { + ec = GPG_ERR_PUBKEY_ALGO; + if (report) + report ("pubkey", algo, "module", + module && !(module->flags & FLAG_MODULE_DISABLED)? + "no selftest available" : + module? "algorithm disabled" : "algorithm not found"); + } + + if (module) + { + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + } + return gpg_error (ec); +} + + +/* This function is only used by ac.c! */ +gcry_err_code_t +_gcry_pk_get_elements (int algo, char **enc, char **sig) +{ + gcry_module_t pubkey; + gcry_pk_spec_t *spec; + gcry_err_code_t err; + char *enc_cp; + char *sig_cp; + + REGISTER_DEFAULT_PUBKEYS; + + enc_cp = NULL; + sig_cp = NULL; + spec = NULL; + + pubkey = _gcry_module_lookup_id (pubkeys_registered, algo); + if (! pubkey) + { + err = GPG_ERR_INTERNAL; + goto out; + } + spec = pubkey->spec; + + if (enc) + { + enc_cp = strdup (spec->elements_enc); + if (! enc_cp) + { + err = gpg_err_code_from_syserror (); + goto out; + } + } + + if (sig) + { + sig_cp = strdup (spec->elements_sig); + if (! sig_cp) + { + err = gpg_err_code_from_syserror (); + goto out; + } + } + + if (enc) + *enc = enc_cp; + if (sig) + *sig = sig_cp; + err = 0; + + out: + + _gcry_module_release (pubkey); + if (err) + { + free (enc_cp); + free (sig_cp); + } + + return err; +} diff --git a/grub-core/lib/libgcrypt/cipher/rfc2268.c b/grub-core/lib/libgcrypt/cipher/rfc2268.c new file mode 100644 index 0000000..1c9c8d4 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/rfc2268.c @@ -0,0 +1,344 @@ +/* rfc2268.c - The cipher described in rfc2268; aka Ron's Cipher 2. + * Copyright (C) 2003 Nikos Mavroyanopoulos + * Copyright (C) 2004 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* This implementation was written by Nikos Mavroyanopoulos for GNUTLS + * as a Libgcrypt module (gnutls/lib/x509/rc2.c) and later adapted for + * direct use by Libgcrypt by Werner Koch. This implementation is + * only useful for pkcs#12 decryption. + * + * The implementation here is based on Peter Gutmann's RRC.2 paper. + */ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "g10lib.h" +#include "types.h" +#include "cipher.h" + +#define RFC2268_BLOCKSIZE 8 + +typedef struct +{ + u16 S[64]; +} RFC2268_context; + +static const unsigned char rfc2268_sbox[] = { + 217, 120, 249, 196, 25, 221, 181, 237, + 40, 233, 253, 121, 74, 160, 216, 157, + 198, 126, 55, 131, 43, 118, 83, 142, + 98, 76, 100, 136, 68, 139, 251, 162, + 23, 154, 89, 245, 135, 179, 79, 19, + 97, 69, 109, 141, 9, 129, 125, 50, + 189, 143, 64, 235, 134, 183, 123, 11, + 240, 149, 33, 34, 92, 107, 78, 130, + 84, 214, 101, 147, 206, 96, 178, 28, + 115, 86, 192, 20, 167, 140, 241, 220, + 18, 117, 202, 31, 59, 190, 228, 209, + 66, 61, 212, 48, 163, 60, 182, 38, + 111, 191, 14, 218, 70, 105, 7, 87, + 39, 242, 29, 155, 188, 148, 67, 3, + 248, 17, 199, 246, 144, 239, 62, 231, + 6, 195, 213, 47, 200, 102, 30, 215, + 8, 232, 234, 222, 128, 82, 238, 247, + 132, 170, 114, 172, 53, 77, 106, 42, + 150, 26, 210, 113, 90, 21, 73, 116, + 75, 159, 208, 94, 4, 24, 164, 236, + 194, 224, 65, 110, 15, 81, 203, 204, + 36, 145, 175, 80, 161, 244, 112, 57, + 153, 124, 58, 133, 35, 184, 180, 122, + 252, 2, 54, 91, 37, 85, 151, 49, + 45, 93, 250, 152, 227, 138, 146, 174, + 5, 223, 41, 16, 103, 108, 186, 201, + 211, 0, 230, 207, 225, 158, 168, 44, + 99, 22, 1, 63, 88, 226, 137, 169, + 13, 56, 52, 27, 171, 51, 255, 176, + 187, 72, 12, 95, 185, 177, 205, 46, + 197, 243, 219, 71, 229, 165, 156, 119, + 10, 166, 32, 104, 254, 127, 193, 173 +}; + +#define rotl16(x,n) (((x) << ((u16)(n))) | ((x) >> (16 - (u16)(n)))) +#define rotr16(x,n) (((x) >> ((u16)(n))) | ((x) << (16 - (u16)(n)))) + +static const char *selftest (void); + + +static void +do_encrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) +{ + RFC2268_context *ctx = context; + register int i, j; + u16 word0 = 0, word1 = 0, word2 = 0, word3 = 0; + + word0 = (word0 << 8) | inbuf[1]; + word0 = (word0 << 8) | inbuf[0]; + word1 = (word1 << 8) | inbuf[3]; + word1 = (word1 << 8) | inbuf[2]; + word2 = (word2 << 8) | inbuf[5]; + word2 = (word2 << 8) | inbuf[4]; + word3 = (word3 << 8) | inbuf[7]; + word3 = (word3 << 8) | inbuf[6]; + + for (i = 0; i < 16; i++) + { + j = i * 4; + /* For some reason I cannot combine those steps. */ + word0 += (word1 & ~word3) + (word2 & word3) + ctx->S[j]; + word0 = rotl16(word0, 1); + + word1 += (word2 & ~word0) + (word3 & word0) + ctx->S[j + 1]; + word1 = rotl16(word1, 2); + + word2 += (word3 & ~word1) + (word0 & word1) + ctx->S[j + 2]; + word2 = rotl16(word2, 3); + + word3 += (word0 & ~word2) + (word1 & word2) + ctx->S[j + 3]; + word3 = rotl16(word3, 5); + + if (i == 4 || i == 10) + { + word0 += ctx->S[word3 & 63]; + word1 += ctx->S[word0 & 63]; + word2 += ctx->S[word1 & 63]; + word3 += ctx->S[word2 & 63]; + } + + } + + outbuf[0] = word0 & 255; + outbuf[1] = word0 >> 8; + outbuf[2] = word1 & 255; + outbuf[3] = word1 >> 8; + outbuf[4] = word2 & 255; + outbuf[5] = word2 >> 8; + outbuf[6] = word3 & 255; + outbuf[7] = word3 >> 8; +} + +static void +do_decrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) +{ + RFC2268_context *ctx = context; + register int i, j; + u16 word0 = 0, word1 = 0, word2 = 0, word3 = 0; + + word0 = (word0 << 8) | inbuf[1]; + word0 = (word0 << 8) | inbuf[0]; + word1 = (word1 << 8) | inbuf[3]; + word1 = (word1 << 8) | inbuf[2]; + word2 = (word2 << 8) | inbuf[5]; + word2 = (word2 << 8) | inbuf[4]; + word3 = (word3 << 8) | inbuf[7]; + word3 = (word3 << 8) | inbuf[6]; + + for (i = 15; i >= 0; i--) + { + j = i * 4; + + word3 = rotr16(word3, 5); + word3 -= (word0 & ~word2) + (word1 & word2) + ctx->S[j + 3]; + + word2 = rotr16(word2, 3); + word2 -= (word3 & ~word1) + (word0 & word1) + ctx->S[j + 2]; + + word1 = rotr16(word1, 2); + word1 -= (word2 & ~word0) + (word3 & word0) + ctx->S[j + 1]; + + word0 = rotr16(word0, 1); + word0 -= (word1 & ~word3) + (word2 & word3) + ctx->S[j]; + + if (i == 5 || i == 11) + { + word3 = word3 - ctx->S[word2 & 63]; + word2 = word2 - ctx->S[word1 & 63]; + word1 = word1 - ctx->S[word0 & 63]; + word0 = word0 - ctx->S[word3 & 63]; + } + + } + + outbuf[0] = word0 & 255; + outbuf[1] = word0 >> 8; + outbuf[2] = word1 & 255; + outbuf[3] = word1 >> 8; + outbuf[4] = word2 & 255; + outbuf[5] = word2 >> 8; + outbuf[6] = word3 & 255; + outbuf[7] = word3 >> 8; +} + + +static gpg_err_code_t +setkey_core (void *context, const unsigned char *key, unsigned int keylen, int with_phase2) +{ + static int initialized; + static const char *selftest_failed; + RFC2268_context *ctx = context; + unsigned int i; + unsigned char *S, x; + int len; + int bits = keylen * 8; + + if (!initialized) + { + initialized = 1; + selftest_failed = selftest (); + if (selftest_failed) + log_error ("RFC2268 selftest failed (%s).\n", selftest_failed); + } + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + if (keylen < 40 / 8) /* We want at least 40 bits. */ + return GPG_ERR_INV_KEYLEN; + + S = (unsigned char *) ctx->S; + + for (i = 0; i < keylen; i++) + S[i] = key[i]; + + for (i = keylen; i < 128; i++) + S[i] = rfc2268_sbox[(S[i - keylen] + S[i - 1]) & 255]; + + S[0] = rfc2268_sbox[S[0]]; + + /* Phase 2 - reduce effective key size to "bits". This was not + * discussed in Gutmann's paper. I've copied that from the public + * domain code posted in sci.crypt. */ + if (with_phase2) + { + len = (bits + 7) >> 3; + i = 128 - len; + x = rfc2268_sbox[S[i] & (255 >> (7 & -bits))]; + S[i] = x; + + while (i--) + { + x = rfc2268_sbox[x ^ S[i + len]]; + S[i] = x; + } + } + + /* Make the expanded key, endian independent. */ + for (i = 0; i < 64; i++) + ctx->S[i] = ( (u16) S[i * 2] | (((u16) S[i * 2 + 1]) << 8)); + + return 0; +} + +static gpg_err_code_t +do_setkey (void *context, const unsigned char *key, unsigned int keylen) +{ + return setkey_core (context, key, keylen, 1); +} + +static const char * +selftest (void) +{ + RFC2268_context ctx; + unsigned char scratch[16]; + + /* Test vectors from Peter Gutmann's paper. */ + static unsigned char key_1[] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + static unsigned char plaintext_1[] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static const unsigned char ciphertext_1[] = + { 0x1C, 0x19, 0x8A, 0x83, 0x8D, 0xF0, 0x28, 0xB7 }; + + static unsigned char key_2[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }; + static unsigned char plaintext_2[] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static unsigned char ciphertext_2[] = + { 0x50, 0xDC, 0x01, 0x62, 0xBD, 0x75, 0x7F, 0x31 }; + + /* This one was checked against libmcrypt's RFC2268. */ + static unsigned char key_3[] = + { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + static unsigned char plaintext_3[] = + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static unsigned char ciphertext_3[] = + { 0x8f, 0xd1, 0x03, 0x89, 0x33, 0x6b, 0xf9, 0x5e }; + + + /* First test. */ + setkey_core (&ctx, key_1, sizeof(key_1), 0); + do_encrypt (&ctx, scratch, plaintext_1); + + if (memcmp (scratch, ciphertext_1, sizeof(ciphertext_1))) + return "RFC2268 encryption test 1 failed."; + + setkey_core (&ctx, key_1, sizeof(key_1), 0); + do_decrypt (&ctx, scratch, scratch); + if (memcmp (scratch, plaintext_1, sizeof(plaintext_1))) + return "RFC2268 decryption test 1 failed."; + + /* Second test. */ + setkey_core (&ctx, key_2, sizeof(key_2), 0); + do_encrypt (&ctx, scratch, plaintext_2); + if (memcmp (scratch, ciphertext_2, sizeof(ciphertext_2))) + return "RFC2268 encryption test 2 failed."; + + setkey_core (&ctx, key_2, sizeof(key_2), 0); + do_decrypt (&ctx, scratch, scratch); + if (memcmp (scratch, plaintext_2, sizeof(plaintext_2))) + return "RFC2268 decryption test 2 failed."; + + /* Third test. */ + setkey_core(&ctx, key_3, sizeof(key_3), 0); + do_encrypt(&ctx, scratch, plaintext_3); + + if (memcmp(scratch, ciphertext_3, sizeof(ciphertext_3))) + return "RFC2268 encryption test 3 failed."; + + setkey_core (&ctx, key_3, sizeof(key_3), 0); + do_decrypt (&ctx, scratch, scratch); + if (memcmp(scratch, plaintext_3, sizeof(plaintext_3))) + return "RFC2268 decryption test 3 failed."; + + return NULL; +} + + + +static gcry_cipher_oid_spec_t oids_rfc2268_40[] = + { + /*{ "1.2.840.113549.3.2", GCRY_CIPHER_MODE_CBC },*/ + /* pbeWithSHAAnd40BitRC2_CBC */ + { "1.2.840.113549.1.12.1.6", GCRY_CIPHER_MODE_CBC }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_40 = { + "RFC2268_40", NULL, oids_rfc2268_40, + RFC2268_BLOCKSIZE, 40, sizeof(RFC2268_context), + do_setkey, do_encrypt, do_decrypt +}; diff --git a/grub-core/lib/libgcrypt/cipher/rijndael-tables.h b/grub-core/lib/libgcrypt/cipher/rijndael-tables.h new file mode 100644 index 0000000..b6a5b15 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/rijndael-tables.h @@ -0,0 +1,1686 @@ +/* rijndael-tables.h - Rijndael (AES) for GnuPG, + * Copyright (C) 2000, 2001, 2002, 2003, 2007, + * 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* To keep the actual implementation at a readable size we use this + include file to define the tables. */ + +static const unsigned char S[256] = + { + 99, 124, 119, 123, 242, 107, 111, 197, + 48, 1, 103, 43, 254, 215, 171, 118, + 202, 130, 201, 125, 250, 89, 71, 240, + 173, 212, 162, 175, 156, 164, 114, 192, + 183, 253, 147, 38, 54, 63, 247, 204, + 52, 165, 229, 241, 113, 216, 49, 21, + 4, 199, 35, 195, 24, 150, 5, 154, + 7, 18, 128, 226, 235, 39, 178, 117, + 9, 131, 44, 26, 27, 110, 90, 160, + 82, 59, 214, 179, 41, 227, 47, 132, + 83, 209, 0, 237, 32, 252, 177, 91, + 106, 203, 190, 57, 74, 76, 88, 207, + 208, 239, 170, 251, 67, 77, 51, 133, + 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, + 188, 182, 218, 33, 16, 255, 243, 210, + 205, 12, 19, 236, 95, 151, 68, 23, + 196, 167, 126, 61, 100, 93, 25, 115, + 96, 129, 79, 220, 34, 42, 144, 136, + 70, 238, 184, 20, 222, 94, 11, 219, + 224, 50, 58, 10, 73, 6, 36, 92, + 194, 211, 172, 98, 145, 149, 228, 121, + 231, 200, 55, 109, 141, 213, 78, 169, + 108, 86, 244, 234, 101, 122, 174, 8, + 186, 120, 37, 46, 28, 166, 180, 198, + 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, + 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, + 155, 30, 135, 233, 206, 85, 40, 223, + 140, 161, 137, 13, 191, 230, 66, 104, + 65, 153, 45, 15, 176, 84, 187, 22 + }; + + +static const unsigned char T1[256][4] = + { + { 0xc6,0x63,0x63,0xa5 }, { 0xf8,0x7c,0x7c,0x84 }, + { 0xee,0x77,0x77,0x99 }, { 0xf6,0x7b,0x7b,0x8d }, + { 0xff,0xf2,0xf2,0x0d }, { 0xd6,0x6b,0x6b,0xbd }, + { 0xde,0x6f,0x6f,0xb1 }, { 0x91,0xc5,0xc5,0x54 }, + { 0x60,0x30,0x30,0x50 }, { 0x02,0x01,0x01,0x03 }, + { 0xce,0x67,0x67,0xa9 }, { 0x56,0x2b,0x2b,0x7d }, + { 0xe7,0xfe,0xfe,0x19 }, { 0xb5,0xd7,0xd7,0x62 }, + { 0x4d,0xab,0xab,0xe6 }, { 0xec,0x76,0x76,0x9a }, + { 0x8f,0xca,0xca,0x45 }, { 0x1f,0x82,0x82,0x9d }, + { 0x89,0xc9,0xc9,0x40 }, { 0xfa,0x7d,0x7d,0x87 }, + { 0xef,0xfa,0xfa,0x15 }, { 0xb2,0x59,0x59,0xeb }, + { 0x8e,0x47,0x47,0xc9 }, { 0xfb,0xf0,0xf0,0x0b }, + { 0x41,0xad,0xad,0xec }, { 0xb3,0xd4,0xd4,0x67 }, + { 0x5f,0xa2,0xa2,0xfd }, { 0x45,0xaf,0xaf,0xea }, + { 0x23,0x9c,0x9c,0xbf }, { 0x53,0xa4,0xa4,0xf7 }, + { 0xe4,0x72,0x72,0x96 }, { 0x9b,0xc0,0xc0,0x5b }, + { 0x75,0xb7,0xb7,0xc2 }, { 0xe1,0xfd,0xfd,0x1c }, + { 0x3d,0x93,0x93,0xae }, { 0x4c,0x26,0x26,0x6a }, + { 0x6c,0x36,0x36,0x5a }, { 0x7e,0x3f,0x3f,0x41 }, + { 0xf5,0xf7,0xf7,0x02 }, { 0x83,0xcc,0xcc,0x4f }, + { 0x68,0x34,0x34,0x5c }, { 0x51,0xa5,0xa5,0xf4 }, + { 0xd1,0xe5,0xe5,0x34 }, { 0xf9,0xf1,0xf1,0x08 }, + { 0xe2,0x71,0x71,0x93 }, { 0xab,0xd8,0xd8,0x73 }, + { 0x62,0x31,0x31,0x53 }, { 0x2a,0x15,0x15,0x3f }, + { 0x08,0x04,0x04,0x0c }, { 0x95,0xc7,0xc7,0x52 }, + { 0x46,0x23,0x23,0x65 }, { 0x9d,0xc3,0xc3,0x5e }, + { 0x30,0x18,0x18,0x28 }, { 0x37,0x96,0x96,0xa1 }, + { 0x0a,0x05,0x05,0x0f }, { 0x2f,0x9a,0x9a,0xb5 }, + { 0x0e,0x07,0x07,0x09 }, { 0x24,0x12,0x12,0x36 }, + { 0x1b,0x80,0x80,0x9b }, { 0xdf,0xe2,0xe2,0x3d }, + { 0xcd,0xeb,0xeb,0x26 }, { 0x4e,0x27,0x27,0x69 }, + { 0x7f,0xb2,0xb2,0xcd }, { 0xea,0x75,0x75,0x9f }, + { 0x12,0x09,0x09,0x1b }, { 0x1d,0x83,0x83,0x9e }, + { 0x58,0x2c,0x2c,0x74 }, { 0x34,0x1a,0x1a,0x2e }, + { 0x36,0x1b,0x1b,0x2d }, { 0xdc,0x6e,0x6e,0xb2 }, + { 0xb4,0x5a,0x5a,0xee }, { 0x5b,0xa0,0xa0,0xfb }, + { 0xa4,0x52,0x52,0xf6 }, { 0x76,0x3b,0x3b,0x4d }, + { 0xb7,0xd6,0xd6,0x61 }, { 0x7d,0xb3,0xb3,0xce }, + { 0x52,0x29,0x29,0x7b }, { 0xdd,0xe3,0xe3,0x3e }, + { 0x5e,0x2f,0x2f,0x71 }, { 0x13,0x84,0x84,0x97 }, + { 0xa6,0x53,0x53,0xf5 }, { 0xb9,0xd1,0xd1,0x68 }, + { 0x00,0x00,0x00,0x00 }, { 0xc1,0xed,0xed,0x2c }, + { 0x40,0x20,0x20,0x60 }, { 0xe3,0xfc,0xfc,0x1f }, + { 0x79,0xb1,0xb1,0xc8 }, { 0xb6,0x5b,0x5b,0xed }, + { 0xd4,0x6a,0x6a,0xbe }, { 0x8d,0xcb,0xcb,0x46 }, + { 0x67,0xbe,0xbe,0xd9 }, { 0x72,0x39,0x39,0x4b }, + { 0x94,0x4a,0x4a,0xde }, { 0x98,0x4c,0x4c,0xd4 }, + { 0xb0,0x58,0x58,0xe8 }, { 0x85,0xcf,0xcf,0x4a }, + { 0xbb,0xd0,0xd0,0x6b }, { 0xc5,0xef,0xef,0x2a }, + { 0x4f,0xaa,0xaa,0xe5 }, { 0xed,0xfb,0xfb,0x16 }, + { 0x86,0x43,0x43,0xc5 }, { 0x9a,0x4d,0x4d,0xd7 }, + { 0x66,0x33,0x33,0x55 }, { 0x11,0x85,0x85,0x94 }, + { 0x8a,0x45,0x45,0xcf }, { 0xe9,0xf9,0xf9,0x10 }, + { 0x04,0x02,0x02,0x06 }, { 0xfe,0x7f,0x7f,0x81 }, + { 0xa0,0x50,0x50,0xf0 }, { 0x78,0x3c,0x3c,0x44 }, + { 0x25,0x9f,0x9f,0xba }, { 0x4b,0xa8,0xa8,0xe3 }, + { 0xa2,0x51,0x51,0xf3 }, { 0x5d,0xa3,0xa3,0xfe }, + { 0x80,0x40,0x40,0xc0 }, { 0x05,0x8f,0x8f,0x8a }, + { 0x3f,0x92,0x92,0xad }, { 0x21,0x9d,0x9d,0xbc }, + { 0x70,0x38,0x38,0x48 }, { 0xf1,0xf5,0xf5,0x04 }, + { 0x63,0xbc,0xbc,0xdf }, { 0x77,0xb6,0xb6,0xc1 }, + { 0xaf,0xda,0xda,0x75 }, { 0x42,0x21,0x21,0x63 }, + { 0x20,0x10,0x10,0x30 }, { 0xe5,0xff,0xff,0x1a }, + { 0xfd,0xf3,0xf3,0x0e }, { 0xbf,0xd2,0xd2,0x6d }, + { 0x81,0xcd,0xcd,0x4c }, { 0x18,0x0c,0x0c,0x14 }, + { 0x26,0x13,0x13,0x35 }, { 0xc3,0xec,0xec,0x2f }, + { 0xbe,0x5f,0x5f,0xe1 }, { 0x35,0x97,0x97,0xa2 }, + { 0x88,0x44,0x44,0xcc }, { 0x2e,0x17,0x17,0x39 }, + { 0x93,0xc4,0xc4,0x57 }, { 0x55,0xa7,0xa7,0xf2 }, + { 0xfc,0x7e,0x7e,0x82 }, { 0x7a,0x3d,0x3d,0x47 }, + { 0xc8,0x64,0x64,0xac }, { 0xba,0x5d,0x5d,0xe7 }, + { 0x32,0x19,0x19,0x2b }, { 0xe6,0x73,0x73,0x95 }, + { 0xc0,0x60,0x60,0xa0 }, { 0x19,0x81,0x81,0x98 }, + { 0x9e,0x4f,0x4f,0xd1 }, { 0xa3,0xdc,0xdc,0x7f }, + { 0x44,0x22,0x22,0x66 }, { 0x54,0x2a,0x2a,0x7e }, + { 0x3b,0x90,0x90,0xab }, { 0x0b,0x88,0x88,0x83 }, + { 0x8c,0x46,0x46,0xca }, { 0xc7,0xee,0xee,0x29 }, + { 0x6b,0xb8,0xb8,0xd3 }, { 0x28,0x14,0x14,0x3c }, + { 0xa7,0xde,0xde,0x79 }, { 0xbc,0x5e,0x5e,0xe2 }, + { 0x16,0x0b,0x0b,0x1d }, { 0xad,0xdb,0xdb,0x76 }, + { 0xdb,0xe0,0xe0,0x3b }, { 0x64,0x32,0x32,0x56 }, + { 0x74,0x3a,0x3a,0x4e }, { 0x14,0x0a,0x0a,0x1e }, + { 0x92,0x49,0x49,0xdb }, { 0x0c,0x06,0x06,0x0a }, + { 0x48,0x24,0x24,0x6c }, { 0xb8,0x5c,0x5c,0xe4 }, + { 0x9f,0xc2,0xc2,0x5d }, { 0xbd,0xd3,0xd3,0x6e }, + { 0x43,0xac,0xac,0xef }, { 0xc4,0x62,0x62,0xa6 }, + { 0x39,0x91,0x91,0xa8 }, { 0x31,0x95,0x95,0xa4 }, + { 0xd3,0xe4,0xe4,0x37 }, { 0xf2,0x79,0x79,0x8b }, + { 0xd5,0xe7,0xe7,0x32 }, { 0x8b,0xc8,0xc8,0x43 }, + { 0x6e,0x37,0x37,0x59 }, { 0xda,0x6d,0x6d,0xb7 }, + { 0x01,0x8d,0x8d,0x8c }, { 0xb1,0xd5,0xd5,0x64 }, + { 0x9c,0x4e,0x4e,0xd2 }, { 0x49,0xa9,0xa9,0xe0 }, + { 0xd8,0x6c,0x6c,0xb4 }, { 0xac,0x56,0x56,0xfa }, + { 0xf3,0xf4,0xf4,0x07 }, { 0xcf,0xea,0xea,0x25 }, + { 0xca,0x65,0x65,0xaf }, { 0xf4,0x7a,0x7a,0x8e }, + { 0x47,0xae,0xae,0xe9 }, { 0x10,0x08,0x08,0x18 }, + { 0x6f,0xba,0xba,0xd5 }, { 0xf0,0x78,0x78,0x88 }, + { 0x4a,0x25,0x25,0x6f }, { 0x5c,0x2e,0x2e,0x72 }, + { 0x38,0x1c,0x1c,0x24 }, { 0x57,0xa6,0xa6,0xf1 }, + { 0x73,0xb4,0xb4,0xc7 }, { 0x97,0xc6,0xc6,0x51 }, + { 0xcb,0xe8,0xe8,0x23 }, { 0xa1,0xdd,0xdd,0x7c }, + { 0xe8,0x74,0x74,0x9c }, { 0x3e,0x1f,0x1f,0x21 }, + { 0x96,0x4b,0x4b,0xdd }, { 0x61,0xbd,0xbd,0xdc }, + { 0x0d,0x8b,0x8b,0x86 }, { 0x0f,0x8a,0x8a,0x85 }, + { 0xe0,0x70,0x70,0x90 }, { 0x7c,0x3e,0x3e,0x42 }, + { 0x71,0xb5,0xb5,0xc4 }, { 0xcc,0x66,0x66,0xaa }, + { 0x90,0x48,0x48,0xd8 }, { 0x06,0x03,0x03,0x05 }, + { 0xf7,0xf6,0xf6,0x01 }, { 0x1c,0x0e,0x0e,0x12 }, + { 0xc2,0x61,0x61,0xa3 }, { 0x6a,0x35,0x35,0x5f }, + { 0xae,0x57,0x57,0xf9 }, { 0x69,0xb9,0xb9,0xd0 }, + { 0x17,0x86,0x86,0x91 }, { 0x99,0xc1,0xc1,0x58 }, + { 0x3a,0x1d,0x1d,0x27 }, { 0x27,0x9e,0x9e,0xb9 }, + { 0xd9,0xe1,0xe1,0x38 }, { 0xeb,0xf8,0xf8,0x13 }, + { 0x2b,0x98,0x98,0xb3 }, { 0x22,0x11,0x11,0x33 }, + { 0xd2,0x69,0x69,0xbb }, { 0xa9,0xd9,0xd9,0x70 }, + { 0x07,0x8e,0x8e,0x89 }, { 0x33,0x94,0x94,0xa7 }, + { 0x2d,0x9b,0x9b,0xb6 }, { 0x3c,0x1e,0x1e,0x22 }, + { 0x15,0x87,0x87,0x92 }, { 0xc9,0xe9,0xe9,0x20 }, + { 0x87,0xce,0xce,0x49 }, { 0xaa,0x55,0x55,0xff }, + { 0x50,0x28,0x28,0x78 }, { 0xa5,0xdf,0xdf,0x7a }, + { 0x03,0x8c,0x8c,0x8f }, { 0x59,0xa1,0xa1,0xf8 }, + { 0x09,0x89,0x89,0x80 }, { 0x1a,0x0d,0x0d,0x17 }, + { 0x65,0xbf,0xbf,0xda }, { 0xd7,0xe6,0xe6,0x31 }, + { 0x84,0x42,0x42,0xc6 }, { 0xd0,0x68,0x68,0xb8 }, + { 0x82,0x41,0x41,0xc3 }, { 0x29,0x99,0x99,0xb0 }, + { 0x5a,0x2d,0x2d,0x77 }, { 0x1e,0x0f,0x0f,0x11 }, + { 0x7b,0xb0,0xb0,0xcb }, { 0xa8,0x54,0x54,0xfc }, + { 0x6d,0xbb,0xbb,0xd6 }, { 0x2c,0x16,0x16,0x3a } + }; + +static const unsigned char T2[256][4] = + { + { 0xa5,0xc6,0x63,0x63 }, { 0x84,0xf8,0x7c,0x7c }, + { 0x99,0xee,0x77,0x77 }, { 0x8d,0xf6,0x7b,0x7b }, + { 0x0d,0xff,0xf2,0xf2 }, { 0xbd,0xd6,0x6b,0x6b }, + { 0xb1,0xde,0x6f,0x6f }, { 0x54,0x91,0xc5,0xc5 }, + { 0x50,0x60,0x30,0x30 }, { 0x03,0x02,0x01,0x01 }, + { 0xa9,0xce,0x67,0x67 }, { 0x7d,0x56,0x2b,0x2b }, + { 0x19,0xe7,0xfe,0xfe }, { 0x62,0xb5,0xd7,0xd7 }, + { 0xe6,0x4d,0xab,0xab }, { 0x9a,0xec,0x76,0x76 }, + { 0x45,0x8f,0xca,0xca }, { 0x9d,0x1f,0x82,0x82 }, + { 0x40,0x89,0xc9,0xc9 }, { 0x87,0xfa,0x7d,0x7d }, + { 0x15,0xef,0xfa,0xfa }, { 0xeb,0xb2,0x59,0x59 }, + { 0xc9,0x8e,0x47,0x47 }, { 0x0b,0xfb,0xf0,0xf0 }, + { 0xec,0x41,0xad,0xad }, { 0x67,0xb3,0xd4,0xd4 }, + { 0xfd,0x5f,0xa2,0xa2 }, { 0xea,0x45,0xaf,0xaf }, + { 0xbf,0x23,0x9c,0x9c }, { 0xf7,0x53,0xa4,0xa4 }, + { 0x96,0xe4,0x72,0x72 }, { 0x5b,0x9b,0xc0,0xc0 }, + { 0xc2,0x75,0xb7,0xb7 }, { 0x1c,0xe1,0xfd,0xfd }, + { 0xae,0x3d,0x93,0x93 }, { 0x6a,0x4c,0x26,0x26 }, + { 0x5a,0x6c,0x36,0x36 }, { 0x41,0x7e,0x3f,0x3f }, + { 0x02,0xf5,0xf7,0xf7 }, { 0x4f,0x83,0xcc,0xcc }, + { 0x5c,0x68,0x34,0x34 }, { 0xf4,0x51,0xa5,0xa5 }, + { 0x34,0xd1,0xe5,0xe5 }, { 0x08,0xf9,0xf1,0xf1 }, + { 0x93,0xe2,0x71,0x71 }, { 0x73,0xab,0xd8,0xd8 }, + { 0x53,0x62,0x31,0x31 }, { 0x3f,0x2a,0x15,0x15 }, + { 0x0c,0x08,0x04,0x04 }, { 0x52,0x95,0xc7,0xc7 }, + { 0x65,0x46,0x23,0x23 }, { 0x5e,0x9d,0xc3,0xc3 }, + { 0x28,0x30,0x18,0x18 }, { 0xa1,0x37,0x96,0x96 }, + { 0x0f,0x0a,0x05,0x05 }, { 0xb5,0x2f,0x9a,0x9a }, + { 0x09,0x0e,0x07,0x07 }, { 0x36,0x24,0x12,0x12 }, + { 0x9b,0x1b,0x80,0x80 }, { 0x3d,0xdf,0xe2,0xe2 }, + { 0x26,0xcd,0xeb,0xeb }, { 0x69,0x4e,0x27,0x27 }, + { 0xcd,0x7f,0xb2,0xb2 }, { 0x9f,0xea,0x75,0x75 }, + { 0x1b,0x12,0x09,0x09 }, { 0x9e,0x1d,0x83,0x83 }, + { 0x74,0x58,0x2c,0x2c }, { 0x2e,0x34,0x1a,0x1a }, + { 0x2d,0x36,0x1b,0x1b }, { 0xb2,0xdc,0x6e,0x6e }, + { 0xee,0xb4,0x5a,0x5a }, { 0xfb,0x5b,0xa0,0xa0 }, + { 0xf6,0xa4,0x52,0x52 }, { 0x4d,0x76,0x3b,0x3b }, + { 0x61,0xb7,0xd6,0xd6 }, { 0xce,0x7d,0xb3,0xb3 }, + { 0x7b,0x52,0x29,0x29 }, { 0x3e,0xdd,0xe3,0xe3 }, + { 0x71,0x5e,0x2f,0x2f }, { 0x97,0x13,0x84,0x84 }, + { 0xf5,0xa6,0x53,0x53 }, { 0x68,0xb9,0xd1,0xd1 }, + { 0x00,0x00,0x00,0x00 }, { 0x2c,0xc1,0xed,0xed }, + { 0x60,0x40,0x20,0x20 }, { 0x1f,0xe3,0xfc,0xfc }, + { 0xc8,0x79,0xb1,0xb1 }, { 0xed,0xb6,0x5b,0x5b }, + { 0xbe,0xd4,0x6a,0x6a }, { 0x46,0x8d,0xcb,0xcb }, + { 0xd9,0x67,0xbe,0xbe }, { 0x4b,0x72,0x39,0x39 }, + { 0xde,0x94,0x4a,0x4a }, { 0xd4,0x98,0x4c,0x4c }, + { 0xe8,0xb0,0x58,0x58 }, { 0x4a,0x85,0xcf,0xcf }, + { 0x6b,0xbb,0xd0,0xd0 }, { 0x2a,0xc5,0xef,0xef }, + { 0xe5,0x4f,0xaa,0xaa }, { 0x16,0xed,0xfb,0xfb }, + { 0xc5,0x86,0x43,0x43 }, { 0xd7,0x9a,0x4d,0x4d }, + { 0x55,0x66,0x33,0x33 }, { 0x94,0x11,0x85,0x85 }, + { 0xcf,0x8a,0x45,0x45 }, { 0x10,0xe9,0xf9,0xf9 }, + { 0x06,0x04,0x02,0x02 }, { 0x81,0xfe,0x7f,0x7f }, + { 0xf0,0xa0,0x50,0x50 }, { 0x44,0x78,0x3c,0x3c }, + { 0xba,0x25,0x9f,0x9f }, { 0xe3,0x4b,0xa8,0xa8 }, + { 0xf3,0xa2,0x51,0x51 }, { 0xfe,0x5d,0xa3,0xa3 }, + { 0xc0,0x80,0x40,0x40 }, { 0x8a,0x05,0x8f,0x8f }, + { 0xad,0x3f,0x92,0x92 }, { 0xbc,0x21,0x9d,0x9d }, + { 0x48,0x70,0x38,0x38 }, { 0x04,0xf1,0xf5,0xf5 }, + { 0xdf,0x63,0xbc,0xbc }, { 0xc1,0x77,0xb6,0xb6 }, + { 0x75,0xaf,0xda,0xda }, { 0x63,0x42,0x21,0x21 }, + { 0x30,0x20,0x10,0x10 }, { 0x1a,0xe5,0xff,0xff }, + { 0x0e,0xfd,0xf3,0xf3 }, { 0x6d,0xbf,0xd2,0xd2 }, + { 0x4c,0x81,0xcd,0xcd }, { 0x14,0x18,0x0c,0x0c }, + { 0x35,0x26,0x13,0x13 }, { 0x2f,0xc3,0xec,0xec }, + { 0xe1,0xbe,0x5f,0x5f }, { 0xa2,0x35,0x97,0x97 }, + { 0xcc,0x88,0x44,0x44 }, { 0x39,0x2e,0x17,0x17 }, + { 0x57,0x93,0xc4,0xc4 }, { 0xf2,0x55,0xa7,0xa7 }, + { 0x82,0xfc,0x7e,0x7e }, { 0x47,0x7a,0x3d,0x3d }, + { 0xac,0xc8,0x64,0x64 }, { 0xe7,0xba,0x5d,0x5d }, + { 0x2b,0x32,0x19,0x19 }, { 0x95,0xe6,0x73,0x73 }, + { 0xa0,0xc0,0x60,0x60 }, { 0x98,0x19,0x81,0x81 }, + { 0xd1,0x9e,0x4f,0x4f }, { 0x7f,0xa3,0xdc,0xdc }, + { 0x66,0x44,0x22,0x22 }, { 0x7e,0x54,0x2a,0x2a }, + { 0xab,0x3b,0x90,0x90 }, { 0x83,0x0b,0x88,0x88 }, + { 0xca,0x8c,0x46,0x46 }, { 0x29,0xc7,0xee,0xee }, + { 0xd3,0x6b,0xb8,0xb8 }, { 0x3c,0x28,0x14,0x14 }, + { 0x79,0xa7,0xde,0xde }, { 0xe2,0xbc,0x5e,0x5e }, + { 0x1d,0x16,0x0b,0x0b }, { 0x76,0xad,0xdb,0xdb }, + { 0x3b,0xdb,0xe0,0xe0 }, { 0x56,0x64,0x32,0x32 }, + { 0x4e,0x74,0x3a,0x3a }, { 0x1e,0x14,0x0a,0x0a }, + { 0xdb,0x92,0x49,0x49 }, { 0x0a,0x0c,0x06,0x06 }, + { 0x6c,0x48,0x24,0x24 }, { 0xe4,0xb8,0x5c,0x5c }, + { 0x5d,0x9f,0xc2,0xc2 }, { 0x6e,0xbd,0xd3,0xd3 }, + { 0xef,0x43,0xac,0xac }, { 0xa6,0xc4,0x62,0x62 }, + { 0xa8,0x39,0x91,0x91 }, { 0xa4,0x31,0x95,0x95 }, + { 0x37,0xd3,0xe4,0xe4 }, { 0x8b,0xf2,0x79,0x79 }, + { 0x32,0xd5,0xe7,0xe7 }, { 0x43,0x8b,0xc8,0xc8 }, + { 0x59,0x6e,0x37,0x37 }, { 0xb7,0xda,0x6d,0x6d }, + { 0x8c,0x01,0x8d,0x8d }, { 0x64,0xb1,0xd5,0xd5 }, + { 0xd2,0x9c,0x4e,0x4e }, { 0xe0,0x49,0xa9,0xa9 }, + { 0xb4,0xd8,0x6c,0x6c }, { 0xfa,0xac,0x56,0x56 }, + { 0x07,0xf3,0xf4,0xf4 }, { 0x25,0xcf,0xea,0xea }, + { 0xaf,0xca,0x65,0x65 }, { 0x8e,0xf4,0x7a,0x7a }, + { 0xe9,0x47,0xae,0xae }, { 0x18,0x10,0x08,0x08 }, + { 0xd5,0x6f,0xba,0xba }, { 0x88,0xf0,0x78,0x78 }, + { 0x6f,0x4a,0x25,0x25 }, { 0x72,0x5c,0x2e,0x2e }, + { 0x24,0x38,0x1c,0x1c }, { 0xf1,0x57,0xa6,0xa6 }, + { 0xc7,0x73,0xb4,0xb4 }, { 0x51,0x97,0xc6,0xc6 }, + { 0x23,0xcb,0xe8,0xe8 }, { 0x7c,0xa1,0xdd,0xdd }, + { 0x9c,0xe8,0x74,0x74 }, { 0x21,0x3e,0x1f,0x1f }, + { 0xdd,0x96,0x4b,0x4b }, { 0xdc,0x61,0xbd,0xbd }, + { 0x86,0x0d,0x8b,0x8b }, { 0x85,0x0f,0x8a,0x8a }, + { 0x90,0xe0,0x70,0x70 }, { 0x42,0x7c,0x3e,0x3e }, + { 0xc4,0x71,0xb5,0xb5 }, { 0xaa,0xcc,0x66,0x66 }, + { 0xd8,0x90,0x48,0x48 }, { 0x05,0x06,0x03,0x03 }, + { 0x01,0xf7,0xf6,0xf6 }, { 0x12,0x1c,0x0e,0x0e }, + { 0xa3,0xc2,0x61,0x61 }, { 0x5f,0x6a,0x35,0x35 }, + { 0xf9,0xae,0x57,0x57 }, { 0xd0,0x69,0xb9,0xb9 }, + { 0x91,0x17,0x86,0x86 }, { 0x58,0x99,0xc1,0xc1 }, + { 0x27,0x3a,0x1d,0x1d }, { 0xb9,0x27,0x9e,0x9e }, + { 0x38,0xd9,0xe1,0xe1 }, { 0x13,0xeb,0xf8,0xf8 }, + { 0xb3,0x2b,0x98,0x98 }, { 0x33,0x22,0x11,0x11 }, + { 0xbb,0xd2,0x69,0x69 }, { 0x70,0xa9,0xd9,0xd9 }, + { 0x89,0x07,0x8e,0x8e }, { 0xa7,0x33,0x94,0x94 }, + { 0xb6,0x2d,0x9b,0x9b }, { 0x22,0x3c,0x1e,0x1e }, + { 0x92,0x15,0x87,0x87 }, { 0x20,0xc9,0xe9,0xe9 }, + { 0x49,0x87,0xce,0xce }, { 0xff,0xaa,0x55,0x55 }, + { 0x78,0x50,0x28,0x28 }, { 0x7a,0xa5,0xdf,0xdf }, + { 0x8f,0x03,0x8c,0x8c }, { 0xf8,0x59,0xa1,0xa1 }, + { 0x80,0x09,0x89,0x89 }, { 0x17,0x1a,0x0d,0x0d }, + { 0xda,0x65,0xbf,0xbf }, { 0x31,0xd7,0xe6,0xe6 }, + { 0xc6,0x84,0x42,0x42 }, { 0xb8,0xd0,0x68,0x68 }, + { 0xc3,0x82,0x41,0x41 }, { 0xb0,0x29,0x99,0x99 }, + { 0x77,0x5a,0x2d,0x2d }, { 0x11,0x1e,0x0f,0x0f }, + { 0xcb,0x7b,0xb0,0xb0 }, { 0xfc,0xa8,0x54,0x54 }, + { 0xd6,0x6d,0xbb,0xbb }, { 0x3a,0x2c,0x16,0x16 } + }; + +static const unsigned char T3[256][4] = + { + { 0x63,0xa5,0xc6,0x63 }, { 0x7c,0x84,0xf8,0x7c }, + { 0x77,0x99,0xee,0x77 }, { 0x7b,0x8d,0xf6,0x7b }, + { 0xf2,0x0d,0xff,0xf2 }, { 0x6b,0xbd,0xd6,0x6b }, + { 0x6f,0xb1,0xde,0x6f }, { 0xc5,0x54,0x91,0xc5 }, + { 0x30,0x50,0x60,0x30 }, { 0x01,0x03,0x02,0x01 }, + { 0x67,0xa9,0xce,0x67 }, { 0x2b,0x7d,0x56,0x2b }, + { 0xfe,0x19,0xe7,0xfe }, { 0xd7,0x62,0xb5,0xd7 }, + { 0xab,0xe6,0x4d,0xab }, { 0x76,0x9a,0xec,0x76 }, + { 0xca,0x45,0x8f,0xca }, { 0x82,0x9d,0x1f,0x82 }, + { 0xc9,0x40,0x89,0xc9 }, { 0x7d,0x87,0xfa,0x7d }, + { 0xfa,0x15,0xef,0xfa }, { 0x59,0xeb,0xb2,0x59 }, + { 0x47,0xc9,0x8e,0x47 }, { 0xf0,0x0b,0xfb,0xf0 }, + { 0xad,0xec,0x41,0xad }, { 0xd4,0x67,0xb3,0xd4 }, + { 0xa2,0xfd,0x5f,0xa2 }, { 0xaf,0xea,0x45,0xaf }, + { 0x9c,0xbf,0x23,0x9c }, { 0xa4,0xf7,0x53,0xa4 }, + { 0x72,0x96,0xe4,0x72 }, { 0xc0,0x5b,0x9b,0xc0 }, + { 0xb7,0xc2,0x75,0xb7 }, { 0xfd,0x1c,0xe1,0xfd }, + { 0x93,0xae,0x3d,0x93 }, { 0x26,0x6a,0x4c,0x26 }, + { 0x36,0x5a,0x6c,0x36 }, { 0x3f,0x41,0x7e,0x3f }, + { 0xf7,0x02,0xf5,0xf7 }, { 0xcc,0x4f,0x83,0xcc }, + { 0x34,0x5c,0x68,0x34 }, { 0xa5,0xf4,0x51,0xa5 }, + { 0xe5,0x34,0xd1,0xe5 }, { 0xf1,0x08,0xf9,0xf1 }, + { 0x71,0x93,0xe2,0x71 }, { 0xd8,0x73,0xab,0xd8 }, + { 0x31,0x53,0x62,0x31 }, { 0x15,0x3f,0x2a,0x15 }, + { 0x04,0x0c,0x08,0x04 }, { 0xc7,0x52,0x95,0xc7 }, + { 0x23,0x65,0x46,0x23 }, { 0xc3,0x5e,0x9d,0xc3 }, + { 0x18,0x28,0x30,0x18 }, { 0x96,0xa1,0x37,0x96 }, + { 0x05,0x0f,0x0a,0x05 }, { 0x9a,0xb5,0x2f,0x9a }, + { 0x07,0x09,0x0e,0x07 }, { 0x12,0x36,0x24,0x12 }, + { 0x80,0x9b,0x1b,0x80 }, { 0xe2,0x3d,0xdf,0xe2 }, + { 0xeb,0x26,0xcd,0xeb }, { 0x27,0x69,0x4e,0x27 }, + { 0xb2,0xcd,0x7f,0xb2 }, { 0x75,0x9f,0xea,0x75 }, + { 0x09,0x1b,0x12,0x09 }, { 0x83,0x9e,0x1d,0x83 }, + { 0x2c,0x74,0x58,0x2c }, { 0x1a,0x2e,0x34,0x1a }, + { 0x1b,0x2d,0x36,0x1b }, { 0x6e,0xb2,0xdc,0x6e }, + { 0x5a,0xee,0xb4,0x5a }, { 0xa0,0xfb,0x5b,0xa0 }, + { 0x52,0xf6,0xa4,0x52 }, { 0x3b,0x4d,0x76,0x3b }, + { 0xd6,0x61,0xb7,0xd6 }, { 0xb3,0xce,0x7d,0xb3 }, + { 0x29,0x7b,0x52,0x29 }, { 0xe3,0x3e,0xdd,0xe3 }, + { 0x2f,0x71,0x5e,0x2f }, { 0x84,0x97,0x13,0x84 }, + { 0x53,0xf5,0xa6,0x53 }, { 0xd1,0x68,0xb9,0xd1 }, + { 0x00,0x00,0x00,0x00 }, { 0xed,0x2c,0xc1,0xed }, + { 0x20,0x60,0x40,0x20 }, { 0xfc,0x1f,0xe3,0xfc }, + { 0xb1,0xc8,0x79,0xb1 }, { 0x5b,0xed,0xb6,0x5b }, + { 0x6a,0xbe,0xd4,0x6a }, { 0xcb,0x46,0x8d,0xcb }, + { 0xbe,0xd9,0x67,0xbe }, { 0x39,0x4b,0x72,0x39 }, + { 0x4a,0xde,0x94,0x4a }, { 0x4c,0xd4,0x98,0x4c }, + { 0x58,0xe8,0xb0,0x58 }, { 0xcf,0x4a,0x85,0xcf }, + { 0xd0,0x6b,0xbb,0xd0 }, { 0xef,0x2a,0xc5,0xef }, + { 0xaa,0xe5,0x4f,0xaa }, { 0xfb,0x16,0xed,0xfb }, + { 0x43,0xc5,0x86,0x43 }, { 0x4d,0xd7,0x9a,0x4d }, + { 0x33,0x55,0x66,0x33 }, { 0x85,0x94,0x11,0x85 }, + { 0x45,0xcf,0x8a,0x45 }, { 0xf9,0x10,0xe9,0xf9 }, + { 0x02,0x06,0x04,0x02 }, { 0x7f,0x81,0xfe,0x7f }, + { 0x50,0xf0,0xa0,0x50 }, { 0x3c,0x44,0x78,0x3c }, + { 0x9f,0xba,0x25,0x9f }, { 0xa8,0xe3,0x4b,0xa8 }, + { 0x51,0xf3,0xa2,0x51 }, { 0xa3,0xfe,0x5d,0xa3 }, + { 0x40,0xc0,0x80,0x40 }, { 0x8f,0x8a,0x05,0x8f }, + { 0x92,0xad,0x3f,0x92 }, { 0x9d,0xbc,0x21,0x9d }, + { 0x38,0x48,0x70,0x38 }, { 0xf5,0x04,0xf1,0xf5 }, + { 0xbc,0xdf,0x63,0xbc }, { 0xb6,0xc1,0x77,0xb6 }, + { 0xda,0x75,0xaf,0xda }, { 0x21,0x63,0x42,0x21 }, + { 0x10,0x30,0x20,0x10 }, { 0xff,0x1a,0xe5,0xff }, + { 0xf3,0x0e,0xfd,0xf3 }, { 0xd2,0x6d,0xbf,0xd2 }, + { 0xcd,0x4c,0x81,0xcd }, { 0x0c,0x14,0x18,0x0c }, + { 0x13,0x35,0x26,0x13 }, { 0xec,0x2f,0xc3,0xec }, + { 0x5f,0xe1,0xbe,0x5f }, { 0x97,0xa2,0x35,0x97 }, + { 0x44,0xcc,0x88,0x44 }, { 0x17,0x39,0x2e,0x17 }, + { 0xc4,0x57,0x93,0xc4 }, { 0xa7,0xf2,0x55,0xa7 }, + { 0x7e,0x82,0xfc,0x7e }, { 0x3d,0x47,0x7a,0x3d }, + { 0x64,0xac,0xc8,0x64 }, { 0x5d,0xe7,0xba,0x5d }, + { 0x19,0x2b,0x32,0x19 }, { 0x73,0x95,0xe6,0x73 }, + { 0x60,0xa0,0xc0,0x60 }, { 0x81,0x98,0x19,0x81 }, + { 0x4f,0xd1,0x9e,0x4f }, { 0xdc,0x7f,0xa3,0xdc }, + { 0x22,0x66,0x44,0x22 }, { 0x2a,0x7e,0x54,0x2a }, + { 0x90,0xab,0x3b,0x90 }, { 0x88,0x83,0x0b,0x88 }, + { 0x46,0xca,0x8c,0x46 }, { 0xee,0x29,0xc7,0xee }, + { 0xb8,0xd3,0x6b,0xb8 }, { 0x14,0x3c,0x28,0x14 }, + { 0xde,0x79,0xa7,0xde }, { 0x5e,0xe2,0xbc,0x5e }, + { 0x0b,0x1d,0x16,0x0b }, { 0xdb,0x76,0xad,0xdb }, + { 0xe0,0x3b,0xdb,0xe0 }, { 0x32,0x56,0x64,0x32 }, + { 0x3a,0x4e,0x74,0x3a }, { 0x0a,0x1e,0x14,0x0a }, + { 0x49,0xdb,0x92,0x49 }, { 0x06,0x0a,0x0c,0x06 }, + { 0x24,0x6c,0x48,0x24 }, { 0x5c,0xe4,0xb8,0x5c }, + { 0xc2,0x5d,0x9f,0xc2 }, { 0xd3,0x6e,0xbd,0xd3 }, + { 0xac,0xef,0x43,0xac }, { 0x62,0xa6,0xc4,0x62 }, + { 0x91,0xa8,0x39,0x91 }, { 0x95,0xa4,0x31,0x95 }, + { 0xe4,0x37,0xd3,0xe4 }, { 0x79,0x8b,0xf2,0x79 }, + { 0xe7,0x32,0xd5,0xe7 }, { 0xc8,0x43,0x8b,0xc8 }, + { 0x37,0x59,0x6e,0x37 }, { 0x6d,0xb7,0xda,0x6d }, + { 0x8d,0x8c,0x01,0x8d }, { 0xd5,0x64,0xb1,0xd5 }, + { 0x4e,0xd2,0x9c,0x4e }, { 0xa9,0xe0,0x49,0xa9 }, + { 0x6c,0xb4,0xd8,0x6c }, { 0x56,0xfa,0xac,0x56 }, + { 0xf4,0x07,0xf3,0xf4 }, { 0xea,0x25,0xcf,0xea }, + { 0x65,0xaf,0xca,0x65 }, { 0x7a,0x8e,0xf4,0x7a }, + { 0xae,0xe9,0x47,0xae }, { 0x08,0x18,0x10,0x08 }, + { 0xba,0xd5,0x6f,0xba }, { 0x78,0x88,0xf0,0x78 }, + { 0x25,0x6f,0x4a,0x25 }, { 0x2e,0x72,0x5c,0x2e }, + { 0x1c,0x24,0x38,0x1c }, { 0xa6,0xf1,0x57,0xa6 }, + { 0xb4,0xc7,0x73,0xb4 }, { 0xc6,0x51,0x97,0xc6 }, + { 0xe8,0x23,0xcb,0xe8 }, { 0xdd,0x7c,0xa1,0xdd }, + { 0x74,0x9c,0xe8,0x74 }, { 0x1f,0x21,0x3e,0x1f }, + { 0x4b,0xdd,0x96,0x4b }, { 0xbd,0xdc,0x61,0xbd }, + { 0x8b,0x86,0x0d,0x8b }, { 0x8a,0x85,0x0f,0x8a }, + { 0x70,0x90,0xe0,0x70 }, { 0x3e,0x42,0x7c,0x3e }, + { 0xb5,0xc4,0x71,0xb5 }, { 0x66,0xaa,0xcc,0x66 }, + { 0x48,0xd8,0x90,0x48 }, { 0x03,0x05,0x06,0x03 }, + { 0xf6,0x01,0xf7,0xf6 }, { 0x0e,0x12,0x1c,0x0e }, + { 0x61,0xa3,0xc2,0x61 }, { 0x35,0x5f,0x6a,0x35 }, + { 0x57,0xf9,0xae,0x57 }, { 0xb9,0xd0,0x69,0xb9 }, + { 0x86,0x91,0x17,0x86 }, { 0xc1,0x58,0x99,0xc1 }, + { 0x1d,0x27,0x3a,0x1d }, { 0x9e,0xb9,0x27,0x9e }, + { 0xe1,0x38,0xd9,0xe1 }, { 0xf8,0x13,0xeb,0xf8 }, + { 0x98,0xb3,0x2b,0x98 }, { 0x11,0x33,0x22,0x11 }, + { 0x69,0xbb,0xd2,0x69 }, { 0xd9,0x70,0xa9,0xd9 }, + { 0x8e,0x89,0x07,0x8e }, { 0x94,0xa7,0x33,0x94 }, + { 0x9b,0xb6,0x2d,0x9b }, { 0x1e,0x22,0x3c,0x1e }, + { 0x87,0x92,0x15,0x87 }, { 0xe9,0x20,0xc9,0xe9 }, + { 0xce,0x49,0x87,0xce }, { 0x55,0xff,0xaa,0x55 }, + { 0x28,0x78,0x50,0x28 }, { 0xdf,0x7a,0xa5,0xdf }, + { 0x8c,0x8f,0x03,0x8c }, { 0xa1,0xf8,0x59,0xa1 }, + { 0x89,0x80,0x09,0x89 }, { 0x0d,0x17,0x1a,0x0d }, + { 0xbf,0xda,0x65,0xbf }, { 0xe6,0x31,0xd7,0xe6 }, + { 0x42,0xc6,0x84,0x42 }, { 0x68,0xb8,0xd0,0x68 }, + { 0x41,0xc3,0x82,0x41 }, { 0x99,0xb0,0x29,0x99 }, + { 0x2d,0x77,0x5a,0x2d }, { 0x0f,0x11,0x1e,0x0f }, + { 0xb0,0xcb,0x7b,0xb0 }, { 0x54,0xfc,0xa8,0x54 }, + { 0xbb,0xd6,0x6d,0xbb }, { 0x16,0x3a,0x2c,0x16 } + }; + +static const unsigned char T4[256][4] = + { + { 0x63,0x63,0xa5,0xc6 }, { 0x7c,0x7c,0x84,0xf8 }, + { 0x77,0x77,0x99,0xee }, { 0x7b,0x7b,0x8d,0xf6 }, + { 0xf2,0xf2,0x0d,0xff }, { 0x6b,0x6b,0xbd,0xd6 }, + { 0x6f,0x6f,0xb1,0xde }, { 0xc5,0xc5,0x54,0x91 }, + { 0x30,0x30,0x50,0x60 }, { 0x01,0x01,0x03,0x02 }, + { 0x67,0x67,0xa9,0xce }, { 0x2b,0x2b,0x7d,0x56 }, + { 0xfe,0xfe,0x19,0xe7 }, { 0xd7,0xd7,0x62,0xb5 }, + { 0xab,0xab,0xe6,0x4d }, { 0x76,0x76,0x9a,0xec }, + { 0xca,0xca,0x45,0x8f }, { 0x82,0x82,0x9d,0x1f }, + { 0xc9,0xc9,0x40,0x89 }, { 0x7d,0x7d,0x87,0xfa }, + { 0xfa,0xfa,0x15,0xef }, { 0x59,0x59,0xeb,0xb2 }, + { 0x47,0x47,0xc9,0x8e }, { 0xf0,0xf0,0x0b,0xfb }, + { 0xad,0xad,0xec,0x41 }, { 0xd4,0xd4,0x67,0xb3 }, + { 0xa2,0xa2,0xfd,0x5f }, { 0xaf,0xaf,0xea,0x45 }, + { 0x9c,0x9c,0xbf,0x23 }, { 0xa4,0xa4,0xf7,0x53 }, + { 0x72,0x72,0x96,0xe4 }, { 0xc0,0xc0,0x5b,0x9b }, + { 0xb7,0xb7,0xc2,0x75 }, { 0xfd,0xfd,0x1c,0xe1 }, + { 0x93,0x93,0xae,0x3d }, { 0x26,0x26,0x6a,0x4c }, + { 0x36,0x36,0x5a,0x6c }, { 0x3f,0x3f,0x41,0x7e }, + { 0xf7,0xf7,0x02,0xf5 }, { 0xcc,0xcc,0x4f,0x83 }, + { 0x34,0x34,0x5c,0x68 }, { 0xa5,0xa5,0xf4,0x51 }, + { 0xe5,0xe5,0x34,0xd1 }, { 0xf1,0xf1,0x08,0xf9 }, + { 0x71,0x71,0x93,0xe2 }, { 0xd8,0xd8,0x73,0xab }, + { 0x31,0x31,0x53,0x62 }, { 0x15,0x15,0x3f,0x2a }, + { 0x04,0x04,0x0c,0x08 }, { 0xc7,0xc7,0x52,0x95 }, + { 0x23,0x23,0x65,0x46 }, { 0xc3,0xc3,0x5e,0x9d }, + { 0x18,0x18,0x28,0x30 }, { 0x96,0x96,0xa1,0x37 }, + { 0x05,0x05,0x0f,0x0a }, { 0x9a,0x9a,0xb5,0x2f }, + { 0x07,0x07,0x09,0x0e }, { 0x12,0x12,0x36,0x24 }, + { 0x80,0x80,0x9b,0x1b }, { 0xe2,0xe2,0x3d,0xdf }, + { 0xeb,0xeb,0x26,0xcd }, { 0x27,0x27,0x69,0x4e }, + { 0xb2,0xb2,0xcd,0x7f }, { 0x75,0x75,0x9f,0xea }, + { 0x09,0x09,0x1b,0x12 }, { 0x83,0x83,0x9e,0x1d }, + { 0x2c,0x2c,0x74,0x58 }, { 0x1a,0x1a,0x2e,0x34 }, + { 0x1b,0x1b,0x2d,0x36 }, { 0x6e,0x6e,0xb2,0xdc }, + { 0x5a,0x5a,0xee,0xb4 }, { 0xa0,0xa0,0xfb,0x5b }, + { 0x52,0x52,0xf6,0xa4 }, { 0x3b,0x3b,0x4d,0x76 }, + { 0xd6,0xd6,0x61,0xb7 }, { 0xb3,0xb3,0xce,0x7d }, + { 0x29,0x29,0x7b,0x52 }, { 0xe3,0xe3,0x3e,0xdd }, + { 0x2f,0x2f,0x71,0x5e }, { 0x84,0x84,0x97,0x13 }, + { 0x53,0x53,0xf5,0xa6 }, { 0xd1,0xd1,0x68,0xb9 }, + { 0x00,0x00,0x00,0x00 }, { 0xed,0xed,0x2c,0xc1 }, + { 0x20,0x20,0x60,0x40 }, { 0xfc,0xfc,0x1f,0xe3 }, + { 0xb1,0xb1,0xc8,0x79 }, { 0x5b,0x5b,0xed,0xb6 }, + { 0x6a,0x6a,0xbe,0xd4 }, { 0xcb,0xcb,0x46,0x8d }, + { 0xbe,0xbe,0xd9,0x67 }, { 0x39,0x39,0x4b,0x72 }, + { 0x4a,0x4a,0xde,0x94 }, { 0x4c,0x4c,0xd4,0x98 }, + { 0x58,0x58,0xe8,0xb0 }, { 0xcf,0xcf,0x4a,0x85 }, + { 0xd0,0xd0,0x6b,0xbb }, { 0xef,0xef,0x2a,0xc5 }, + { 0xaa,0xaa,0xe5,0x4f }, { 0xfb,0xfb,0x16,0xed }, + { 0x43,0x43,0xc5,0x86 }, { 0x4d,0x4d,0xd7,0x9a }, + { 0x33,0x33,0x55,0x66 }, { 0x85,0x85,0x94,0x11 }, + { 0x45,0x45,0xcf,0x8a }, { 0xf9,0xf9,0x10,0xe9 }, + { 0x02,0x02,0x06,0x04 }, { 0x7f,0x7f,0x81,0xfe }, + { 0x50,0x50,0xf0,0xa0 }, { 0x3c,0x3c,0x44,0x78 }, + { 0x9f,0x9f,0xba,0x25 }, { 0xa8,0xa8,0xe3,0x4b }, + { 0x51,0x51,0xf3,0xa2 }, { 0xa3,0xa3,0xfe,0x5d }, + { 0x40,0x40,0xc0,0x80 }, { 0x8f,0x8f,0x8a,0x05 }, + { 0x92,0x92,0xad,0x3f }, { 0x9d,0x9d,0xbc,0x21 }, + { 0x38,0x38,0x48,0x70 }, { 0xf5,0xf5,0x04,0xf1 }, + { 0xbc,0xbc,0xdf,0x63 }, { 0xb6,0xb6,0xc1,0x77 }, + { 0xda,0xda,0x75,0xaf }, { 0x21,0x21,0x63,0x42 }, + { 0x10,0x10,0x30,0x20 }, { 0xff,0xff,0x1a,0xe5 }, + { 0xf3,0xf3,0x0e,0xfd }, { 0xd2,0xd2,0x6d,0xbf }, + { 0xcd,0xcd,0x4c,0x81 }, { 0x0c,0x0c,0x14,0x18 }, + { 0x13,0x13,0x35,0x26 }, { 0xec,0xec,0x2f,0xc3 }, + { 0x5f,0x5f,0xe1,0xbe }, { 0x97,0x97,0xa2,0x35 }, + { 0x44,0x44,0xcc,0x88 }, { 0x17,0x17,0x39,0x2e }, + { 0xc4,0xc4,0x57,0x93 }, { 0xa7,0xa7,0xf2,0x55 }, + { 0x7e,0x7e,0x82,0xfc }, { 0x3d,0x3d,0x47,0x7a }, + { 0x64,0x64,0xac,0xc8 }, { 0x5d,0x5d,0xe7,0xba }, + { 0x19,0x19,0x2b,0x32 }, { 0x73,0x73,0x95,0xe6 }, + { 0x60,0x60,0xa0,0xc0 }, { 0x81,0x81,0x98,0x19 }, + { 0x4f,0x4f,0xd1,0x9e }, { 0xdc,0xdc,0x7f,0xa3 }, + { 0x22,0x22,0x66,0x44 }, { 0x2a,0x2a,0x7e,0x54 }, + { 0x90,0x90,0xab,0x3b }, { 0x88,0x88,0x83,0x0b }, + { 0x46,0x46,0xca,0x8c }, { 0xee,0xee,0x29,0xc7 }, + { 0xb8,0xb8,0xd3,0x6b }, { 0x14,0x14,0x3c,0x28 }, + { 0xde,0xde,0x79,0xa7 }, { 0x5e,0x5e,0xe2,0xbc }, + { 0x0b,0x0b,0x1d,0x16 }, { 0xdb,0xdb,0x76,0xad }, + { 0xe0,0xe0,0x3b,0xdb }, { 0x32,0x32,0x56,0x64 }, + { 0x3a,0x3a,0x4e,0x74 }, { 0x0a,0x0a,0x1e,0x14 }, + { 0x49,0x49,0xdb,0x92 }, { 0x06,0x06,0x0a,0x0c }, + { 0x24,0x24,0x6c,0x48 }, { 0x5c,0x5c,0xe4,0xb8 }, + { 0xc2,0xc2,0x5d,0x9f }, { 0xd3,0xd3,0x6e,0xbd }, + { 0xac,0xac,0xef,0x43 }, { 0x62,0x62,0xa6,0xc4 }, + { 0x91,0x91,0xa8,0x39 }, { 0x95,0x95,0xa4,0x31 }, + { 0xe4,0xe4,0x37,0xd3 }, { 0x79,0x79,0x8b,0xf2 }, + { 0xe7,0xe7,0x32,0xd5 }, { 0xc8,0xc8,0x43,0x8b }, + { 0x37,0x37,0x59,0x6e }, { 0x6d,0x6d,0xb7,0xda }, + { 0x8d,0x8d,0x8c,0x01 }, { 0xd5,0xd5,0x64,0xb1 }, + { 0x4e,0x4e,0xd2,0x9c }, { 0xa9,0xa9,0xe0,0x49 }, + { 0x6c,0x6c,0xb4,0xd8 }, { 0x56,0x56,0xfa,0xac }, + { 0xf4,0xf4,0x07,0xf3 }, { 0xea,0xea,0x25,0xcf }, + { 0x65,0x65,0xaf,0xca }, { 0x7a,0x7a,0x8e,0xf4 }, + { 0xae,0xae,0xe9,0x47 }, { 0x08,0x08,0x18,0x10 }, + { 0xba,0xba,0xd5,0x6f }, { 0x78,0x78,0x88,0xf0 }, + { 0x25,0x25,0x6f,0x4a }, { 0x2e,0x2e,0x72,0x5c }, + { 0x1c,0x1c,0x24,0x38 }, { 0xa6,0xa6,0xf1,0x57 }, + { 0xb4,0xb4,0xc7,0x73 }, { 0xc6,0xc6,0x51,0x97 }, + { 0xe8,0xe8,0x23,0xcb }, { 0xdd,0xdd,0x7c,0xa1 }, + { 0x74,0x74,0x9c,0xe8 }, { 0x1f,0x1f,0x21,0x3e }, + { 0x4b,0x4b,0xdd,0x96 }, { 0xbd,0xbd,0xdc,0x61 }, + { 0x8b,0x8b,0x86,0x0d }, { 0x8a,0x8a,0x85,0x0f }, + { 0x70,0x70,0x90,0xe0 }, { 0x3e,0x3e,0x42,0x7c }, + { 0xb5,0xb5,0xc4,0x71 }, { 0x66,0x66,0xaa,0xcc }, + { 0x48,0x48,0xd8,0x90 }, { 0x03,0x03,0x05,0x06 }, + { 0xf6,0xf6,0x01,0xf7 }, { 0x0e,0x0e,0x12,0x1c }, + { 0x61,0x61,0xa3,0xc2 }, { 0x35,0x35,0x5f,0x6a }, + { 0x57,0x57,0xf9,0xae }, { 0xb9,0xb9,0xd0,0x69 }, + { 0x86,0x86,0x91,0x17 }, { 0xc1,0xc1,0x58,0x99 }, + { 0x1d,0x1d,0x27,0x3a }, { 0x9e,0x9e,0xb9,0x27 }, + { 0xe1,0xe1,0x38,0xd9 }, { 0xf8,0xf8,0x13,0xeb }, + { 0x98,0x98,0xb3,0x2b }, { 0x11,0x11,0x33,0x22 }, + { 0x69,0x69,0xbb,0xd2 }, { 0xd9,0xd9,0x70,0xa9 }, + { 0x8e,0x8e,0x89,0x07 }, { 0x94,0x94,0xa7,0x33 }, + { 0x9b,0x9b,0xb6,0x2d }, { 0x1e,0x1e,0x22,0x3c }, + { 0x87,0x87,0x92,0x15 }, { 0xe9,0xe9,0x20,0xc9 }, + { 0xce,0xce,0x49,0x87 }, { 0x55,0x55,0xff,0xaa }, + { 0x28,0x28,0x78,0x50 }, { 0xdf,0xdf,0x7a,0xa5 }, + { 0x8c,0x8c,0x8f,0x03 }, { 0xa1,0xa1,0xf8,0x59 }, + { 0x89,0x89,0x80,0x09 }, { 0x0d,0x0d,0x17,0x1a }, + { 0xbf,0xbf,0xda,0x65 }, { 0xe6,0xe6,0x31,0xd7 }, + { 0x42,0x42,0xc6,0x84 }, { 0x68,0x68,0xb8,0xd0 }, + { 0x41,0x41,0xc3,0x82 }, { 0x99,0x99,0xb0,0x29 }, + { 0x2d,0x2d,0x77,0x5a }, { 0x0f,0x0f,0x11,0x1e }, + { 0xb0,0xb0,0xcb,0x7b }, { 0x54,0x54,0xfc,0xa8 }, + { 0xbb,0xbb,0xd6,0x6d }, { 0x16,0x16,0x3a,0x2c } + }; + +static const unsigned char T5[256][4] = + { + { 0x51,0xf4,0xa7,0x50 }, { 0x7e,0x41,0x65,0x53 }, + { 0x1a,0x17,0xa4,0xc3 }, { 0x3a,0x27,0x5e,0x96 }, + { 0x3b,0xab,0x6b,0xcb }, { 0x1f,0x9d,0x45,0xf1 }, + { 0xac,0xfa,0x58,0xab }, { 0x4b,0xe3,0x03,0x93 }, + { 0x20,0x30,0xfa,0x55 }, { 0xad,0x76,0x6d,0xf6 }, + { 0x88,0xcc,0x76,0x91 }, { 0xf5,0x02,0x4c,0x25 }, + { 0x4f,0xe5,0xd7,0xfc }, { 0xc5,0x2a,0xcb,0xd7 }, + { 0x26,0x35,0x44,0x80 }, { 0xb5,0x62,0xa3,0x8f }, + { 0xde,0xb1,0x5a,0x49 }, { 0x25,0xba,0x1b,0x67 }, + { 0x45,0xea,0x0e,0x98 }, { 0x5d,0xfe,0xc0,0xe1 }, + { 0xc3,0x2f,0x75,0x02 }, { 0x81,0x4c,0xf0,0x12 }, + { 0x8d,0x46,0x97,0xa3 }, { 0x6b,0xd3,0xf9,0xc6 }, + { 0x03,0x8f,0x5f,0xe7 }, { 0x15,0x92,0x9c,0x95 }, + { 0xbf,0x6d,0x7a,0xeb }, { 0x95,0x52,0x59,0xda }, + { 0xd4,0xbe,0x83,0x2d }, { 0x58,0x74,0x21,0xd3 }, + { 0x49,0xe0,0x69,0x29 }, { 0x8e,0xc9,0xc8,0x44 }, + { 0x75,0xc2,0x89,0x6a }, { 0xf4,0x8e,0x79,0x78 }, + { 0x99,0x58,0x3e,0x6b }, { 0x27,0xb9,0x71,0xdd }, + { 0xbe,0xe1,0x4f,0xb6 }, { 0xf0,0x88,0xad,0x17 }, + { 0xc9,0x20,0xac,0x66 }, { 0x7d,0xce,0x3a,0xb4 }, + { 0x63,0xdf,0x4a,0x18 }, { 0xe5,0x1a,0x31,0x82 }, + { 0x97,0x51,0x33,0x60 }, { 0x62,0x53,0x7f,0x45 }, + { 0xb1,0x64,0x77,0xe0 }, { 0xbb,0x6b,0xae,0x84 }, + { 0xfe,0x81,0xa0,0x1c }, { 0xf9,0x08,0x2b,0x94 }, + { 0x70,0x48,0x68,0x58 }, { 0x8f,0x45,0xfd,0x19 }, + { 0x94,0xde,0x6c,0x87 }, { 0x52,0x7b,0xf8,0xb7 }, + { 0xab,0x73,0xd3,0x23 }, { 0x72,0x4b,0x02,0xe2 }, + { 0xe3,0x1f,0x8f,0x57 }, { 0x66,0x55,0xab,0x2a }, + { 0xb2,0xeb,0x28,0x07 }, { 0x2f,0xb5,0xc2,0x03 }, + { 0x86,0xc5,0x7b,0x9a }, { 0xd3,0x37,0x08,0xa5 }, + { 0x30,0x28,0x87,0xf2 }, { 0x23,0xbf,0xa5,0xb2 }, + { 0x02,0x03,0x6a,0xba }, { 0xed,0x16,0x82,0x5c }, + { 0x8a,0xcf,0x1c,0x2b }, { 0xa7,0x79,0xb4,0x92 }, + { 0xf3,0x07,0xf2,0xf0 }, { 0x4e,0x69,0xe2,0xa1 }, + { 0x65,0xda,0xf4,0xcd }, { 0x06,0x05,0xbe,0xd5 }, + { 0xd1,0x34,0x62,0x1f }, { 0xc4,0xa6,0xfe,0x8a }, + { 0x34,0x2e,0x53,0x9d }, { 0xa2,0xf3,0x55,0xa0 }, + { 0x05,0x8a,0xe1,0x32 }, { 0xa4,0xf6,0xeb,0x75 }, + { 0x0b,0x83,0xec,0x39 }, { 0x40,0x60,0xef,0xaa }, + { 0x5e,0x71,0x9f,0x06 }, { 0xbd,0x6e,0x10,0x51 }, + { 0x3e,0x21,0x8a,0xf9 }, { 0x96,0xdd,0x06,0x3d }, + { 0xdd,0x3e,0x05,0xae }, { 0x4d,0xe6,0xbd,0x46 }, + { 0x91,0x54,0x8d,0xb5 }, { 0x71,0xc4,0x5d,0x05 }, + { 0x04,0x06,0xd4,0x6f }, { 0x60,0x50,0x15,0xff }, + { 0x19,0x98,0xfb,0x24 }, { 0xd6,0xbd,0xe9,0x97 }, + { 0x89,0x40,0x43,0xcc }, { 0x67,0xd9,0x9e,0x77 }, + { 0xb0,0xe8,0x42,0xbd }, { 0x07,0x89,0x8b,0x88 }, + { 0xe7,0x19,0x5b,0x38 }, { 0x79,0xc8,0xee,0xdb }, + { 0xa1,0x7c,0x0a,0x47 }, { 0x7c,0x42,0x0f,0xe9 }, + { 0xf8,0x84,0x1e,0xc9 }, { 0x00,0x00,0x00,0x00 }, + { 0x09,0x80,0x86,0x83 }, { 0x32,0x2b,0xed,0x48 }, + { 0x1e,0x11,0x70,0xac }, { 0x6c,0x5a,0x72,0x4e }, + { 0xfd,0x0e,0xff,0xfb }, { 0x0f,0x85,0x38,0x56 }, + { 0x3d,0xae,0xd5,0x1e }, { 0x36,0x2d,0x39,0x27 }, + { 0x0a,0x0f,0xd9,0x64 }, { 0x68,0x5c,0xa6,0x21 }, + { 0x9b,0x5b,0x54,0xd1 }, { 0x24,0x36,0x2e,0x3a }, + { 0x0c,0x0a,0x67,0xb1 }, { 0x93,0x57,0xe7,0x0f }, + { 0xb4,0xee,0x96,0xd2 }, { 0x1b,0x9b,0x91,0x9e }, + { 0x80,0xc0,0xc5,0x4f }, { 0x61,0xdc,0x20,0xa2 }, + { 0x5a,0x77,0x4b,0x69 }, { 0x1c,0x12,0x1a,0x16 }, + { 0xe2,0x93,0xba,0x0a }, { 0xc0,0xa0,0x2a,0xe5 }, + { 0x3c,0x22,0xe0,0x43 }, { 0x12,0x1b,0x17,0x1d }, + { 0x0e,0x09,0x0d,0x0b }, { 0xf2,0x8b,0xc7,0xad }, + { 0x2d,0xb6,0xa8,0xb9 }, { 0x14,0x1e,0xa9,0xc8 }, + { 0x57,0xf1,0x19,0x85 }, { 0xaf,0x75,0x07,0x4c }, + { 0xee,0x99,0xdd,0xbb }, { 0xa3,0x7f,0x60,0xfd }, + { 0xf7,0x01,0x26,0x9f }, { 0x5c,0x72,0xf5,0xbc }, + { 0x44,0x66,0x3b,0xc5 }, { 0x5b,0xfb,0x7e,0x34 }, + { 0x8b,0x43,0x29,0x76 }, { 0xcb,0x23,0xc6,0xdc }, + { 0xb6,0xed,0xfc,0x68 }, { 0xb8,0xe4,0xf1,0x63 }, + { 0xd7,0x31,0xdc,0xca }, { 0x42,0x63,0x85,0x10 }, + { 0x13,0x97,0x22,0x40 }, { 0x84,0xc6,0x11,0x20 }, + { 0x85,0x4a,0x24,0x7d }, { 0xd2,0xbb,0x3d,0xf8 }, + { 0xae,0xf9,0x32,0x11 }, { 0xc7,0x29,0xa1,0x6d }, + { 0x1d,0x9e,0x2f,0x4b }, { 0xdc,0xb2,0x30,0xf3 }, + { 0x0d,0x86,0x52,0xec }, { 0x77,0xc1,0xe3,0xd0 }, + { 0x2b,0xb3,0x16,0x6c }, { 0xa9,0x70,0xb9,0x99 }, + { 0x11,0x94,0x48,0xfa }, { 0x47,0xe9,0x64,0x22 }, + { 0xa8,0xfc,0x8c,0xc4 }, { 0xa0,0xf0,0x3f,0x1a }, + { 0x56,0x7d,0x2c,0xd8 }, { 0x22,0x33,0x90,0xef }, + { 0x87,0x49,0x4e,0xc7 }, { 0xd9,0x38,0xd1,0xc1 }, + { 0x8c,0xca,0xa2,0xfe }, { 0x98,0xd4,0x0b,0x36 }, + { 0xa6,0xf5,0x81,0xcf }, { 0xa5,0x7a,0xde,0x28 }, + { 0xda,0xb7,0x8e,0x26 }, { 0x3f,0xad,0xbf,0xa4 }, + { 0x2c,0x3a,0x9d,0xe4 }, { 0x50,0x78,0x92,0x0d }, + { 0x6a,0x5f,0xcc,0x9b }, { 0x54,0x7e,0x46,0x62 }, + { 0xf6,0x8d,0x13,0xc2 }, { 0x90,0xd8,0xb8,0xe8 }, + { 0x2e,0x39,0xf7,0x5e }, { 0x82,0xc3,0xaf,0xf5 }, + { 0x9f,0x5d,0x80,0xbe }, { 0x69,0xd0,0x93,0x7c }, + { 0x6f,0xd5,0x2d,0xa9 }, { 0xcf,0x25,0x12,0xb3 }, + { 0xc8,0xac,0x99,0x3b }, { 0x10,0x18,0x7d,0xa7 }, + { 0xe8,0x9c,0x63,0x6e }, { 0xdb,0x3b,0xbb,0x7b }, + { 0xcd,0x26,0x78,0x09 }, { 0x6e,0x59,0x18,0xf4 }, + { 0xec,0x9a,0xb7,0x01 }, { 0x83,0x4f,0x9a,0xa8 }, + { 0xe6,0x95,0x6e,0x65 }, { 0xaa,0xff,0xe6,0x7e }, + { 0x21,0xbc,0xcf,0x08 }, { 0xef,0x15,0xe8,0xe6 }, + { 0xba,0xe7,0x9b,0xd9 }, { 0x4a,0x6f,0x36,0xce }, + { 0xea,0x9f,0x09,0xd4 }, { 0x29,0xb0,0x7c,0xd6 }, + { 0x31,0xa4,0xb2,0xaf }, { 0x2a,0x3f,0x23,0x31 }, + { 0xc6,0xa5,0x94,0x30 }, { 0x35,0xa2,0x66,0xc0 }, + { 0x74,0x4e,0xbc,0x37 }, { 0xfc,0x82,0xca,0xa6 }, + { 0xe0,0x90,0xd0,0xb0 }, { 0x33,0xa7,0xd8,0x15 }, + { 0xf1,0x04,0x98,0x4a }, { 0x41,0xec,0xda,0xf7 }, + { 0x7f,0xcd,0x50,0x0e }, { 0x17,0x91,0xf6,0x2f }, + { 0x76,0x4d,0xd6,0x8d }, { 0x43,0xef,0xb0,0x4d }, + { 0xcc,0xaa,0x4d,0x54 }, { 0xe4,0x96,0x04,0xdf }, + { 0x9e,0xd1,0xb5,0xe3 }, { 0x4c,0x6a,0x88,0x1b }, + { 0xc1,0x2c,0x1f,0xb8 }, { 0x46,0x65,0x51,0x7f }, + { 0x9d,0x5e,0xea,0x04 }, { 0x01,0x8c,0x35,0x5d }, + { 0xfa,0x87,0x74,0x73 }, { 0xfb,0x0b,0x41,0x2e }, + { 0xb3,0x67,0x1d,0x5a }, { 0x92,0xdb,0xd2,0x52 }, + { 0xe9,0x10,0x56,0x33 }, { 0x6d,0xd6,0x47,0x13 }, + { 0x9a,0xd7,0x61,0x8c }, { 0x37,0xa1,0x0c,0x7a }, + { 0x59,0xf8,0x14,0x8e }, { 0xeb,0x13,0x3c,0x89 }, + { 0xce,0xa9,0x27,0xee }, { 0xb7,0x61,0xc9,0x35 }, + { 0xe1,0x1c,0xe5,0xed }, { 0x7a,0x47,0xb1,0x3c }, + { 0x9c,0xd2,0xdf,0x59 }, { 0x55,0xf2,0x73,0x3f }, + { 0x18,0x14,0xce,0x79 }, { 0x73,0xc7,0x37,0xbf }, + { 0x53,0xf7,0xcd,0xea }, { 0x5f,0xfd,0xaa,0x5b }, + { 0xdf,0x3d,0x6f,0x14 }, { 0x78,0x44,0xdb,0x86 }, + { 0xca,0xaf,0xf3,0x81 }, { 0xb9,0x68,0xc4,0x3e }, + { 0x38,0x24,0x34,0x2c }, { 0xc2,0xa3,0x40,0x5f }, + { 0x16,0x1d,0xc3,0x72 }, { 0xbc,0xe2,0x25,0x0c }, + { 0x28,0x3c,0x49,0x8b }, { 0xff,0x0d,0x95,0x41 }, + { 0x39,0xa8,0x01,0x71 }, { 0x08,0x0c,0xb3,0xde }, + { 0xd8,0xb4,0xe4,0x9c }, { 0x64,0x56,0xc1,0x90 }, + { 0x7b,0xcb,0x84,0x61 }, { 0xd5,0x32,0xb6,0x70 }, + { 0x48,0x6c,0x5c,0x74 }, { 0xd0,0xb8,0x57,0x42 } + }; + +static const unsigned char T6[256][4] = + { + { 0x50,0x51,0xf4,0xa7 }, { 0x53,0x7e,0x41,0x65 }, + { 0xc3,0x1a,0x17,0xa4 }, { 0x96,0x3a,0x27,0x5e }, + { 0xcb,0x3b,0xab,0x6b }, { 0xf1,0x1f,0x9d,0x45 }, + { 0xab,0xac,0xfa,0x58 }, { 0x93,0x4b,0xe3,0x03 }, + { 0x55,0x20,0x30,0xfa }, { 0xf6,0xad,0x76,0x6d }, + { 0x91,0x88,0xcc,0x76 }, { 0x25,0xf5,0x02,0x4c }, + { 0xfc,0x4f,0xe5,0xd7 }, { 0xd7,0xc5,0x2a,0xcb }, + { 0x80,0x26,0x35,0x44 }, { 0x8f,0xb5,0x62,0xa3 }, + { 0x49,0xde,0xb1,0x5a }, { 0x67,0x25,0xba,0x1b }, + { 0x98,0x45,0xea,0x0e }, { 0xe1,0x5d,0xfe,0xc0 }, + { 0x02,0xc3,0x2f,0x75 }, { 0x12,0x81,0x4c,0xf0 }, + { 0xa3,0x8d,0x46,0x97 }, { 0xc6,0x6b,0xd3,0xf9 }, + { 0xe7,0x03,0x8f,0x5f }, { 0x95,0x15,0x92,0x9c }, + { 0xeb,0xbf,0x6d,0x7a }, { 0xda,0x95,0x52,0x59 }, + { 0x2d,0xd4,0xbe,0x83 }, { 0xd3,0x58,0x74,0x21 }, + { 0x29,0x49,0xe0,0x69 }, { 0x44,0x8e,0xc9,0xc8 }, + { 0x6a,0x75,0xc2,0x89 }, { 0x78,0xf4,0x8e,0x79 }, + { 0x6b,0x99,0x58,0x3e }, { 0xdd,0x27,0xb9,0x71 }, + { 0xb6,0xbe,0xe1,0x4f }, { 0x17,0xf0,0x88,0xad }, + { 0x66,0xc9,0x20,0xac }, { 0xb4,0x7d,0xce,0x3a }, + { 0x18,0x63,0xdf,0x4a }, { 0x82,0xe5,0x1a,0x31 }, + { 0x60,0x97,0x51,0x33 }, { 0x45,0x62,0x53,0x7f }, + { 0xe0,0xb1,0x64,0x77 }, { 0x84,0xbb,0x6b,0xae }, + { 0x1c,0xfe,0x81,0xa0 }, { 0x94,0xf9,0x08,0x2b }, + { 0x58,0x70,0x48,0x68 }, { 0x19,0x8f,0x45,0xfd }, + { 0x87,0x94,0xde,0x6c }, { 0xb7,0x52,0x7b,0xf8 }, + { 0x23,0xab,0x73,0xd3 }, { 0xe2,0x72,0x4b,0x02 }, + { 0x57,0xe3,0x1f,0x8f }, { 0x2a,0x66,0x55,0xab }, + { 0x07,0xb2,0xeb,0x28 }, { 0x03,0x2f,0xb5,0xc2 }, + { 0x9a,0x86,0xc5,0x7b }, { 0xa5,0xd3,0x37,0x08 }, + { 0xf2,0x30,0x28,0x87 }, { 0xb2,0x23,0xbf,0xa5 }, + { 0xba,0x02,0x03,0x6a }, { 0x5c,0xed,0x16,0x82 }, + { 0x2b,0x8a,0xcf,0x1c }, { 0x92,0xa7,0x79,0xb4 }, + { 0xf0,0xf3,0x07,0xf2 }, { 0xa1,0x4e,0x69,0xe2 }, + { 0xcd,0x65,0xda,0xf4 }, { 0xd5,0x06,0x05,0xbe }, + { 0x1f,0xd1,0x34,0x62 }, { 0x8a,0xc4,0xa6,0xfe }, + { 0x9d,0x34,0x2e,0x53 }, { 0xa0,0xa2,0xf3,0x55 }, + { 0x32,0x05,0x8a,0xe1 }, { 0x75,0xa4,0xf6,0xeb }, + { 0x39,0x0b,0x83,0xec }, { 0xaa,0x40,0x60,0xef }, + { 0x06,0x5e,0x71,0x9f }, { 0x51,0xbd,0x6e,0x10 }, + { 0xf9,0x3e,0x21,0x8a }, { 0x3d,0x96,0xdd,0x06 }, + { 0xae,0xdd,0x3e,0x05 }, { 0x46,0x4d,0xe6,0xbd }, + { 0xb5,0x91,0x54,0x8d }, { 0x05,0x71,0xc4,0x5d }, + { 0x6f,0x04,0x06,0xd4 }, { 0xff,0x60,0x50,0x15 }, + { 0x24,0x19,0x98,0xfb }, { 0x97,0xd6,0xbd,0xe9 }, + { 0xcc,0x89,0x40,0x43 }, { 0x77,0x67,0xd9,0x9e }, + { 0xbd,0xb0,0xe8,0x42 }, { 0x88,0x07,0x89,0x8b }, + { 0x38,0xe7,0x19,0x5b }, { 0xdb,0x79,0xc8,0xee }, + { 0x47,0xa1,0x7c,0x0a }, { 0xe9,0x7c,0x42,0x0f }, + { 0xc9,0xf8,0x84,0x1e }, { 0x00,0x00,0x00,0x00 }, + { 0x83,0x09,0x80,0x86 }, { 0x48,0x32,0x2b,0xed }, + { 0xac,0x1e,0x11,0x70 }, { 0x4e,0x6c,0x5a,0x72 }, + { 0xfb,0xfd,0x0e,0xff }, { 0x56,0x0f,0x85,0x38 }, + { 0x1e,0x3d,0xae,0xd5 }, { 0x27,0x36,0x2d,0x39 }, + { 0x64,0x0a,0x0f,0xd9 }, { 0x21,0x68,0x5c,0xa6 }, + { 0xd1,0x9b,0x5b,0x54 }, { 0x3a,0x24,0x36,0x2e }, + { 0xb1,0x0c,0x0a,0x67 }, { 0x0f,0x93,0x57,0xe7 }, + { 0xd2,0xb4,0xee,0x96 }, { 0x9e,0x1b,0x9b,0x91 }, + { 0x4f,0x80,0xc0,0xc5 }, { 0xa2,0x61,0xdc,0x20 }, + { 0x69,0x5a,0x77,0x4b }, { 0x16,0x1c,0x12,0x1a }, + { 0x0a,0xe2,0x93,0xba }, { 0xe5,0xc0,0xa0,0x2a }, + { 0x43,0x3c,0x22,0xe0 }, { 0x1d,0x12,0x1b,0x17 }, + { 0x0b,0x0e,0x09,0x0d }, { 0xad,0xf2,0x8b,0xc7 }, + { 0xb9,0x2d,0xb6,0xa8 }, { 0xc8,0x14,0x1e,0xa9 }, + { 0x85,0x57,0xf1,0x19 }, { 0x4c,0xaf,0x75,0x07 }, + { 0xbb,0xee,0x99,0xdd }, { 0xfd,0xa3,0x7f,0x60 }, + { 0x9f,0xf7,0x01,0x26 }, { 0xbc,0x5c,0x72,0xf5 }, + { 0xc5,0x44,0x66,0x3b }, { 0x34,0x5b,0xfb,0x7e }, + { 0x76,0x8b,0x43,0x29 }, { 0xdc,0xcb,0x23,0xc6 }, + { 0x68,0xb6,0xed,0xfc }, { 0x63,0xb8,0xe4,0xf1 }, + { 0xca,0xd7,0x31,0xdc }, { 0x10,0x42,0x63,0x85 }, + { 0x40,0x13,0x97,0x22 }, { 0x20,0x84,0xc6,0x11 }, + { 0x7d,0x85,0x4a,0x24 }, { 0xf8,0xd2,0xbb,0x3d }, + { 0x11,0xae,0xf9,0x32 }, { 0x6d,0xc7,0x29,0xa1 }, + { 0x4b,0x1d,0x9e,0x2f }, { 0xf3,0xdc,0xb2,0x30 }, + { 0xec,0x0d,0x86,0x52 }, { 0xd0,0x77,0xc1,0xe3 }, + { 0x6c,0x2b,0xb3,0x16 }, { 0x99,0xa9,0x70,0xb9 }, + { 0xfa,0x11,0x94,0x48 }, { 0x22,0x47,0xe9,0x64 }, + { 0xc4,0xa8,0xfc,0x8c }, { 0x1a,0xa0,0xf0,0x3f }, + { 0xd8,0x56,0x7d,0x2c }, { 0xef,0x22,0x33,0x90 }, + { 0xc7,0x87,0x49,0x4e }, { 0xc1,0xd9,0x38,0xd1 }, + { 0xfe,0x8c,0xca,0xa2 }, { 0x36,0x98,0xd4,0x0b }, + { 0xcf,0xa6,0xf5,0x81 }, { 0x28,0xa5,0x7a,0xde }, + { 0x26,0xda,0xb7,0x8e }, { 0xa4,0x3f,0xad,0xbf }, + { 0xe4,0x2c,0x3a,0x9d }, { 0x0d,0x50,0x78,0x92 }, + { 0x9b,0x6a,0x5f,0xcc }, { 0x62,0x54,0x7e,0x46 }, + { 0xc2,0xf6,0x8d,0x13 }, { 0xe8,0x90,0xd8,0xb8 }, + { 0x5e,0x2e,0x39,0xf7 }, { 0xf5,0x82,0xc3,0xaf }, + { 0xbe,0x9f,0x5d,0x80 }, { 0x7c,0x69,0xd0,0x93 }, + { 0xa9,0x6f,0xd5,0x2d }, { 0xb3,0xcf,0x25,0x12 }, + { 0x3b,0xc8,0xac,0x99 }, { 0xa7,0x10,0x18,0x7d }, + { 0x6e,0xe8,0x9c,0x63 }, { 0x7b,0xdb,0x3b,0xbb }, + { 0x09,0xcd,0x26,0x78 }, { 0xf4,0x6e,0x59,0x18 }, + { 0x01,0xec,0x9a,0xb7 }, { 0xa8,0x83,0x4f,0x9a }, + { 0x65,0xe6,0x95,0x6e }, { 0x7e,0xaa,0xff,0xe6 }, + { 0x08,0x21,0xbc,0xcf }, { 0xe6,0xef,0x15,0xe8 }, + { 0xd9,0xba,0xe7,0x9b }, { 0xce,0x4a,0x6f,0x36 }, + { 0xd4,0xea,0x9f,0x09 }, { 0xd6,0x29,0xb0,0x7c }, + { 0xaf,0x31,0xa4,0xb2 }, { 0x31,0x2a,0x3f,0x23 }, + { 0x30,0xc6,0xa5,0x94 }, { 0xc0,0x35,0xa2,0x66 }, + { 0x37,0x74,0x4e,0xbc }, { 0xa6,0xfc,0x82,0xca }, + { 0xb0,0xe0,0x90,0xd0 }, { 0x15,0x33,0xa7,0xd8 }, + { 0x4a,0xf1,0x04,0x98 }, { 0xf7,0x41,0xec,0xda }, + { 0x0e,0x7f,0xcd,0x50 }, { 0x2f,0x17,0x91,0xf6 }, + { 0x8d,0x76,0x4d,0xd6 }, { 0x4d,0x43,0xef,0xb0 }, + { 0x54,0xcc,0xaa,0x4d }, { 0xdf,0xe4,0x96,0x04 }, + { 0xe3,0x9e,0xd1,0xb5 }, { 0x1b,0x4c,0x6a,0x88 }, + { 0xb8,0xc1,0x2c,0x1f }, { 0x7f,0x46,0x65,0x51 }, + { 0x04,0x9d,0x5e,0xea }, { 0x5d,0x01,0x8c,0x35 }, + { 0x73,0xfa,0x87,0x74 }, { 0x2e,0xfb,0x0b,0x41 }, + { 0x5a,0xb3,0x67,0x1d }, { 0x52,0x92,0xdb,0xd2 }, + { 0x33,0xe9,0x10,0x56 }, { 0x13,0x6d,0xd6,0x47 }, + { 0x8c,0x9a,0xd7,0x61 }, { 0x7a,0x37,0xa1,0x0c }, + { 0x8e,0x59,0xf8,0x14 }, { 0x89,0xeb,0x13,0x3c }, + { 0xee,0xce,0xa9,0x27 }, { 0x35,0xb7,0x61,0xc9 }, + { 0xed,0xe1,0x1c,0xe5 }, { 0x3c,0x7a,0x47,0xb1 }, + { 0x59,0x9c,0xd2,0xdf }, { 0x3f,0x55,0xf2,0x73 }, + { 0x79,0x18,0x14,0xce }, { 0xbf,0x73,0xc7,0x37 }, + { 0xea,0x53,0xf7,0xcd }, { 0x5b,0x5f,0xfd,0xaa }, + { 0x14,0xdf,0x3d,0x6f }, { 0x86,0x78,0x44,0xdb }, + { 0x81,0xca,0xaf,0xf3 }, { 0x3e,0xb9,0x68,0xc4 }, + { 0x2c,0x38,0x24,0x34 }, { 0x5f,0xc2,0xa3,0x40 }, + { 0x72,0x16,0x1d,0xc3 }, { 0x0c,0xbc,0xe2,0x25 }, + { 0x8b,0x28,0x3c,0x49 }, { 0x41,0xff,0x0d,0x95 }, + { 0x71,0x39,0xa8,0x01 }, { 0xde,0x08,0x0c,0xb3 }, + { 0x9c,0xd8,0xb4,0xe4 }, { 0x90,0x64,0x56,0xc1 }, + { 0x61,0x7b,0xcb,0x84 }, { 0x70,0xd5,0x32,0xb6 }, + { 0x74,0x48,0x6c,0x5c }, { 0x42,0xd0,0xb8,0x57 } + }; + +static const unsigned char T7[256][4] = + { + { 0xa7,0x50,0x51,0xf4 }, { 0x65,0x53,0x7e,0x41 }, + { 0xa4,0xc3,0x1a,0x17 }, { 0x5e,0x96,0x3a,0x27 }, + { 0x6b,0xcb,0x3b,0xab }, { 0x45,0xf1,0x1f,0x9d }, + { 0x58,0xab,0xac,0xfa }, { 0x03,0x93,0x4b,0xe3 }, + { 0xfa,0x55,0x20,0x30 }, { 0x6d,0xf6,0xad,0x76 }, + { 0x76,0x91,0x88,0xcc }, { 0x4c,0x25,0xf5,0x02 }, + { 0xd7,0xfc,0x4f,0xe5 }, { 0xcb,0xd7,0xc5,0x2a }, + { 0x44,0x80,0x26,0x35 }, { 0xa3,0x8f,0xb5,0x62 }, + { 0x5a,0x49,0xde,0xb1 }, { 0x1b,0x67,0x25,0xba }, + { 0x0e,0x98,0x45,0xea }, { 0xc0,0xe1,0x5d,0xfe }, + { 0x75,0x02,0xc3,0x2f }, { 0xf0,0x12,0x81,0x4c }, + { 0x97,0xa3,0x8d,0x46 }, { 0xf9,0xc6,0x6b,0xd3 }, + { 0x5f,0xe7,0x03,0x8f }, { 0x9c,0x95,0x15,0x92 }, + { 0x7a,0xeb,0xbf,0x6d }, { 0x59,0xda,0x95,0x52 }, + { 0x83,0x2d,0xd4,0xbe }, { 0x21,0xd3,0x58,0x74 }, + { 0x69,0x29,0x49,0xe0 }, { 0xc8,0x44,0x8e,0xc9 }, + { 0x89,0x6a,0x75,0xc2 }, { 0x79,0x78,0xf4,0x8e }, + { 0x3e,0x6b,0x99,0x58 }, { 0x71,0xdd,0x27,0xb9 }, + { 0x4f,0xb6,0xbe,0xe1 }, { 0xad,0x17,0xf0,0x88 }, + { 0xac,0x66,0xc9,0x20 }, { 0x3a,0xb4,0x7d,0xce }, + { 0x4a,0x18,0x63,0xdf }, { 0x31,0x82,0xe5,0x1a }, + { 0x33,0x60,0x97,0x51 }, { 0x7f,0x45,0x62,0x53 }, + { 0x77,0xe0,0xb1,0x64 }, { 0xae,0x84,0xbb,0x6b }, + { 0xa0,0x1c,0xfe,0x81 }, { 0x2b,0x94,0xf9,0x08 }, + { 0x68,0x58,0x70,0x48 }, { 0xfd,0x19,0x8f,0x45 }, + { 0x6c,0x87,0x94,0xde }, { 0xf8,0xb7,0x52,0x7b }, + { 0xd3,0x23,0xab,0x73 }, { 0x02,0xe2,0x72,0x4b }, + { 0x8f,0x57,0xe3,0x1f }, { 0xab,0x2a,0x66,0x55 }, + { 0x28,0x07,0xb2,0xeb }, { 0xc2,0x03,0x2f,0xb5 }, + { 0x7b,0x9a,0x86,0xc5 }, { 0x08,0xa5,0xd3,0x37 }, + { 0x87,0xf2,0x30,0x28 }, { 0xa5,0xb2,0x23,0xbf }, + { 0x6a,0xba,0x02,0x03 }, { 0x82,0x5c,0xed,0x16 }, + { 0x1c,0x2b,0x8a,0xcf }, { 0xb4,0x92,0xa7,0x79 }, + { 0xf2,0xf0,0xf3,0x07 }, { 0xe2,0xa1,0x4e,0x69 }, + { 0xf4,0xcd,0x65,0xda }, { 0xbe,0xd5,0x06,0x05 }, + { 0x62,0x1f,0xd1,0x34 }, { 0xfe,0x8a,0xc4,0xa6 }, + { 0x53,0x9d,0x34,0x2e }, { 0x55,0xa0,0xa2,0xf3 }, + { 0xe1,0x32,0x05,0x8a }, { 0xeb,0x75,0xa4,0xf6 }, + { 0xec,0x39,0x0b,0x83 }, { 0xef,0xaa,0x40,0x60 }, + { 0x9f,0x06,0x5e,0x71 }, { 0x10,0x51,0xbd,0x6e }, + { 0x8a,0xf9,0x3e,0x21 }, { 0x06,0x3d,0x96,0xdd }, + { 0x05,0xae,0xdd,0x3e }, { 0xbd,0x46,0x4d,0xe6 }, + { 0x8d,0xb5,0x91,0x54 }, { 0x5d,0x05,0x71,0xc4 }, + { 0xd4,0x6f,0x04,0x06 }, { 0x15,0xff,0x60,0x50 }, + { 0xfb,0x24,0x19,0x98 }, { 0xe9,0x97,0xd6,0xbd }, + { 0x43,0xcc,0x89,0x40 }, { 0x9e,0x77,0x67,0xd9 }, + { 0x42,0xbd,0xb0,0xe8 }, { 0x8b,0x88,0x07,0x89 }, + { 0x5b,0x38,0xe7,0x19 }, { 0xee,0xdb,0x79,0xc8 }, + { 0x0a,0x47,0xa1,0x7c }, { 0x0f,0xe9,0x7c,0x42 }, + { 0x1e,0xc9,0xf8,0x84 }, { 0x00,0x00,0x00,0x00 }, + { 0x86,0x83,0x09,0x80 }, { 0xed,0x48,0x32,0x2b }, + { 0x70,0xac,0x1e,0x11 }, { 0x72,0x4e,0x6c,0x5a }, + { 0xff,0xfb,0xfd,0x0e }, { 0x38,0x56,0x0f,0x85 }, + { 0xd5,0x1e,0x3d,0xae }, { 0x39,0x27,0x36,0x2d }, + { 0xd9,0x64,0x0a,0x0f }, { 0xa6,0x21,0x68,0x5c }, + { 0x54,0xd1,0x9b,0x5b }, { 0x2e,0x3a,0x24,0x36 }, + { 0x67,0xb1,0x0c,0x0a }, { 0xe7,0x0f,0x93,0x57 }, + { 0x96,0xd2,0xb4,0xee }, { 0x91,0x9e,0x1b,0x9b }, + { 0xc5,0x4f,0x80,0xc0 }, { 0x20,0xa2,0x61,0xdc }, + { 0x4b,0x69,0x5a,0x77 }, { 0x1a,0x16,0x1c,0x12 }, + { 0xba,0x0a,0xe2,0x93 }, { 0x2a,0xe5,0xc0,0xa0 }, + { 0xe0,0x43,0x3c,0x22 }, { 0x17,0x1d,0x12,0x1b }, + { 0x0d,0x0b,0x0e,0x09 }, { 0xc7,0xad,0xf2,0x8b }, + { 0xa8,0xb9,0x2d,0xb6 }, { 0xa9,0xc8,0x14,0x1e }, + { 0x19,0x85,0x57,0xf1 }, { 0x07,0x4c,0xaf,0x75 }, + { 0xdd,0xbb,0xee,0x99 }, { 0x60,0xfd,0xa3,0x7f }, + { 0x26,0x9f,0xf7,0x01 }, { 0xf5,0xbc,0x5c,0x72 }, + { 0x3b,0xc5,0x44,0x66 }, { 0x7e,0x34,0x5b,0xfb }, + { 0x29,0x76,0x8b,0x43 }, { 0xc6,0xdc,0xcb,0x23 }, + { 0xfc,0x68,0xb6,0xed }, { 0xf1,0x63,0xb8,0xe4 }, + { 0xdc,0xca,0xd7,0x31 }, { 0x85,0x10,0x42,0x63 }, + { 0x22,0x40,0x13,0x97 }, { 0x11,0x20,0x84,0xc6 }, + { 0x24,0x7d,0x85,0x4a }, { 0x3d,0xf8,0xd2,0xbb }, + { 0x32,0x11,0xae,0xf9 }, { 0xa1,0x6d,0xc7,0x29 }, + { 0x2f,0x4b,0x1d,0x9e }, { 0x30,0xf3,0xdc,0xb2 }, + { 0x52,0xec,0x0d,0x86 }, { 0xe3,0xd0,0x77,0xc1 }, + { 0x16,0x6c,0x2b,0xb3 }, { 0xb9,0x99,0xa9,0x70 }, + { 0x48,0xfa,0x11,0x94 }, { 0x64,0x22,0x47,0xe9 }, + { 0x8c,0xc4,0xa8,0xfc }, { 0x3f,0x1a,0xa0,0xf0 }, + { 0x2c,0xd8,0x56,0x7d }, { 0x90,0xef,0x22,0x33 }, + { 0x4e,0xc7,0x87,0x49 }, { 0xd1,0xc1,0xd9,0x38 }, + { 0xa2,0xfe,0x8c,0xca }, { 0x0b,0x36,0x98,0xd4 }, + { 0x81,0xcf,0xa6,0xf5 }, { 0xde,0x28,0xa5,0x7a }, + { 0x8e,0x26,0xda,0xb7 }, { 0xbf,0xa4,0x3f,0xad }, + { 0x9d,0xe4,0x2c,0x3a }, { 0x92,0x0d,0x50,0x78 }, + { 0xcc,0x9b,0x6a,0x5f }, { 0x46,0x62,0x54,0x7e }, + { 0x13,0xc2,0xf6,0x8d }, { 0xb8,0xe8,0x90,0xd8 }, + { 0xf7,0x5e,0x2e,0x39 }, { 0xaf,0xf5,0x82,0xc3 }, + { 0x80,0xbe,0x9f,0x5d }, { 0x93,0x7c,0x69,0xd0 }, + { 0x2d,0xa9,0x6f,0xd5 }, { 0x12,0xb3,0xcf,0x25 }, + { 0x99,0x3b,0xc8,0xac }, { 0x7d,0xa7,0x10,0x18 }, + { 0x63,0x6e,0xe8,0x9c }, { 0xbb,0x7b,0xdb,0x3b }, + { 0x78,0x09,0xcd,0x26 }, { 0x18,0xf4,0x6e,0x59 }, + { 0xb7,0x01,0xec,0x9a }, { 0x9a,0xa8,0x83,0x4f }, + { 0x6e,0x65,0xe6,0x95 }, { 0xe6,0x7e,0xaa,0xff }, + { 0xcf,0x08,0x21,0xbc }, { 0xe8,0xe6,0xef,0x15 }, + { 0x9b,0xd9,0xba,0xe7 }, { 0x36,0xce,0x4a,0x6f }, + { 0x09,0xd4,0xea,0x9f }, { 0x7c,0xd6,0x29,0xb0 }, + { 0xb2,0xaf,0x31,0xa4 }, { 0x23,0x31,0x2a,0x3f }, + { 0x94,0x30,0xc6,0xa5 }, { 0x66,0xc0,0x35,0xa2 }, + { 0xbc,0x37,0x74,0x4e }, { 0xca,0xa6,0xfc,0x82 }, + { 0xd0,0xb0,0xe0,0x90 }, { 0xd8,0x15,0x33,0xa7 }, + { 0x98,0x4a,0xf1,0x04 }, { 0xda,0xf7,0x41,0xec }, + { 0x50,0x0e,0x7f,0xcd }, { 0xf6,0x2f,0x17,0x91 }, + { 0xd6,0x8d,0x76,0x4d }, { 0xb0,0x4d,0x43,0xef }, + { 0x4d,0x54,0xcc,0xaa }, { 0x04,0xdf,0xe4,0x96 }, + { 0xb5,0xe3,0x9e,0xd1 }, { 0x88,0x1b,0x4c,0x6a }, + { 0x1f,0xb8,0xc1,0x2c }, { 0x51,0x7f,0x46,0x65 }, + { 0xea,0x04,0x9d,0x5e }, { 0x35,0x5d,0x01,0x8c }, + { 0x74,0x73,0xfa,0x87 }, { 0x41,0x2e,0xfb,0x0b }, + { 0x1d,0x5a,0xb3,0x67 }, { 0xd2,0x52,0x92,0xdb }, + { 0x56,0x33,0xe9,0x10 }, { 0x47,0x13,0x6d,0xd6 }, + { 0x61,0x8c,0x9a,0xd7 }, { 0x0c,0x7a,0x37,0xa1 }, + { 0x14,0x8e,0x59,0xf8 }, { 0x3c,0x89,0xeb,0x13 }, + { 0x27,0xee,0xce,0xa9 }, { 0xc9,0x35,0xb7,0x61 }, + { 0xe5,0xed,0xe1,0x1c }, { 0xb1,0x3c,0x7a,0x47 }, + { 0xdf,0x59,0x9c,0xd2 }, { 0x73,0x3f,0x55,0xf2 }, + { 0xce,0x79,0x18,0x14 }, { 0x37,0xbf,0x73,0xc7 }, + { 0xcd,0xea,0x53,0xf7 }, { 0xaa,0x5b,0x5f,0xfd }, + { 0x6f,0x14,0xdf,0x3d }, { 0xdb,0x86,0x78,0x44 }, + { 0xf3,0x81,0xca,0xaf }, { 0xc4,0x3e,0xb9,0x68 }, + { 0x34,0x2c,0x38,0x24 }, { 0x40,0x5f,0xc2,0xa3 }, + { 0xc3,0x72,0x16,0x1d }, { 0x25,0x0c,0xbc,0xe2 }, + { 0x49,0x8b,0x28,0x3c }, { 0x95,0x41,0xff,0x0d }, + { 0x01,0x71,0x39,0xa8 }, { 0xb3,0xde,0x08,0x0c }, + { 0xe4,0x9c,0xd8,0xb4 }, { 0xc1,0x90,0x64,0x56 }, + { 0x84,0x61,0x7b,0xcb }, { 0xb6,0x70,0xd5,0x32 }, + { 0x5c,0x74,0x48,0x6c }, { 0x57,0x42,0xd0,0xb8 } + }; + +static const unsigned char T8[256][4] = + { + { 0xf4,0xa7,0x50,0x51 }, { 0x41,0x65,0x53,0x7e }, + { 0x17,0xa4,0xc3,0x1a }, { 0x27,0x5e,0x96,0x3a }, + { 0xab,0x6b,0xcb,0x3b }, { 0x9d,0x45,0xf1,0x1f }, + { 0xfa,0x58,0xab,0xac }, { 0xe3,0x03,0x93,0x4b }, + { 0x30,0xfa,0x55,0x20 }, { 0x76,0x6d,0xf6,0xad }, + { 0xcc,0x76,0x91,0x88 }, { 0x02,0x4c,0x25,0xf5 }, + { 0xe5,0xd7,0xfc,0x4f }, { 0x2a,0xcb,0xd7,0xc5 }, + { 0x35,0x44,0x80,0x26 }, { 0x62,0xa3,0x8f,0xb5 }, + { 0xb1,0x5a,0x49,0xde }, { 0xba,0x1b,0x67,0x25 }, + { 0xea,0x0e,0x98,0x45 }, { 0xfe,0xc0,0xe1,0x5d }, + { 0x2f,0x75,0x02,0xc3 }, { 0x4c,0xf0,0x12,0x81 }, + { 0x46,0x97,0xa3,0x8d }, { 0xd3,0xf9,0xc6,0x6b }, + { 0x8f,0x5f,0xe7,0x03 }, { 0x92,0x9c,0x95,0x15 }, + { 0x6d,0x7a,0xeb,0xbf }, { 0x52,0x59,0xda,0x95 }, + { 0xbe,0x83,0x2d,0xd4 }, { 0x74,0x21,0xd3,0x58 }, + { 0xe0,0x69,0x29,0x49 }, { 0xc9,0xc8,0x44,0x8e }, + { 0xc2,0x89,0x6a,0x75 }, { 0x8e,0x79,0x78,0xf4 }, + { 0x58,0x3e,0x6b,0x99 }, { 0xb9,0x71,0xdd,0x27 }, + { 0xe1,0x4f,0xb6,0xbe }, { 0x88,0xad,0x17,0xf0 }, + { 0x20,0xac,0x66,0xc9 }, { 0xce,0x3a,0xb4,0x7d }, + { 0xdf,0x4a,0x18,0x63 }, { 0x1a,0x31,0x82,0xe5 }, + { 0x51,0x33,0x60,0x97 }, { 0x53,0x7f,0x45,0x62 }, + { 0x64,0x77,0xe0,0xb1 }, { 0x6b,0xae,0x84,0xbb }, + { 0x81,0xa0,0x1c,0xfe }, { 0x08,0x2b,0x94,0xf9 }, + { 0x48,0x68,0x58,0x70 }, { 0x45,0xfd,0x19,0x8f }, + { 0xde,0x6c,0x87,0x94 }, { 0x7b,0xf8,0xb7,0x52 }, + { 0x73,0xd3,0x23,0xab }, { 0x4b,0x02,0xe2,0x72 }, + { 0x1f,0x8f,0x57,0xe3 }, { 0x55,0xab,0x2a,0x66 }, + { 0xeb,0x28,0x07,0xb2 }, { 0xb5,0xc2,0x03,0x2f }, + { 0xc5,0x7b,0x9a,0x86 }, { 0x37,0x08,0xa5,0xd3 }, + { 0x28,0x87,0xf2,0x30 }, { 0xbf,0xa5,0xb2,0x23 }, + { 0x03,0x6a,0xba,0x02 }, { 0x16,0x82,0x5c,0xed }, + { 0xcf,0x1c,0x2b,0x8a }, { 0x79,0xb4,0x92,0xa7 }, + { 0x07,0xf2,0xf0,0xf3 }, { 0x69,0xe2,0xa1,0x4e }, + { 0xda,0xf4,0xcd,0x65 }, { 0x05,0xbe,0xd5,0x06 }, + { 0x34,0x62,0x1f,0xd1 }, { 0xa6,0xfe,0x8a,0xc4 }, + { 0x2e,0x53,0x9d,0x34 }, { 0xf3,0x55,0xa0,0xa2 }, + { 0x8a,0xe1,0x32,0x05 }, { 0xf6,0xeb,0x75,0xa4 }, + { 0x83,0xec,0x39,0x0b }, { 0x60,0xef,0xaa,0x40 }, + { 0x71,0x9f,0x06,0x5e }, { 0x6e,0x10,0x51,0xbd }, + { 0x21,0x8a,0xf9,0x3e }, { 0xdd,0x06,0x3d,0x96 }, + { 0x3e,0x05,0xae,0xdd }, { 0xe6,0xbd,0x46,0x4d }, + { 0x54,0x8d,0xb5,0x91 }, { 0xc4,0x5d,0x05,0x71 }, + { 0x06,0xd4,0x6f,0x04 }, { 0x50,0x15,0xff,0x60 }, + { 0x98,0xfb,0x24,0x19 }, { 0xbd,0xe9,0x97,0xd6 }, + { 0x40,0x43,0xcc,0x89 }, { 0xd9,0x9e,0x77,0x67 }, + { 0xe8,0x42,0xbd,0xb0 }, { 0x89,0x8b,0x88,0x07 }, + { 0x19,0x5b,0x38,0xe7 }, { 0xc8,0xee,0xdb,0x79 }, + { 0x7c,0x0a,0x47,0xa1 }, { 0x42,0x0f,0xe9,0x7c }, + { 0x84,0x1e,0xc9,0xf8 }, { 0x00,0x00,0x00,0x00 }, + { 0x80,0x86,0x83,0x09 }, { 0x2b,0xed,0x48,0x32 }, + { 0x11,0x70,0xac,0x1e }, { 0x5a,0x72,0x4e,0x6c }, + { 0x0e,0xff,0xfb,0xfd }, { 0x85,0x38,0x56,0x0f }, + { 0xae,0xd5,0x1e,0x3d }, { 0x2d,0x39,0x27,0x36 }, + { 0x0f,0xd9,0x64,0x0a }, { 0x5c,0xa6,0x21,0x68 }, + { 0x5b,0x54,0xd1,0x9b }, { 0x36,0x2e,0x3a,0x24 }, + { 0x0a,0x67,0xb1,0x0c }, { 0x57,0xe7,0x0f,0x93 }, + { 0xee,0x96,0xd2,0xb4 }, { 0x9b,0x91,0x9e,0x1b }, + { 0xc0,0xc5,0x4f,0x80 }, { 0xdc,0x20,0xa2,0x61 }, + { 0x77,0x4b,0x69,0x5a }, { 0x12,0x1a,0x16,0x1c }, + { 0x93,0xba,0x0a,0xe2 }, { 0xa0,0x2a,0xe5,0xc0 }, + { 0x22,0xe0,0x43,0x3c }, { 0x1b,0x17,0x1d,0x12 }, + { 0x09,0x0d,0x0b,0x0e }, { 0x8b,0xc7,0xad,0xf2 }, + { 0xb6,0xa8,0xb9,0x2d }, { 0x1e,0xa9,0xc8,0x14 }, + { 0xf1,0x19,0x85,0x57 }, { 0x75,0x07,0x4c,0xaf }, + { 0x99,0xdd,0xbb,0xee }, { 0x7f,0x60,0xfd,0xa3 }, + { 0x01,0x26,0x9f,0xf7 }, { 0x72,0xf5,0xbc,0x5c }, + { 0x66,0x3b,0xc5,0x44 }, { 0xfb,0x7e,0x34,0x5b }, + { 0x43,0x29,0x76,0x8b }, { 0x23,0xc6,0xdc,0xcb }, + { 0xed,0xfc,0x68,0xb6 }, { 0xe4,0xf1,0x63,0xb8 }, + { 0x31,0xdc,0xca,0xd7 }, { 0x63,0x85,0x10,0x42 }, + { 0x97,0x22,0x40,0x13 }, { 0xc6,0x11,0x20,0x84 }, + { 0x4a,0x24,0x7d,0x85 }, { 0xbb,0x3d,0xf8,0xd2 }, + { 0xf9,0x32,0x11,0xae }, { 0x29,0xa1,0x6d,0xc7 }, + { 0x9e,0x2f,0x4b,0x1d }, { 0xb2,0x30,0xf3,0xdc }, + { 0x86,0x52,0xec,0x0d }, { 0xc1,0xe3,0xd0,0x77 }, + { 0xb3,0x16,0x6c,0x2b }, { 0x70,0xb9,0x99,0xa9 }, + { 0x94,0x48,0xfa,0x11 }, { 0xe9,0x64,0x22,0x47 }, + { 0xfc,0x8c,0xc4,0xa8 }, { 0xf0,0x3f,0x1a,0xa0 }, + { 0x7d,0x2c,0xd8,0x56 }, { 0x33,0x90,0xef,0x22 }, + { 0x49,0x4e,0xc7,0x87 }, { 0x38,0xd1,0xc1,0xd9 }, + { 0xca,0xa2,0xfe,0x8c }, { 0xd4,0x0b,0x36,0x98 }, + { 0xf5,0x81,0xcf,0xa6 }, { 0x7a,0xde,0x28,0xa5 }, + { 0xb7,0x8e,0x26,0xda }, { 0xad,0xbf,0xa4,0x3f }, + { 0x3a,0x9d,0xe4,0x2c }, { 0x78,0x92,0x0d,0x50 }, + { 0x5f,0xcc,0x9b,0x6a }, { 0x7e,0x46,0x62,0x54 }, + { 0x8d,0x13,0xc2,0xf6 }, { 0xd8,0xb8,0xe8,0x90 }, + { 0x39,0xf7,0x5e,0x2e }, { 0xc3,0xaf,0xf5,0x82 }, + { 0x5d,0x80,0xbe,0x9f }, { 0xd0,0x93,0x7c,0x69 }, + { 0xd5,0x2d,0xa9,0x6f }, { 0x25,0x12,0xb3,0xcf }, + { 0xac,0x99,0x3b,0xc8 }, { 0x18,0x7d,0xa7,0x10 }, + { 0x9c,0x63,0x6e,0xe8 }, { 0x3b,0xbb,0x7b,0xdb }, + { 0x26,0x78,0x09,0xcd }, { 0x59,0x18,0xf4,0x6e }, + { 0x9a,0xb7,0x01,0xec }, { 0x4f,0x9a,0xa8,0x83 }, + { 0x95,0x6e,0x65,0xe6 }, { 0xff,0xe6,0x7e,0xaa }, + { 0xbc,0xcf,0x08,0x21 }, { 0x15,0xe8,0xe6,0xef }, + { 0xe7,0x9b,0xd9,0xba }, { 0x6f,0x36,0xce,0x4a }, + { 0x9f,0x09,0xd4,0xea }, { 0xb0,0x7c,0xd6,0x29 }, + { 0xa4,0xb2,0xaf,0x31 }, { 0x3f,0x23,0x31,0x2a }, + { 0xa5,0x94,0x30,0xc6 }, { 0xa2,0x66,0xc0,0x35 }, + { 0x4e,0xbc,0x37,0x74 }, { 0x82,0xca,0xa6,0xfc }, + { 0x90,0xd0,0xb0,0xe0 }, { 0xa7,0xd8,0x15,0x33 }, + { 0x04,0x98,0x4a,0xf1 }, { 0xec,0xda,0xf7,0x41 }, + { 0xcd,0x50,0x0e,0x7f }, { 0x91,0xf6,0x2f,0x17 }, + { 0x4d,0xd6,0x8d,0x76 }, { 0xef,0xb0,0x4d,0x43 }, + { 0xaa,0x4d,0x54,0xcc }, { 0x96,0x04,0xdf,0xe4 }, + { 0xd1,0xb5,0xe3,0x9e }, { 0x6a,0x88,0x1b,0x4c }, + { 0x2c,0x1f,0xb8,0xc1 }, { 0x65,0x51,0x7f,0x46 }, + { 0x5e,0xea,0x04,0x9d }, { 0x8c,0x35,0x5d,0x01 }, + { 0x87,0x74,0x73,0xfa }, { 0x0b,0x41,0x2e,0xfb }, + { 0x67,0x1d,0x5a,0xb3 }, { 0xdb,0xd2,0x52,0x92 }, + { 0x10,0x56,0x33,0xe9 }, { 0xd6,0x47,0x13,0x6d }, + { 0xd7,0x61,0x8c,0x9a }, { 0xa1,0x0c,0x7a,0x37 }, + { 0xf8,0x14,0x8e,0x59 }, { 0x13,0x3c,0x89,0xeb }, + { 0xa9,0x27,0xee,0xce }, { 0x61,0xc9,0x35,0xb7 }, + { 0x1c,0xe5,0xed,0xe1 }, { 0x47,0xb1,0x3c,0x7a }, + { 0xd2,0xdf,0x59,0x9c }, { 0xf2,0x73,0x3f,0x55 }, + { 0x14,0xce,0x79,0x18 }, { 0xc7,0x37,0xbf,0x73 }, + { 0xf7,0xcd,0xea,0x53 }, { 0xfd,0xaa,0x5b,0x5f }, + { 0x3d,0x6f,0x14,0xdf }, { 0x44,0xdb,0x86,0x78 }, + { 0xaf,0xf3,0x81,0xca }, { 0x68,0xc4,0x3e,0xb9 }, + { 0x24,0x34,0x2c,0x38 }, { 0xa3,0x40,0x5f,0xc2 }, + { 0x1d,0xc3,0x72,0x16 }, { 0xe2,0x25,0x0c,0xbc }, + { 0x3c,0x49,0x8b,0x28 }, { 0x0d,0x95,0x41,0xff }, + { 0xa8,0x01,0x71,0x39 }, { 0x0c,0xb3,0xde,0x08 }, + { 0xb4,0xe4,0x9c,0xd8 }, { 0x56,0xc1,0x90,0x64 }, + { 0xcb,0x84,0x61,0x7b }, { 0x32,0xb6,0x70,0xd5 }, + { 0x6c,0x5c,0x74,0x48 }, { 0xb8,0x57,0x42,0xd0 } + }; + +static const unsigned char S5[256] = + { + 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38, + 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, + 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87, + 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, + 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d, + 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, + 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2, + 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, + 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16, + 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, + 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda, + 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, + 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a, + 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, + 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02, + 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, + 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea, + 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, + 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85, + 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, + 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89, + 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, + 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20, + 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, + 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31, + 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, + 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d, + 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, + 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0, + 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, + 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26, + 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d + }; + +static const unsigned char U1[256][4] = + { + { 0x00,0x00,0x00,0x00 }, { 0x0e,0x09,0x0d,0x0b }, + { 0x1c,0x12,0x1a,0x16 }, { 0x12,0x1b,0x17,0x1d }, + { 0x38,0x24,0x34,0x2c }, { 0x36,0x2d,0x39,0x27 }, + { 0x24,0x36,0x2e,0x3a }, { 0x2a,0x3f,0x23,0x31 }, + { 0x70,0x48,0x68,0x58 }, { 0x7e,0x41,0x65,0x53 }, + { 0x6c,0x5a,0x72,0x4e }, { 0x62,0x53,0x7f,0x45 }, + { 0x48,0x6c,0x5c,0x74 }, { 0x46,0x65,0x51,0x7f }, + { 0x54,0x7e,0x46,0x62 }, { 0x5a,0x77,0x4b,0x69 }, + { 0xe0,0x90,0xd0,0xb0 }, { 0xee,0x99,0xdd,0xbb }, + { 0xfc,0x82,0xca,0xa6 }, { 0xf2,0x8b,0xc7,0xad }, + { 0xd8,0xb4,0xe4,0x9c }, { 0xd6,0xbd,0xe9,0x97 }, + { 0xc4,0xa6,0xfe,0x8a }, { 0xca,0xaf,0xf3,0x81 }, + { 0x90,0xd8,0xb8,0xe8 }, { 0x9e,0xd1,0xb5,0xe3 }, + { 0x8c,0xca,0xa2,0xfe }, { 0x82,0xc3,0xaf,0xf5 }, + { 0xa8,0xfc,0x8c,0xc4 }, { 0xa6,0xf5,0x81,0xcf }, + { 0xb4,0xee,0x96,0xd2 }, { 0xba,0xe7,0x9b,0xd9 }, + { 0xdb,0x3b,0xbb,0x7b }, { 0xd5,0x32,0xb6,0x70 }, + { 0xc7,0x29,0xa1,0x6d }, { 0xc9,0x20,0xac,0x66 }, + { 0xe3,0x1f,0x8f,0x57 }, { 0xed,0x16,0x82,0x5c }, + { 0xff,0x0d,0x95,0x41 }, { 0xf1,0x04,0x98,0x4a }, + { 0xab,0x73,0xd3,0x23 }, { 0xa5,0x7a,0xde,0x28 }, + { 0xb7,0x61,0xc9,0x35 }, { 0xb9,0x68,0xc4,0x3e }, + { 0x93,0x57,0xe7,0x0f }, { 0x9d,0x5e,0xea,0x04 }, + { 0x8f,0x45,0xfd,0x19 }, { 0x81,0x4c,0xf0,0x12 }, + { 0x3b,0xab,0x6b,0xcb }, { 0x35,0xa2,0x66,0xc0 }, + { 0x27,0xb9,0x71,0xdd }, { 0x29,0xb0,0x7c,0xd6 }, + { 0x03,0x8f,0x5f,0xe7 }, { 0x0d,0x86,0x52,0xec }, + { 0x1f,0x9d,0x45,0xf1 }, { 0x11,0x94,0x48,0xfa }, + { 0x4b,0xe3,0x03,0x93 }, { 0x45,0xea,0x0e,0x98 }, + { 0x57,0xf1,0x19,0x85 }, { 0x59,0xf8,0x14,0x8e }, + { 0x73,0xc7,0x37,0xbf }, { 0x7d,0xce,0x3a,0xb4 }, + { 0x6f,0xd5,0x2d,0xa9 }, { 0x61,0xdc,0x20,0xa2 }, + { 0xad,0x76,0x6d,0xf6 }, { 0xa3,0x7f,0x60,0xfd }, + { 0xb1,0x64,0x77,0xe0 }, { 0xbf,0x6d,0x7a,0xeb }, + { 0x95,0x52,0x59,0xda }, { 0x9b,0x5b,0x54,0xd1 }, + { 0x89,0x40,0x43,0xcc }, { 0x87,0x49,0x4e,0xc7 }, + { 0xdd,0x3e,0x05,0xae }, { 0xd3,0x37,0x08,0xa5 }, + { 0xc1,0x2c,0x1f,0xb8 }, { 0xcf,0x25,0x12,0xb3 }, + { 0xe5,0x1a,0x31,0x82 }, { 0xeb,0x13,0x3c,0x89 }, + { 0xf9,0x08,0x2b,0x94 }, { 0xf7,0x01,0x26,0x9f }, + { 0x4d,0xe6,0xbd,0x46 }, { 0x43,0xef,0xb0,0x4d }, + { 0x51,0xf4,0xa7,0x50 }, { 0x5f,0xfd,0xaa,0x5b }, + { 0x75,0xc2,0x89,0x6a }, { 0x7b,0xcb,0x84,0x61 }, + { 0x69,0xd0,0x93,0x7c }, { 0x67,0xd9,0x9e,0x77 }, + { 0x3d,0xae,0xd5,0x1e }, { 0x33,0xa7,0xd8,0x15 }, + { 0x21,0xbc,0xcf,0x08 }, { 0x2f,0xb5,0xc2,0x03 }, + { 0x05,0x8a,0xe1,0x32 }, { 0x0b,0x83,0xec,0x39 }, + { 0x19,0x98,0xfb,0x24 }, { 0x17,0x91,0xf6,0x2f }, + { 0x76,0x4d,0xd6,0x8d }, { 0x78,0x44,0xdb,0x86 }, + { 0x6a,0x5f,0xcc,0x9b }, { 0x64,0x56,0xc1,0x90 }, + { 0x4e,0x69,0xe2,0xa1 }, { 0x40,0x60,0xef,0xaa }, + { 0x52,0x7b,0xf8,0xb7 }, { 0x5c,0x72,0xf5,0xbc }, + { 0x06,0x05,0xbe,0xd5 }, { 0x08,0x0c,0xb3,0xde }, + { 0x1a,0x17,0xa4,0xc3 }, { 0x14,0x1e,0xa9,0xc8 }, + { 0x3e,0x21,0x8a,0xf9 }, { 0x30,0x28,0x87,0xf2 }, + { 0x22,0x33,0x90,0xef }, { 0x2c,0x3a,0x9d,0xe4 }, + { 0x96,0xdd,0x06,0x3d }, { 0x98,0xd4,0x0b,0x36 }, + { 0x8a,0xcf,0x1c,0x2b }, { 0x84,0xc6,0x11,0x20 }, + { 0xae,0xf9,0x32,0x11 }, { 0xa0,0xf0,0x3f,0x1a }, + { 0xb2,0xeb,0x28,0x07 }, { 0xbc,0xe2,0x25,0x0c }, + { 0xe6,0x95,0x6e,0x65 }, { 0xe8,0x9c,0x63,0x6e }, + { 0xfa,0x87,0x74,0x73 }, { 0xf4,0x8e,0x79,0x78 }, + { 0xde,0xb1,0x5a,0x49 }, { 0xd0,0xb8,0x57,0x42 }, + { 0xc2,0xa3,0x40,0x5f }, { 0xcc,0xaa,0x4d,0x54 }, + { 0x41,0xec,0xda,0xf7 }, { 0x4f,0xe5,0xd7,0xfc }, + { 0x5d,0xfe,0xc0,0xe1 }, { 0x53,0xf7,0xcd,0xea }, + { 0x79,0xc8,0xee,0xdb }, { 0x77,0xc1,0xe3,0xd0 }, + { 0x65,0xda,0xf4,0xcd }, { 0x6b,0xd3,0xf9,0xc6 }, + { 0x31,0xa4,0xb2,0xaf }, { 0x3f,0xad,0xbf,0xa4 }, + { 0x2d,0xb6,0xa8,0xb9 }, { 0x23,0xbf,0xa5,0xb2 }, + { 0x09,0x80,0x86,0x83 }, { 0x07,0x89,0x8b,0x88 }, + { 0x15,0x92,0x9c,0x95 }, { 0x1b,0x9b,0x91,0x9e }, + { 0xa1,0x7c,0x0a,0x47 }, { 0xaf,0x75,0x07,0x4c }, + { 0xbd,0x6e,0x10,0x51 }, { 0xb3,0x67,0x1d,0x5a }, + { 0x99,0x58,0x3e,0x6b }, { 0x97,0x51,0x33,0x60 }, + { 0x85,0x4a,0x24,0x7d }, { 0x8b,0x43,0x29,0x76 }, + { 0xd1,0x34,0x62,0x1f }, { 0xdf,0x3d,0x6f,0x14 }, + { 0xcd,0x26,0x78,0x09 }, { 0xc3,0x2f,0x75,0x02 }, + { 0xe9,0x10,0x56,0x33 }, { 0xe7,0x19,0x5b,0x38 }, + { 0xf5,0x02,0x4c,0x25 }, { 0xfb,0x0b,0x41,0x2e }, + { 0x9a,0xd7,0x61,0x8c }, { 0x94,0xde,0x6c,0x87 }, + { 0x86,0xc5,0x7b,0x9a }, { 0x88,0xcc,0x76,0x91 }, + { 0xa2,0xf3,0x55,0xa0 }, { 0xac,0xfa,0x58,0xab }, + { 0xbe,0xe1,0x4f,0xb6 }, { 0xb0,0xe8,0x42,0xbd }, + { 0xea,0x9f,0x09,0xd4 }, { 0xe4,0x96,0x04,0xdf }, + { 0xf6,0x8d,0x13,0xc2 }, { 0xf8,0x84,0x1e,0xc9 }, + { 0xd2,0xbb,0x3d,0xf8 }, { 0xdc,0xb2,0x30,0xf3 }, + { 0xce,0xa9,0x27,0xee }, { 0xc0,0xa0,0x2a,0xe5 }, + { 0x7a,0x47,0xb1,0x3c }, { 0x74,0x4e,0xbc,0x37 }, + { 0x66,0x55,0xab,0x2a }, { 0x68,0x5c,0xa6,0x21 }, + { 0x42,0x63,0x85,0x10 }, { 0x4c,0x6a,0x88,0x1b }, + { 0x5e,0x71,0x9f,0x06 }, { 0x50,0x78,0x92,0x0d }, + { 0x0a,0x0f,0xd9,0x64 }, { 0x04,0x06,0xd4,0x6f }, + { 0x16,0x1d,0xc3,0x72 }, { 0x18,0x14,0xce,0x79 }, + { 0x32,0x2b,0xed,0x48 }, { 0x3c,0x22,0xe0,0x43 }, + { 0x2e,0x39,0xf7,0x5e }, { 0x20,0x30,0xfa,0x55 }, + { 0xec,0x9a,0xb7,0x01 }, { 0xe2,0x93,0xba,0x0a }, + { 0xf0,0x88,0xad,0x17 }, { 0xfe,0x81,0xa0,0x1c }, + { 0xd4,0xbe,0x83,0x2d }, { 0xda,0xb7,0x8e,0x26 }, + { 0xc8,0xac,0x99,0x3b }, { 0xc6,0xa5,0x94,0x30 }, + { 0x9c,0xd2,0xdf,0x59 }, { 0x92,0xdb,0xd2,0x52 }, + { 0x80,0xc0,0xc5,0x4f }, { 0x8e,0xc9,0xc8,0x44 }, + { 0xa4,0xf6,0xeb,0x75 }, { 0xaa,0xff,0xe6,0x7e }, + { 0xb8,0xe4,0xf1,0x63 }, { 0xb6,0xed,0xfc,0x68 }, + { 0x0c,0x0a,0x67,0xb1 }, { 0x02,0x03,0x6a,0xba }, + { 0x10,0x18,0x7d,0xa7 }, { 0x1e,0x11,0x70,0xac }, + { 0x34,0x2e,0x53,0x9d }, { 0x3a,0x27,0x5e,0x96 }, + { 0x28,0x3c,0x49,0x8b }, { 0x26,0x35,0x44,0x80 }, + { 0x7c,0x42,0x0f,0xe9 }, { 0x72,0x4b,0x02,0xe2 }, + { 0x60,0x50,0x15,0xff }, { 0x6e,0x59,0x18,0xf4 }, + { 0x44,0x66,0x3b,0xc5 }, { 0x4a,0x6f,0x36,0xce }, + { 0x58,0x74,0x21,0xd3 }, { 0x56,0x7d,0x2c,0xd8 }, + { 0x37,0xa1,0x0c,0x7a }, { 0x39,0xa8,0x01,0x71 }, + { 0x2b,0xb3,0x16,0x6c }, { 0x25,0xba,0x1b,0x67 }, + { 0x0f,0x85,0x38,0x56 }, { 0x01,0x8c,0x35,0x5d }, + { 0x13,0x97,0x22,0x40 }, { 0x1d,0x9e,0x2f,0x4b }, + { 0x47,0xe9,0x64,0x22 }, { 0x49,0xe0,0x69,0x29 }, + { 0x5b,0xfb,0x7e,0x34 }, { 0x55,0xf2,0x73,0x3f }, + { 0x7f,0xcd,0x50,0x0e }, { 0x71,0xc4,0x5d,0x05 }, + { 0x63,0xdf,0x4a,0x18 }, { 0x6d,0xd6,0x47,0x13 }, + { 0xd7,0x31,0xdc,0xca }, { 0xd9,0x38,0xd1,0xc1 }, + { 0xcb,0x23,0xc6,0xdc }, { 0xc5,0x2a,0xcb,0xd7 }, + { 0xef,0x15,0xe8,0xe6 }, { 0xe1,0x1c,0xe5,0xed }, + { 0xf3,0x07,0xf2,0xf0 }, { 0xfd,0x0e,0xff,0xfb }, + { 0xa7,0x79,0xb4,0x92 }, { 0xa9,0x70,0xb9,0x99 }, + { 0xbb,0x6b,0xae,0x84 }, { 0xb5,0x62,0xa3,0x8f }, + { 0x9f,0x5d,0x80,0xbe }, { 0x91,0x54,0x8d,0xb5 }, + { 0x83,0x4f,0x9a,0xa8 }, { 0x8d,0x46,0x97,0xa3 } + }; + +static const unsigned char U2[256][4] = + { + { 0x00,0x00,0x00,0x00 }, { 0x0b,0x0e,0x09,0x0d }, + { 0x16,0x1c,0x12,0x1a }, { 0x1d,0x12,0x1b,0x17 }, + { 0x2c,0x38,0x24,0x34 }, { 0x27,0x36,0x2d,0x39 }, + { 0x3a,0x24,0x36,0x2e }, { 0x31,0x2a,0x3f,0x23 }, + { 0x58,0x70,0x48,0x68 }, { 0x53,0x7e,0x41,0x65 }, + { 0x4e,0x6c,0x5a,0x72 }, { 0x45,0x62,0x53,0x7f }, + { 0x74,0x48,0x6c,0x5c }, { 0x7f,0x46,0x65,0x51 }, + { 0x62,0x54,0x7e,0x46 }, { 0x69,0x5a,0x77,0x4b }, + { 0xb0,0xe0,0x90,0xd0 }, { 0xbb,0xee,0x99,0xdd }, + { 0xa6,0xfc,0x82,0xca }, { 0xad,0xf2,0x8b,0xc7 }, + { 0x9c,0xd8,0xb4,0xe4 }, { 0x97,0xd6,0xbd,0xe9 }, + { 0x8a,0xc4,0xa6,0xfe }, { 0x81,0xca,0xaf,0xf3 }, + { 0xe8,0x90,0xd8,0xb8 }, { 0xe3,0x9e,0xd1,0xb5 }, + { 0xfe,0x8c,0xca,0xa2 }, { 0xf5,0x82,0xc3,0xaf }, + { 0xc4,0xa8,0xfc,0x8c }, { 0xcf,0xa6,0xf5,0x81 }, + { 0xd2,0xb4,0xee,0x96 }, { 0xd9,0xba,0xe7,0x9b }, + { 0x7b,0xdb,0x3b,0xbb }, { 0x70,0xd5,0x32,0xb6 }, + { 0x6d,0xc7,0x29,0xa1 }, { 0x66,0xc9,0x20,0xac }, + { 0x57,0xe3,0x1f,0x8f }, { 0x5c,0xed,0x16,0x82 }, + { 0x41,0xff,0x0d,0x95 }, { 0x4a,0xf1,0x04,0x98 }, + { 0x23,0xab,0x73,0xd3 }, { 0x28,0xa5,0x7a,0xde }, + { 0x35,0xb7,0x61,0xc9 }, { 0x3e,0xb9,0x68,0xc4 }, + { 0x0f,0x93,0x57,0xe7 }, { 0x04,0x9d,0x5e,0xea }, + { 0x19,0x8f,0x45,0xfd }, { 0x12,0x81,0x4c,0xf0 }, + { 0xcb,0x3b,0xab,0x6b }, { 0xc0,0x35,0xa2,0x66 }, + { 0xdd,0x27,0xb9,0x71 }, { 0xd6,0x29,0xb0,0x7c }, + { 0xe7,0x03,0x8f,0x5f }, { 0xec,0x0d,0x86,0x52 }, + { 0xf1,0x1f,0x9d,0x45 }, { 0xfa,0x11,0x94,0x48 }, + { 0x93,0x4b,0xe3,0x03 }, { 0x98,0x45,0xea,0x0e }, + { 0x85,0x57,0xf1,0x19 }, { 0x8e,0x59,0xf8,0x14 }, + { 0xbf,0x73,0xc7,0x37 }, { 0xb4,0x7d,0xce,0x3a }, + { 0xa9,0x6f,0xd5,0x2d }, { 0xa2,0x61,0xdc,0x20 }, + { 0xf6,0xad,0x76,0x6d }, { 0xfd,0xa3,0x7f,0x60 }, + { 0xe0,0xb1,0x64,0x77 }, { 0xeb,0xbf,0x6d,0x7a }, + { 0xda,0x95,0x52,0x59 }, { 0xd1,0x9b,0x5b,0x54 }, + { 0xcc,0x89,0x40,0x43 }, { 0xc7,0x87,0x49,0x4e }, + { 0xae,0xdd,0x3e,0x05 }, { 0xa5,0xd3,0x37,0x08 }, + { 0xb8,0xc1,0x2c,0x1f }, { 0xb3,0xcf,0x25,0x12 }, + { 0x82,0xe5,0x1a,0x31 }, { 0x89,0xeb,0x13,0x3c }, + { 0x94,0xf9,0x08,0x2b }, { 0x9f,0xf7,0x01,0x26 }, + { 0x46,0x4d,0xe6,0xbd }, { 0x4d,0x43,0xef,0xb0 }, + { 0x50,0x51,0xf4,0xa7 }, { 0x5b,0x5f,0xfd,0xaa }, + { 0x6a,0x75,0xc2,0x89 }, { 0x61,0x7b,0xcb,0x84 }, + { 0x7c,0x69,0xd0,0x93 }, { 0x77,0x67,0xd9,0x9e }, + { 0x1e,0x3d,0xae,0xd5 }, { 0x15,0x33,0xa7,0xd8 }, + { 0x08,0x21,0xbc,0xcf }, { 0x03,0x2f,0xb5,0xc2 }, + { 0x32,0x05,0x8a,0xe1 }, { 0x39,0x0b,0x83,0xec }, + { 0x24,0x19,0x98,0xfb }, { 0x2f,0x17,0x91,0xf6 }, + { 0x8d,0x76,0x4d,0xd6 }, { 0x86,0x78,0x44,0xdb }, + { 0x9b,0x6a,0x5f,0xcc }, { 0x90,0x64,0x56,0xc1 }, + { 0xa1,0x4e,0x69,0xe2 }, { 0xaa,0x40,0x60,0xef }, + { 0xb7,0x52,0x7b,0xf8 }, { 0xbc,0x5c,0x72,0xf5 }, + { 0xd5,0x06,0x05,0xbe }, { 0xde,0x08,0x0c,0xb3 }, + { 0xc3,0x1a,0x17,0xa4 }, { 0xc8,0x14,0x1e,0xa9 }, + { 0xf9,0x3e,0x21,0x8a }, { 0xf2,0x30,0x28,0x87 }, + { 0xef,0x22,0x33,0x90 }, { 0xe4,0x2c,0x3a,0x9d }, + { 0x3d,0x96,0xdd,0x06 }, { 0x36,0x98,0xd4,0x0b }, + { 0x2b,0x8a,0xcf,0x1c }, { 0x20,0x84,0xc6,0x11 }, + { 0x11,0xae,0xf9,0x32 }, { 0x1a,0xa0,0xf0,0x3f }, + { 0x07,0xb2,0xeb,0x28 }, { 0x0c,0xbc,0xe2,0x25 }, + { 0x65,0xe6,0x95,0x6e }, { 0x6e,0xe8,0x9c,0x63 }, + { 0x73,0xfa,0x87,0x74 }, { 0x78,0xf4,0x8e,0x79 }, + { 0x49,0xde,0xb1,0x5a }, { 0x42,0xd0,0xb8,0x57 }, + { 0x5f,0xc2,0xa3,0x40 }, { 0x54,0xcc,0xaa,0x4d }, + { 0xf7,0x41,0xec,0xda }, { 0xfc,0x4f,0xe5,0xd7 }, + { 0xe1,0x5d,0xfe,0xc0 }, { 0xea,0x53,0xf7,0xcd }, + { 0xdb,0x79,0xc8,0xee }, { 0xd0,0x77,0xc1,0xe3 }, + { 0xcd,0x65,0xda,0xf4 }, { 0xc6,0x6b,0xd3,0xf9 }, + { 0xaf,0x31,0xa4,0xb2 }, { 0xa4,0x3f,0xad,0xbf }, + { 0xb9,0x2d,0xb6,0xa8 }, { 0xb2,0x23,0xbf,0xa5 }, + { 0x83,0x09,0x80,0x86 }, { 0x88,0x07,0x89,0x8b }, + { 0x95,0x15,0x92,0x9c }, { 0x9e,0x1b,0x9b,0x91 }, + { 0x47,0xa1,0x7c,0x0a }, { 0x4c,0xaf,0x75,0x07 }, + { 0x51,0xbd,0x6e,0x10 }, { 0x5a,0xb3,0x67,0x1d }, + { 0x6b,0x99,0x58,0x3e }, { 0x60,0x97,0x51,0x33 }, + { 0x7d,0x85,0x4a,0x24 }, { 0x76,0x8b,0x43,0x29 }, + { 0x1f,0xd1,0x34,0x62 }, { 0x14,0xdf,0x3d,0x6f }, + { 0x09,0xcd,0x26,0x78 }, { 0x02,0xc3,0x2f,0x75 }, + { 0x33,0xe9,0x10,0x56 }, { 0x38,0xe7,0x19,0x5b }, + { 0x25,0xf5,0x02,0x4c }, { 0x2e,0xfb,0x0b,0x41 }, + { 0x8c,0x9a,0xd7,0x61 }, { 0x87,0x94,0xde,0x6c }, + { 0x9a,0x86,0xc5,0x7b }, { 0x91,0x88,0xcc,0x76 }, + { 0xa0,0xa2,0xf3,0x55 }, { 0xab,0xac,0xfa,0x58 }, + { 0xb6,0xbe,0xe1,0x4f }, { 0xbd,0xb0,0xe8,0x42 }, + { 0xd4,0xea,0x9f,0x09 }, { 0xdf,0xe4,0x96,0x04 }, + { 0xc2,0xf6,0x8d,0x13 }, { 0xc9,0xf8,0x84,0x1e }, + { 0xf8,0xd2,0xbb,0x3d }, { 0xf3,0xdc,0xb2,0x30 }, + { 0xee,0xce,0xa9,0x27 }, { 0xe5,0xc0,0xa0,0x2a }, + { 0x3c,0x7a,0x47,0xb1 }, { 0x37,0x74,0x4e,0xbc }, + { 0x2a,0x66,0x55,0xab }, { 0x21,0x68,0x5c,0xa6 }, + { 0x10,0x42,0x63,0x85 }, { 0x1b,0x4c,0x6a,0x88 }, + { 0x06,0x5e,0x71,0x9f }, { 0x0d,0x50,0x78,0x92 }, + { 0x64,0x0a,0x0f,0xd9 }, { 0x6f,0x04,0x06,0xd4 }, + { 0x72,0x16,0x1d,0xc3 }, { 0x79,0x18,0x14,0xce }, + { 0x48,0x32,0x2b,0xed }, { 0x43,0x3c,0x22,0xe0 }, + { 0x5e,0x2e,0x39,0xf7 }, { 0x55,0x20,0x30,0xfa }, + { 0x01,0xec,0x9a,0xb7 }, { 0x0a,0xe2,0x93,0xba }, + { 0x17,0xf0,0x88,0xad }, { 0x1c,0xfe,0x81,0xa0 }, + { 0x2d,0xd4,0xbe,0x83 }, { 0x26,0xda,0xb7,0x8e }, + { 0x3b,0xc8,0xac,0x99 }, { 0x30,0xc6,0xa5,0x94 }, + { 0x59,0x9c,0xd2,0xdf }, { 0x52,0x92,0xdb,0xd2 }, + { 0x4f,0x80,0xc0,0xc5 }, { 0x44,0x8e,0xc9,0xc8 }, + { 0x75,0xa4,0xf6,0xeb }, { 0x7e,0xaa,0xff,0xe6 }, + { 0x63,0xb8,0xe4,0xf1 }, { 0x68,0xb6,0xed,0xfc }, + { 0xb1,0x0c,0x0a,0x67 }, { 0xba,0x02,0x03,0x6a }, + { 0xa7,0x10,0x18,0x7d }, { 0xac,0x1e,0x11,0x70 }, + { 0x9d,0x34,0x2e,0x53 }, { 0x96,0x3a,0x27,0x5e }, + { 0x8b,0x28,0x3c,0x49 }, { 0x80,0x26,0x35,0x44 }, + { 0xe9,0x7c,0x42,0x0f }, { 0xe2,0x72,0x4b,0x02 }, + { 0xff,0x60,0x50,0x15 }, { 0xf4,0x6e,0x59,0x18 }, + { 0xc5,0x44,0x66,0x3b }, { 0xce,0x4a,0x6f,0x36 }, + { 0xd3,0x58,0x74,0x21 }, { 0xd8,0x56,0x7d,0x2c }, + { 0x7a,0x37,0xa1,0x0c }, { 0x71,0x39,0xa8,0x01 }, + { 0x6c,0x2b,0xb3,0x16 }, { 0x67,0x25,0xba,0x1b }, + { 0x56,0x0f,0x85,0x38 }, { 0x5d,0x01,0x8c,0x35 }, + { 0x40,0x13,0x97,0x22 }, { 0x4b,0x1d,0x9e,0x2f }, + { 0x22,0x47,0xe9,0x64 }, { 0x29,0x49,0xe0,0x69 }, + { 0x34,0x5b,0xfb,0x7e }, { 0x3f,0x55,0xf2,0x73 }, + { 0x0e,0x7f,0xcd,0x50 }, { 0x05,0x71,0xc4,0x5d }, + { 0x18,0x63,0xdf,0x4a }, { 0x13,0x6d,0xd6,0x47 }, + { 0xca,0xd7,0x31,0xdc }, { 0xc1,0xd9,0x38,0xd1 }, + { 0xdc,0xcb,0x23,0xc6 }, { 0xd7,0xc5,0x2a,0xcb }, + { 0xe6,0xef,0x15,0xe8 }, { 0xed,0xe1,0x1c,0xe5 }, + { 0xf0,0xf3,0x07,0xf2 }, { 0xfb,0xfd,0x0e,0xff }, + { 0x92,0xa7,0x79,0xb4 }, { 0x99,0xa9,0x70,0xb9 }, + { 0x84,0xbb,0x6b,0xae }, { 0x8f,0xb5,0x62,0xa3 }, + { 0xbe,0x9f,0x5d,0x80 }, { 0xb5,0x91,0x54,0x8d }, + { 0xa8,0x83,0x4f,0x9a }, { 0xa3,0x8d,0x46,0x97 } + }; + +static const unsigned char U3[256][4] = + { + { 0x00,0x00,0x00,0x00 }, { 0x0d,0x0b,0x0e,0x09 }, + { 0x1a,0x16,0x1c,0x12 }, { 0x17,0x1d,0x12,0x1b }, + { 0x34,0x2c,0x38,0x24 }, { 0x39,0x27,0x36,0x2d }, + { 0x2e,0x3a,0x24,0x36 }, { 0x23,0x31,0x2a,0x3f }, + { 0x68,0x58,0x70,0x48 }, { 0x65,0x53,0x7e,0x41 }, + { 0x72,0x4e,0x6c,0x5a }, { 0x7f,0x45,0x62,0x53 }, + { 0x5c,0x74,0x48,0x6c }, { 0x51,0x7f,0x46,0x65 }, + { 0x46,0x62,0x54,0x7e }, { 0x4b,0x69,0x5a,0x77 }, + { 0xd0,0xb0,0xe0,0x90 }, { 0xdd,0xbb,0xee,0x99 }, + { 0xca,0xa6,0xfc,0x82 }, { 0xc7,0xad,0xf2,0x8b }, + { 0xe4,0x9c,0xd8,0xb4 }, { 0xe9,0x97,0xd6,0xbd }, + { 0xfe,0x8a,0xc4,0xa6 }, { 0xf3,0x81,0xca,0xaf }, + { 0xb8,0xe8,0x90,0xd8 }, { 0xb5,0xe3,0x9e,0xd1 }, + { 0xa2,0xfe,0x8c,0xca }, { 0xaf,0xf5,0x82,0xc3 }, + { 0x8c,0xc4,0xa8,0xfc }, { 0x81,0xcf,0xa6,0xf5 }, + { 0x96,0xd2,0xb4,0xee }, { 0x9b,0xd9,0xba,0xe7 }, + { 0xbb,0x7b,0xdb,0x3b }, { 0xb6,0x70,0xd5,0x32 }, + { 0xa1,0x6d,0xc7,0x29 }, { 0xac,0x66,0xc9,0x20 }, + { 0x8f,0x57,0xe3,0x1f }, { 0x82,0x5c,0xed,0x16 }, + { 0x95,0x41,0xff,0x0d }, { 0x98,0x4a,0xf1,0x04 }, + { 0xd3,0x23,0xab,0x73 }, { 0xde,0x28,0xa5,0x7a }, + { 0xc9,0x35,0xb7,0x61 }, { 0xc4,0x3e,0xb9,0x68 }, + { 0xe7,0x0f,0x93,0x57 }, { 0xea,0x04,0x9d,0x5e }, + { 0xfd,0x19,0x8f,0x45 }, { 0xf0,0x12,0x81,0x4c }, + { 0x6b,0xcb,0x3b,0xab }, { 0x66,0xc0,0x35,0xa2 }, + { 0x71,0xdd,0x27,0xb9 }, { 0x7c,0xd6,0x29,0xb0 }, + { 0x5f,0xe7,0x03,0x8f }, { 0x52,0xec,0x0d,0x86 }, + { 0x45,0xf1,0x1f,0x9d }, { 0x48,0xfa,0x11,0x94 }, + { 0x03,0x93,0x4b,0xe3 }, { 0x0e,0x98,0x45,0xea }, + { 0x19,0x85,0x57,0xf1 }, { 0x14,0x8e,0x59,0xf8 }, + { 0x37,0xbf,0x73,0xc7 }, { 0x3a,0xb4,0x7d,0xce }, + { 0x2d,0xa9,0x6f,0xd5 }, { 0x20,0xa2,0x61,0xdc }, + { 0x6d,0xf6,0xad,0x76 }, { 0x60,0xfd,0xa3,0x7f }, + { 0x77,0xe0,0xb1,0x64 }, { 0x7a,0xeb,0xbf,0x6d }, + { 0x59,0xda,0x95,0x52 }, { 0x54,0xd1,0x9b,0x5b }, + { 0x43,0xcc,0x89,0x40 }, { 0x4e,0xc7,0x87,0x49 }, + { 0x05,0xae,0xdd,0x3e }, { 0x08,0xa5,0xd3,0x37 }, + { 0x1f,0xb8,0xc1,0x2c }, { 0x12,0xb3,0xcf,0x25 }, + { 0x31,0x82,0xe5,0x1a }, { 0x3c,0x89,0xeb,0x13 }, + { 0x2b,0x94,0xf9,0x08 }, { 0x26,0x9f,0xf7,0x01 }, + { 0xbd,0x46,0x4d,0xe6 }, { 0xb0,0x4d,0x43,0xef }, + { 0xa7,0x50,0x51,0xf4 }, { 0xaa,0x5b,0x5f,0xfd }, + { 0x89,0x6a,0x75,0xc2 }, { 0x84,0x61,0x7b,0xcb }, + { 0x93,0x7c,0x69,0xd0 }, { 0x9e,0x77,0x67,0xd9 }, + { 0xd5,0x1e,0x3d,0xae }, { 0xd8,0x15,0x33,0xa7 }, + { 0xcf,0x08,0x21,0xbc }, { 0xc2,0x03,0x2f,0xb5 }, + { 0xe1,0x32,0x05,0x8a }, { 0xec,0x39,0x0b,0x83 }, + { 0xfb,0x24,0x19,0x98 }, { 0xf6,0x2f,0x17,0x91 }, + { 0xd6,0x8d,0x76,0x4d }, { 0xdb,0x86,0x78,0x44 }, + { 0xcc,0x9b,0x6a,0x5f }, { 0xc1,0x90,0x64,0x56 }, + { 0xe2,0xa1,0x4e,0x69 }, { 0xef,0xaa,0x40,0x60 }, + { 0xf8,0xb7,0x52,0x7b }, { 0xf5,0xbc,0x5c,0x72 }, + { 0xbe,0xd5,0x06,0x05 }, { 0xb3,0xde,0x08,0x0c }, + { 0xa4,0xc3,0x1a,0x17 }, { 0xa9,0xc8,0x14,0x1e }, + { 0x8a,0xf9,0x3e,0x21 }, { 0x87,0xf2,0x30,0x28 }, + { 0x90,0xef,0x22,0x33 }, { 0x9d,0xe4,0x2c,0x3a }, + { 0x06,0x3d,0x96,0xdd }, { 0x0b,0x36,0x98,0xd4 }, + { 0x1c,0x2b,0x8a,0xcf }, { 0x11,0x20,0x84,0xc6 }, + { 0x32,0x11,0xae,0xf9 }, { 0x3f,0x1a,0xa0,0xf0 }, + { 0x28,0x07,0xb2,0xeb }, { 0x25,0x0c,0xbc,0xe2 }, + { 0x6e,0x65,0xe6,0x95 }, { 0x63,0x6e,0xe8,0x9c }, + { 0x74,0x73,0xfa,0x87 }, { 0x79,0x78,0xf4,0x8e }, + { 0x5a,0x49,0xde,0xb1 }, { 0x57,0x42,0xd0,0xb8 }, + { 0x40,0x5f,0xc2,0xa3 }, { 0x4d,0x54,0xcc,0xaa }, + { 0xda,0xf7,0x41,0xec }, { 0xd7,0xfc,0x4f,0xe5 }, + { 0xc0,0xe1,0x5d,0xfe }, { 0xcd,0xea,0x53,0xf7 }, + { 0xee,0xdb,0x79,0xc8 }, { 0xe3,0xd0,0x77,0xc1 }, + { 0xf4,0xcd,0x65,0xda }, { 0xf9,0xc6,0x6b,0xd3 }, + { 0xb2,0xaf,0x31,0xa4 }, { 0xbf,0xa4,0x3f,0xad }, + { 0xa8,0xb9,0x2d,0xb6 }, { 0xa5,0xb2,0x23,0xbf }, + { 0x86,0x83,0x09,0x80 }, { 0x8b,0x88,0x07,0x89 }, + { 0x9c,0x95,0x15,0x92 }, { 0x91,0x9e,0x1b,0x9b }, + { 0x0a,0x47,0xa1,0x7c }, { 0x07,0x4c,0xaf,0x75 }, + { 0x10,0x51,0xbd,0x6e }, { 0x1d,0x5a,0xb3,0x67 }, + { 0x3e,0x6b,0x99,0x58 }, { 0x33,0x60,0x97,0x51 }, + { 0x24,0x7d,0x85,0x4a }, { 0x29,0x76,0x8b,0x43 }, + { 0x62,0x1f,0xd1,0x34 }, { 0x6f,0x14,0xdf,0x3d }, + { 0x78,0x09,0xcd,0x26 }, { 0x75,0x02,0xc3,0x2f }, + { 0x56,0x33,0xe9,0x10 }, { 0x5b,0x38,0xe7,0x19 }, + { 0x4c,0x25,0xf5,0x02 }, { 0x41,0x2e,0xfb,0x0b }, + { 0x61,0x8c,0x9a,0xd7 }, { 0x6c,0x87,0x94,0xde }, + { 0x7b,0x9a,0x86,0xc5 }, { 0x76,0x91,0x88,0xcc }, + { 0x55,0xa0,0xa2,0xf3 }, { 0x58,0xab,0xac,0xfa }, + { 0x4f,0xb6,0xbe,0xe1 }, { 0x42,0xbd,0xb0,0xe8 }, + { 0x09,0xd4,0xea,0x9f }, { 0x04,0xdf,0xe4,0x96 }, + { 0x13,0xc2,0xf6,0x8d }, { 0x1e,0xc9,0xf8,0x84 }, + { 0x3d,0xf8,0xd2,0xbb }, { 0x30,0xf3,0xdc,0xb2 }, + { 0x27,0xee,0xce,0xa9 }, { 0x2a,0xe5,0xc0,0xa0 }, + { 0xb1,0x3c,0x7a,0x47 }, { 0xbc,0x37,0x74,0x4e }, + { 0xab,0x2a,0x66,0x55 }, { 0xa6,0x21,0x68,0x5c }, + { 0x85,0x10,0x42,0x63 }, { 0x88,0x1b,0x4c,0x6a }, + { 0x9f,0x06,0x5e,0x71 }, { 0x92,0x0d,0x50,0x78 }, + { 0xd9,0x64,0x0a,0x0f }, { 0xd4,0x6f,0x04,0x06 }, + { 0xc3,0x72,0x16,0x1d }, { 0xce,0x79,0x18,0x14 }, + { 0xed,0x48,0x32,0x2b }, { 0xe0,0x43,0x3c,0x22 }, + { 0xf7,0x5e,0x2e,0x39 }, { 0xfa,0x55,0x20,0x30 }, + { 0xb7,0x01,0xec,0x9a }, { 0xba,0x0a,0xe2,0x93 }, + { 0xad,0x17,0xf0,0x88 }, { 0xa0,0x1c,0xfe,0x81 }, + { 0x83,0x2d,0xd4,0xbe }, { 0x8e,0x26,0xda,0xb7 }, + { 0x99,0x3b,0xc8,0xac }, { 0x94,0x30,0xc6,0xa5 }, + { 0xdf,0x59,0x9c,0xd2 }, { 0xd2,0x52,0x92,0xdb }, + { 0xc5,0x4f,0x80,0xc0 }, { 0xc8,0x44,0x8e,0xc9 }, + { 0xeb,0x75,0xa4,0xf6 }, { 0xe6,0x7e,0xaa,0xff }, + { 0xf1,0x63,0xb8,0xe4 }, { 0xfc,0x68,0xb6,0xed }, + { 0x67,0xb1,0x0c,0x0a }, { 0x6a,0xba,0x02,0x03 }, + { 0x7d,0xa7,0x10,0x18 }, { 0x70,0xac,0x1e,0x11 }, + { 0x53,0x9d,0x34,0x2e }, { 0x5e,0x96,0x3a,0x27 }, + { 0x49,0x8b,0x28,0x3c }, { 0x44,0x80,0x26,0x35 }, + { 0x0f,0xe9,0x7c,0x42 }, { 0x02,0xe2,0x72,0x4b }, + { 0x15,0xff,0x60,0x50 }, { 0x18,0xf4,0x6e,0x59 }, + { 0x3b,0xc5,0x44,0x66 }, { 0x36,0xce,0x4a,0x6f }, + { 0x21,0xd3,0x58,0x74 }, { 0x2c,0xd8,0x56,0x7d }, + { 0x0c,0x7a,0x37,0xa1 }, { 0x01,0x71,0x39,0xa8 }, + { 0x16,0x6c,0x2b,0xb3 }, { 0x1b,0x67,0x25,0xba }, + { 0x38,0x56,0x0f,0x85 }, { 0x35,0x5d,0x01,0x8c }, + { 0x22,0x40,0x13,0x97 }, { 0x2f,0x4b,0x1d,0x9e }, + { 0x64,0x22,0x47,0xe9 }, { 0x69,0x29,0x49,0xe0 }, + { 0x7e,0x34,0x5b,0xfb }, { 0x73,0x3f,0x55,0xf2 }, + { 0x50,0x0e,0x7f,0xcd }, { 0x5d,0x05,0x71,0xc4 }, + { 0x4a,0x18,0x63,0xdf }, { 0x47,0x13,0x6d,0xd6 }, + { 0xdc,0xca,0xd7,0x31 }, { 0xd1,0xc1,0xd9,0x38 }, + { 0xc6,0xdc,0xcb,0x23 }, { 0xcb,0xd7,0xc5,0x2a }, + { 0xe8,0xe6,0xef,0x15 }, { 0xe5,0xed,0xe1,0x1c }, + { 0xf2,0xf0,0xf3,0x07 }, { 0xff,0xfb,0xfd,0x0e }, + { 0xb4,0x92,0xa7,0x79 }, { 0xb9,0x99,0xa9,0x70 }, + { 0xae,0x84,0xbb,0x6b }, { 0xa3,0x8f,0xb5,0x62 }, + { 0x80,0xbe,0x9f,0x5d }, { 0x8d,0xb5,0x91,0x54 }, + { 0x9a,0xa8,0x83,0x4f }, { 0x97,0xa3,0x8d,0x46 } + }; + +static const unsigned char U4[256][4] = + { + { 0x00,0x00,0x00,0x00 }, { 0x09,0x0d,0x0b,0x0e }, + { 0x12,0x1a,0x16,0x1c }, { 0x1b,0x17,0x1d,0x12 }, + { 0x24,0x34,0x2c,0x38 }, { 0x2d,0x39,0x27,0x36 }, + { 0x36,0x2e,0x3a,0x24 }, { 0x3f,0x23,0x31,0x2a }, + { 0x48,0x68,0x58,0x70 }, { 0x41,0x65,0x53,0x7e }, + { 0x5a,0x72,0x4e,0x6c }, { 0x53,0x7f,0x45,0x62 }, + { 0x6c,0x5c,0x74,0x48 }, { 0x65,0x51,0x7f,0x46 }, + { 0x7e,0x46,0x62,0x54 }, { 0x77,0x4b,0x69,0x5a }, + { 0x90,0xd0,0xb0,0xe0 }, { 0x99,0xdd,0xbb,0xee }, + { 0x82,0xca,0xa6,0xfc }, { 0x8b,0xc7,0xad,0xf2 }, + { 0xb4,0xe4,0x9c,0xd8 }, { 0xbd,0xe9,0x97,0xd6 }, + { 0xa6,0xfe,0x8a,0xc4 }, { 0xaf,0xf3,0x81,0xca }, + { 0xd8,0xb8,0xe8,0x90 }, { 0xd1,0xb5,0xe3,0x9e }, + { 0xca,0xa2,0xfe,0x8c }, { 0xc3,0xaf,0xf5,0x82 }, + { 0xfc,0x8c,0xc4,0xa8 }, { 0xf5,0x81,0xcf,0xa6 }, + { 0xee,0x96,0xd2,0xb4 }, { 0xe7,0x9b,0xd9,0xba }, + { 0x3b,0xbb,0x7b,0xdb }, { 0x32,0xb6,0x70,0xd5 }, + { 0x29,0xa1,0x6d,0xc7 }, { 0x20,0xac,0x66,0xc9 }, + { 0x1f,0x8f,0x57,0xe3 }, { 0x16,0x82,0x5c,0xed }, + { 0x0d,0x95,0x41,0xff }, { 0x04,0x98,0x4a,0xf1 }, + { 0x73,0xd3,0x23,0xab }, { 0x7a,0xde,0x28,0xa5 }, + { 0x61,0xc9,0x35,0xb7 }, { 0x68,0xc4,0x3e,0xb9 }, + { 0x57,0xe7,0x0f,0x93 }, { 0x5e,0xea,0x04,0x9d }, + { 0x45,0xfd,0x19,0x8f }, { 0x4c,0xf0,0x12,0x81 }, + { 0xab,0x6b,0xcb,0x3b }, { 0xa2,0x66,0xc0,0x35 }, + { 0xb9,0x71,0xdd,0x27 }, { 0xb0,0x7c,0xd6,0x29 }, + { 0x8f,0x5f,0xe7,0x03 }, { 0x86,0x52,0xec,0x0d }, + { 0x9d,0x45,0xf1,0x1f }, { 0x94,0x48,0xfa,0x11 }, + { 0xe3,0x03,0x93,0x4b }, { 0xea,0x0e,0x98,0x45 }, + { 0xf1,0x19,0x85,0x57 }, { 0xf8,0x14,0x8e,0x59 }, + { 0xc7,0x37,0xbf,0x73 }, { 0xce,0x3a,0xb4,0x7d }, + { 0xd5,0x2d,0xa9,0x6f }, { 0xdc,0x20,0xa2,0x61 }, + { 0x76,0x6d,0xf6,0xad }, { 0x7f,0x60,0xfd,0xa3 }, + { 0x64,0x77,0xe0,0xb1 }, { 0x6d,0x7a,0xeb,0xbf }, + { 0x52,0x59,0xda,0x95 }, { 0x5b,0x54,0xd1,0x9b }, + { 0x40,0x43,0xcc,0x89 }, { 0x49,0x4e,0xc7,0x87 }, + { 0x3e,0x05,0xae,0xdd }, { 0x37,0x08,0xa5,0xd3 }, + { 0x2c,0x1f,0xb8,0xc1 }, { 0x25,0x12,0xb3,0xcf }, + { 0x1a,0x31,0x82,0xe5 }, { 0x13,0x3c,0x89,0xeb }, + { 0x08,0x2b,0x94,0xf9 }, { 0x01,0x26,0x9f,0xf7 }, + { 0xe6,0xbd,0x46,0x4d }, { 0xef,0xb0,0x4d,0x43 }, + { 0xf4,0xa7,0x50,0x51 }, { 0xfd,0xaa,0x5b,0x5f }, + { 0xc2,0x89,0x6a,0x75 }, { 0xcb,0x84,0x61,0x7b }, + { 0xd0,0x93,0x7c,0x69 }, { 0xd9,0x9e,0x77,0x67 }, + { 0xae,0xd5,0x1e,0x3d }, { 0xa7,0xd8,0x15,0x33 }, + { 0xbc,0xcf,0x08,0x21 }, { 0xb5,0xc2,0x03,0x2f }, + { 0x8a,0xe1,0x32,0x05 }, { 0x83,0xec,0x39,0x0b }, + { 0x98,0xfb,0x24,0x19 }, { 0x91,0xf6,0x2f,0x17 }, + { 0x4d,0xd6,0x8d,0x76 }, { 0x44,0xdb,0x86,0x78 }, + { 0x5f,0xcc,0x9b,0x6a }, { 0x56,0xc1,0x90,0x64 }, + { 0x69,0xe2,0xa1,0x4e }, { 0x60,0xef,0xaa,0x40 }, + { 0x7b,0xf8,0xb7,0x52 }, { 0x72,0xf5,0xbc,0x5c }, + { 0x05,0xbe,0xd5,0x06 }, { 0x0c,0xb3,0xde,0x08 }, + { 0x17,0xa4,0xc3,0x1a }, { 0x1e,0xa9,0xc8,0x14 }, + { 0x21,0x8a,0xf9,0x3e }, { 0x28,0x87,0xf2,0x30 }, + { 0x33,0x90,0xef,0x22 }, { 0x3a,0x9d,0xe4,0x2c }, + { 0xdd,0x06,0x3d,0x96 }, { 0xd4,0x0b,0x36,0x98 }, + { 0xcf,0x1c,0x2b,0x8a }, { 0xc6,0x11,0x20,0x84 }, + { 0xf9,0x32,0x11,0xae }, { 0xf0,0x3f,0x1a,0xa0 }, + { 0xeb,0x28,0x07,0xb2 }, { 0xe2,0x25,0x0c,0xbc }, + { 0x95,0x6e,0x65,0xe6 }, { 0x9c,0x63,0x6e,0xe8 }, + { 0x87,0x74,0x73,0xfa }, { 0x8e,0x79,0x78,0xf4 }, + { 0xb1,0x5a,0x49,0xde }, { 0xb8,0x57,0x42,0xd0 }, + { 0xa3,0x40,0x5f,0xc2 }, { 0xaa,0x4d,0x54,0xcc }, + { 0xec,0xda,0xf7,0x41 }, { 0xe5,0xd7,0xfc,0x4f }, + { 0xfe,0xc0,0xe1,0x5d }, { 0xf7,0xcd,0xea,0x53 }, + { 0xc8,0xee,0xdb,0x79 }, { 0xc1,0xe3,0xd0,0x77 }, + { 0xda,0xf4,0xcd,0x65 }, { 0xd3,0xf9,0xc6,0x6b }, + { 0xa4,0xb2,0xaf,0x31 }, { 0xad,0xbf,0xa4,0x3f }, + { 0xb6,0xa8,0xb9,0x2d }, { 0xbf,0xa5,0xb2,0x23 }, + { 0x80,0x86,0x83,0x09 }, { 0x89,0x8b,0x88,0x07 }, + { 0x92,0x9c,0x95,0x15 }, { 0x9b,0x91,0x9e,0x1b }, + { 0x7c,0x0a,0x47,0xa1 }, { 0x75,0x07,0x4c,0xaf }, + { 0x6e,0x10,0x51,0xbd }, { 0x67,0x1d,0x5a,0xb3 }, + { 0x58,0x3e,0x6b,0x99 }, { 0x51,0x33,0x60,0x97 }, + { 0x4a,0x24,0x7d,0x85 }, { 0x43,0x29,0x76,0x8b }, + { 0x34,0x62,0x1f,0xd1 }, { 0x3d,0x6f,0x14,0xdf }, + { 0x26,0x78,0x09,0xcd }, { 0x2f,0x75,0x02,0xc3 }, + { 0x10,0x56,0x33,0xe9 }, { 0x19,0x5b,0x38,0xe7 }, + { 0x02,0x4c,0x25,0xf5 }, { 0x0b,0x41,0x2e,0xfb }, + { 0xd7,0x61,0x8c,0x9a }, { 0xde,0x6c,0x87,0x94 }, + { 0xc5,0x7b,0x9a,0x86 }, { 0xcc,0x76,0x91,0x88 }, + { 0xf3,0x55,0xa0,0xa2 }, { 0xfa,0x58,0xab,0xac }, + { 0xe1,0x4f,0xb6,0xbe }, { 0xe8,0x42,0xbd,0xb0 }, + { 0x9f,0x09,0xd4,0xea }, { 0x96,0x04,0xdf,0xe4 }, + { 0x8d,0x13,0xc2,0xf6 }, { 0x84,0x1e,0xc9,0xf8 }, + { 0xbb,0x3d,0xf8,0xd2 }, { 0xb2,0x30,0xf3,0xdc }, + { 0xa9,0x27,0xee,0xce }, { 0xa0,0x2a,0xe5,0xc0 }, + { 0x47,0xb1,0x3c,0x7a }, { 0x4e,0xbc,0x37,0x74 }, + { 0x55,0xab,0x2a,0x66 }, { 0x5c,0xa6,0x21,0x68 }, + { 0x63,0x85,0x10,0x42 }, { 0x6a,0x88,0x1b,0x4c }, + { 0x71,0x9f,0x06,0x5e }, { 0x78,0x92,0x0d,0x50 }, + { 0x0f,0xd9,0x64,0x0a }, { 0x06,0xd4,0x6f,0x04 }, + { 0x1d,0xc3,0x72,0x16 }, { 0x14,0xce,0x79,0x18 }, + { 0x2b,0xed,0x48,0x32 }, { 0x22,0xe0,0x43,0x3c }, + { 0x39,0xf7,0x5e,0x2e }, { 0x30,0xfa,0x55,0x20 }, + { 0x9a,0xb7,0x01,0xec }, { 0x93,0xba,0x0a,0xe2 }, + { 0x88,0xad,0x17,0xf0 }, { 0x81,0xa0,0x1c,0xfe }, + { 0xbe,0x83,0x2d,0xd4 }, { 0xb7,0x8e,0x26,0xda }, + { 0xac,0x99,0x3b,0xc8 }, { 0xa5,0x94,0x30,0xc6 }, + { 0xd2,0xdf,0x59,0x9c }, { 0xdb,0xd2,0x52,0x92 }, + { 0xc0,0xc5,0x4f,0x80 }, { 0xc9,0xc8,0x44,0x8e }, + { 0xf6,0xeb,0x75,0xa4 }, { 0xff,0xe6,0x7e,0xaa }, + { 0xe4,0xf1,0x63,0xb8 }, { 0xed,0xfc,0x68,0xb6 }, + { 0x0a,0x67,0xb1,0x0c }, { 0x03,0x6a,0xba,0x02 }, + { 0x18,0x7d,0xa7,0x10 }, { 0x11,0x70,0xac,0x1e }, + { 0x2e,0x53,0x9d,0x34 }, { 0x27,0x5e,0x96,0x3a }, + { 0x3c,0x49,0x8b,0x28 }, { 0x35,0x44,0x80,0x26 }, + { 0x42,0x0f,0xe9,0x7c }, { 0x4b,0x02,0xe2,0x72 }, + { 0x50,0x15,0xff,0x60 }, { 0x59,0x18,0xf4,0x6e }, + { 0x66,0x3b,0xc5,0x44 }, { 0x6f,0x36,0xce,0x4a }, + { 0x74,0x21,0xd3,0x58 }, { 0x7d,0x2c,0xd8,0x56 }, + { 0xa1,0x0c,0x7a,0x37 }, { 0xa8,0x01,0x71,0x39 }, + { 0xb3,0x16,0x6c,0x2b }, { 0xba,0x1b,0x67,0x25 }, + { 0x85,0x38,0x56,0x0f }, { 0x8c,0x35,0x5d,0x01 }, + { 0x97,0x22,0x40,0x13 }, { 0x9e,0x2f,0x4b,0x1d }, + { 0xe9,0x64,0x22,0x47 }, { 0xe0,0x69,0x29,0x49 }, + { 0xfb,0x7e,0x34,0x5b }, { 0xf2,0x73,0x3f,0x55 }, + { 0xcd,0x50,0x0e,0x7f }, { 0xc4,0x5d,0x05,0x71 }, + { 0xdf,0x4a,0x18,0x63 }, { 0xd6,0x47,0x13,0x6d }, + { 0x31,0xdc,0xca,0xd7 }, { 0x38,0xd1,0xc1,0xd9 }, + { 0x23,0xc6,0xdc,0xcb }, { 0x2a,0xcb,0xd7,0xc5 }, + { 0x15,0xe8,0xe6,0xef }, { 0x1c,0xe5,0xed,0xe1 }, + { 0x07,0xf2,0xf0,0xf3 }, { 0x0e,0xff,0xfb,0xfd }, + { 0x79,0xb4,0x92,0xa7 }, { 0x70,0xb9,0x99,0xa9 }, + { 0x6b,0xae,0x84,0xbb }, { 0x62,0xa3,0x8f,0xb5 }, + { 0x5d,0x80,0xbe,0x9f }, { 0x54,0x8d,0xb5,0x91 }, + { 0x4f,0x9a,0xa8,0x83 }, { 0x46,0x97,0xa3,0x8d } + }; + +static const u32 rcon[30] = + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, + 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 + }; diff --git a/grub-core/lib/libgcrypt/cipher/rijndael.c b/grub-core/lib/libgcrypt/cipher/rijndael.c new file mode 100644 index 0000000..559550b --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/rijndael.c @@ -0,0 +1,2092 @@ +/* Rijndael (AES) for GnuPG + * Copyright (C) 2000, 2001, 2002, 2003, 2007, + * 2008, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + ******************************************************************* + * The code here is based on the optimized implementation taken from + * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ on Oct 2, 2000, + * which carries this notice: + *------------------------------------------ + * rijndael-alg-fst.c v2.3 April '2000 + * + * Optimised ANSI C code + * + * authors: v1.0: Antoon Bosselaers + * v2.0: Vincent Rijmen + * v2.3: Paulo Barreto + * + * This code is placed in the public domain. + *------------------------------------------ + * + * The SP800-38a document is available at: + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + * + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> /* for memcmp() */ + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + +#define MAXKC (256/32) +#define MAXROUNDS 14 +#define BLOCKSIZE (128/8) + + +/* Helper macro to force alignment to 16 bytes. */ +#ifdef __GNUC__ +# define ATTR_ALIGNED_16 __attribute__ ((aligned (16))) +#else +# define ATTR_ALIGNED_16 +#endif + + +/* USE_PADLOCK indicates whether to compile the padlock specific + code. */ +#undef USE_PADLOCK +#ifdef ENABLE_PADLOCK_SUPPORT +# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) +# define USE_PADLOCK 1 +# endif +#endif /*ENABLE_PADLOCK_SUPPORT*/ + +/* USE_AESNI inidicates whether to compile with Intel AES-NI code. We + need the vector-size attribute which seems to be available since + gcc 3. However, to be on the safe side we require at least gcc 4. */ +#undef USE_AESNI +#ifdef ENABLE_AESNI_SUPPORT +# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4 +# define USE_AESNI 1 +# endif +#endif /* ENABLE_AESNI_SUPPORT */ + +#ifdef USE_AESNI + typedef int m128i_t __attribute__ ((__vector_size__ (16))); +#endif /*USE_AESNI*/ + +/* Define an u32 variant for the sake of gcc 4.4's strict aliasing. */ +#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 4 ) +typedef u32 __attribute__ ((__may_alias__)) u32_a_t; +#else +typedef u32 u32_a_t; +#endif + + + +/* Our context object. */ +typedef struct +{ + /* The first fields are the keyschedule arrays. This is so that + they are aligned on a 16 byte boundary if using gcc. This + alignment is required for the AES-NI code and a good idea in any + case. The alignment is guaranteed due to the way cipher.c + allocates the space for the context. The PROPERLY_ALIGNED_TYPE + hack is used to force a minimal alignment if not using gcc of if + the alignment requirement is higher that 16 bytes. */ + union + { + PROPERLY_ALIGNED_TYPE dummy; + byte keyschedule[MAXROUNDS+1][4][4]; +#ifdef USE_PADLOCK + /* The key as passed to the padlock engine. It is only used if + the padlock engine is used (USE_PADLOCK, below). */ + unsigned char padlock_key[16] __attribute__ ((aligned (16))); +#endif /*USE_PADLOCK*/ + } u1; + union + { + PROPERLY_ALIGNED_TYPE dummy; + byte keyschedule[MAXROUNDS+1][4][4]; + } u2; + int rounds; /* Key-length-dependent number of rounds. */ + int decryption_prepared; /* The decryption key schedule is available. */ +#ifdef USE_PADLOCK + int use_padlock; /* Padlock shall be used. */ +#endif /*USE_PADLOCK*/ +#ifdef USE_AESNI + int use_aesni; /* AES-NI shall be used. */ +#endif /*USE_AESNI*/ +} RIJNDAEL_context ATTR_ALIGNED_16; + +/* Macros defining alias for the keyschedules. */ +#define keyschenc u1.keyschedule +#define keyschdec u2.keyschedule +#define padlockkey u1.padlock_key + +/* Two macros to be called prior and after the use of AESNI + instructions. There should be no external function calls between + the use of these macros. There purpose is to make sure that the + SSE regsiters are cleared and won't reveal any information about + the key or the data. */ +#ifdef USE_AESNI +# define aesni_prepare() do { } while (0) +# define aesni_cleanup() \ + do { asm volatile ("pxor %%xmm0, %%xmm0\n\t" \ + "pxor %%xmm1, %%xmm1\n" :: ); \ + } while (0) +# define aesni_cleanup_2_4() \ + do { asm volatile ("pxor %%xmm2, %%xmm2\n\t" \ + "pxor %%xmm3, %%xmm3\n" \ + "pxor %%xmm4, %%xmm4\n":: ); \ + } while (0) +#else +# define aesni_prepare() do { } while (0) +# define aesni_cleanup() do { } while (0) +#endif + + +/* All the numbers. */ +#include "rijndael-tables.h" + + + +/* Function prototypes. */ +#ifdef USE_AESNI +/* We don't want to inline these functions to help gcc allocate enough + registers. */ +static void do_aesni_ctr (const RIJNDAEL_context *ctx, unsigned char *ctr, + unsigned char *b, const unsigned char *a) + __attribute__ ((__noinline__)); +static void do_aesni_ctr_4 (const RIJNDAEL_context *ctx, unsigned char *ctr, + unsigned char *b, const unsigned char *a) + __attribute__ ((__noinline__)); +#endif /*USE_AESNI*/ + +static const char *selftest(void); + + + +/* Perform the key setup. */ +static gcry_err_code_t +do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) +{ + static int initialized = 0; + static const char *selftest_failed=0; + int rounds; + int i,j, r, t, rconpointer = 0; + int KC; + union + { + PROPERLY_ALIGNED_TYPE dummy; + byte k[MAXKC][4]; + } k; +#define k k.k + union + { + PROPERLY_ALIGNED_TYPE dummy; + byte tk[MAXKC][4]; + } tk; +#define tk tk.tk + + /* The on-the-fly self tests are only run in non-fips mode. In fips + mode explicit self-tests are required. Actually the on-the-fly + self-tests are not fully thread-safe and it might happen that a + failed self-test won't get noticed in another thread. + + FIXME: We might want to have a central registry of succeeded + self-tests. */ + if (!fips_mode () && !initialized) + { + initialized = 1; + selftest_failed = selftest (); + if (selftest_failed) + log_error ("%s\n", selftest_failed ); + } + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + ctx->decryption_prepared = 0; +#ifdef USE_PADLOCK + ctx->use_padlock = 0; +#endif +#ifdef USE_AESNI + ctx->use_aesni = 0; +#endif + + if( keylen == 128/8 ) + { + rounds = 10; + KC = 4; + + if (0) + ; +#ifdef USE_PADLOCK + else if ((_gcry_get_hw_features () & HWF_PADLOCK_AES)) + { + ctx->use_padlock = 1; + memcpy (ctx->padlockkey, key, keylen); + } +#endif +#ifdef USE_AESNI + else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI)) + { + ctx->use_aesni = 1; + } +#endif + } + else if ( keylen == 192/8 ) + { + rounds = 12; + KC = 6; + + if (0) + { + ; + } +#ifdef USE_AESNI + else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI)) + { + ctx->use_aesni = 1; + } +#endif + } + else if ( keylen == 256/8 ) + { + rounds = 14; + KC = 8; + + if (0) + { + ; + } +#ifdef USE_AESNI + else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI)) + { + ctx->use_aesni = 1; + } +#endif + } + else + return GPG_ERR_INV_KEYLEN; + + ctx->rounds = rounds; + + /* NB: We don't yet support Padlock hardware key generation. */ + + if (0) + ; +#ifdef USE_AESNI_is_disabled_here + else if (ctx->use_aesni && ctx->rounds == 10) + { + /* Note: This code works for AES-128 but it is not much better + than using the standard key schedule. We disable it for + now and don't put any effort into implementing this for + AES-192 and AES-256. */ + asm volatile ("movl %[key], %%esi\n\t" + "movdqu (%%esi), %%xmm1\n\t" /* xmm1 := key */ + "movl %[ksch], %%esi\n\t" + "movdqa %%xmm1, (%%esi)\n\t" /* ksch[0] := xmm1 */ + "aeskeygenassist $0x01, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x10(%%esi)\n\t" /* ksch[1] := xmm1 */ + "aeskeygenassist $0x02, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x20(%%esi)\n\t" /* ksch[2] := xmm1 */ + "aeskeygenassist $0x04, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x30(%%esi)\n\t" /* ksch[3] := xmm1 */ + "aeskeygenassist $0x08, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x40(%%esi)\n\t" /* ksch[4] := xmm1 */ + "aeskeygenassist $0x10, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x50(%%esi)\n\t" /* ksch[5] := xmm1 */ + "aeskeygenassist $0x20, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x60(%%esi)\n\t" /* ksch[6] := xmm1 */ + "aeskeygenassist $0x40, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x70(%%esi)\n\t" /* ksch[7] := xmm1 */ + "aeskeygenassist $0x80, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x80(%%esi)\n\t" /* ksch[8] := xmm1 */ + "aeskeygenassist $0x1b, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0x90(%%esi)\n\t" /* ksch[9] := xmm1 */ + "aeskeygenassist $0x36, %%xmm1, %%xmm2\n\t" + "call .Lexpand128_%=\n\t" + "movdqa %%xmm1, 0xa0(%%esi)\n\t" /* ksch[10] := xmm1 */ + "jmp .Lleave%=\n" + + ".Lexpand128_%=:\n\t" + "pshufd $0xff, %%xmm2, %%xmm2\n\t" + "movdqa %%xmm1, %%xmm3\n\t" + "pslldq $4, %%xmm3\n\t" + "pxor %%xmm3, %%xmm1\n\t" + "pslldq $4, %%xmm3\n\t" + "pxor %%xmm3, %%xmm1\n\t" + "pslldq $4, %%xmm3\n\t" + "pxor %%xmm3, %%xmm2\n\t" + "pxor %%xmm2, %%xmm1\n\t" + "ret\n" + + ".Lleave%=:\n\t" + "pxor %%xmm1, %%xmm1\n\t" + "pxor %%xmm2, %%xmm2\n\t" + "pxor %%xmm3, %%xmm3\n" + : + : [key] "g" (key), [ksch] "g" (ctx->keyschenc) + : "%esi", "cc", "memory" ); + } +#endif /*USE_AESNI*/ + else + { +#define W (ctx->keyschenc) + for (i = 0; i < keylen; i++) + { + k[i >> 2][i & 3] = key[i]; + } + + for (j = KC-1; j >= 0; j--) + { + *((u32_a_t*)tk[j]) = *((u32_a_t*)k[j]); + } + r = 0; + t = 0; + /* Copy values into round key array. */ + for (j = 0; (j < KC) && (r < rounds + 1); ) + { + for (; (j < KC) && (t < 4); j++, t++) + { + *((u32_a_t*)W[r][t]) = *((u32_a_t*)tk[j]); + } + if (t == 4) + { + r++; + t = 0; + } + } + + while (r < rounds + 1) + { + /* While not enough round key material calculated calculate + new values. */ + tk[0][0] ^= S[tk[KC-1][1]]; + tk[0][1] ^= S[tk[KC-1][2]]; + tk[0][2] ^= S[tk[KC-1][3]]; + tk[0][3] ^= S[tk[KC-1][0]]; + tk[0][0] ^= rcon[rconpointer++]; + + if (KC != 8) + { + for (j = 1; j < KC; j++) + { + *((u32_a_t*)tk[j]) ^= *((u32_a_t*)tk[j-1]); + } + } + else + { + for (j = 1; j < KC/2; j++) + { + *((u32_a_t*)tk[j]) ^= *((u32_a_t*)tk[j-1]); + } + tk[KC/2][0] ^= S[tk[KC/2 - 1][0]]; + tk[KC/2][1] ^= S[tk[KC/2 - 1][1]]; + tk[KC/2][2] ^= S[tk[KC/2 - 1][2]]; + tk[KC/2][3] ^= S[tk[KC/2 - 1][3]]; + for (j = KC/2 + 1; j < KC; j++) + { + *((u32_a_t*)tk[j]) ^= *((u32_a_t*)tk[j-1]); + } + } + + /* Copy values into round key array. */ + for (j = 0; (j < KC) && (r < rounds + 1); ) + { + for (; (j < KC) && (t < 4); j++, t++) + { + *((u32_a_t*)W[r][t]) = *((u32_a_t*)tk[j]); + } + if (t == 4) + { + r++; + t = 0; + } + } + } +#undef W + } + + return 0; +#undef tk +#undef k +} + + +static gcry_err_code_t +rijndael_setkey (void *context, const byte *key, const unsigned keylen) +{ + RIJNDAEL_context *ctx = context; + + int rc = do_setkey (ctx, key, keylen); + _gcry_burn_stack ( 100 + 16*sizeof(int)); + return rc; +} + + +/* Make a decryption key from an encryption key. */ +static void +prepare_decryption( RIJNDAEL_context *ctx ) +{ + int r; + +#ifdef USE_AESNI + if (ctx->use_aesni) + { + /* The AES-NI decrypt instructions use the Equivalent Inverse + Cipher, thus we can't use the the standard decrypt key + preparation. */ + m128i_t *ekey = (m128i_t*)ctx->keyschenc; + m128i_t *dkey = (m128i_t*)ctx->keyschdec; + int rr; + + dkey[0] = ekey[ctx->rounds]; + for (r=1, rr=ctx->rounds-1; r < ctx->rounds; r++, rr--) + { + asm volatile + ("movdqu %[ekey], %%xmm1\n\t" + /*"aesimc %%xmm1, %%xmm1\n\t"*/ + ".byte 0x66, 0x0f, 0x38, 0xdb, 0xc9\n\t" + "movdqu %%xmm1, %[dkey]" + : [dkey] "=m" (dkey[r]) + : [ekey] "m" (ekey[rr]) ); + } + dkey[r] = ekey[0]; + } + else +#endif /*USE_AESNI*/ + { + union + { + PROPERLY_ALIGNED_TYPE dummy; + byte *w; + } w; +#define w w.w + + for (r=0; r < MAXROUNDS+1; r++ ) + { + *((u32_a_t*)ctx->keyschdec[r][0]) = *((u32_a_t*)ctx->keyschenc[r][0]); + *((u32_a_t*)ctx->keyschdec[r][1]) = *((u32_a_t*)ctx->keyschenc[r][1]); + *((u32_a_t*)ctx->keyschdec[r][2]) = *((u32_a_t*)ctx->keyschenc[r][2]); + *((u32_a_t*)ctx->keyschdec[r][3]) = *((u32_a_t*)ctx->keyschenc[r][3]); + } +#define W (ctx->keyschdec) + for (r = 1; r < ctx->rounds; r++) + { + w = W[r][0]; + *((u32_a_t*)w) = *((u32_a_t*)U1[w[0]]) ^ *((u32_a_t*)U2[w[1]]) + ^ *((u32_a_t*)U3[w[2]]) ^ *((u32_a_t*)U4[w[3]]); + + w = W[r][1]; + *((u32_a_t*)w) = *((u32_a_t*)U1[w[0]]) ^ *((u32_a_t*)U2[w[1]]) + ^ *((u32_a_t*)U3[w[2]]) ^ *((u32_a_t*)U4[w[3]]); + + w = W[r][2]; + *((u32_a_t*)w) = *((u32_a_t*)U1[w[0]]) ^ *((u32_a_t*)U2[w[1]]) + ^ *((u32_a_t*)U3[w[2]]) ^ *((u32_a_t*)U4[w[3]]); + + w = W[r][3]; + *((u32_a_t*)w) = *((u32_a_t*)U1[w[0]]) ^ *((u32_a_t*)U2[w[1]]) + ^ *((u32_a_t*)U3[w[2]]) ^ *((u32_a_t*)U4[w[3]]); + } +#undef W +#undef w + } +} + + +/* Encrypt one block. A and B need to be aligned on a 4 byte + boundary. A and B may be the same. */ +static void +do_encrypt_aligned (const RIJNDAEL_context *ctx, + unsigned char *b, const unsigned char *a) +{ +#define rk (ctx->keyschenc) + int rounds = ctx->rounds; + int r; + union + { + u32 tempu32[4]; /* Force correct alignment. */ + byte temp[4][4]; + } u; + + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(a )) ^ *((u32_a_t*)rk[0][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(a+ 4)) ^ *((u32_a_t*)rk[0][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(a+ 8)) ^ *((u32_a_t*)rk[0][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(a+12)) ^ *((u32_a_t*)rk[0][3]); + *((u32_a_t*)(b )) = (*((u32_a_t*)T1[u.temp[0][0]]) + ^ *((u32_a_t*)T2[u.temp[1][1]]) + ^ *((u32_a_t*)T3[u.temp[2][2]]) + ^ *((u32_a_t*)T4[u.temp[3][3]])); + *((u32_a_t*)(b + 4)) = (*((u32_a_t*)T1[u.temp[1][0]]) + ^ *((u32_a_t*)T2[u.temp[2][1]]) + ^ *((u32_a_t*)T3[u.temp[3][2]]) + ^ *((u32_a_t*)T4[u.temp[0][3]])); + *((u32_a_t*)(b + 8)) = (*((u32_a_t*)T1[u.temp[2][0]]) + ^ *((u32_a_t*)T2[u.temp[3][1]]) + ^ *((u32_a_t*)T3[u.temp[0][2]]) + ^ *((u32_a_t*)T4[u.temp[1][3]])); + *((u32_a_t*)(b +12)) = (*((u32_a_t*)T1[u.temp[3][0]]) + ^ *((u32_a_t*)T2[u.temp[0][1]]) + ^ *((u32_a_t*)T3[u.temp[1][2]]) + ^ *((u32_a_t*)T4[u.temp[2][3]])); + + for (r = 1; r < rounds-1; r++) + { + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(b )) ^ *((u32_a_t*)rk[r][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(b+ 4)) ^ *((u32_a_t*)rk[r][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(b+ 8)) ^ *((u32_a_t*)rk[r][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(b+12)) ^ *((u32_a_t*)rk[r][3]); + + *((u32_a_t*)(b )) = (*((u32_a_t*)T1[u.temp[0][0]]) + ^ *((u32_a_t*)T2[u.temp[1][1]]) + ^ *((u32_a_t*)T3[u.temp[2][2]]) + ^ *((u32_a_t*)T4[u.temp[3][3]])); + *((u32_a_t*)(b + 4)) = (*((u32_a_t*)T1[u.temp[1][0]]) + ^ *((u32_a_t*)T2[u.temp[2][1]]) + ^ *((u32_a_t*)T3[u.temp[3][2]]) + ^ *((u32_a_t*)T4[u.temp[0][3]])); + *((u32_a_t*)(b + 8)) = (*((u32_a_t*)T1[u.temp[2][0]]) + ^ *((u32_a_t*)T2[u.temp[3][1]]) + ^ *((u32_a_t*)T3[u.temp[0][2]]) + ^ *((u32_a_t*)T4[u.temp[1][3]])); + *((u32_a_t*)(b +12)) = (*((u32_a_t*)T1[u.temp[3][0]]) + ^ *((u32_a_t*)T2[u.temp[0][1]]) + ^ *((u32_a_t*)T3[u.temp[1][2]]) + ^ *((u32_a_t*)T4[u.temp[2][3]])); + } + + /* Last round is special. */ + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(b )) ^ *((u32_a_t*)rk[rounds-1][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(b+ 4)) ^ *((u32_a_t*)rk[rounds-1][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(b+ 8)) ^ *((u32_a_t*)rk[rounds-1][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(b+12)) ^ *((u32_a_t*)rk[rounds-1][3]); + b[ 0] = T1[u.temp[0][0]][1]; + b[ 1] = T1[u.temp[1][1]][1]; + b[ 2] = T1[u.temp[2][2]][1]; + b[ 3] = T1[u.temp[3][3]][1]; + b[ 4] = T1[u.temp[1][0]][1]; + b[ 5] = T1[u.temp[2][1]][1]; + b[ 6] = T1[u.temp[3][2]][1]; + b[ 7] = T1[u.temp[0][3]][1]; + b[ 8] = T1[u.temp[2][0]][1]; + b[ 9] = T1[u.temp[3][1]][1]; + b[10] = T1[u.temp[0][2]][1]; + b[11] = T1[u.temp[1][3]][1]; + b[12] = T1[u.temp[3][0]][1]; + b[13] = T1[u.temp[0][1]][1]; + b[14] = T1[u.temp[1][2]][1]; + b[15] = T1[u.temp[2][3]][1]; + *((u32_a_t*)(b )) ^= *((u32_a_t*)rk[rounds][0]); + *((u32_a_t*)(b+ 4)) ^= *((u32_a_t*)rk[rounds][1]); + *((u32_a_t*)(b+ 8)) ^= *((u32_a_t*)rk[rounds][2]); + *((u32_a_t*)(b+12)) ^= *((u32_a_t*)rk[rounds][3]); +#undef rk +} + + +static void +do_encrypt (const RIJNDAEL_context *ctx, + unsigned char *bx, const unsigned char *ax) +{ + /* BX and AX are not necessary correctly aligned. Thus we might + need to copy them here. We try to align to a 16 bytes. */ + if (((size_t)ax & 0x0f) || ((size_t)bx & 0x0f)) + { + union + { + u32 dummy[4]; + byte a[16] ATTR_ALIGNED_16; + } a; + union + { + u32 dummy[4]; + byte b[16] ATTR_ALIGNED_16; + } b; + + memcpy (a.a, ax, 16); + do_encrypt_aligned (ctx, b.b, a.a); + memcpy (bx, b.b, 16); + } + else + { + do_encrypt_aligned (ctx, bx, ax); + } +} + + +/* Encrypt or decrypt one block using the padlock engine. A and B may + be the same. */ +#ifdef USE_PADLOCK +static void +do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag, + unsigned char *bx, const unsigned char *ax) +{ + /* BX and AX are not necessary correctly aligned. Thus we need to + copy them here. */ + unsigned char a[16] __attribute__ ((aligned (16))); + unsigned char b[16] __attribute__ ((aligned (16))); + unsigned int cword[4] __attribute__ ((aligned (16))); + + /* The control word fields are: + 127:12 11:10 9 8 7 6 5 4 3:0 + RESERVED KSIZE CRYPT INTER KEYGN CIPHR ALIGN DGEST ROUND */ + cword[0] = (ctx->rounds & 15); /* (The mask is just a safeguard.) */ + cword[1] = 0; + cword[2] = 0; + cword[3] = 0; + if (decrypt_flag) + cword[0] |= 0x00000200; + + memcpy (a, ax, 16); + + asm volatile + ("pushfl\n\t" /* Force key reload. */ + "popfl\n\t" + "xchg %3, %%ebx\n\t" /* Load key. */ + "movl $1, %%ecx\n\t" /* Init counter for just one block. */ + ".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XSTORE ECB. */ + "xchg %3, %%ebx\n" /* Restore GOT register. */ + : /* No output */ + : "S" (a), "D" (b), "d" (cword), "r" (ctx->padlockkey) + : "%ecx", "cc", "memory" + ); + + memcpy (bx, b, 16); + +} +#endif /*USE_PADLOCK*/ + + +#ifdef USE_AESNI +/* Encrypt one block using the Intel AES-NI instructions. A and B may + be the same; they need to be properly aligned to 16 bytes. + + Our problem here is that gcc does not allow the "x" constraint for + SSE registers in asm unless you compile with -msse. The common + wisdom is to use a separate file for SSE instructions and build it + separately. This would require a lot of extra build system stuff, + similar to what we do in mpi/ for the asm stuff. What we do + instead is to use standard registers and a bit more of plain asm + which copies the data and key stuff to the SSE registers and later + back. If we decide to implement some block modes with parallelized + AES instructions, it might indeed be better to use plain asm ala + mpi/. */ +static void +do_aesni_enc_aligned (const RIJNDAEL_context *ctx, + unsigned char *b, const unsigned char *a) +{ +#define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" +#define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" + /* Note: For now we relax the alignment requirement for A and B: It + does not make much difference because in many case we would need + to memcpy them to an extra buffer; using the movdqu is much faster + that memcpy and movdqa. For CFB we know that the IV is properly + aligned but that is a special case. We should better implement + CFB direct in asm. */ + asm volatile ("movdqu %[src], %%xmm0\n\t" /* xmm0 := *a */ + "movl %[key], %%esi\n\t" /* esi := keyschenc */ + "movdqa (%%esi), %%xmm1\n\t" /* xmm1 := key[0] */ + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ + "movdqa 0x10(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x20(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x30(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x40(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x50(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x60(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x70(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x80(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x90(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xa0(%%esi), %%xmm1\n\t" + "cmp $10, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xb0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xc0(%%esi), %%xmm1\n\t" + "cmp $12, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xd0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xe0(%%esi), %%xmm1\n" + + ".Lenclast%=:\n\t" + aesenclast_xmm1_xmm0 + "movdqu %%xmm0, %[dst]\n" + : [dst] "=m" (*b) + : [src] "m" (*a), + [key] "r" (ctx->keyschenc), + [rounds] "r" (ctx->rounds) + : "%esi", "cc", "memory"); +#undef aesenc_xmm1_xmm0 +#undef aesenclast_xmm1_xmm0 +} + + +static void +do_aesni_dec_aligned (const RIJNDAEL_context *ctx, + unsigned char *b, const unsigned char *a) +{ +#define aesdec_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc1\n\t" +#define aesdeclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc1\n\t" + asm volatile ("movdqu %[src], %%xmm0\n\t" /* xmm0 := *a */ + "movl %[key], %%esi\n\t" + "movdqa (%%esi), %%xmm1\n\t" + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ + "movdqa 0x10(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x20(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x30(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x40(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x50(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x60(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x70(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x80(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0x90(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0xa0(%%esi), %%xmm1\n\t" + "cmp $10, %[rounds]\n\t" + "jz .Ldeclast%=\n\t" + aesdec_xmm1_xmm0 + "movdqa 0xb0(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0xc0(%%esi), %%xmm1\n\t" + "cmp $12, %[rounds]\n\t" + "jz .Ldeclast%=\n\t" + aesdec_xmm1_xmm0 + "movdqa 0xd0(%%esi), %%xmm1\n\t" + aesdec_xmm1_xmm0 + "movdqa 0xe0(%%esi), %%xmm1\n" + + ".Ldeclast%=:\n\t" + aesdeclast_xmm1_xmm0 + "movdqu %%xmm0, %[dst]\n" + : [dst] "=m" (*b) + : [src] "m" (*a), + [key] "r" (ctx->keyschdec), + [rounds] "r" (ctx->rounds) + : "%esi", "cc", "memory"); +#undef aesdec_xmm1_xmm0 +#undef aesdeclast_xmm1_xmm0 +} + + +/* Perform a CFB encryption or decryption round using the + initialization vector IV and the input block A. Write the result + to the output block B and update IV. IV needs to be 16 byte + aligned. */ +static void +do_aesni_cfb (const RIJNDAEL_context *ctx, int decrypt_flag, + unsigned char *iv, unsigned char *b, const unsigned char *a) +{ +#define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" +#define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" + asm volatile ("movdqa %[iv], %%xmm0\n\t" /* xmm0 := IV */ + "movl %[key], %%esi\n\t" /* esi := keyschenc */ + "movdqa (%%esi), %%xmm1\n\t" /* xmm1 := key[0] */ + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ + "movdqa 0x10(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x20(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x30(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x40(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x50(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x60(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x70(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x80(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x90(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xa0(%%esi), %%xmm1\n\t" + "cmp $10, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xb0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xc0(%%esi), %%xmm1\n\t" + "cmp $12, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xd0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xe0(%%esi), %%xmm1\n" + + ".Lenclast%=:\n\t" + aesenclast_xmm1_xmm0 + "movdqu %[src], %%xmm1\n\t" /* Save input. */ + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 = input ^ IV */ + + "cmp $1, %[decrypt]\n\t" + "jz .Ldecrypt_%=\n\t" + "movdqa %%xmm0, %[iv]\n\t" /* [encrypt] Store IV. */ + "jmp .Lleave_%=\n" + ".Ldecrypt_%=:\n\t" + "movdqa %%xmm1, %[iv]\n" /* [decrypt] Store IV. */ + ".Lleave_%=:\n\t" + "movdqu %%xmm0, %[dst]\n" /* Store output. */ + : [iv] "+m" (*iv), [dst] "=m" (*b) + : [src] "m" (*a), + [key] "g" (ctx->keyschenc), + [rounds] "g" (ctx->rounds), + [decrypt] "m" (decrypt_flag) + : "%esi", "cc", "memory"); +#undef aesenc_xmm1_xmm0 +#undef aesenclast_xmm1_xmm0 +} + +/* Perform a CTR encryption round using the counter CTR and the input + block A. Write the result to the output block B and update CTR. + CTR needs to be a 16 byte aligned little-endian value. */ +static void +do_aesni_ctr (const RIJNDAEL_context *ctx, + unsigned char *ctr, unsigned char *b, const unsigned char *a) +{ +#define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" +#define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" + static unsigned char be_mask[16] __attribute__ ((aligned (16))) = + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + + asm volatile ("movdqa %[ctr], %%xmm0\n\t" /* xmm0, xmm2 := CTR */ + "movaps %%xmm0, %%xmm2\n\t" + "mov $1, %%esi\n\t" /* xmm2++ (big-endian) */ + "movd %%esi, %%xmm1\n\t" + "pshufb %[mask], %%xmm2\n\t" + "paddq %%xmm1, %%xmm2\n\t" + "pshufb %[mask], %%xmm2\n\t" + "movdqa %%xmm2, %[ctr]\n" /* Update CTR. */ + + "movl %[key], %%esi\n\t" /* esi := keyschenc */ + "movdqa (%%esi), %%xmm1\n\t" /* xmm1 := key[0] */ + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ + "movdqa 0x10(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x20(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x30(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x40(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x50(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x60(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x70(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x80(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0x90(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xa0(%%esi), %%xmm1\n\t" + "cmp $10, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xb0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xc0(%%esi), %%xmm1\n\t" + "cmp $12, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xd0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + "movdqa 0xe0(%%esi), %%xmm1\n" + + ".Lenclast%=:\n\t" + aesenclast_xmm1_xmm0 + "movdqu %[src], %%xmm1\n\t" /* xmm1 := input */ + "pxor %%xmm1, %%xmm0\n\t" /* EncCTR ^= input */ + "movdqu %%xmm0, %[dst]" /* Store EncCTR. */ + + : [ctr] "+m" (*ctr), [dst] "=m" (*b) + : [src] "m" (*a), + [key] "g" (ctx->keyschenc), + [rounds] "g" (ctx->rounds), + [mask] "m" (*be_mask) + : "%esi", "cc", "memory"); +#undef aesenc_xmm1_xmm0 +#undef aesenclast_xmm1_xmm0 +} + + +/* Four blocks at a time variant of do_aesni_ctr. */ +static void +do_aesni_ctr_4 (const RIJNDAEL_context *ctx, + unsigned char *ctr, unsigned char *b, const unsigned char *a) +{ +#define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" +#define aesenc_xmm1_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd1\n\t" +#define aesenc_xmm1_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd9\n\t" +#define aesenc_xmm1_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe1\n\t" +#define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" +#define aesenclast_xmm1_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd1\n\t" +#define aesenclast_xmm1_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd9\n\t" +#define aesenclast_xmm1_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe1\n\t" + + static unsigned char be_mask[16] __attribute__ ((aligned (16))) = + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + + /* Register usage: + esi keyschedule + xmm0 CTR-0 + xmm1 temp / round key + xmm2 CTR-1 + xmm3 CTR-2 + xmm4 CTR-3 + xmm5 temp + */ + + asm volatile ("movdqa %[ctr], %%xmm0\n\t" /* xmm0, xmm2 := CTR */ + "movaps %%xmm0, %%xmm2\n\t" + "mov $1, %%esi\n\t" /* xmm1 := 1 */ + "movd %%esi, %%xmm1\n\t" + "pshufb %[mask], %%xmm2\n\t" /* xmm2 := le(xmm2) */ + "paddq %%xmm1, %%xmm2\n\t" /* xmm2++ */ + "movaps %%xmm2, %%xmm3\n\t" /* xmm3 := xmm2 */ + "paddq %%xmm1, %%xmm3\n\t" /* xmm3++ */ + "movaps %%xmm3, %%xmm4\n\t" /* xmm4 := xmm3 */ + "paddq %%xmm1, %%xmm4\n\t" /* xmm4++ */ + "movaps %%xmm4, %%xmm5\n\t" /* xmm5 := xmm4 */ + "paddq %%xmm1, %%xmm5\n\t" /* xmm5++ */ + "pshufb %[mask], %%xmm2\n\t" /* xmm2 := be(xmm2) */ + "pshufb %[mask], %%xmm3\n\t" /* xmm3 := be(xmm3) */ + "pshufb %[mask], %%xmm4\n\t" /* xmm4 := be(xmm4) */ + "pshufb %[mask], %%xmm5\n\t" /* xmm5 := be(xmm5) */ + "movdqa %%xmm5, %[ctr]\n" /* Update CTR. */ + + "movl %[key], %%esi\n\t" /* esi := keyschenc */ + "movdqa (%%esi), %%xmm1\n\t" /* xmm1 := key[0] */ + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ + "pxor %%xmm1, %%xmm2\n\t" /* xmm2 ^= key[0] */ + "pxor %%xmm1, %%xmm3\n\t" /* xmm3 ^= key[0] */ + "pxor %%xmm1, %%xmm4\n\t" /* xmm4 ^= key[0] */ + "movdqa 0x10(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x20(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x30(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x40(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x50(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x60(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x70(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x80(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0x90(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0xa0(%%esi), %%xmm1\n\t" + "cmp $10, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0xb0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0xc0(%%esi), %%xmm1\n\t" + "cmp $12, %[rounds]\n\t" + "jz .Lenclast%=\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0xd0(%%esi), %%xmm1\n\t" + aesenc_xmm1_xmm0 + aesenc_xmm1_xmm2 + aesenc_xmm1_xmm3 + aesenc_xmm1_xmm4 + "movdqa 0xe0(%%esi), %%xmm1\n" + + ".Lenclast%=:\n\t" + aesenclast_xmm1_xmm0 + aesenclast_xmm1_xmm2 + aesenclast_xmm1_xmm3 + aesenclast_xmm1_xmm4 + + "movdqu %[src], %%xmm1\n\t" /* Get block 1. */ + "pxor %%xmm1, %%xmm0\n\t" /* EncCTR-1 ^= input */ + "movdqu %%xmm0, %[dst]\n\t" /* Store block 1 */ + + "movdqu (16)%[src], %%xmm1\n\t" /* Get block 2. */ + "pxor %%xmm1, %%xmm2\n\t" /* EncCTR-2 ^= input */ + "movdqu %%xmm2, (16)%[dst]\n\t" /* Store block 2. */ + + "movdqu (32)%[src], %%xmm1\n\t" /* Get block 3. */ + "pxor %%xmm1, %%xmm3\n\t" /* EncCTR-3 ^= input */ + "movdqu %%xmm3, (32)%[dst]\n\t" /* Store block 3. */ + + "movdqu (48)%[src], %%xmm1\n\t" /* Get block 4. */ + "pxor %%xmm1, %%xmm4\n\t" /* EncCTR-4 ^= input */ + "movdqu %%xmm4, (48)%[dst]" /* Store block 4. */ + + : [ctr] "+m" (*ctr), [dst] "=m" (*b) + : [src] "m" (*a), + [key] "g" (ctx->keyschenc), + [rounds] "g" (ctx->rounds), + [mask] "m" (*be_mask) + : "%esi", "cc", "memory"); +#undef aesenc_xmm1_xmm0 +#undef aesenc_xmm1_xmm2 +#undef aesenc_xmm1_xmm3 +#undef aesenc_xmm1_xmm4 +#undef aesenclast_xmm1_xmm0 +#undef aesenclast_xmm1_xmm2 +#undef aesenclast_xmm1_xmm3 +#undef aesenclast_xmm1_xmm4 +} + + +static void +do_aesni (RIJNDAEL_context *ctx, int decrypt_flag, + unsigned char *bx, const unsigned char *ax) +{ + + if (decrypt_flag) + { + if (!ctx->decryption_prepared ) + { + prepare_decryption ( ctx ); + ctx->decryption_prepared = 1; + } + do_aesni_dec_aligned (ctx, bx, ax); + } + else + do_aesni_enc_aligned (ctx, bx, ax); +} +#endif /*USE_AESNI*/ + + +static void +rijndael_encrypt (void *context, byte *b, const byte *a) +{ + RIJNDAEL_context *ctx = context; + + if (0) + ; +#ifdef USE_PADLOCK + else if (ctx->use_padlock) + { + do_padlock (ctx, 0, b, a); + _gcry_burn_stack (48 + 15 /* possible padding for alignment */); + } +#endif /*USE_PADLOCK*/ +#ifdef USE_AESNI + else if (ctx->use_aesni) + { + aesni_prepare (); + do_aesni (ctx, 0, b, a); + aesni_cleanup (); + } +#endif /*USE_AESNI*/ + else + { + do_encrypt (ctx, b, a); + _gcry_burn_stack (56 + 2*sizeof(int)); + } +} + + +/* Bulk encryption of complete blocks in CFB mode. Caller needs to + make sure that IV is aligned on an unsigned long boundary. This + function is only intended for the bulk encryption feature of + cipher.c. */ +void +_gcry_aes_cfb_enc (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks) +{ + RIJNDAEL_context *ctx = context; + unsigned char *outbuf = outbuf_arg; + const unsigned char *inbuf = inbuf_arg; + unsigned char *ivp; + int i; + + if (0) + ; +#ifdef USE_PADLOCK + else if (ctx->use_padlock) + { + /* Fixme: Let Padlock do the CFBing. */ + for ( ;nblocks; nblocks-- ) + { + /* Encrypt the IV. */ + do_padlock (ctx, 0, iv, iv); + /* XOR the input with the IV and store input into IV. */ + for (ivp=iv,i=0; i < BLOCKSIZE; i++ ) + *outbuf++ = (*ivp++ ^= *inbuf++); + } + } +#endif /*USE_PADLOCK*/ +#ifdef USE_AESNI + else if (ctx->use_aesni) + { + aesni_prepare (); + for ( ;nblocks; nblocks-- ) + { + do_aesni_cfb (ctx, 0, iv, outbuf, inbuf); + outbuf += BLOCKSIZE; + inbuf += BLOCKSIZE; + } + aesni_cleanup (); + } +#endif /*USE_AESNI*/ + else + { + for ( ;nblocks; nblocks-- ) + { + /* Encrypt the IV. */ + do_encrypt_aligned (ctx, iv, iv); + /* XOR the input with the IV and store input into IV. */ + for (ivp=iv,i=0; i < BLOCKSIZE; i++ ) + *outbuf++ = (*ivp++ ^= *inbuf++); + } + } + + _gcry_burn_stack (48 + 2*sizeof(int)); +} + + +/* Bulk encryption of complete blocks in CBC mode. Caller needs to + make sure that IV is aligned on an unsigned long boundary. This + function is only intended for the bulk encryption feature of + cipher.c. */ +void +_gcry_aes_cbc_enc (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks, int cbc_mac) +{ + RIJNDAEL_context *ctx = context; + unsigned char *outbuf = outbuf_arg; + const unsigned char *inbuf = inbuf_arg; + unsigned char *ivp; + int i; + +#ifdef USE_AESNI + if (ctx->use_aesni) + aesni_prepare (); +#endif /*USE_AESNI*/ + + for ( ;nblocks; nblocks-- ) + { + for (ivp=iv, i=0; i < BLOCKSIZE; i++ ) + outbuf[i] = inbuf[i] ^ *ivp++; + + if (0) + ; +#ifdef USE_PADLOCK + else if (ctx->use_padlock) + do_padlock (ctx, 0, outbuf, outbuf); +#endif /*USE_PADLOCK*/ +#ifdef USE_AESNI + else if (ctx->use_aesni) + do_aesni (ctx, 0, outbuf, outbuf); +#endif /*USE_AESNI*/ + else + do_encrypt (ctx, outbuf, outbuf ); + + memcpy (iv, outbuf, BLOCKSIZE); + inbuf += BLOCKSIZE; + if (!cbc_mac) + outbuf += BLOCKSIZE; + } + +#ifdef USE_AESNI + if (ctx->use_aesni) + aesni_cleanup (); +#endif /*USE_AESNI*/ + + _gcry_burn_stack (48 + 2*sizeof(int)); +} + + +/* Bulk encryption of complete blocks in CTR mode. Caller needs to + make sure that CTR is aligned on a 16 byte boundary if AESNI; the + minimum alignment is for an u32. This function is only intended + for the bulk encryption feature of cipher.c. CTR is expected to be + of size BLOCKSIZE. */ +void +_gcry_aes_ctr_enc (void *context, unsigned char *ctr, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks) +{ + RIJNDAEL_context *ctx = context; + unsigned char *outbuf = outbuf_arg; + const unsigned char *inbuf = inbuf_arg; + unsigned char *p; + int i; + + if (0) + ; +#ifdef USE_AESNI + else if (ctx->use_aesni) + { + aesni_prepare (); + for ( ;nblocks > 3 ; nblocks -= 4 ) + { + do_aesni_ctr_4 (ctx, ctr, outbuf, inbuf); + outbuf += 4*BLOCKSIZE; + inbuf += 4*BLOCKSIZE; + } + for ( ;nblocks; nblocks-- ) + { + do_aesni_ctr (ctx, ctr, outbuf, inbuf); + outbuf += BLOCKSIZE; + inbuf += BLOCKSIZE; + } + aesni_cleanup (); + aesni_cleanup_2_4 (); + } +#endif /*USE_AESNI*/ + else + { + union { unsigned char x1[16]; u32 x32[4]; } tmp; + + for ( ;nblocks; nblocks-- ) + { + /* Encrypt the counter. */ + do_encrypt_aligned (ctx, tmp.x1, ctr); + /* XOR the input with the encrypted counter and store in output. */ + for (p=tmp.x1, i=0; i < BLOCKSIZE; i++) + *outbuf++ = (*p++ ^= *inbuf++); + /* Increment the counter. */ + for (i = BLOCKSIZE; i > 0; i--) + { + ctr[i-1]++; + if (ctr[i-1]) + break; + } + } + } + + _gcry_burn_stack (48 + 2*sizeof(int)); +} + + + +/* Decrypt one block. A and B need to be aligned on a 4 byte boundary + and the decryption must have been prepared. A and B may be the + same. */ +static void +do_decrypt_aligned (RIJNDAEL_context *ctx, + unsigned char *b, const unsigned char *a) +{ +#define rk (ctx->keyschdec) + int rounds = ctx->rounds; + int r; + union + { + u32 tempu32[4]; /* Force correct alignment. */ + byte temp[4][4]; + } u; + + + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(a )) ^ *((u32_a_t*)rk[rounds][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(a+ 4)) ^ *((u32_a_t*)rk[rounds][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(a+ 8)) ^ *((u32_a_t*)rk[rounds][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(a+12)) ^ *((u32_a_t*)rk[rounds][3]); + + *((u32_a_t*)(b )) = (*((u32_a_t*)T5[u.temp[0][0]]) + ^ *((u32_a_t*)T6[u.temp[3][1]]) + ^ *((u32_a_t*)T7[u.temp[2][2]]) + ^ *((u32_a_t*)T8[u.temp[1][3]])); + *((u32_a_t*)(b+ 4)) = (*((u32_a_t*)T5[u.temp[1][0]]) + ^ *((u32_a_t*)T6[u.temp[0][1]]) + ^ *((u32_a_t*)T7[u.temp[3][2]]) + ^ *((u32_a_t*)T8[u.temp[2][3]])); + *((u32_a_t*)(b+ 8)) = (*((u32_a_t*)T5[u.temp[2][0]]) + ^ *((u32_a_t*)T6[u.temp[1][1]]) + ^ *((u32_a_t*)T7[u.temp[0][2]]) + ^ *((u32_a_t*)T8[u.temp[3][3]])); + *((u32_a_t*)(b+12)) = (*((u32_a_t*)T5[u.temp[3][0]]) + ^ *((u32_a_t*)T6[u.temp[2][1]]) + ^ *((u32_a_t*)T7[u.temp[1][2]]) + ^ *((u32_a_t*)T8[u.temp[0][3]])); + + for (r = rounds-1; r > 1; r--) + { + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(b )) ^ *((u32_a_t*)rk[r][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(b+ 4)) ^ *((u32_a_t*)rk[r][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(b+ 8)) ^ *((u32_a_t*)rk[r][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(b+12)) ^ *((u32_a_t*)rk[r][3]); + *((u32_a_t*)(b )) = (*((u32_a_t*)T5[u.temp[0][0]]) + ^ *((u32_a_t*)T6[u.temp[3][1]]) + ^ *((u32_a_t*)T7[u.temp[2][2]]) + ^ *((u32_a_t*)T8[u.temp[1][3]])); + *((u32_a_t*)(b+ 4)) = (*((u32_a_t*)T5[u.temp[1][0]]) + ^ *((u32_a_t*)T6[u.temp[0][1]]) + ^ *((u32_a_t*)T7[u.temp[3][2]]) + ^ *((u32_a_t*)T8[u.temp[2][3]])); + *((u32_a_t*)(b+ 8)) = (*((u32_a_t*)T5[u.temp[2][0]]) + ^ *((u32_a_t*)T6[u.temp[1][1]]) + ^ *((u32_a_t*)T7[u.temp[0][2]]) + ^ *((u32_a_t*)T8[u.temp[3][3]])); + *((u32_a_t*)(b+12)) = (*((u32_a_t*)T5[u.temp[3][0]]) + ^ *((u32_a_t*)T6[u.temp[2][1]]) + ^ *((u32_a_t*)T7[u.temp[1][2]]) + ^ *((u32_a_t*)T8[u.temp[0][3]])); + } + + /* Last round is special. */ + *((u32_a_t*)u.temp[0]) = *((u32_a_t*)(b )) ^ *((u32_a_t*)rk[1][0]); + *((u32_a_t*)u.temp[1]) = *((u32_a_t*)(b+ 4)) ^ *((u32_a_t*)rk[1][1]); + *((u32_a_t*)u.temp[2]) = *((u32_a_t*)(b+ 8)) ^ *((u32_a_t*)rk[1][2]); + *((u32_a_t*)u.temp[3]) = *((u32_a_t*)(b+12)) ^ *((u32_a_t*)rk[1][3]); + b[ 0] = S5[u.temp[0][0]]; + b[ 1] = S5[u.temp[3][1]]; + b[ 2] = S5[u.temp[2][2]]; + b[ 3] = S5[u.temp[1][3]]; + b[ 4] = S5[u.temp[1][0]]; + b[ 5] = S5[u.temp[0][1]]; + b[ 6] = S5[u.temp[3][2]]; + b[ 7] = S5[u.temp[2][3]]; + b[ 8] = S5[u.temp[2][0]]; + b[ 9] = S5[u.temp[1][1]]; + b[10] = S5[u.temp[0][2]]; + b[11] = S5[u.temp[3][3]]; + b[12] = S5[u.temp[3][0]]; + b[13] = S5[u.temp[2][1]]; + b[14] = S5[u.temp[1][2]]; + b[15] = S5[u.temp[0][3]]; + *((u32_a_t*)(b )) ^= *((u32_a_t*)rk[0][0]); + *((u32_a_t*)(b+ 4)) ^= *((u32_a_t*)rk[0][1]); + *((u32_a_t*)(b+ 8)) ^= *((u32_a_t*)rk[0][2]); + *((u32_a_t*)(b+12)) ^= *((u32_a_t*)rk[0][3]); +#undef rk +} + + +/* Decrypt one block. AX and BX may be the same. */ +static void +do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax) +{ + if ( !ctx->decryption_prepared ) + { + prepare_decryption ( ctx ); + _gcry_burn_stack (64); + ctx->decryption_prepared = 1; + } + + /* BX and AX are not necessary correctly aligned. Thus we might + need to copy them here. We try to align to a 16 bytes. */ + if (((size_t)ax & 0x0f) || ((size_t)bx & 0x0f)) + { + union + { + u32 dummy[4]; + byte a[16] ATTR_ALIGNED_16; + } a; + union + { + u32 dummy[4]; + byte b[16] ATTR_ALIGNED_16; + } b; + + memcpy (a.a, ax, 16); + do_decrypt_aligned (ctx, b.b, a.a); + memcpy (bx, b.b, 16); + } + else + { + do_decrypt_aligned (ctx, bx, ax); + } +} + + + + +static void +rijndael_decrypt (void *context, byte *b, const byte *a) +{ + RIJNDAEL_context *ctx = context; + + if (0) + ; +#ifdef USE_PADLOCK + else if (ctx->use_padlock) + { + do_padlock (ctx, 1, b, a); + _gcry_burn_stack (48 + 2*sizeof(int) /* FIXME */); + } +#endif /*USE_PADLOCK*/ +#ifdef USE_AESNI + else if (ctx->use_aesni) + { + aesni_prepare (); + do_aesni (ctx, 1, b, a); + aesni_cleanup (); + } +#endif /*USE_AESNI*/ + else + { + do_decrypt (ctx, b, a); + _gcry_burn_stack (56+2*sizeof(int)); + } +} + + +/* Bulk decryption of complete blocks in CFB mode. Caller needs to + make sure that IV is aligned on an unisgned lonhg boundary. This + function is only intended for the bulk encryption feature of + cipher.c. */ +void +_gcry_aes_cfb_dec (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks) +{ + RIJNDAEL_context *ctx = context; + unsigned char *outbuf = outbuf_arg; + const unsigned char *inbuf = inbuf_arg; + unsigned char *ivp; + unsigned char temp; + int i; + + if (0) + ; +#ifdef USE_PADLOCK + else if (ctx->use_padlock) + { + /* Fixme: Let Padlock do the CFBing. */ + for ( ;nblocks; nblocks-- ) + { + do_padlock (ctx, 0, iv, iv); + for (ivp=iv,i=0; i < BLOCKSIZE; i++ ) + { + temp = *inbuf++; + *outbuf++ = *ivp ^ temp; + *ivp++ = temp; + } + } + } +#endif /*USE_PADLOCK*/ +#ifdef USE_AESNI + else if (ctx->use_aesni) + { + aesni_prepare (); + for ( ;nblocks; nblocks-- ) + { + do_aesni_cfb (ctx, 1, iv, outbuf, inbuf); + outbuf += BLOCKSIZE; + inbuf += BLOCKSIZE; + } + aesni_cleanup (); + } +#endif /*USE_AESNI*/ + else + { + for ( ;nblocks; nblocks-- ) + { + do_encrypt_aligned (ctx, iv, iv); + for (ivp=iv,i=0; i < BLOCKSIZE; i++ ) + { + temp = *inbuf++; + *outbuf++ = *ivp ^ temp; + *ivp++ = temp; + } + } + } + + _gcry_burn_stack (48 + 2*sizeof(int)); +} + + +/* Bulk decryption of complete blocks in CBC mode. Caller needs to + make sure that IV is aligned on an unsigned long boundary. This + function is only intended for the bulk encryption feature of + cipher.c. */ +void +_gcry_aes_cbc_dec (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks) +{ + RIJNDAEL_context *ctx = context; + unsigned char *outbuf = outbuf_arg; + const unsigned char *inbuf = inbuf_arg; + unsigned char *ivp; + int i; + unsigned char savebuf[BLOCKSIZE]; + +#ifdef USE_AESNI + if (ctx->use_aesni) + aesni_prepare (); +#endif /*USE_AESNI*/ + + for ( ;nblocks; nblocks-- ) + { + /* We need to save INBUF away because it may be identical to + OUTBUF. */ + memcpy (savebuf, inbuf, BLOCKSIZE); + + if (0) + ; +#ifdef USE_PADLOCK + else if (ctx->use_padlock) + do_padlock (ctx, 1, outbuf, inbuf); +#endif /*USE_PADLOCK*/ +#ifdef USE_AESNI + else if (ctx->use_aesni) + do_aesni (ctx, 1, outbuf, inbuf); +#endif /*USE_AESNI*/ + else + do_decrypt (ctx, outbuf, inbuf); + + for (ivp=iv, i=0; i < BLOCKSIZE; i++ ) + outbuf[i] ^= *ivp++; + memcpy (iv, savebuf, BLOCKSIZE); + inbuf += BLOCKSIZE; + outbuf += BLOCKSIZE; + } + +#ifdef USE_AESNI + if (ctx->use_aesni) + aesni_cleanup (); +#endif /*USE_AESNI*/ + + _gcry_burn_stack (48 + 2*sizeof(int) + BLOCKSIZE + 4*sizeof (char*)); +} + + + + +/* Run the self-tests for AES 128. Returns NULL on success. */ +static const char* +selftest_basic_128 (void) +{ + RIJNDAEL_context ctx; + unsigned char scratch[16]; + + /* The test vectors are from the AES supplied ones; more or less + randomly taken from ecb_tbl.txt (I=42,81,14) */ +#if 1 + static const unsigned char plaintext_128[16] = + { + 0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33, + 0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A + }; + static const unsigned char key_128[16] = + { + 0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0, + 0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA + }; + static const unsigned char ciphertext_128[16] = + { + 0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2, + 0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD + }; +#else + /* Test vectors from fips-197, appendix C. */ +# warning debug test vectors in use + static const unsigned char plaintext_128[16] = + { + 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77, + 0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff + }; + static const unsigned char key_128[16] = + { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f + /* 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, */ + /* 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c */ + }; + static const unsigned char ciphertext_128[16] = + { + 0x69,0xc4,0xe0,0xd8,0x6a,0x7b,0x04,0x30, + 0xd8,0xcd,0xb7,0x80,0x70,0xb4,0xc5,0x5a + }; +#endif + + rijndael_setkey (&ctx, key_128, sizeof (key_128)); + rijndael_encrypt (&ctx, scratch, plaintext_128); + if (memcmp (scratch, ciphertext_128, sizeof (ciphertext_128))) + return "AES-128 test encryption failed."; + rijndael_decrypt (&ctx, scratch, scratch); + if (memcmp (scratch, plaintext_128, sizeof (plaintext_128))) + return "AES-128 test decryption failed."; + + return NULL; +} + +/* Run the self-tests for AES 192. Returns NULL on success. */ +static const char* +selftest_basic_192 (void) +{ + RIJNDAEL_context ctx; + unsigned char scratch[16]; + + static unsigned char plaintext_192[16] = + { + 0x76,0x77,0x74,0x75,0xF1,0xF2,0xF3,0xF4, + 0xF8,0xF9,0xE6,0xE7,0x77,0x70,0x71,0x72 + }; + static unsigned char key_192[24] = + { + 0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C, + 0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16, + 0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20 + }; + static const unsigned char ciphertext_192[16] = + { + 0x5D,0x1E,0xF2,0x0D,0xCE,0xD6,0xBC,0xBC, + 0x12,0x13,0x1A,0xC7,0xC5,0x47,0x88,0xAA + }; + + rijndael_setkey (&ctx, key_192, sizeof(key_192)); + rijndael_encrypt (&ctx, scratch, plaintext_192); + if (memcmp (scratch, ciphertext_192, sizeof (ciphertext_192))) + return "AES-192 test encryption failed."; + rijndael_decrypt (&ctx, scratch, scratch); + if (memcmp (scratch, plaintext_192, sizeof (plaintext_192))) + return "AES-192 test decryption failed."; + + return NULL; +} + + +/* Run the self-tests for AES 256. Returns NULL on success. */ +static const char* +selftest_basic_256 (void) +{ + RIJNDAEL_context ctx; + unsigned char scratch[16]; + + static unsigned char plaintext_256[16] = + { + 0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F, + 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21 + }; + static unsigned char key_256[32] = + { + 0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10, + 0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A, + 0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24, + 0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E + }; + static const unsigned char ciphertext_256[16] = + { + 0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71, + 0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3 + }; + + rijndael_setkey (&ctx, key_256, sizeof(key_256)); + rijndael_encrypt (&ctx, scratch, plaintext_256); + if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256))) + return "AES-256 test encryption failed."; + rijndael_decrypt (&ctx, scratch, scratch); + if (memcmp (scratch, plaintext_256, sizeof (plaintext_256))) + return "AES-256 test decryption failed."; + + return NULL; +} + +/* Run all the self-tests and return NULL on success. This function + is used for the on-the-fly self-tests. */ +static const char * +selftest (void) +{ + const char *r; + + if ( (r = selftest_basic_128 ()) + || (r = selftest_basic_192 ()) + || (r = selftest_basic_256 ()) ) + return r; + + return r; +} + + +/* SP800-38a.pdf for AES-128. */ +static const char * +selftest_fips_128_38a (int requested_mode) +{ + struct tv + { + int mode; + const unsigned char key[16]; + const unsigned char iv[16]; + struct + { + const unsigned char input[16]; + const unsigned char output[16]; + } data[4]; + } tv[2] = + { + { + GCRY_CIPHER_MODE_CFB, /* F.3.13, CFB128-AES128 */ + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { + { { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, + { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, + 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } }, + + { { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 }, + { 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, + 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b } }, + + { { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef }, + { 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40, + 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf } }, + + { { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, + { 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e, + 0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6 } } + } + }, + { + GCRY_CIPHER_MODE_OFB, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { + { { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, + { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, + 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a } }, + + { { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 }, + { 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25 } }, + + { { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef }, + { 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, + 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc } }, + + { { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, + { 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, + 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e } }, + } + } + }; + unsigned char scratch[16]; + gpg_error_t err; + int tvi, idx; + gcry_cipher_hd_t hdenc = NULL; + gcry_cipher_hd_t hddec = NULL; + +#define Fail(a) do { \ + _gcry_cipher_close (hdenc); \ + _gcry_cipher_close (hddec); \ + return a; \ + } while (0) + + gcry_assert (sizeof tv[0].data[0].input == sizeof scratch); + gcry_assert (sizeof tv[0].data[0].output == sizeof scratch); + + for (tvi=0; tvi < DIM (tv); tvi++) + if (tv[tvi].mode == requested_mode) + break; + if (tvi == DIM (tv)) + Fail ("no test data for this mode"); + + err = _gcry_cipher_open (&hdenc, GCRY_CIPHER_AES, tv[tvi].mode, 0); + if (err) + Fail ("open"); + err = _gcry_cipher_open (&hddec, GCRY_CIPHER_AES, tv[tvi].mode, 0); + if (err) + Fail ("open"); + err = _gcry_cipher_setkey (hdenc, tv[tvi].key, sizeof tv[tvi].key); + if (!err) + err = _gcry_cipher_setkey (hddec, tv[tvi].key, sizeof tv[tvi].key); + if (err) + Fail ("set key"); + err = _gcry_cipher_setiv (hdenc, tv[tvi].iv, sizeof tv[tvi].iv); + if (!err) + err = _gcry_cipher_setiv (hddec, tv[tvi].iv, sizeof tv[tvi].iv); + if (err) + Fail ("set IV"); + for (idx=0; idx < DIM (tv[tvi].data); idx++) + { + err = _gcry_cipher_encrypt (hdenc, scratch, sizeof scratch, + tv[tvi].data[idx].input, + sizeof tv[tvi].data[idx].input); + if (err) + Fail ("encrypt command"); + if (memcmp (scratch, tv[tvi].data[idx].output, sizeof scratch)) + Fail ("encrypt mismatch"); + err = _gcry_cipher_decrypt (hddec, scratch, sizeof scratch, + tv[tvi].data[idx].output, + sizeof tv[tvi].data[idx].output); + if (err) + Fail ("decrypt command"); + if (memcmp (scratch, tv[tvi].data[idx].input, sizeof scratch)) + Fail ("decrypt mismatch"); + } + +#undef Fail + _gcry_cipher_close (hdenc); + _gcry_cipher_close (hddec); + return NULL; +} + + +/* Complete selftest for AES-128 with all modes and driver code. */ +static gpg_err_code_t +selftest_fips_128 (int extended, selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + + what = "low-level"; + errtxt = selftest_basic_128 (); + if (errtxt) + goto failed; + + if (extended) + { + what = "cfb"; + errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_CFB); + if (errtxt) + goto failed; + + what = "ofb"; + errtxt = selftest_fips_128_38a (GCRY_CIPHER_MODE_OFB); + if (errtxt) + goto failed; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("cipher", GCRY_CIPHER_AES128, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + +/* Complete selftest for AES-192. */ +static gpg_err_code_t +selftest_fips_192 (int extended, selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + + (void)extended; /* No extended tests available. */ + + what = "low-level"; + errtxt = selftest_basic_192 (); + if (errtxt) + goto failed; + + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("cipher", GCRY_CIPHER_AES192, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + +/* Complete selftest for AES-256. */ +static gpg_err_code_t +selftest_fips_256 (int extended, selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + + (void)extended; /* No extended tests available. */ + + what = "low-level"; + errtxt = selftest_basic_256 (); + if (errtxt) + goto failed; + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("cipher", GCRY_CIPHER_AES256, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + + +/* Run a full self-test for ALGO and return 0 on success. */ +static gpg_err_code_t +run_selftests (int algo, int extended, selftest_report_func_t report) +{ + gpg_err_code_t ec; + + switch (algo) + { + case GCRY_CIPHER_AES128: + ec = selftest_fips_128 (extended, report); + break; + case GCRY_CIPHER_AES192: + ec = selftest_fips_192 (extended, report); + break; + case GCRY_CIPHER_AES256: + ec = selftest_fips_256 (extended, report); + break; + default: + ec = GPG_ERR_CIPHER_ALGO; + break; + + } + return ec; +} + + + + +static const char *rijndael_names[] = + { + "RIJNDAEL", + "AES128", + "AES-128", + NULL + }; + +static gcry_cipher_oid_spec_t rijndael_oids[] = + { + { "2.16.840.1.101.3.4.1.1", GCRY_CIPHER_MODE_ECB }, + { "2.16.840.1.101.3.4.1.2", GCRY_CIPHER_MODE_CBC }, + { "2.16.840.1.101.3.4.1.3", GCRY_CIPHER_MODE_OFB }, + { "2.16.840.1.101.3.4.1.4", GCRY_CIPHER_MODE_CFB }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_aes = + { + "AES", rijndael_names, rijndael_oids, 16, 128, sizeof (RIJNDAEL_context), + rijndael_setkey, rijndael_encrypt, rijndael_decrypt + }; +cipher_extra_spec_t _gcry_cipher_extraspec_aes = + { + run_selftests + }; + +static const char *rijndael192_names[] = + { + "RIJNDAEL192", + "AES-192", + NULL + }; + +static gcry_cipher_oid_spec_t rijndael192_oids[] = + { + { "2.16.840.1.101.3.4.1.21", GCRY_CIPHER_MODE_ECB }, + { "2.16.840.1.101.3.4.1.22", GCRY_CIPHER_MODE_CBC }, + { "2.16.840.1.101.3.4.1.23", GCRY_CIPHER_MODE_OFB }, + { "2.16.840.1.101.3.4.1.24", GCRY_CIPHER_MODE_CFB }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_aes192 = + { + "AES192", rijndael192_names, rijndael192_oids, 16, 192, sizeof (RIJNDAEL_context), + rijndael_setkey, rijndael_encrypt, rijndael_decrypt + }; +cipher_extra_spec_t _gcry_cipher_extraspec_aes192 = + { + run_selftests + }; + +static const char *rijndael256_names[] = + { + "RIJNDAEL256", + "AES-256", + NULL + }; + +static gcry_cipher_oid_spec_t rijndael256_oids[] = + { + { "2.16.840.1.101.3.4.1.41", GCRY_CIPHER_MODE_ECB }, + { "2.16.840.1.101.3.4.1.42", GCRY_CIPHER_MODE_CBC }, + { "2.16.840.1.101.3.4.1.43", GCRY_CIPHER_MODE_OFB }, + { "2.16.840.1.101.3.4.1.44", GCRY_CIPHER_MODE_CFB }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_aes256 = + { + "AES256", rijndael256_names, rijndael256_oids, 16, 256, + sizeof (RIJNDAEL_context), + rijndael_setkey, rijndael_encrypt, rijndael_decrypt + }; + +cipher_extra_spec_t _gcry_cipher_extraspec_aes256 = + { + run_selftests + }; diff --git a/grub-core/lib/libgcrypt/cipher/rmd.h b/grub-core/lib/libgcrypt/cipher/rmd.h new file mode 100644 index 0000000..6a9fe31 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/rmd.h @@ -0,0 +1,36 @@ +/* rmd.h - RIPE-MD hash functions + * Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef G10_RMD_H +#define G10_RMD_H + + +/* We need this here because random.c must have direct access. */ +typedef struct +{ + u32 h0,h1,h2,h3,h4; + u32 nblocks; + byte buf[64]; + int count; +} RMD160_CONTEXT; + +void _gcry_rmd160_init ( void *context ); +void _gcry_rmd160_mixblock ( RMD160_CONTEXT *hd, void *blockof64byte ); + +#endif /*G10_RMD_H*/ diff --git a/grub-core/lib/libgcrypt/cipher/rmd160.c b/grub-core/lib/libgcrypt/cipher/rmd160.c new file mode 100644 index 0000000..179a4d9 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/rmd160.c @@ -0,0 +1,572 @@ +/* rmd160.c - RIPE-MD160 + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "g10lib.h" +#include "rmd.h" +#include "cipher.h" /* Only used for the rmd160_hash_buffer() prototype. */ + +#include "bithelp.h" + +/********************************* + * RIPEMD-160 is not patented, see (as of 25.10.97) + * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html + * Note that the code uses Little Endian byteorder, which is good for + * 386 etc, but we must add some conversion when used on a big endian box. + * + * + * Pseudo-code for RIPEMD-160 + * + * RIPEMD-160 is an iterative hash function that operates on 32-bit words. + * The round function takes as input a 5-word chaining variable and a 16-word + * message block and maps this to a new chaining variable. All operations are + * defined on 32-bit words. Padding is identical to that of MD4. + * + * + * RIPEMD-160: definitions + * + * + * nonlinear functions at bit level: exor, mux, -, mux, - + * + * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) + * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) + * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) + * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) + * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) + * + * + * added constants (hexadecimal) + * + * K(j) = 0x00000000 (0 <= j <= 15) + * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) + * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) + * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) + * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) + * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) + * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) + * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) + * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) + * K'(j) = 0x00000000 (64 <= j <= 79) + * + * + * selection of message word + * + * r(j) = j (0 <= j <= 15) + * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 + * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 + * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 + * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 + * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 + * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 + * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 + * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 + * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 + * + * + * amount for rotate left (rol) + * + * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 + * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 + * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 + * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 + * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 + * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 + * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 + * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 + * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 + * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 + * + * + * initial value (hexadecimal) + * + * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; + * h4 = 0xC3D2E1F0; + * + * + * RIPEMD-160: pseudo-code + * + * It is assumed that the message after padding consists of t 16-word blocks + * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. + * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left + * shift (rotate) over s positions. + * + * + * for i := 0 to t-1 { + * A := h0; B := h1; C := h2; D = h3; E = h4; + * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; + * for j := 0 to 79 { + * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; + * A := E; E := D; D := rol_10(C); C := B; B := T; + * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] + [+] K'(j)) [+] E'; + * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; + * } + * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; + * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; + * } + */ + +/* Some examples: + * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 + * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe + * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc + * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 + * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc + * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b + * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 + * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb + * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 + */ + + +void +_gcry_rmd160_init (void *context) +{ + RMD160_CONTEXT *hd = context; + + hd->h0 = 0x67452301; + hd->h1 = 0xEFCDAB89; + hd->h2 = 0x98BADCFE; + hd->h3 = 0x10325476; + hd->h4 = 0xC3D2E1F0; + hd->nblocks = 0; + hd->count = 0; +} + + + +/**************** + * Transform the message X which consists of 16 32-bit-words + */ +static void +transform ( RMD160_CONTEXT *hd, const unsigned char *data ) +{ + register u32 a,b,c,d,e; + u32 aa,bb,cc,dd,ee,t; +#ifdef WORDS_BIGENDIAN + u32 x[16]; + { + int i; + byte *p2; + const byte *p1; + for (i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) + { + p2[3] = *p1++; + p2[2] = *p1++; + p2[1] = *p1++; + p2[0] = *p1++; + } + } +#else + /* This version is better because it is always aligned; + * The performance penalty on a 586-100 is about 6% which + * is acceptable - because the data is more local it might + * also be possible that this is faster on some machines. + * This function (when compiled with -02 on gcc 2.7.2) + * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; + * [measured with a 4MB data and "gpgm --print-md rmd160"] */ + u32 x[16]; + memcpy( x, data, 64 ); +#endif + + +#define K0 0x00000000 +#define K1 0x5A827999 +#define K2 0x6ED9EBA1 +#define K3 0x8F1BBCDC +#define K4 0xA953FD4E +#define KK0 0x50A28BE6 +#define KK1 0x5C4DD124 +#define KK2 0x6D703EF3 +#define KK3 0x7A6D76E9 +#define KK4 0x00000000 +#define F0(x,y,z) ( (x) ^ (y) ^ (z) ) +#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) +#define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) +#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) +#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) +#define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ + a = rol(t,s) + e; \ + c = rol(c,10); \ + } while(0) + + /* left lane */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + R( a, b, c, d, e, F0, K0, 0, 11 ); + R( e, a, b, c, d, F0, K0, 1, 14 ); + R( d, e, a, b, c, F0, K0, 2, 15 ); + R( c, d, e, a, b, F0, K0, 3, 12 ); + R( b, c, d, e, a, F0, K0, 4, 5 ); + R( a, b, c, d, e, F0, K0, 5, 8 ); + R( e, a, b, c, d, F0, K0, 6, 7 ); + R( d, e, a, b, c, F0, K0, 7, 9 ); + R( c, d, e, a, b, F0, K0, 8, 11 ); + R( b, c, d, e, a, F0, K0, 9, 13 ); + R( a, b, c, d, e, F0, K0, 10, 14 ); + R( e, a, b, c, d, F0, K0, 11, 15 ); + R( d, e, a, b, c, F0, K0, 12, 6 ); + R( c, d, e, a, b, F0, K0, 13, 7 ); + R( b, c, d, e, a, F0, K0, 14, 9 ); + R( a, b, c, d, e, F0, K0, 15, 8 ); + R( e, a, b, c, d, F1, K1, 7, 7 ); + R( d, e, a, b, c, F1, K1, 4, 6 ); + R( c, d, e, a, b, F1, K1, 13, 8 ); + R( b, c, d, e, a, F1, K1, 1, 13 ); + R( a, b, c, d, e, F1, K1, 10, 11 ); + R( e, a, b, c, d, F1, K1, 6, 9 ); + R( d, e, a, b, c, F1, K1, 15, 7 ); + R( c, d, e, a, b, F1, K1, 3, 15 ); + R( b, c, d, e, a, F1, K1, 12, 7 ); + R( a, b, c, d, e, F1, K1, 0, 12 ); + R( e, a, b, c, d, F1, K1, 9, 15 ); + R( d, e, a, b, c, F1, K1, 5, 9 ); + R( c, d, e, a, b, F1, K1, 2, 11 ); + R( b, c, d, e, a, F1, K1, 14, 7 ); + R( a, b, c, d, e, F1, K1, 11, 13 ); + R( e, a, b, c, d, F1, K1, 8, 12 ); + R( d, e, a, b, c, F2, K2, 3, 11 ); + R( c, d, e, a, b, F2, K2, 10, 13 ); + R( b, c, d, e, a, F2, K2, 14, 6 ); + R( a, b, c, d, e, F2, K2, 4, 7 ); + R( e, a, b, c, d, F2, K2, 9, 14 ); + R( d, e, a, b, c, F2, K2, 15, 9 ); + R( c, d, e, a, b, F2, K2, 8, 13 ); + R( b, c, d, e, a, F2, K2, 1, 15 ); + R( a, b, c, d, e, F2, K2, 2, 14 ); + R( e, a, b, c, d, F2, K2, 7, 8 ); + R( d, e, a, b, c, F2, K2, 0, 13 ); + R( c, d, e, a, b, F2, K2, 6, 6 ); + R( b, c, d, e, a, F2, K2, 13, 5 ); + R( a, b, c, d, e, F2, K2, 11, 12 ); + R( e, a, b, c, d, F2, K2, 5, 7 ); + R( d, e, a, b, c, F2, K2, 12, 5 ); + R( c, d, e, a, b, F3, K3, 1, 11 ); + R( b, c, d, e, a, F3, K3, 9, 12 ); + R( a, b, c, d, e, F3, K3, 11, 14 ); + R( e, a, b, c, d, F3, K3, 10, 15 ); + R( d, e, a, b, c, F3, K3, 0, 14 ); + R( c, d, e, a, b, F3, K3, 8, 15 ); + R( b, c, d, e, a, F3, K3, 12, 9 ); + R( a, b, c, d, e, F3, K3, 4, 8 ); + R( e, a, b, c, d, F3, K3, 13, 9 ); + R( d, e, a, b, c, F3, K3, 3, 14 ); + R( c, d, e, a, b, F3, K3, 7, 5 ); + R( b, c, d, e, a, F3, K3, 15, 6 ); + R( a, b, c, d, e, F3, K3, 14, 8 ); + R( e, a, b, c, d, F3, K3, 5, 6 ); + R( d, e, a, b, c, F3, K3, 6, 5 ); + R( c, d, e, a, b, F3, K3, 2, 12 ); + R( b, c, d, e, a, F4, K4, 4, 9 ); + R( a, b, c, d, e, F4, K4, 0, 15 ); + R( e, a, b, c, d, F4, K4, 5, 5 ); + R( d, e, a, b, c, F4, K4, 9, 11 ); + R( c, d, e, a, b, F4, K4, 7, 6 ); + R( b, c, d, e, a, F4, K4, 12, 8 ); + R( a, b, c, d, e, F4, K4, 2, 13 ); + R( e, a, b, c, d, F4, K4, 10, 12 ); + R( d, e, a, b, c, F4, K4, 14, 5 ); + R( c, d, e, a, b, F4, K4, 1, 12 ); + R( b, c, d, e, a, F4, K4, 3, 13 ); + R( a, b, c, d, e, F4, K4, 8, 14 ); + R( e, a, b, c, d, F4, K4, 11, 11 ); + R( d, e, a, b, c, F4, K4, 6, 8 ); + R( c, d, e, a, b, F4, K4, 15, 5 ); + R( b, c, d, e, a, F4, K4, 13, 6 ); + + aa = a; bb = b; cc = c; dd = d; ee = e; + + /* right lane */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + R( a, b, c, d, e, F4, KK0, 5, 8); + R( e, a, b, c, d, F4, KK0, 14, 9); + R( d, e, a, b, c, F4, KK0, 7, 9); + R( c, d, e, a, b, F4, KK0, 0, 11); + R( b, c, d, e, a, F4, KK0, 9, 13); + R( a, b, c, d, e, F4, KK0, 2, 15); + R( e, a, b, c, d, F4, KK0, 11, 15); + R( d, e, a, b, c, F4, KK0, 4, 5); + R( c, d, e, a, b, F4, KK0, 13, 7); + R( b, c, d, e, a, F4, KK0, 6, 7); + R( a, b, c, d, e, F4, KK0, 15, 8); + R( e, a, b, c, d, F4, KK0, 8, 11); + R( d, e, a, b, c, F4, KK0, 1, 14); + R( c, d, e, a, b, F4, KK0, 10, 14); + R( b, c, d, e, a, F4, KK0, 3, 12); + R( a, b, c, d, e, F4, KK0, 12, 6); + R( e, a, b, c, d, F3, KK1, 6, 9); + R( d, e, a, b, c, F3, KK1, 11, 13); + R( c, d, e, a, b, F3, KK1, 3, 15); + R( b, c, d, e, a, F3, KK1, 7, 7); + R( a, b, c, d, e, F3, KK1, 0, 12); + R( e, a, b, c, d, F3, KK1, 13, 8); + R( d, e, a, b, c, F3, KK1, 5, 9); + R( c, d, e, a, b, F3, KK1, 10, 11); + R( b, c, d, e, a, F3, KK1, 14, 7); + R( a, b, c, d, e, F3, KK1, 15, 7); + R( e, a, b, c, d, F3, KK1, 8, 12); + R( d, e, a, b, c, F3, KK1, 12, 7); + R( c, d, e, a, b, F3, KK1, 4, 6); + R( b, c, d, e, a, F3, KK1, 9, 15); + R( a, b, c, d, e, F3, KK1, 1, 13); + R( e, a, b, c, d, F3, KK1, 2, 11); + R( d, e, a, b, c, F2, KK2, 15, 9); + R( c, d, e, a, b, F2, KK2, 5, 7); + R( b, c, d, e, a, F2, KK2, 1, 15); + R( a, b, c, d, e, F2, KK2, 3, 11); + R( e, a, b, c, d, F2, KK2, 7, 8); + R( d, e, a, b, c, F2, KK2, 14, 6); + R( c, d, e, a, b, F2, KK2, 6, 6); + R( b, c, d, e, a, F2, KK2, 9, 14); + R( a, b, c, d, e, F2, KK2, 11, 12); + R( e, a, b, c, d, F2, KK2, 8, 13); + R( d, e, a, b, c, F2, KK2, 12, 5); + R( c, d, e, a, b, F2, KK2, 2, 14); + R( b, c, d, e, a, F2, KK2, 10, 13); + R( a, b, c, d, e, F2, KK2, 0, 13); + R( e, a, b, c, d, F2, KK2, 4, 7); + R( d, e, a, b, c, F2, KK2, 13, 5); + R( c, d, e, a, b, F1, KK3, 8, 15); + R( b, c, d, e, a, F1, KK3, 6, 5); + R( a, b, c, d, e, F1, KK3, 4, 8); + R( e, a, b, c, d, F1, KK3, 1, 11); + R( d, e, a, b, c, F1, KK3, 3, 14); + R( c, d, e, a, b, F1, KK3, 11, 14); + R( b, c, d, e, a, F1, KK3, 15, 6); + R( a, b, c, d, e, F1, KK3, 0, 14); + R( e, a, b, c, d, F1, KK3, 5, 6); + R( d, e, a, b, c, F1, KK3, 12, 9); + R( c, d, e, a, b, F1, KK3, 2, 12); + R( b, c, d, e, a, F1, KK3, 13, 9); + R( a, b, c, d, e, F1, KK3, 9, 12); + R( e, a, b, c, d, F1, KK3, 7, 5); + R( d, e, a, b, c, F1, KK3, 10, 15); + R( c, d, e, a, b, F1, KK3, 14, 8); + R( b, c, d, e, a, F0, KK4, 12, 8); + R( a, b, c, d, e, F0, KK4, 15, 5); + R( e, a, b, c, d, F0, KK4, 10, 12); + R( d, e, a, b, c, F0, KK4, 4, 9); + R( c, d, e, a, b, F0, KK4, 1, 12); + R( b, c, d, e, a, F0, KK4, 5, 5); + R( a, b, c, d, e, F0, KK4, 8, 14); + R( e, a, b, c, d, F0, KK4, 7, 6); + R( d, e, a, b, c, F0, KK4, 6, 8); + R( c, d, e, a, b, F0, KK4, 2, 13); + R( b, c, d, e, a, F0, KK4, 13, 6); + R( a, b, c, d, e, F0, KK4, 14, 5); + R( e, a, b, c, d, F0, KK4, 0, 15); + R( d, e, a, b, c, F0, KK4, 3, 13); + R( c, d, e, a, b, F0, KK4, 9, 11); + R( b, c, d, e, a, F0, KK4, 11, 11); + + + t = hd->h1 + d + cc; + hd->h1 = hd->h2 + e + dd; + hd->h2 = hd->h3 + a + ee; + hd->h3 = hd->h4 + b + aa; + hd->h4 = hd->h0 + c + bb; + hd->h0 = t; +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +rmd160_write ( void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + RMD160_CONTEXT *hd = context; + + if( hd->count == 64 ) /* flush the buffer */ + { + transform( hd, hd->buf ); + _gcry_burn_stack (108+5*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + if( hd->count ) + { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + rmd160_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + + while( inlen >= 64 ) + { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + _gcry_burn_stack (108+5*sizeof(void*)); + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; +} + +/**************** + * Apply the rmd160 transform function on the buffer which must have + * a length 64 bytes. Do not use this function together with the + * other functions, use rmd160_init to initialize internal variables. + * Returns: 16 bytes in buffer with the mixed contentes of buffer. + */ +void +_gcry_rmd160_mixblock ( RMD160_CONTEXT *hd, void *blockof64byte ) +{ + char *p = blockof64byte; + + transform ( hd, blockof64byte ); +#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) + X(0); + X(1); + X(2); + X(3); + X(4); +#undef X +} + + +/* The routine terminates the computation + */ + +static void +rmd160_final( void *context ) +{ + RMD160_CONTEXT *hd = context; + u32 t, msb, lsb; + byte *p; + + rmd160_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) /* enough room */ + { + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else /* need one extra block */ + { + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + rmd160_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + _gcry_burn_stack (108+5*sizeof(void*)); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ + *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) +#else /* little endian */ +#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) +#endif + X(0); + X(1); + X(2); + X(3); + X(4); +#undef X +} + +static byte * +rmd160_read( void *context ) +{ + RMD160_CONTEXT *hd = context; + + return hd->buf; +} + + + +/**************** + * Shortcut functions which puts the hash value of the supplied buffer + * into outbuf which must have a size of 20 bytes. + */ +void +_gcry_rmd160_hash_buffer (void *outbuf, const void *buffer, size_t length ) +{ + RMD160_CONTEXT hd; + + _gcry_rmd160_init ( &hd ); + rmd160_write ( &hd, buffer, length ); + rmd160_final ( &hd ); + memcpy ( outbuf, hd.buf, 20 ); +} + +static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; + +static gcry_md_oid_spec_t oid_spec_rmd160[] = + { + /* rsaSignatureWithripemd160 */ + { "1.3.36.3.3.1.2" }, + /* TeleTrust hash algorithm. */ + { "1.3.36.3.2.1" }, + { NULL } + }; + +gcry_md_spec_t _gcry_digest_spec_rmd160 = + { + "RIPEMD160", asn, DIM (asn), oid_spec_rmd160, 20, + _gcry_rmd160_init, rmd160_write, rmd160_final, rmd160_read, + sizeof (RMD160_CONTEXT) + }; diff --git a/grub-core/lib/libgcrypt/cipher/rsa.c b/grub-core/lib/libgcrypt/cipher/rsa.c new file mode 100644 index 0000000..ccc9f96 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/rsa.c @@ -0,0 +1,1390 @@ +/* rsa.c - RSA implementation + * Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn) + * Copyright (C) 2000, 2001, 2002, 2003, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* This code uses an algorithm protected by U.S. Patent #4,405,829 + which expired on September 20, 2000. The patent holder placed that + patent into the public domain on Sep 6th, 2000. +*/ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "g10lib.h" +#include "mpi.h" +#include "cipher.h" + + +typedef struct +{ + gcry_mpi_t n; /* modulus */ + gcry_mpi_t e; /* exponent */ +} RSA_public_key; + + +typedef struct +{ + gcry_mpi_t n; /* public modulus */ + gcry_mpi_t e; /* public exponent */ + gcry_mpi_t d; /* exponent */ + gcry_mpi_t p; /* prime p. */ + gcry_mpi_t q; /* prime q. */ + gcry_mpi_t u; /* inverse of p mod q. */ +} RSA_secret_key; + + +/* A sample 1024 bit RSA key used for the selftests. */ +static const char sample_secret_key[] = +"(private-key" +" (rsa" +" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" +" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" +" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" +" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)" +" (e #010001#)" +" (d #046129f2489d71579be0a75fe029bd6cdb574ebf57ea8a5b0fda942cab943b11" +" 7d7bb95e5d28875e0f9fc5fcc06a72f6d502464dabded78ef6b716177b83d5bd" +" c543dc5d3fed932e59f5897e92e6f58a0f33424106a3b6fa2cbf877510e4ac21" +" c3ee47851e97d12996222ac3566d4ccb0b83d164074abf7de655fc2446da1781#)" +" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" +" fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)" +" (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9" +" 35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)" +" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" +" ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)))"; +/* A sample 1024 bit RSA key used for the selftests (public only). */ +static const char sample_public_key[] = +"(public-key" +" (rsa" +" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" +" 2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" +" ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" +" 891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)" +" (e #010001#)))"; + + + + +static int test_keys (RSA_secret_key *sk, unsigned nbits); +static int check_secret_key (RSA_secret_key *sk); +static void public (gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *skey); +static void secret (gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey); + + +/* Check that a freshly generated key actually works. Returns 0 on success. */ +static int +test_keys (RSA_secret_key *sk, unsigned int nbits) +{ + int result = -1; /* Default to failure. */ + RSA_public_key pk; + gcry_mpi_t plaintext = gcry_mpi_new (nbits); + gcry_mpi_t ciphertext = gcry_mpi_new (nbits); + gcry_mpi_t decr_plaintext = gcry_mpi_new (nbits); + gcry_mpi_t signature = gcry_mpi_new (nbits); + + /* Put the relevant parameters into a public key structure. */ + pk.n = sk->n; + pk.e = sk->e; + + /* Create a random plaintext. */ + gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM); + + /* Encrypt using the public key. */ + public (ciphertext, plaintext, &pk); + + /* Check that the cipher text does not match the plaintext. */ + if (!gcry_mpi_cmp (ciphertext, plaintext)) + goto leave; /* Ciphertext is identical to the plaintext. */ + + /* Decrypt using the secret key. */ + secret (decr_plaintext, ciphertext, sk); + + /* Check that the decrypted plaintext matches the original plaintext. */ + if (gcry_mpi_cmp (decr_plaintext, plaintext)) + goto leave; /* Plaintext does not match. */ + + /* Create another random plaintext as data for signature checking. */ + gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM); + + /* Use the RSA secret function to create a signature of the plaintext. */ + secret (signature, plaintext, sk); + + /* Use the RSA public function to verify this signature. */ + public (decr_plaintext, signature, &pk); + if (gcry_mpi_cmp (decr_plaintext, plaintext)) + goto leave; /* Signature does not match. */ + + /* Modify the signature and check that the signing fails. */ + gcry_mpi_add_ui (signature, signature, 1); + public (decr_plaintext, signature, &pk); + if (!gcry_mpi_cmp (decr_plaintext, plaintext)) + goto leave; /* Signature matches but should not. */ + + result = 0; /* All tests succeeded. */ + + leave: + gcry_mpi_release (signature); + gcry_mpi_release (decr_plaintext); + gcry_mpi_release (ciphertext); + gcry_mpi_release (plaintext); + return result; +} + + +/* Callback used by the prime generation to test whether the exponent + is suitable. Returns 0 if the test has been passed. */ +static int +check_exponent (void *arg, gcry_mpi_t a) +{ + gcry_mpi_t e = arg; + gcry_mpi_t tmp; + int result; + + mpi_sub_ui (a, a, 1); + tmp = _gcry_mpi_alloc_like (a); + result = !gcry_mpi_gcd(tmp, e, a); /* GCD is not 1. */ + gcry_mpi_release (tmp); + mpi_add_ui (a, a, 1); + return result; +} + +/**************** + * Generate a key pair with a key of size NBITS. + * USE_E = 0 let Libcgrypt decide what exponent to use. + * = 1 request the use of a "secure" exponent; this is required by some + * specification to be 65537. + * > 2 Use this public exponent. If the given exponent + * is not odd one is internally added to it. + * TRANSIENT_KEY: If true, generate the primes using the standard RNG. + * Returns: 2 structures filled with all needed values + */ +static gpg_err_code_t +generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e, + int transient_key) +{ + gcry_mpi_t p, q; /* the two primes */ + gcry_mpi_t d; /* the private key */ + gcry_mpi_t u; + gcry_mpi_t t1, t2; + gcry_mpi_t n; /* the public key */ + gcry_mpi_t e; /* the exponent */ + gcry_mpi_t phi; /* helper: (p-1)(q-1) */ + gcry_mpi_t g; + gcry_mpi_t f; + gcry_random_level_t random_level; + + if (fips_mode ()) + { + if (nbits < 1024) + return GPG_ERR_INV_VALUE; + if (transient_key) + return GPG_ERR_INV_VALUE; + } + + /* The random quality depends on the transient_key flag. */ + random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; + + /* Make sure that nbits is even so that we generate p, q of equal size. */ + if ( (nbits&1) ) + nbits++; + + if (use_e == 1) /* Alias for a secure value */ + use_e = 65537; /* as demanded by Sphinx. */ + + /* Public exponent: + In general we use 41 as this is quite fast and more secure than the + commonly used 17. Benchmarking the RSA verify function + with a 1024 bit key yields (2001-11-08): + e=17 0.54 ms + e=41 0.75 ms + e=257 0.95 ms + e=65537 1.80 ms + */ + e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); + if (!use_e) + mpi_set_ui (e, 41); /* This is a reasonable secure and fast value */ + else + { + use_e |= 1; /* make sure this is odd */ + mpi_set_ui (e, use_e); + } + + n = gcry_mpi_new (nbits); + + p = q = NULL; + do + { + /* select two (very secret) primes */ + if (p) + gcry_mpi_release (p); + if (q) + gcry_mpi_release (q); + if (use_e) + { /* Do an extra test to ensure that the given exponent is + suitable. */ + p = _gcry_generate_secret_prime (nbits/2, random_level, + check_exponent, e); + q = _gcry_generate_secret_prime (nbits/2, random_level, + check_exponent, e); + } + else + { /* We check the exponent later. */ + p = _gcry_generate_secret_prime (nbits/2, random_level, NULL, NULL); + q = _gcry_generate_secret_prime (nbits/2, random_level, NULL, NULL); + } + if (mpi_cmp (p, q) > 0 ) /* p shall be smaller than q (for calc of u)*/ + mpi_swap(p,q); + /* calculate the modulus */ + mpi_mul( n, p, q ); + } + while ( mpi_get_nbits(n) != nbits ); + + /* calculate Euler totient: phi = (p-1)(q-1) */ + t1 = mpi_alloc_secure( mpi_get_nlimbs(p) ); + t2 = mpi_alloc_secure( mpi_get_nlimbs(p) ); + phi = gcry_mpi_snew ( nbits ); + g = gcry_mpi_snew ( nbits ); + f = gcry_mpi_snew ( nbits ); + mpi_sub_ui( t1, p, 1 ); + mpi_sub_ui( t2, q, 1 ); + mpi_mul( phi, t1, t2 ); + gcry_mpi_gcd(g, t1, t2); + mpi_fdiv_q(f, phi, g); + + while (!gcry_mpi_gcd(t1, e, phi)) /* (while gcd is not 1) */ + { + if (use_e) + BUG (); /* The prime generator already made sure that we + never can get to here. */ + mpi_add_ui (e, e, 2); + } + + /* calculate the secret key d = e^1 mod phi */ + d = gcry_mpi_snew ( nbits ); + mpi_invm(d, e, f ); + /* calculate the inverse of p and q (used for chinese remainder theorem)*/ + u = gcry_mpi_snew ( nbits ); + mpi_invm(u, p, q ); + + if( DBG_CIPHER ) + { + log_mpidump(" p= ", p ); + log_mpidump(" q= ", q ); + log_mpidump("phi= ", phi ); + log_mpidump(" g= ", g ); + log_mpidump(" f= ", f ); + log_mpidump(" n= ", n ); + log_mpidump(" e= ", e ); + log_mpidump(" d= ", d ); + log_mpidump(" u= ", u ); + } + + gcry_mpi_release (t1); + gcry_mpi_release (t2); + gcry_mpi_release (phi); + gcry_mpi_release (f); + gcry_mpi_release (g); + + sk->n = n; + sk->e = e; + sk->p = p; + sk->q = q; + sk->d = d; + sk->u = u; + + /* Now we can test our keys. */ + if (test_keys (sk, nbits - 64)) + { + gcry_mpi_release (sk->n); sk->n = NULL; + gcry_mpi_release (sk->e); sk->e = NULL; + gcry_mpi_release (sk->p); sk->p = NULL; + gcry_mpi_release (sk->q); sk->q = NULL; + gcry_mpi_release (sk->d); sk->d = NULL; + gcry_mpi_release (sk->u); sk->u = NULL; + fips_signal_error ("self-test after key generation failed"); + return GPG_ERR_SELFTEST_FAILED; + } + + return 0; +} + + +/* Helper for generate_x931. */ +static gcry_mpi_t +gen_x931_parm_xp (unsigned int nbits) +{ + gcry_mpi_t xp; + + xp = gcry_mpi_snew (nbits); + gcry_mpi_randomize (xp, nbits, GCRY_VERY_STRONG_RANDOM); + + /* The requirement for Xp is: + + sqrt{2}*2^{nbits-1} <= xp <= 2^{nbits} - 1 + + We set the two high order bits to 1 to satisfy the lower bound. + By using mpi_set_highbit we make sure that the upper bound is + satisfied as well. */ + mpi_set_highbit (xp, nbits-1); + mpi_set_bit (xp, nbits-2); + gcry_assert ( mpi_get_nbits (xp) == nbits ); + + return xp; +} + + +/* Helper for generate_x931. */ +static gcry_mpi_t +gen_x931_parm_xi (void) +{ + gcry_mpi_t xi; + + xi = gcry_mpi_snew (101); + gcry_mpi_randomize (xi, 101, GCRY_VERY_STRONG_RANDOM); + mpi_set_highbit (xi, 100); + gcry_assert ( mpi_get_nbits (xi) == 101 ); + + return xi; +} + + + +/* Variant of the standard key generation code using the algorithm + from X9.31. Using this algorithm has the advantage that the + generation can be made deterministic which is required for CAVS + testing. */ +static gpg_err_code_t +generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value, + gcry_sexp_t deriveparms, int *swapped) +{ + gcry_mpi_t p, q; /* The two primes. */ + gcry_mpi_t e; /* The public exponent. */ + gcry_mpi_t n; /* The public key. */ + gcry_mpi_t d; /* The private key */ + gcry_mpi_t u; /* The inverse of p and q. */ + gcry_mpi_t pm1; /* p - 1 */ + gcry_mpi_t qm1; /* q - 1 */ + gcry_mpi_t phi; /* Euler totient. */ + gcry_mpi_t f, g; /* Helper. */ + + *swapped = 0; + + if (e_value == 1) /* Alias for a secure value. */ + e_value = 65537; + + /* Point 1 of section 4.1: k = 1024 + 256s with S >= 0 */ + if (nbits < 1024 || (nbits % 256)) + return GPG_ERR_INV_VALUE; + + /* Point 2: 2 <= bitlength(e) < 2^{k-2} + Note that we do not need to check the upper bound because we use + an unsigned long for E and thus there is no way for E to reach + that limit. */ + if (e_value < 3) + return GPG_ERR_INV_VALUE; + + /* Our implementaion requires E to be odd. */ + if (!(e_value & 1)) + return GPG_ERR_INV_VALUE; + + /* Point 3: e > 0 or e 0 if it is to be randomly generated. + We support only a fixed E and thus there is no need for an extra test. */ + + + /* Compute or extract the derive parameters. */ + { + gcry_mpi_t xp1 = NULL; + gcry_mpi_t xp2 = NULL; + gcry_mpi_t xp = NULL; + gcry_mpi_t xq1 = NULL; + gcry_mpi_t xq2 = NULL; + gcry_mpi_t xq = NULL; + gcry_mpi_t tmpval; + + if (!deriveparms) + { + /* Not given: Generate them. */ + xp = gen_x931_parm_xp (nbits/2); + /* Make sure that |xp - xq| > 2^{nbits - 100} holds. */ + tmpval = gcry_mpi_snew (nbits/2); + do + { + gcry_mpi_release (xq); + xq = gen_x931_parm_xp (nbits/2); + mpi_sub (tmpval, xp, xq); + } + while (mpi_get_nbits (tmpval) <= (nbits/2 - 100)); + gcry_mpi_release (tmpval); + + xp1 = gen_x931_parm_xi (); + xp2 = gen_x931_parm_xi (); + xq1 = gen_x931_parm_xi (); + xq2 = gen_x931_parm_xi (); + + } + else + { + /* Parameters to derive the key are given. */ + /* Note that we explicitly need to setup the values of tbl + because some compilers (e.g. OpenWatcom, IRIX) don't allow + to initialize a structure with automatic variables. */ + struct { const char *name; gcry_mpi_t *value; } tbl[] = { + { "Xp1" }, + { "Xp2" }, + { "Xp" }, + { "Xq1" }, + { "Xq2" }, + { "Xq" }, + { NULL } + }; + int idx; + gcry_sexp_t oneparm; + + tbl[0].value = &xp1; + tbl[1].value = &xp2; + tbl[2].value = &xp; + tbl[3].value = &xq1; + tbl[4].value = &xq2; + tbl[5].value = &xq; + + for (idx=0; tbl[idx].name; idx++) + { + oneparm = gcry_sexp_find_token (deriveparms, tbl[idx].name, 0); + if (oneparm) + { + *tbl[idx].value = gcry_sexp_nth_mpi (oneparm, 1, + GCRYMPI_FMT_USG); + gcry_sexp_release (oneparm); + } + } + for (idx=0; tbl[idx].name; idx++) + if (!*tbl[idx].value) + break; + if (tbl[idx].name) + { + /* At least one parameter is missing. */ + for (idx=0; tbl[idx].name; idx++) + gcry_mpi_release (*tbl[idx].value); + return GPG_ERR_MISSING_VALUE; + } + } + + e = mpi_alloc_set_ui (e_value); + + /* Find two prime numbers. */ + p = _gcry_derive_x931_prime (xp, xp1, xp2, e, NULL, NULL); + q = _gcry_derive_x931_prime (xq, xq1, xq2, e, NULL, NULL); + gcry_mpi_release (xp); xp = NULL; + gcry_mpi_release (xp1); xp1 = NULL; + gcry_mpi_release (xp2); xp2 = NULL; + gcry_mpi_release (xq); xq = NULL; + gcry_mpi_release (xq1); xq1 = NULL; + gcry_mpi_release (xq2); xq2 = NULL; + if (!p || !q) + { + gcry_mpi_release (p); + gcry_mpi_release (q); + gcry_mpi_release (e); + return GPG_ERR_NO_PRIME; + } + } + + + /* Compute the public modulus. We make sure that p is smaller than + q to allow the use of the CRT. */ + if (mpi_cmp (p, q) > 0 ) + { + mpi_swap (p, q); + *swapped = 1; + } + n = gcry_mpi_new (nbits); + mpi_mul (n, p, q); + + /* Compute the Euler totient: phi = (p-1)(q-1) */ + pm1 = gcry_mpi_snew (nbits/2); + qm1 = gcry_mpi_snew (nbits/2); + phi = gcry_mpi_snew (nbits); + mpi_sub_ui (pm1, p, 1); + mpi_sub_ui (qm1, q, 1); + mpi_mul (phi, pm1, qm1); + + g = gcry_mpi_snew (nbits); + gcry_assert (gcry_mpi_gcd (g, e, phi)); + + /* Compute: f = lcm(p-1,q-1) = phi / gcd(p-1,q-1) */ + gcry_mpi_gcd (g, pm1, qm1); + f = pm1; pm1 = NULL; + gcry_mpi_release (qm1); qm1 = NULL; + mpi_fdiv_q (f, phi, g); + gcry_mpi_release (phi); phi = NULL; + d = g; g = NULL; + /* Compute the secret key: d = e^{-1} mod lcm(p-1,q-1) */ + mpi_invm (d, e, f); + + /* Compute the inverse of p and q. */ + u = f; f = NULL; + mpi_invm (u, p, q ); + + if( DBG_CIPHER ) + { + if (*swapped) + log_debug ("p and q are swapped\n"); + log_mpidump(" p", p ); + log_mpidump(" q", q ); + log_mpidump(" n", n ); + log_mpidump(" e", e ); + log_mpidump(" d", d ); + log_mpidump(" u", u ); + } + + + sk->n = n; + sk->e = e; + sk->p = p; + sk->q = q; + sk->d = d; + sk->u = u; + + /* Now we can test our keys. */ + if (test_keys (sk, nbits - 64)) + { + gcry_mpi_release (sk->n); sk->n = NULL; + gcry_mpi_release (sk->e); sk->e = NULL; + gcry_mpi_release (sk->p); sk->p = NULL; + gcry_mpi_release (sk->q); sk->q = NULL; + gcry_mpi_release (sk->d); sk->d = NULL; + gcry_mpi_release (sk->u); sk->u = NULL; + fips_signal_error ("self-test after key generation failed"); + return GPG_ERR_SELFTEST_FAILED; + } + + return 0; +} + + +/**************** + * Test whether the secret key is valid. + * Returns: true if this is a valid key. + */ +static int +check_secret_key( RSA_secret_key *sk ) +{ + int rc; + gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 ); + + mpi_mul(temp, sk->p, sk->q ); + rc = mpi_cmp( temp, sk->n ); + mpi_free(temp); + return !rc; +} + + + +/**************** + * Public key operation. Encrypt INPUT with PKEY and put result into OUTPUT. + * + * c = m^e mod n + * + * Where c is OUTPUT, m is INPUT and e,n are elements of PKEY. + */ +static void +public(gcry_mpi_t output, gcry_mpi_t input, RSA_public_key *pkey ) +{ + if( output == input ) /* powm doesn't like output and input the same */ + { + gcry_mpi_t x = mpi_alloc( mpi_get_nlimbs(input)*2 ); + mpi_powm( x, input, pkey->e, pkey->n ); + mpi_set(output, x); + mpi_free(x); + } + else + mpi_powm( output, input, pkey->e, pkey->n ); +} + +#if 0 +static void +stronger_key_check ( RSA_secret_key *skey ) +{ + gcry_mpi_t t = mpi_alloc_secure ( 0 ); + gcry_mpi_t t1 = mpi_alloc_secure ( 0 ); + gcry_mpi_t t2 = mpi_alloc_secure ( 0 ); + gcry_mpi_t phi = mpi_alloc_secure ( 0 ); + + /* check that n == p * q */ + mpi_mul( t, skey->p, skey->q); + if (mpi_cmp( t, skey->n) ) + log_info ( "RSA Oops: n != p * q\n" ); + + /* check that p is less than q */ + if( mpi_cmp( skey->p, skey->q ) > 0 ) + { + log_info ("RSA Oops: p >= q - fixed\n"); + _gcry_mpi_swap ( skey->p, skey->q); + } + + /* check that e divides neither p-1 nor q-1 */ + mpi_sub_ui(t, skey->p, 1 ); + mpi_fdiv_r(t, t, skey->e ); + if ( !mpi_cmp_ui( t, 0) ) + log_info ( "RSA Oops: e divides p-1\n" ); + mpi_sub_ui(t, skey->q, 1 ); + mpi_fdiv_r(t, t, skey->e ); + if ( !mpi_cmp_ui( t, 0) ) + log_info ( "RSA Oops: e divides q-1\n" ); + + /* check that d is correct */ + mpi_sub_ui( t1, skey->p, 1 ); + mpi_sub_ui( t2, skey->q, 1 ); + mpi_mul( phi, t1, t2 ); + gcry_mpi_gcd(t, t1, t2); + mpi_fdiv_q(t, phi, t); + mpi_invm(t, skey->e, t ); + if ( mpi_cmp(t, skey->d ) ) + { + log_info ( "RSA Oops: d is wrong - fixed\n"); + mpi_set (skey->d, t); + _gcry_log_mpidump (" fixed d", skey->d); + } + + /* check for correctness of u */ + mpi_invm(t, skey->p, skey->q ); + if ( mpi_cmp(t, skey->u ) ) + { + log_info ( "RSA Oops: u is wrong - fixed\n"); + mpi_set (skey->u, t); + _gcry_log_mpidump (" fixed u", skey->u); + } + + log_info ( "RSA secret key check finished\n"); + + mpi_free (t); + mpi_free (t1); + mpi_free (t2); + mpi_free (phi); +} +#endif + + + +/**************** + * Secret key operation. Encrypt INPUT with SKEY and put result into OUTPUT. + * + * m = c^d mod n + * + * Or faster: + * + * m1 = c ^ (d mod (p-1)) mod p + * m2 = c ^ (d mod (q-1)) mod q + * h = u * (m2 - m1) mod q + * m = m1 + h * p + * + * Where m is OUTPUT, c is INPUT and d,n,p,q,u are elements of SKEY. + */ +static void +secret(gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey ) +{ + if (!skey->p || !skey->q || !skey->u) + { + mpi_powm (output, input, skey->d, skey->n); + } + else + { + gcry_mpi_t m1 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); + gcry_mpi_t m2 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); + gcry_mpi_t h = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); + + /* m1 = c ^ (d mod (p-1)) mod p */ + mpi_sub_ui( h, skey->p, 1 ); + mpi_fdiv_r( h, skey->d, h ); + mpi_powm( m1, input, h, skey->p ); + /* m2 = c ^ (d mod (q-1)) mod q */ + mpi_sub_ui( h, skey->q, 1 ); + mpi_fdiv_r( h, skey->d, h ); + mpi_powm( m2, input, h, skey->q ); + /* h = u * ( m2 - m1 ) mod q */ + mpi_sub( h, m2, m1 ); + if ( mpi_is_neg( h ) ) + mpi_add ( h, h, skey->q ); + mpi_mulm( h, skey->u, h, skey->q ); + /* m = m2 + h * p */ + mpi_mul ( h, h, skey->p ); + mpi_add ( output, m1, h ); + + mpi_free ( h ); + mpi_free ( m1 ); + mpi_free ( m2 ); + } +} + + + +/* Perform RSA blinding. */ +static gcry_mpi_t +rsa_blind (gcry_mpi_t x, gcry_mpi_t r, gcry_mpi_t e, gcry_mpi_t n) +{ + /* A helper. */ + gcry_mpi_t a; + + /* Result. */ + gcry_mpi_t y; + + a = gcry_mpi_snew (gcry_mpi_get_nbits (n)); + y = gcry_mpi_snew (gcry_mpi_get_nbits (n)); + + /* Now we calculate: y = (x * r^e) mod n, where r is the random + number, e is the public exponent, x is the non-blinded data and n + is the RSA modulus. */ + gcry_mpi_powm (a, r, e, n); + gcry_mpi_mulm (y, a, x, n); + + gcry_mpi_release (a); + + return y; +} + +/* Undo RSA blinding. */ +static gcry_mpi_t +rsa_unblind (gcry_mpi_t x, gcry_mpi_t ri, gcry_mpi_t n) +{ + gcry_mpi_t y; + + y = gcry_mpi_snew (gcry_mpi_get_nbits (n)); + + /* Here we calculate: y = (x * r^-1) mod n, where x is the blinded + decrypted data, ri is the modular multiplicative inverse of r and + n is the RSA modulus. */ + + gcry_mpi_mulm (y, ri, x, n); + + return y; +} + +/********************************************* + ************** interface ****************** + *********************************************/ + +static gcry_err_code_t +rsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, + const gcry_sexp_t genparms, + gcry_mpi_t *skey, gcry_mpi_t **retfactors, + gcry_sexp_t *r_extrainfo) +{ + RSA_secret_key sk; + gpg_err_code_t ec; + gcry_sexp_t deriveparms; + int transient_key = 0; + int use_x931 = 0; + gcry_sexp_t l1; + + (void)algo; + + *retfactors = NULL; /* We don't return them. */ + + deriveparms = (genparms? + gcry_sexp_find_token (genparms, "derive-parms", 0) : NULL); + if (!deriveparms) + { + /* Parse the optional "use-x931" flag. */ + l1 = gcry_sexp_find_token (genparms, "use-x931", 0); + if (l1) + { + use_x931 = 1; + gcry_sexp_release (l1); + } + } + + if (deriveparms || use_x931 || fips_mode ()) + { + int swapped; + ec = generate_x931 (&sk, nbits, evalue, deriveparms, &swapped); + gcry_sexp_release (deriveparms); + if (!ec && r_extrainfo && swapped) + { + ec = gcry_sexp_new (r_extrainfo, + "(misc-key-info(p-q-swapped))", 0, 1); + if (ec) + { + gcry_mpi_release (sk.n); sk.n = NULL; + gcry_mpi_release (sk.e); sk.e = NULL; + gcry_mpi_release (sk.p); sk.p = NULL; + gcry_mpi_release (sk.q); sk.q = NULL; + gcry_mpi_release (sk.d); sk.d = NULL; + gcry_mpi_release (sk.u); sk.u = NULL; + } + } + } + else + { + /* Parse the optional "transient-key" flag. */ + l1 = gcry_sexp_find_token (genparms, "transient-key", 0); + if (l1) + { + transient_key = 1; + gcry_sexp_release (l1); + } + /* Generate. */ + ec = generate_std (&sk, nbits, evalue, transient_key); + } + + if (!ec) + { + skey[0] = sk.n; + skey[1] = sk.e; + skey[2] = sk.d; + skey[3] = sk.p; + skey[4] = sk.q; + skey[5] = sk.u; + } + + return ec; +} + + +static gcry_err_code_t +rsa_generate (int algo, unsigned int nbits, unsigned long evalue, + gcry_mpi_t *skey, gcry_mpi_t **retfactors) +{ + return rsa_generate_ext (algo, nbits, evalue, NULL, skey, retfactors, NULL); +} + + +static gcry_err_code_t +rsa_check_secret_key (int algo, gcry_mpi_t *skey) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + RSA_secret_key sk; + + (void)algo; + + sk.n = skey[0]; + sk.e = skey[1]; + sk.d = skey[2]; + sk.p = skey[3]; + sk.q = skey[4]; + sk.u = skey[5]; + + if (!sk.p || !sk.q || !sk.u) + err = GPG_ERR_NO_OBJ; /* To check the key we need the optional + parameters. */ + else if (!check_secret_key (&sk)) + err = GPG_ERR_BAD_SECKEY; + + return err; +} + + +static gcry_err_code_t +rsa_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, + gcry_mpi_t *pkey, int flags) +{ + RSA_public_key pk; + + (void)algo; + (void)flags; + + pk.n = pkey[0]; + pk.e = pkey[1]; + resarr[0] = mpi_alloc (mpi_get_nlimbs (pk.n)); + public (resarr[0], data, &pk); + + return GPG_ERR_NO_ERROR; +} + + +static gcry_err_code_t +rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, + gcry_mpi_t *skey, int flags) +{ + RSA_secret_key sk; + gcry_mpi_t r = MPI_NULL; /* Random number needed for blinding. */ + gcry_mpi_t ri = MPI_NULL; /* Modular multiplicative inverse of + r. */ + gcry_mpi_t x = MPI_NULL; /* Data to decrypt. */ + gcry_mpi_t y; /* Result. */ + + (void)algo; + + /* Extract private key. */ + sk.n = skey[0]; + sk.e = skey[1]; + sk.d = skey[2]; + sk.p = skey[3]; /* Optional. */ + sk.q = skey[4]; /* Optional. */ + sk.u = skey[5]; /* Optional. */ + + y = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); + + /* We use blinding by default to mitigate timing attacks which can + be practically mounted over the network as shown by Brumley and + Boney in 2003. */ + if (! (flags & PUBKEY_FLAG_NO_BLINDING)) + { + /* Initialize blinding. */ + + /* First, we need a random number r between 0 and n - 1, which + is relatively prime to n (i.e. it is neither p nor q). The + random number needs to be only unpredictable, thus we employ + the gcry_create_nonce function by using GCRY_WEAK_RANDOM with + gcry_mpi_randomize. */ + r = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); + ri = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); + + gcry_mpi_randomize (r, gcry_mpi_get_nbits (sk.n), GCRY_WEAK_RANDOM); + gcry_mpi_mod (r, r, sk.n); + + /* Calculate inverse of r. It practically impossible that the + following test fails, thus we do not add code to release + allocated resources. */ + if (!gcry_mpi_invm (ri, r, sk.n)) + return GPG_ERR_INTERNAL; + } + + if (! (flags & PUBKEY_FLAG_NO_BLINDING)) + x = rsa_blind (data[0], r, sk.e, sk.n); + else + x = data[0]; + + /* Do the encryption. */ + secret (y, x, &sk); + + if (! (flags & PUBKEY_FLAG_NO_BLINDING)) + { + /* Undo blinding. */ + gcry_mpi_t a = gcry_mpi_copy (y); + + gcry_mpi_release (y); + y = rsa_unblind (a, ri, sk.n); + + gcry_mpi_release (a); + } + + if (! (flags & PUBKEY_FLAG_NO_BLINDING)) + { + /* Deallocate resources needed for blinding. */ + gcry_mpi_release (x); + gcry_mpi_release (r); + gcry_mpi_release (ri); + } + + /* Copy out result. */ + *result = y; + + return GPG_ERR_NO_ERROR; +} + + +static gcry_err_code_t +rsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) +{ + RSA_secret_key sk; + + (void)algo; + + sk.n = skey[0]; + sk.e = skey[1]; + sk.d = skey[2]; + sk.p = skey[3]; + sk.q = skey[4]; + sk.u = skey[5]; + resarr[0] = mpi_alloc( mpi_get_nlimbs (sk.n)); + secret (resarr[0], data, &sk); + + return GPG_ERR_NO_ERROR; +} + + +static gcry_err_code_t +rsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, + int (*cmp) (void *opaque, gcry_mpi_t tmp), + void *opaquev) +{ + RSA_public_key pk; + gcry_mpi_t result; + gcry_err_code_t rc; + + (void)algo; + (void)cmp; + (void)opaquev; + + pk.n = pkey[0]; + pk.e = pkey[1]; + result = gcry_mpi_new ( 160 ); + public( result, data[0], &pk ); +#ifdef IS_DEVELOPMENT_VERSION + if (DBG_CIPHER) + { + log_mpidump ("rsa verify result:", result ); + log_mpidump (" hash:", hash ); + } +#endif /*IS_DEVELOPMENT_VERSION*/ + if (cmp) + rc = (*cmp) (opaquev, result); + else + rc = mpi_cmp (result, hash) ? GPG_ERR_BAD_SIGNATURE : GPG_ERR_NO_ERROR; + gcry_mpi_release (result); + + return rc; +} + + +static unsigned int +rsa_get_nbits (int algo, gcry_mpi_t *pkey) +{ + (void)algo; + + return mpi_get_nbits (pkey[0]); +} + + +/* Compute a keygrip. MD is the hash context which we are going to + update. KEYPARAM is an S-expression with the key parameters, this + is usually a public key but may also be a secret key. An example + of such an S-expression is: + + (rsa + (n #00B...#) + (e #010001#)) + + PKCS-15 says that for RSA only the modulus should be hashed - + however, it is not clear whether this is meant to use the raw bytes + (assuming this is an unsigned integer) or whether the DER required + 0 should be prefixed. We hash the raw bytes. */ +static gpg_err_code_t +compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) +{ + gcry_sexp_t l1; + const char *data; + size_t datalen; + + l1 = gcry_sexp_find_token (keyparam, "n", 1); + if (!l1) + return GPG_ERR_NO_OBJ; + + data = gcry_sexp_nth_data (l1, 1, &datalen); + if (!data) + { + gcry_sexp_release (l1); + return GPG_ERR_NO_OBJ; + } + + gcry_md_write (md, data, datalen); + gcry_sexp_release (l1); + + return 0; +} + + + + +/* + Self-test section. + */ + +static const char * +selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) +{ + static const char sample_data[] = + "(data (flags pkcs1)" + " (hash sha1 #11223344556677889900aabbccddeeff10203040#))"; + static const char sample_data_bad[] = + "(data (flags pkcs1)" + " (hash sha1 #11223344556677889900aabbccddeeff80203040#))"; + + const char *errtxt = NULL; + gcry_error_t err; + gcry_sexp_t data = NULL; + gcry_sexp_t data_bad = NULL; + gcry_sexp_t sig = NULL; + + err = gcry_sexp_sscan (&data, NULL, + sample_data, strlen (sample_data)); + if (!err) + err = gcry_sexp_sscan (&data_bad, NULL, + sample_data_bad, strlen (sample_data_bad)); + if (err) + { + errtxt = "converting data failed"; + goto leave; + } + + err = gcry_pk_sign (&sig, data, skey); + if (err) + { + errtxt = "signing failed"; + goto leave; + } + err = gcry_pk_verify (sig, data, pkey); + if (err) + { + errtxt = "verify failed"; + goto leave; + } + err = gcry_pk_verify (sig, data_bad, pkey); + if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE) + { + errtxt = "bad signature not detected"; + goto leave; + } + + + leave: + gcry_sexp_release (sig); + gcry_sexp_release (data_bad); + gcry_sexp_release (data); + return errtxt; +} + + + +/* Given an S-expression ENCR_DATA of the form: + + (enc-val + (rsa + (a a-value))) + + as returned by gcry_pk_decrypt, return the the A-VALUE. On error, + return NULL. */ +static gcry_mpi_t +extract_a_from_sexp (gcry_sexp_t encr_data) +{ + gcry_sexp_t l1, l2, l3; + gcry_mpi_t a_value; + + l1 = gcry_sexp_find_token (encr_data, "enc-val", 0); + if (!l1) + return NULL; + l2 = gcry_sexp_find_token (l1, "rsa", 0); + gcry_sexp_release (l1); + if (!l2) + return NULL; + l3 = gcry_sexp_find_token (l2, "a", 0); + gcry_sexp_release (l2); + if (!l3) + return NULL; + a_value = gcry_sexp_nth_mpi (l3, 1, 0); + gcry_sexp_release (l3); + + return a_value; +} + + +static const char * +selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) +{ + const char *errtxt = NULL; + gcry_error_t err; + const unsigned int nbits = 1000; /* Encrypt 1000 random bits. */ + gcry_mpi_t plaintext = NULL; + gcry_sexp_t plain = NULL; + gcry_sexp_t encr = NULL; + gcry_mpi_t ciphertext = NULL; + gcry_sexp_t decr = NULL; + gcry_mpi_t decr_plaintext = NULL; + gcry_sexp_t tmplist = NULL; + + /* Create plaintext. The plaintext is actually a big integer number. */ + plaintext = gcry_mpi_new (nbits); + gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM); + + /* Put the plaintext into an S-expression. */ + err = gcry_sexp_build (&plain, NULL, + "(data (flags raw) (value %m))", plaintext); + if (err) + { + errtxt = "converting data failed"; + goto leave; + } + + /* Encrypt. */ + err = gcry_pk_encrypt (&encr, plain, pkey); + if (err) + { + errtxt = "encrypt failed"; + goto leave; + } + + /* Extraxt the ciphertext from the returned S-expression. */ + /*gcry_sexp_dump (encr);*/ + ciphertext = extract_a_from_sexp (encr); + if (!ciphertext) + { + errtxt = "gcry_pk_decrypt returned garbage"; + goto leave; + } + + /* Check that the ciphertext does no match the plaintext. */ + /* _gcry_log_mpidump ("plaintext", plaintext); */ + /* _gcry_log_mpidump ("ciphertxt", ciphertext); */ + if (!gcry_mpi_cmp (plaintext, ciphertext)) + { + errtxt = "ciphertext matches plaintext"; + goto leave; + } + + /* Decrypt. */ + err = gcry_pk_decrypt (&decr, encr, skey); + if (err) + { + errtxt = "decrypt failed"; + goto leave; + } + + /* Extract the decrypted data from the S-expression. Note that the + output of gcry_pk_decrypt depends on whether a flags lists occurs + in its input data. Because we passed the output of + gcry_pk_encrypt directly to gcry_pk_decrypt, such a flag value + won't be there as of today. To be prepared for future changes we + take care of it anyway. */ + tmplist = gcry_sexp_find_token (decr, "value", 0); + if (tmplist) + decr_plaintext = gcry_sexp_nth_mpi (tmplist, 1, GCRYMPI_FMT_USG); + else + decr_plaintext = gcry_sexp_nth_mpi (decr, 0, GCRYMPI_FMT_USG); + if (!decr_plaintext) + { + errtxt = "decrypt returned no plaintext"; + goto leave; + } + + /* Check that the decrypted plaintext matches the original plaintext. */ + if (gcry_mpi_cmp (plaintext, decr_plaintext)) + { + errtxt = "mismatch"; + goto leave; + } + + leave: + gcry_sexp_release (tmplist); + gcry_mpi_release (decr_plaintext); + gcry_sexp_release (decr); + gcry_mpi_release (ciphertext); + gcry_sexp_release (encr); + gcry_sexp_release (plain); + gcry_mpi_release (plaintext); + return errtxt; +} + + +static gpg_err_code_t +selftests_rsa (selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + gcry_error_t err; + gcry_sexp_t skey = NULL; + gcry_sexp_t pkey = NULL; + + /* Convert the S-expressions into the internal representation. */ + what = "convert"; + err = gcry_sexp_sscan (&skey, NULL, + sample_secret_key, strlen (sample_secret_key)); + if (!err) + err = gcry_sexp_sscan (&pkey, NULL, + sample_public_key, strlen (sample_public_key)); + if (err) + { + errtxt = gcry_strerror (err); + goto failed; + } + + what = "key consistency"; + err = gcry_pk_testkey (skey); + if (err) + { + errtxt = gcry_strerror (err); + goto failed; + } + + what = "sign"; + errtxt = selftest_sign_1024 (pkey, skey); + if (errtxt) + goto failed; + + what = "encrypt"; + errtxt = selftest_encr_1024 (pkey, skey); + if (errtxt) + goto failed; + + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + return 0; /* Succeeded. */ + + failed: + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + if (report) + report ("pubkey", GCRY_PK_RSA, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + +/* Run a full self-test for ALGO and return 0 on success. */ +static gpg_err_code_t +run_selftests (int algo, int extended, selftest_report_func_t report) +{ + gpg_err_code_t ec; + + (void)extended; + + switch (algo) + { + case GCRY_PK_RSA: + ec = selftests_rsa (report); + break; + default: + ec = GPG_ERR_PUBKEY_ALGO; + break; + + } + return ec; +} + + + + +static const char *rsa_names[] = + { + "rsa", + "openpgp-rsa", + "oid.1.2.840.113549.1.1.1", + NULL, + }; + +gcry_pk_spec_t _gcry_pubkey_spec_rsa = + { + "RSA", rsa_names, + "ne", "nedpqu", "a", "s", "n", + GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR, + rsa_generate, + rsa_check_secret_key, + rsa_encrypt, + rsa_decrypt, + rsa_sign, + rsa_verify, + rsa_get_nbits, + }; +pk_extra_spec_t _gcry_pubkey_extraspec_rsa = + { + run_selftests, + rsa_generate_ext, + compute_keygrip + }; diff --git a/grub-core/lib/libgcrypt/cipher/seed.c b/grub-core/lib/libgcrypt/cipher/seed.c new file mode 100644 index 0000000..ae26e67 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/seed.c @@ -0,0 +1,478 @@ +/* SEED for libgcrypt + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -- + * This implementation was provided for libgcrypt in public domain + * by Hye-Shik Chang <perky@FreeBSD.org>, July 2006. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + +#define NUMKC 16 + +#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ + ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) { (ct)[0] = (byte)((st) >> 24); \ + (ct)[1] = (byte)((st) >> 16); \ + (ct)[2] = (byte)((st) >> 8); \ + (ct)[3] = (byte)(st); } + +union wordbuf +{ + u32 w; + byte b[4]; +}; + +#ifdef WORDS_BIGENDIAN +#define b0 b[3] +#define b1 b[2] +#define b2 b[1] +#define b3 b[0] +#else +#define b0 b[0] +#define b1 b[1] +#define b2 b[2] +#define b3 b[3] +#endif + +static const char *selftest(void); + +typedef struct +{ + u32 keyschedule[32]; +} SEED_context; + +static const u32 SS0[256] = { + 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, + 0x2c8ca0ac, 0x25052124, 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, + 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360, 0x28082028, 0x04444044, + 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314, + 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, + 0x12c2d2d0, 0x2ecee2ec, 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, + 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074, 0x2ccce0ec, 0x15859194, + 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100, + 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, + 0x32c2f2f0, 0x19c9d1d8, 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, + 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8, 0x20406060, 0x10405050, + 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c, + 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, + 0x2f8fa3ac, 0x15c5d1d4, 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, + 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008, 0x1f0f131c, 0x19899198, + 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0, + 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, + 0x0e0e020c, 0x2b8ba3a8, 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, + 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208, 0x3f8fb3bc, 0x2fcfe3ec, + 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064, + 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, + 0x2b4b6368, 0x26466264, 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, + 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0, 0x3a4a7278, 0x07474344, + 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc, + 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, + 0x22022220, 0x38083038, 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, + 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394, 0x35053134, 0x0bcbc3c8, + 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188, + 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, + 0x02828280, 0x04c4c0c4, 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, + 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8, 0x0f0f030c, 0x0e8e828c, + 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4, + 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, + 0x2d0d212c, 0x00404040, 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, + 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154, 0x3b0b3338, 0x1cccd0dc, + 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254, + 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, + 0x25456164, 0x3acaf2f8, 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, + 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0, 0x31013130, 0x2acae2e8, + 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088, + 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, + 0x07070304, 0x33033330, 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, + 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298, +}; + +static const u32 SS1[256] = { + 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, + 0xb03383b3, 0xb83888b0, 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, + 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53, 0xc003c3c3, 0x60224262, + 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3, + 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, + 0x34360632, 0x480b4b43, 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, + 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0, 0xc002c2c2, 0x44054541, + 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890, + 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, + 0x0c0d0d01, 0xdc1fcfd3, 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, + 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272, 0x40024242, 0xd414c4d0, + 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83, + 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, + 0xa82a8aa2, 0x34340430, 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, + 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0, 0x54174753, 0xac2e8ea2, + 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1, + 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, + 0x682a4a62, 0xb03181b1, 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, + 0x20220222, 0x04040400, 0x68284860, 0x70314171, 0x04070703, 0xd81bcbd3, + 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951, + 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, + 0xa82b8ba3, 0xd010c0d0, 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, + 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3, 0x94168692, 0x783b4b73, + 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41, + 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, + 0xb83a8ab2, 0x6c2e4e62, 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, + 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0, 0x14150511, 0xf83bcbf3, + 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303, + 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, + 0xe82acae2, 0x08090901, 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, + 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501, 0xf83acaf2, 0x00010101, + 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343, + 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, + 0x48084840, 0x78394971, 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, + 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53, 0x74374773, 0x54144450, + 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642, + 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, + 0xc809c9c1, 0xfc3dcdf1, 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, + 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70, 0x0c0e0e02, 0x50104050, + 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393, + 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, + 0x080a0a02, 0x84078783, 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, + 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3, +}; + +static const u32 SS2[256] = { + 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, + 0xa0ac2c8c, 0x21242505, 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, + 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343, 0x20282808, 0x40440444, + 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707, + 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, + 0xd2d012c2, 0xe2ec2ece, 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, + 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444, 0xe0ec2ccc, 0x91941585, + 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101, + 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, + 0xf2f032c2, 0xd1d819c9, 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, + 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9, 0x60602040, 0x50501040, + 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f, + 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, + 0xa3ac2f8f, 0xd1d415c5, 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, + 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808, 0x131c1f0f, 0x91981989, + 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1, + 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, + 0x020c0e0e, 0xa3a82b8b, 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, + 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a, 0xb3bc3f8f, 0xe3ec2fcf, + 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444, + 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, + 0x63682b4b, 0x62642646, 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, + 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0, 0x72783a4a, 0x43440747, + 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf, + 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, + 0x22202202, 0x30383808, 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, + 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787, 0x31343505, 0xc3c80bcb, + 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989, + 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, + 0x82800282, 0xc0c404c4, 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, + 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888, 0x030c0f0f, 0x828c0e8e, + 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484, + 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, + 0x212c2d0d, 0x40400040, 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, + 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545, 0x33383b0b, 0xd0dc1ccc, + 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646, + 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, + 0x61642545, 0xf2f83aca, 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, + 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282, 0x31303101, 0xe2e82aca, + 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888, + 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, + 0x03040707, 0x33303303, 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, + 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a, +}; + +static const u32 SS3[256] = { + 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, + 0x83b3b033, 0x88b0b838, 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, + 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b, 0xc3c3c003, 0x42626022, + 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427, + 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, + 0x06323436, 0x4b43480b, 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, + 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434, 0xc2c2c002, 0x45414405, + 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818, + 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, + 0x0d010c0d, 0xcfd3dc1f, 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, + 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032, 0x42424002, 0xc4d0d414, + 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b, + 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, + 0x8aa2a82a, 0x04303434, 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, + 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838, 0x47535417, 0x8ea2ac2e, + 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839, + 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, + 0x4a62682a, 0x81b1b031, 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, + 0x02222022, 0x04000404, 0x48606828, 0x41717031, 0x07030407, 0xcbd3d81b, + 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819, + 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, + 0x8ba3a82b, 0xc0d0d010, 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, + 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f, 0x86929416, 0x4b73783b, + 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d, + 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, + 0x8ab2b83a, 0x4e626c2e, 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, + 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c, 0x05111415, 0xcbf3f83b, + 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003, + 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, + 0xcae2e82a, 0x09010809, 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, + 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405, 0xcaf2f83a, 0x01010001, + 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003, + 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, + 0x48404808, 0x49717839, 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, + 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f, 0x47737437, 0x44505414, + 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406, + 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, + 0xc9c1c809, 0xcdf1fc3d, 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, + 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c, 0x0e020c0e, 0x40505010, + 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013, + 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, + 0x0a02080a, 0x87838407, 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, + 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437, +}; + +static const u32 KC[NUMKC] = { + 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc, + 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf, + 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1, + 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b, +}; + + + +/* Perform the key setup. + */ +static gcry_err_code_t +do_setkey (SEED_context *ctx, const byte *key, const unsigned keylen) +{ + static int initialized = 0; + static const char *selftest_failed=0; + u32 x1, x2, x3, x4; + union wordbuf t0, t1; + u32 *keyout = ctx->keyschedule; + int i; + + if (!initialized) + { + initialized = 1; + selftest_failed = selftest (); + if( selftest_failed ) + log_error ("%s\n", selftest_failed ); + } + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + if (keylen != 16) + return GPG_ERR_INV_KEYLEN; + + x1 = GETU32 (key); + x2 = GETU32 (key+4); + x3 = GETU32 (key+8); + x4 = GETU32 (key+12); + + for (i = 0; i < NUMKC; i++) + { + t0.w = x1 + x3 - KC[i]; + t1.w = x2 + KC[i] - x4; + *(keyout++) = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3]; + *(keyout++) = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; + + if (i % 2 == 0) + { + t0.w = x1; + x1 = (x1>>8) ^ (x2<<24); + x2 = (x2>>8) ^ (t0.w<<24); + } + else + { + t0.w = x3; + x3 = (x3<<8) ^ (x4>>24); + x4 = (x4<<8) ^ (t0.w>>24); + } + } + + return 0; +} + +static gcry_err_code_t +seed_setkey (void *context, const byte *key, const unsigned keylen) +{ + SEED_context *ctx = context; + + int rc = do_setkey (ctx, key, keylen); + _gcry_burn_stack (4*6 + sizeof(void*)*2 + sizeof(int)*2); + return rc; +} + + + +#define OP(X1, X2, X3, X4, rbase) \ + t0.w = X3 ^ ctx->keyschedule[rbase]; \ + t1.w = X4 ^ ctx->keyschedule[rbase+1]; \ + t1.w ^= t0.w; \ + t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; \ + t0.w += t1.w; \ + t0.w = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3]; \ + t1.w += t0.w; \ + t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; \ + t0.w += t1.w; \ + X1 ^= t0.w; \ + X2 ^= t1.w; + +/* Encrypt one block. inbuf and outbuf may be the same. */ +static void +do_encrypt (const SEED_context *ctx, byte *outbuf, const byte *inbuf) +{ + u32 x1, x2, x3, x4; + union wordbuf t0, t1; + + x1 = GETU32 (inbuf); + x2 = GETU32 (inbuf+4); + x3 = GETU32 (inbuf+8); + x4 = GETU32 (inbuf+12); + + OP (x1, x2, x3, x4, 0); + OP (x3, x4, x1, x2, 2); + OP (x1, x2, x3, x4, 4); + OP (x3, x4, x1, x2, 6); + OP (x1, x2, x3, x4, 8); + OP (x3, x4, x1, x2, 10); + OP (x1, x2, x3, x4, 12); + OP (x3, x4, x1, x2, 14); + OP (x1, x2, x3, x4, 16); + OP (x3, x4, x1, x2, 18); + OP (x1, x2, x3, x4, 20); + OP (x3, x4, x1, x2, 22); + OP (x1, x2, x3, x4, 24); + OP (x3, x4, x1, x2, 26); + OP (x1, x2, x3, x4, 28); + OP (x3, x4, x1, x2, 30); + + PUTU32 (outbuf, x3); + PUTU32 (outbuf+4, x4); + PUTU32 (outbuf+8, x1); + PUTU32 (outbuf+12, x2); +} + +static void +seed_encrypt (void *context, byte *outbuf, const byte *inbuf) +{ + SEED_context *ctx = context; + + do_encrypt (ctx, outbuf, inbuf); + _gcry_burn_stack (4*6); +} + + + +/* Decrypt one block. inbuf and outbuf may be the same. */ +static void +do_decrypt (SEED_context *ctx, byte *outbuf, const byte *inbuf) +{ + u32 x1, x2, x3, x4; + union wordbuf t0, t1; + + x1 = GETU32 (inbuf); + x2 = GETU32 (inbuf+4); + x3 = GETU32 (inbuf+8); + x4 = GETU32 (inbuf+12); + + OP (x1, x2, x3, x4, 30); + OP (x3, x4, x1, x2, 28); + OP (x1, x2, x3, x4, 26); + OP (x3, x4, x1, x2, 24); + OP (x1, x2, x3, x4, 22); + OP (x3, x4, x1, x2, 20); + OP (x1, x2, x3, x4, 18); + OP (x3, x4, x1, x2, 16); + OP (x1, x2, x3, x4, 14); + OP (x3, x4, x1, x2, 12); + OP (x1, x2, x3, x4, 10); + OP (x3, x4, x1, x2, 8); + OP (x1, x2, x3, x4, 6); + OP (x3, x4, x1, x2, 4); + OP (x1, x2, x3, x4, 2); + OP (x3, x4, x1, x2, 0); + + PUTU32 (outbuf, x3); + PUTU32 (outbuf+4, x4); + PUTU32 (outbuf+8, x1); + PUTU32 (outbuf+12, x2); +} + +static void +seed_decrypt (void *context, byte *outbuf, const byte *inbuf) +{ + SEED_context *ctx = context; + + do_decrypt (ctx, outbuf, inbuf); + _gcry_burn_stack (4*6); +} + + +/* Test a single encryption and decryption with each key size. */ +static const char* +selftest (void) +{ + SEED_context ctx; + byte scratch[16]; + + /* The test vector is taken from the appendix section B.3 of RFC4269. + */ + static const byte plaintext[16] = { + 0x83, 0xA2, 0xF8, 0xA2, 0x88, 0x64, 0x1F, 0xB9, + 0xA4, 0xE9, 0xA5, 0xCC, 0x2F, 0x13, 0x1C, 0x7D + }; + static const byte key[16] = { + 0x47, 0x06, 0x48, 0x08, 0x51, 0xE6, 0x1B, 0xE8, + 0x5D, 0x74, 0xBF, 0xB3, 0xFD, 0x95, 0x61, 0x85 + }; + static const byte ciphertext[16] = { + 0xEE, 0x54, 0xD1, 0x3E, 0xBC, 0xAE, 0x70, 0x6D, + 0x22, 0x6B, 0xC3, 0x14, 0x2C, 0xD4, 0x0D, 0x4A, + }; + + seed_setkey (&ctx, key, sizeof(key)); + seed_encrypt (&ctx, scratch, plaintext); + if (memcmp (scratch, ciphertext, sizeof (ciphertext))) + return "SEED test encryption failed."; + seed_decrypt (&ctx, scratch, scratch); + if (memcmp (scratch, plaintext, sizeof (plaintext))) + return "SEED test decryption failed."; + + return NULL; +} + + + +static gcry_cipher_oid_spec_t seed_oids[] = + { + { "1.2.410.200004.1.3", GCRY_CIPHER_MODE_ECB }, + { "1.2.410.200004.1.4", GCRY_CIPHER_MODE_CBC }, + { "1.2.410.200004.1.5", GCRY_CIPHER_MODE_CFB }, + { "1.2.410.200004.1.6", GCRY_CIPHER_MODE_OFB }, + { NULL } + }; + +gcry_cipher_spec_t _gcry_cipher_spec_seed = + { + "SEED", NULL, seed_oids, 16, 128, sizeof (SEED_context), + seed_setkey, seed_encrypt, seed_decrypt, + }; diff --git a/grub-core/lib/libgcrypt/cipher/serpent.c b/grub-core/lib/libgcrypt/cipher/serpent.c new file mode 100644 index 0000000..ea14c7e --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/serpent.c @@ -0,0 +1,953 @@ +/* serpent.c - Implementation of the Serpent encryption algorithm. + * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <config.h> + +#include <string.h> +#include <stdio.h> + +#include "types.h" +#include "g10lib.h" +#include "cipher.h" +#include "bithelp.h" + +/* Number of rounds per Serpent encrypt/decrypt operation. */ +#define ROUNDS 32 + +/* Magic number, used during generating of the subkeys. */ +#define PHI 0x9E3779B9 + +/* Serpent works on 128 bit blocks. */ +typedef u32 serpent_block_t[4]; + +/* Serpent key, provided by the user. If the original key is shorter + than 256 bits, it is padded. */ +typedef u32 serpent_key_t[8]; + +/* The key schedule consists of 33 128 bit subkeys. */ +typedef u32 serpent_subkeys_t[ROUNDS + 1][4]; + +/* A Serpent context. */ +typedef struct serpent_context +{ + serpent_subkeys_t keys; /* Generated subkeys. */ +} serpent_context_t; + + +/* A prototype. */ +static const char *serpent_test (void); + + +#define byte_swap_32(x) \ + (0 \ + | (((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \ + | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +/* These are the S-Boxes of Serpent. They are copied from Serpents + reference implementation (the optimized one, contained in + `floppy2') and are therefore: + + Copyright (C) 1998 Ross Anderson, Eli Biham, Lars Knudsen. + + To quote the Serpent homepage + (http://www.cl.cam.ac.uk/~rja14/serpent.html): + + "Serpent is now completely in the public domain, and we impose no + restrictions on its use. This was announced on the 21st August at + the First AES Candidate Conference. The optimised implementations + in the submission package are now under the GNU PUBLIC LICENSE + (GPL), although some comments in the code still say otherwise. You + are welcome to use Serpent for any application." */ + +#define SBOX0(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t05, t06, t07, t08, t09; \ + u32 t11, t12, t13, t14, t15, t17, t01; \ + t01 = b ^ c ; \ + t02 = a | d ; \ + t03 = a ^ b ; \ + z = t02 ^ t01; \ + t05 = c | z ; \ + t06 = a ^ d ; \ + t07 = b | c ; \ + t08 = d & t05; \ + t09 = t03 & t07; \ + y = t09 ^ t08; \ + t11 = t09 & y ; \ + t12 = c ^ d ; \ + t13 = t07 ^ t11; \ + t14 = b & t06; \ + t15 = t06 ^ t13; \ + w = ~ t15; \ + t17 = w ^ t14; \ + x = t12 ^ t17; \ + } + +#define SBOX0_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t08, t09, t10; \ + u32 t12, t13, t14, t15, t17, t18, t01; \ + t01 = c ^ d ; \ + t02 = a | b ; \ + t03 = b | c ; \ + t04 = c & t01; \ + t05 = t02 ^ t01; \ + t06 = a | t04; \ + y = ~ t05; \ + t08 = b ^ d ; \ + t09 = t03 & t08; \ + t10 = d | y ; \ + x = t09 ^ t06; \ + t12 = a | t05; \ + t13 = x ^ t12; \ + t14 = t03 ^ t10; \ + t15 = a ^ c ; \ + z = t14 ^ t13; \ + t17 = t05 & t13; \ + t18 = t14 | t17; \ + w = t15 ^ t18; \ + } + +#define SBOX1(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t08; \ + u32 t10, t11, t12, t13, t16, t17, t01; \ + t01 = a | d ; \ + t02 = c ^ d ; \ + t03 = ~ b ; \ + t04 = a ^ c ; \ + t05 = a | t03; \ + t06 = d & t04; \ + t07 = t01 & t02; \ + t08 = b | t06; \ + y = t02 ^ t05; \ + t10 = t07 ^ t08; \ + t11 = t01 ^ t10; \ + t12 = y ^ t11; \ + t13 = b & d ; \ + z = ~ t10; \ + x = t13 ^ t12; \ + t16 = t10 | x ; \ + t17 = t05 & t16; \ + w = c ^ t17; \ + } + +#define SBOX1_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t08; \ + u32 t09, t10, t11, t14, t15, t17, t01; \ + t01 = a ^ b ; \ + t02 = b | d ; \ + t03 = a & c ; \ + t04 = c ^ t02; \ + t05 = a | t04; \ + t06 = t01 & t05; \ + t07 = d | t03; \ + t08 = b ^ t06; \ + t09 = t07 ^ t06; \ + t10 = t04 | t03; \ + t11 = d & t08; \ + y = ~ t09; \ + x = t10 ^ t11; \ + t14 = a | y ; \ + t15 = t06 ^ x ; \ + z = t01 ^ t04; \ + t17 = c ^ t15; \ + w = t14 ^ t17; \ + } + +#define SBOX2(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t05, t06, t07, t08; \ + u32 t09, t10, t12, t13, t14, t01; \ + t01 = a | c ; \ + t02 = a ^ b ; \ + t03 = d ^ t01; \ + w = t02 ^ t03; \ + t05 = c ^ w ; \ + t06 = b ^ t05; \ + t07 = b | t05; \ + t08 = t01 & t06; \ + t09 = t03 ^ t07; \ + t10 = t02 | t09; \ + x = t10 ^ t08; \ + t12 = a | d ; \ + t13 = t09 ^ x ; \ + t14 = b ^ t13; \ + z = ~ t09; \ + y = t12 ^ t14; \ + } + +#define SBOX2_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t06, t07, t08, t09; \ + u32 t10, t11, t12, t15, t16, t17, t01; \ + t01 = a ^ d ; \ + t02 = c ^ d ; \ + t03 = a & c ; \ + t04 = b | t02; \ + w = t01 ^ t04; \ + t06 = a | c ; \ + t07 = d | w ; \ + t08 = ~ d ; \ + t09 = b & t06; \ + t10 = t08 | t03; \ + t11 = b & t07; \ + t12 = t06 & t02; \ + z = t09 ^ t10; \ + x = t12 ^ t11; \ + t15 = c & z ; \ + t16 = w ^ x ; \ + t17 = t10 ^ t15; \ + y = t16 ^ t17; \ + } + +#define SBOX3(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t08; \ + u32 t09, t10, t11, t13, t14, t15, t01; \ + t01 = a ^ c ; \ + t02 = a | d ; \ + t03 = a & d ; \ + t04 = t01 & t02; \ + t05 = b | t03; \ + t06 = a & b ; \ + t07 = d ^ t04; \ + t08 = c | t06; \ + t09 = b ^ t07; \ + t10 = d & t05; \ + t11 = t02 ^ t10; \ + z = t08 ^ t09; \ + t13 = d | z ; \ + t14 = a | t07; \ + t15 = b & t13; \ + y = t08 ^ t11; \ + w = t14 ^ t15; \ + x = t05 ^ t04; \ + } + +#define SBOX3_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t09; \ + u32 t11, t12, t13, t14, t16, t01; \ + t01 = c | d ; \ + t02 = a | d ; \ + t03 = c ^ t02; \ + t04 = b ^ t02; \ + t05 = a ^ d ; \ + t06 = t04 & t03; \ + t07 = b & t01; \ + y = t05 ^ t06; \ + t09 = a ^ t03; \ + w = t07 ^ t03; \ + t11 = w | t05; \ + t12 = t09 & t11; \ + t13 = a & y ; \ + t14 = t01 ^ t05; \ + x = b ^ t12; \ + t16 = b | t13; \ + z = t14 ^ t16; \ + } + +#define SBOX4(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t08, t09; \ + u32 t10, t11, t12, t13, t14, t15, t16, t01; \ + t01 = a | b ; \ + t02 = b | c ; \ + t03 = a ^ t02; \ + t04 = b ^ d ; \ + t05 = d | t03; \ + t06 = d & t01; \ + z = t03 ^ t06; \ + t08 = z & t04; \ + t09 = t04 & t05; \ + t10 = c ^ t06; \ + t11 = b & c ; \ + t12 = t04 ^ t08; \ + t13 = t11 | t03; \ + t14 = t10 ^ t09; \ + t15 = a & t05; \ + t16 = t11 | t12; \ + y = t13 ^ t08; \ + x = t15 ^ t16; \ + w = ~ t14; \ + } + +#define SBOX4_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t09; \ + u32 t10, t11, t12, t13, t15, t01; \ + t01 = b | d ; \ + t02 = c | d ; \ + t03 = a & t01; \ + t04 = b ^ t02; \ + t05 = c ^ d ; \ + t06 = ~ t03; \ + t07 = a & t04; \ + x = t05 ^ t07; \ + t09 = x | t06; \ + t10 = a ^ t07; \ + t11 = t01 ^ t09; \ + t12 = d ^ t04; \ + t13 = c | t10; \ + z = t03 ^ t12; \ + t15 = a ^ t04; \ + y = t11 ^ t13; \ + w = t15 ^ t09; \ + } + +#define SBOX5(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t07, t08, t09; \ + u32 t10, t11, t12, t13, t14, t01; \ + t01 = b ^ d ; \ + t02 = b | d ; \ + t03 = a & t01; \ + t04 = c ^ t02; \ + t05 = t03 ^ t04; \ + w = ~ t05; \ + t07 = a ^ t01; \ + t08 = d | w ; \ + t09 = b | t05; \ + t10 = d ^ t08; \ + t11 = b | t07; \ + t12 = t03 | w ; \ + t13 = t07 | t10; \ + t14 = t01 ^ t11; \ + y = t09 ^ t13; \ + x = t07 ^ t08; \ + z = t12 ^ t14; \ + } + +#define SBOX5_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t07, t08, t09; \ + u32 t10, t12, t13, t15, t16, t01; \ + t01 = a & d ; \ + t02 = c ^ t01; \ + t03 = a ^ d ; \ + t04 = b & t02; \ + t05 = a & c ; \ + w = t03 ^ t04; \ + t07 = a & w ; \ + t08 = t01 ^ w ; \ + t09 = b | t05; \ + t10 = ~ b ; \ + x = t08 ^ t09; \ + t12 = t10 | t07; \ + t13 = w | x ; \ + z = t02 ^ t12; \ + t15 = t02 ^ t13; \ + t16 = b ^ d ; \ + y = t16 ^ t15; \ + } + +#define SBOX6(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t07, t08, t09, t10; \ + u32 t11, t12, t13, t15, t17, t18, t01; \ + t01 = a & d ; \ + t02 = b ^ c ; \ + t03 = a ^ d ; \ + t04 = t01 ^ t02; \ + t05 = b | c ; \ + x = ~ t04; \ + t07 = t03 & t05; \ + t08 = b & x ; \ + t09 = a | c ; \ + t10 = t07 ^ t08; \ + t11 = b | d ; \ + t12 = c ^ t11; \ + t13 = t09 ^ t10; \ + y = ~ t13; \ + t15 = x & t03; \ + z = t12 ^ t07; \ + t17 = a ^ b ; \ + t18 = y ^ t15; \ + w = t17 ^ t18; \ + } + +#define SBOX6_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t07, t08, t09; \ + u32 t12, t13, t14, t15, t16, t17, t01; \ + t01 = a ^ c ; \ + t02 = ~ c ; \ + t03 = b & t01; \ + t04 = b | t02; \ + t05 = d | t03; \ + t06 = b ^ d ; \ + t07 = a & t04; \ + t08 = a | t02; \ + t09 = t07 ^ t05; \ + x = t06 ^ t08; \ + w = ~ t09; \ + t12 = b & w ; \ + t13 = t01 & t05; \ + t14 = t01 ^ t12; \ + t15 = t07 ^ t13; \ + t16 = d | t02; \ + t17 = a ^ x ; \ + z = t17 ^ t15; \ + y = t16 ^ t14; \ + } + +#define SBOX7(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t05, t06, t08, t09, t10; \ + u32 t11, t13, t14, t15, t16, t17, t01; \ + t01 = a & c ; \ + t02 = ~ d ; \ + t03 = a & t02; \ + t04 = b | t01; \ + t05 = a & b ; \ + t06 = c ^ t04; \ + z = t03 ^ t06; \ + t08 = c | z ; \ + t09 = d | t05; \ + t10 = a ^ t08; \ + t11 = t04 & z ; \ + x = t09 ^ t10; \ + t13 = b ^ x ; \ + t14 = t01 ^ x ; \ + t15 = c ^ t05; \ + t16 = t11 | t13; \ + t17 = t02 | t14; \ + w = t15 ^ t17; \ + y = a ^ t16; \ + } + +#define SBOX7_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + u32 t02, t03, t04, t06, t07, t08, t09; \ + u32 t10, t11, t13, t14, t15, t16, t01; \ + t01 = a & b ; \ + t02 = a | b ; \ + t03 = c | t01; \ + t04 = d & t02; \ + z = t03 ^ t04; \ + t06 = b ^ t04; \ + t07 = d ^ z ; \ + t08 = ~ t07; \ + t09 = t06 | t08; \ + t10 = b ^ d ; \ + t11 = a | d ; \ + x = a ^ t09; \ + t13 = c ^ t06; \ + t14 = c & t11; \ + t15 = d | x ; \ + t16 = t01 | t10; \ + w = t13 ^ t15; \ + y = t14 ^ t16; \ + } + +/* XOR BLOCK1 into BLOCK0. */ +#define BLOCK_XOR(block0, block1) \ + { \ + block0[0] ^= block1[0]; \ + block0[1] ^= block1[1]; \ + block0[2] ^= block1[2]; \ + block0[3] ^= block1[3]; \ + } + +/* Copy BLOCK_SRC to BLOCK_DST. */ +#define BLOCK_COPY(block_dst, block_src) \ + { \ + block_dst[0] = block_src[0]; \ + block_dst[1] = block_src[1]; \ + block_dst[2] = block_src[2]; \ + block_dst[3] = block_src[3]; \ + } + +/* Apply SBOX number WHICH to to the block found in ARRAY0 at index + INDEX, writing the output to the block found in ARRAY1 at index + INDEX. */ +#define SBOX(which, array0, array1, index) \ + SBOX##which (array0[index + 0], array0[index + 1], \ + array0[index + 2], array0[index + 3], \ + array1[index + 0], array1[index + 1], \ + array1[index + 2], array1[index + 3]); + +/* Apply inverse SBOX number WHICH to to the block found in ARRAY0 at + index INDEX, writing the output to the block found in ARRAY1 at + index INDEX. */ +#define SBOX_INVERSE(which, array0, array1, index) \ + SBOX##which##_INVERSE (array0[index + 0], array0[index + 1], \ + array0[index + 2], array0[index + 3], \ + array1[index + 0], array1[index + 1], \ + array1[index + 2], array1[index + 3]); + +/* Apply the linear transformation to BLOCK. */ +#define LINEAR_TRANSFORMATION(block) \ + { \ + block[0] = rol (block[0], 13); \ + block[2] = rol (block[2], 3); \ + block[1] = block[1] ^ block[0] ^ block[2]; \ + block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ + block[1] = rol (block[1], 1); \ + block[3] = rol (block[3], 7); \ + block[0] = block[0] ^ block[1] ^ block[3]; \ + block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ + block[0] = rol (block[0], 5); \ + block[2] = rol (block[2], 22); \ + } + +/* Apply the inverse linear transformation to BLOCK. */ +#define LINEAR_TRANSFORMATION_INVERSE(block) \ + { \ + block[2] = ror (block[2], 22); \ + block[0] = ror (block[0] , 5); \ + block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ + block[0] = block[0] ^ block[1] ^ block[3]; \ + block[3] = ror (block[3], 7); \ + block[1] = ror (block[1], 1); \ + block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ + block[1] = block[1] ^ block[0] ^ block[2]; \ + block[2] = ror (block[2], 3); \ + block[0] = ror (block[0], 13); \ + } + +/* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the + subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. + This macro increments `round'. */ +#define ROUND(which, subkeys, block, block_tmp) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round++; \ + SBOX (which, block, block_tmp, 0); \ + LINEAR_TRANSFORMATION (block_tmp); \ + BLOCK_COPY (block, block_tmp); \ + } + +/* Apply the last Serpent round to BLOCK, using the SBOX number WHICH + and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary + storage. The result will be stored in BLOCK_TMP. This macro + increments `round'. */ +#define ROUND_LAST(which, subkeys, block, block_tmp) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round++; \ + SBOX (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkeys[round]); \ + round++; \ + } + +/* Apply an inverse Serpent round to BLOCK, using the SBOX number + WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as + temporary storage. This macro increments `round'. */ +#define ROUND_INVERSE(which, subkey, block, block_tmp) \ + { \ + LINEAR_TRANSFORMATION_INVERSE (block); \ + SBOX_INVERSE (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkey[round]); \ + round--; \ + BLOCK_COPY (block, block_tmp); \ + } + +/* Apply the first Serpent round to BLOCK, using the SBOX number WHICH + and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary + storage. The result will be stored in BLOCK_TMP. This macro + increments `round'. */ +#define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round--; \ + SBOX_INVERSE (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkeys[round]); \ + round--; \ + } + +/* Convert the user provided key KEY of KEY_LENGTH bytes into the + internally used format. */ +static void +serpent_key_prepare (const byte *key, unsigned int key_length, + serpent_key_t key_prepared) +{ + int i; + + /* Copy key. */ + memcpy (key_prepared, key, key_length); + key_length /= 4; +#ifdef WORDS_BIGENDIAN + for (i = 0; i < key_length; i++) + key_prepared[i] = byte_swap_32 (key_prepared[i]); +#else + i = key_length; +#endif + if (i < 8) + { + /* Key must be padded according to the Serpent + specification. */ + key_prepared[i] = 0x00000001; + + for (i++; i < 8; i++) + key_prepared[i] = 0; + } +} + +/* Derive the 33 subkeys from KEY and store them in SUBKEYS. */ +static void +serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys) +{ + u32 w_real[140]; /* The `prekey'. */ + u32 k[132]; + u32 *w = &w_real[8]; + int i, j; + + /* Initialize with key values. */ + for (i = 0; i < 8; i++) + w[i - 8] = key[i]; + + /* Expand to intermediate key using the affine recurrence. */ + for (i = 0; i < 132; i++) + w[i] = rol (w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11); + + /* Calculate subkeys via S-Boxes, in bitslice mode. */ + SBOX (3, w, k, 0); + SBOX (2, w, k, 4); + SBOX (1, w, k, 8); + SBOX (0, w, k, 12); + SBOX (7, w, k, 16); + SBOX (6, w, k, 20); + SBOX (5, w, k, 24); + SBOX (4, w, k, 28); + SBOX (3, w, k, 32); + SBOX (2, w, k, 36); + SBOX (1, w, k, 40); + SBOX (0, w, k, 44); + SBOX (7, w, k, 48); + SBOX (6, w, k, 52); + SBOX (5, w, k, 56); + SBOX (4, w, k, 60); + SBOX (3, w, k, 64); + SBOX (2, w, k, 68); + SBOX (1, w, k, 72); + SBOX (0, w, k, 76); + SBOX (7, w, k, 80); + SBOX (6, w, k, 84); + SBOX (5, w, k, 88); + SBOX (4, w, k, 92); + SBOX (3, w, k, 96); + SBOX (2, w, k, 100); + SBOX (1, w, k, 104); + SBOX (0, w, k, 108); + SBOX (7, w, k, 112); + SBOX (6, w, k, 116); + SBOX (5, w, k, 120); + SBOX (4, w, k, 124); + SBOX (3, w, k, 128); + + /* Renumber subkeys. */ + for (i = 0; i < ROUNDS + 1; i++) + for (j = 0; j < 4; j++) + subkeys[i][j] = k[4 * i + j]; +} + +/* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */ +static void +serpent_setkey_internal (serpent_context_t *context, + const byte *key, unsigned int key_length) +{ + serpent_key_t key_prepared; + + serpent_key_prepare (key, key_length, key_prepared); + serpent_subkeys_generate (key_prepared, context->keys); + _gcry_burn_stack (272 * sizeof (u32)); +} + +/* Initialize CTX with the key KEY of KEY_LENGTH bytes. */ +static gcry_err_code_t +serpent_setkey (void *ctx, + const byte *key, unsigned int key_length) +{ + serpent_context_t *context = ctx; + static const char *serpent_test_ret; + static int serpent_init_done; + gcry_err_code_t ret = GPG_ERR_NO_ERROR; + + if (! serpent_init_done) + { + /* Execute a self-test the first time, Serpent is used. */ + serpent_test_ret = serpent_test (); + if (serpent_test_ret) + log_error ("Serpent test failure: %s\n", serpent_test_ret); + serpent_init_done = 1; + } + + if (serpent_test_ret) + ret = GPG_ERR_SELFTEST_FAILED; + else + { + serpent_setkey_internal (context, key, key_length); + _gcry_burn_stack (sizeof (serpent_key_t)); + } + + return ret; +} + +static void +serpent_encrypt_internal (serpent_context_t *context, + const byte *input, byte *output) +{ + serpent_block_t b, b_next; + int round = 0; + + memcpy (b, input, sizeof (b)); +#ifdef WORDS_BIGENDIAN + b[0] = byte_swap_32 (b[0]); + b[1] = byte_swap_32 (b[1]); + b[2] = byte_swap_32 (b[2]); + b[3] = byte_swap_32 (b[3]); +#endif + + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + ROUND (7, context->keys, b, b_next); + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + ROUND (7, context->keys, b, b_next); + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + ROUND (7, context->keys, b, b_next); + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + + ROUND_LAST (7, context->keys, b, b_next); + +#ifdef WORDS_BIGENDIAN + b_next[0] = byte_swap_32 (b_next[0]); + b_next[1] = byte_swap_32 (b_next[1]); + b_next[2] = byte_swap_32 (b_next[2]); + b_next[3] = byte_swap_32 (b_next[3]); +#endif + memcpy (output, b_next, sizeof (b_next)); +} + +static void +serpent_decrypt_internal (serpent_context_t *context, + const byte *input, byte *output) +{ + serpent_block_t b, b_next; + int round = ROUNDS; + + memcpy (b_next, input, sizeof (b)); +#ifdef WORDS_BIGENDIAN + b_next[0] = byte_swap_32 (b_next[0]); + b_next[1] = byte_swap_32 (b_next[1]); + b_next[2] = byte_swap_32 (b_next[2]); + b_next[3] = byte_swap_32 (b_next[3]); +#endif + + ROUND_FIRST_INVERSE (7, context->keys, b_next, b); + + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + ROUND_INVERSE (7, context->keys, b, b_next); + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + ROUND_INVERSE (7, context->keys, b, b_next); + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + ROUND_INVERSE (7, context->keys, b, b_next); + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + +#ifdef WORDS_BIGENDIAN + b_next[0] = byte_swap_32 (b_next[0]); + b_next[1] = byte_swap_32 (b_next[1]); + b_next[2] = byte_swap_32 (b_next[2]); + b_next[3] = byte_swap_32 (b_next[3]); +#endif + memcpy (output, b_next, sizeof (b_next)); +} + +static void +serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in) +{ + serpent_context_t *context = ctx; + + serpent_encrypt_internal (context, buffer_in, buffer_out); + _gcry_burn_stack (2 * sizeof (serpent_block_t)); +} + +static void +serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in) +{ + serpent_context_t *context = ctx; + + serpent_decrypt_internal (context, buffer_in, buffer_out); + _gcry_burn_stack (2 * sizeof (serpent_block_t)); +} + + + +/* Serpent test. */ + +static const char * +serpent_test (void) +{ + serpent_context_t context; + unsigned char scratch[16]; + unsigned int i; + + static struct test + { + int key_length; + unsigned char key[32]; + unsigned char text_plain[16]; + unsigned char text_cipher[16]; + } test_data[] = + { + { + 16, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\xD2\x9D\x57\x6F\xCE\xA3\xA3\xA7\xED\x90\x99\xF2\x92\x73\xD7\x8E", + "\xB2\x28\x8B\x96\x8A\xE8\xB0\x86\x48\xD1\xCE\x96\x06\xFD\x99\x2D" + }, + { + 24, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\xD2\x9D\x57\x6F\xCE\xAB\xA3\xA7\xED\x98\x99\xF2\x92\x7B\xD7\x8E", + "\x13\x0E\x35\x3E\x10\x37\xC2\x24\x05\xE8\xFA\xEF\xB2\xC3\xC3\xE9" + }, + { + 32, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\xD0\x95\x57\x6F\xCE\xA3\xE3\xA7\xED\x98\xD9\xF2\x90\x73\xD7\x8E", + "\xB9\x0E\xE5\x86\x2D\xE6\x91\x68\xF2\xBD\xD5\x12\x5B\x45\x47\x2B" + }, + { + 32, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00", + "\x20\x61\xA4\x27\x82\xBD\x52\xEC\x69\x1E\xC3\x83\xB0\x3B\xA7\x7C" + }, + { + 0 + }, + }; + + for (i = 0; test_data[i].key_length; i++) + { + serpent_setkey_internal (&context, test_data[i].key, + test_data[i].key_length); + serpent_encrypt_internal (&context, test_data[i].text_plain, scratch); + + if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t))) + switch (test_data[i].key_length) + { + case 16: + return "Serpent-128 test encryption failed."; + case 24: + return "Serpent-192 test encryption failed."; + case 32: + return "Serpent-256 test encryption failed."; + } + + serpent_decrypt_internal (&context, test_data[i].text_cipher, scratch); + if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t))) + switch (test_data[i].key_length) + { + case 16: + return "Serpent-128 test decryption failed."; + case 24: + return "Serpent-192 test decryption failed."; + case 32: + return "Serpent-256 test decryption failed."; + } + } + + return NULL; +} + + + +/* "SERPENT" is an alias for "SERPENT128". */ +static const char *cipher_spec_serpent128_aliases[] = + { + "SERPENT", + NULL + }; + +gcry_cipher_spec_t _gcry_cipher_spec_serpent128 = + { + "SERPENT128", cipher_spec_serpent128_aliases, NULL, 16, 128, + sizeof (serpent_context_t), + serpent_setkey, serpent_encrypt, serpent_decrypt + }; + +gcry_cipher_spec_t _gcry_cipher_spec_serpent192 = + { + "SERPENT192", NULL, NULL, 16, 192, + sizeof (serpent_context_t), + serpent_setkey, serpent_encrypt, serpent_decrypt + }; + +gcry_cipher_spec_t _gcry_cipher_spec_serpent256 = + { + "SERPENT256", NULL, NULL, 16, 256, + sizeof (serpent_context_t), + serpent_setkey, serpent_encrypt, serpent_decrypt + }; diff --git a/grub-core/lib/libgcrypt/cipher/sha1.c b/grub-core/lib/libgcrypt/cipher/sha1.c new file mode 100644 index 0000000..4b784ac --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/sha1.c @@ -0,0 +1,477 @@ +/* sha1.c - SHA1 hash function + * Copyright (C) 1998, 2001, 2002, 2003, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + + +/* Test vectors: + * + * "abc" + * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D + * + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 + */ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif + +#include "g10lib.h" +#include "bithelp.h" +#include "cipher.h" +#include "hash-common.h" + + +/* A macro to test whether P is properly aligned for an u32 type. + Note that config.h provides a suitable replacement for uintptr_t if + it does not exist in stdint.h. */ +/* #if __GNUC__ >= 2 */ +/* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % __alignof__ (u32))) */ +/* #else */ +/* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % sizeof (u32))) */ +/* #endif */ + +#define TRANSFORM(x,d,n) transform ((x), (d), (n)) + + +typedef struct +{ + u32 h0,h1,h2,h3,h4; + u32 nblocks; + unsigned char buf[64]; + int count; +} SHA1_CONTEXT; + + + +static void +sha1_init (void *context) +{ + SHA1_CONTEXT *hd = context; + + hd->h0 = 0x67452301; + hd->h1 = 0xefcdab89; + hd->h2 = 0x98badcfe; + hd->h3 = 0x10325476; + hd->h4 = 0xc3d2e1f0; + hd->nblocks = 0; + hd->count = 0; +} + + +/* Round function macros. */ +#define K1 0x5A827999L +#define K2 0x6ED9EBA1L +#define K3 0x8F1BBCDCL +#define K4 0xCA62C1D6L +#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) +#define F2(x,y,z) ( x ^ y ^ z ) +#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) +#define F4(x,y,z) ( x ^ y ^ z ) +#define M(i) ( tm = x[ i &0x0f] \ + ^ x[(i-14)&0x0f] \ + ^ x[(i-8) &0x0f] \ + ^ x[(i-3) &0x0f], \ + (x[i&0x0f] = rol(tm, 1))) +#define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \ + + f( b, c, d ) \ + + k \ + + m; \ + b = rol( b, 30 ); \ + } while(0) + + +/* + * Transform NBLOCKS of each 64 bytes (16 32-bit words) at DATA. + */ +static void +transform (SHA1_CONTEXT *hd, const unsigned char *data, size_t nblocks) +{ + register u32 a, b, c, d, e; /* Local copies of the chaining variables. */ + register u32 tm; /* Helper. */ + u32 x[16]; /* The array we work on. */ + + /* Loop over all blocks. */ + for ( ;nblocks; nblocks--) + { +#ifdef WORDS_BIGENDIAN + memcpy (x, data, 64); + data += 64; +#else + { + int i; + unsigned char *p; + + for(i=0, p=(unsigned char*)x; i < 16; i++, p += 4 ) + { + p[3] = *data++; + p[2] = *data++; + p[1] = *data++; + p[0] = *data++; + } + } +#endif + /* Get the values of the chaining variables. */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + + /* Transform. */ + R( a, b, c, d, e, F1, K1, x[ 0] ); + R( e, a, b, c, d, F1, K1, x[ 1] ); + R( d, e, a, b, c, F1, K1, x[ 2] ); + R( c, d, e, a, b, F1, K1, x[ 3] ); + R( b, c, d, e, a, F1, K1, x[ 4] ); + R( a, b, c, d, e, F1, K1, x[ 5] ); + R( e, a, b, c, d, F1, K1, x[ 6] ); + R( d, e, a, b, c, F1, K1, x[ 7] ); + R( c, d, e, a, b, F1, K1, x[ 8] ); + R( b, c, d, e, a, F1, K1, x[ 9] ); + R( a, b, c, d, e, F1, K1, x[10] ); + R( e, a, b, c, d, F1, K1, x[11] ); + R( d, e, a, b, c, F1, K1, x[12] ); + R( c, d, e, a, b, F1, K1, x[13] ); + R( b, c, d, e, a, F1, K1, x[14] ); + R( a, b, c, d, e, F1, K1, x[15] ); + R( e, a, b, c, d, F1, K1, M(16) ); + R( d, e, a, b, c, F1, K1, M(17) ); + R( c, d, e, a, b, F1, K1, M(18) ); + R( b, c, d, e, a, F1, K1, M(19) ); + R( a, b, c, d, e, F2, K2, M(20) ); + R( e, a, b, c, d, F2, K2, M(21) ); + R( d, e, a, b, c, F2, K2, M(22) ); + R( c, d, e, a, b, F2, K2, M(23) ); + R( b, c, d, e, a, F2, K2, M(24) ); + R( a, b, c, d, e, F2, K2, M(25) ); + R( e, a, b, c, d, F2, K2, M(26) ); + R( d, e, a, b, c, F2, K2, M(27) ); + R( c, d, e, a, b, F2, K2, M(28) ); + R( b, c, d, e, a, F2, K2, M(29) ); + R( a, b, c, d, e, F2, K2, M(30) ); + R( e, a, b, c, d, F2, K2, M(31) ); + R( d, e, a, b, c, F2, K2, M(32) ); + R( c, d, e, a, b, F2, K2, M(33) ); + R( b, c, d, e, a, F2, K2, M(34) ); + R( a, b, c, d, e, F2, K2, M(35) ); + R( e, a, b, c, d, F2, K2, M(36) ); + R( d, e, a, b, c, F2, K2, M(37) ); + R( c, d, e, a, b, F2, K2, M(38) ); + R( b, c, d, e, a, F2, K2, M(39) ); + R( a, b, c, d, e, F3, K3, M(40) ); + R( e, a, b, c, d, F3, K3, M(41) ); + R( d, e, a, b, c, F3, K3, M(42) ); + R( c, d, e, a, b, F3, K3, M(43) ); + R( b, c, d, e, a, F3, K3, M(44) ); + R( a, b, c, d, e, F3, K3, M(45) ); + R( e, a, b, c, d, F3, K3, M(46) ); + R( d, e, a, b, c, F3, K3, M(47) ); + R( c, d, e, a, b, F3, K3, M(48) ); + R( b, c, d, e, a, F3, K3, M(49) ); + R( a, b, c, d, e, F3, K3, M(50) ); + R( e, a, b, c, d, F3, K3, M(51) ); + R( d, e, a, b, c, F3, K3, M(52) ); + R( c, d, e, a, b, F3, K3, M(53) ); + R( b, c, d, e, a, F3, K3, M(54) ); + R( a, b, c, d, e, F3, K3, M(55) ); + R( e, a, b, c, d, F3, K3, M(56) ); + R( d, e, a, b, c, F3, K3, M(57) ); + R( c, d, e, a, b, F3, K3, M(58) ); + R( b, c, d, e, a, F3, K3, M(59) ); + R( a, b, c, d, e, F4, K4, M(60) ); + R( e, a, b, c, d, F4, K4, M(61) ); + R( d, e, a, b, c, F4, K4, M(62) ); + R( c, d, e, a, b, F4, K4, M(63) ); + R( b, c, d, e, a, F4, K4, M(64) ); + R( a, b, c, d, e, F4, K4, M(65) ); + R( e, a, b, c, d, F4, K4, M(66) ); + R( d, e, a, b, c, F4, K4, M(67) ); + R( c, d, e, a, b, F4, K4, M(68) ); + R( b, c, d, e, a, F4, K4, M(69) ); + R( a, b, c, d, e, F4, K4, M(70) ); + R( e, a, b, c, d, F4, K4, M(71) ); + R( d, e, a, b, c, F4, K4, M(72) ); + R( c, d, e, a, b, F4, K4, M(73) ); + R( b, c, d, e, a, F4, K4, M(74) ); + R( a, b, c, d, e, F4, K4, M(75) ); + R( e, a, b, c, d, F4, K4, M(76) ); + R( d, e, a, b, c, F4, K4, M(77) ); + R( c, d, e, a, b, F4, K4, M(78) ); + R( b, c, d, e, a, F4, K4, M(79) ); + + /* Update the chaining variables. */ + hd->h0 += a; + hd->h1 += b; + hd->h2 += c; + hd->h3 += d; + hd->h4 += e; + } +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +sha1_write( void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + SHA1_CONTEXT *hd = context; + size_t nblocks; + + if (hd->count == 64) /* Flush the buffer. */ + { + TRANSFORM( hd, hd->buf, 1 ); + _gcry_burn_stack (88+4*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if (!inbuf) + return; + + if (hd->count) + { + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; + sha1_write (hd, NULL, 0); + if (!inlen) + return; + } + + nblocks = inlen / 64; + if (nblocks) + { + TRANSFORM (hd, inbuf, nblocks); + hd->count = 0; + hd->nblocks += nblocks; + inlen -= nblocks * 64; + inbuf += nblocks * 64; + } + _gcry_burn_stack (88+4*sizeof(void*)); + + /* Save remaining bytes. */ + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; +} + + +/* The routine final terminates the computation and + * returns the digest. + * The handle is prepared for a new cycle, but adding bytes to the + * handle will the destroy the returned buffer. + * Returns: 20 bytes representing the digest. + */ + +static void +sha1_final(void *context) +{ + SHA1_CONTEXT *hd = context; + + u32 t, msb, lsb; + unsigned char *p; + + sha1_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) /* enough room */ + { + hd->buf[hd->count++] = 0x80; /* pad */ + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else /* need one extra block */ + { + hd->buf[hd->count++] = 0x80; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + sha1_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = msb >> 24; + hd->buf[57] = msb >> 16; + hd->buf[58] = msb >> 8; + hd->buf[59] = msb ; + hd->buf[60] = lsb >> 24; + hd->buf[61] = lsb >> 16; + hd->buf[62] = lsb >> 8; + hd->buf[63] = lsb ; + TRANSFORM( hd, hd->buf, 1 ); + _gcry_burn_stack (88+4*sizeof(void*)); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) +#else /* little endian */ +#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ + *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) +#endif + X(0); + X(1); + X(2); + X(3); + X(4); +#undef X + +} + +static unsigned char * +sha1_read( void *context ) +{ + SHA1_CONTEXT *hd = context; + + return hd->buf; +} + +/**************** + * Shortcut functions which puts the hash value of the supplied buffer + * into outbuf which must have a size of 20 bytes. + */ +void +_gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length) +{ + SHA1_CONTEXT hd; + + sha1_init (&hd); + sha1_write (&hd, buffer, length); + sha1_final (&hd); + memcpy (outbuf, hd.buf, 20); +} + + + +/* + Self-test section. + */ + + +static gpg_err_code_t +selftests_sha1 (int extended, selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + + what = "short string"; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA1, 0, + "abc", 3, + "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E" + "\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D", 20); + if (errtxt) + goto failed; + + if (extended) + { + what = "long string"; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA1, 0, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE" + "\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1", 20); + if (errtxt) + goto failed; + + what = "one million \"a\""; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA1, 1, + NULL, 0, + "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E" + "\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F", 20); + if (errtxt) + goto failed; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("digest", GCRY_MD_SHA1, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + +/* Run a full self-test for ALGO and return 0 on success. */ +static gpg_err_code_t +run_selftests (int algo, int extended, selftest_report_func_t report) +{ + gpg_err_code_t ec; + + switch (algo) + { + case GCRY_MD_SHA1: + ec = selftests_sha1 (extended, report); + break; + default: + ec = GPG_ERR_DIGEST_ALGO; + break; + + } + return ec; +} + + + + +static unsigned char asn[15] = /* Object ID is 1.3.14.3.2.26 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; + +static gcry_md_oid_spec_t oid_spec_sha1[] = + { + /* iso.member-body.us.rsadsi.pkcs.pkcs-1.5 (sha1WithRSAEncryption) */ + { "1.2.840.113549.1.1.5" }, + /* iso.member-body.us.x9-57.x9cm.3 (dsaWithSha1)*/ + { "1.2.840.10040.4.3" }, + /* from NIST's OIW (sha1) */ + { "1.3.14.3.2.26" }, + /* from NIST OIW (sha-1WithRSAEncryption) */ + { "1.3.14.3.2.29" }, + /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha1 */ + { "1.2.840.10045.4.1" }, + { NULL }, + }; + +gcry_md_spec_t _gcry_digest_spec_sha1 = + { + "SHA1", asn, DIM (asn), oid_spec_sha1, 20, + sha1_init, sha1_write, sha1_final, sha1_read, + sizeof (SHA1_CONTEXT) + }; +md_extra_spec_t _gcry_digest_extraspec_sha1 = + { + run_selftests + }; diff --git a/grub-core/lib/libgcrypt/cipher/sha256.c b/grub-core/lib/libgcrypt/cipher/sha256.c new file mode 100644 index 0000000..309fa3b --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/sha256.c @@ -0,0 +1,554 @@ +/* sha256.c - SHA256 hash function + * Copyright (C) 2003, 2006, 2008, 2009 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + + +/* Test vectors: + + "abc" + SHA224: 23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7 + SHA256: ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad + + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + SHA224: 75388b16 512776cc 5dba5da1 fd890150 b0c6455c b4f58b19 52522525 + SHA256: 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1 + + "a" one million times + SHA224: 20794655 980c91d8 bbb4c1ea 97618a4b f03f4258 1948b2ee 4ee7ad67 + SHA256: cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0 + + */ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "g10lib.h" +#include "bithelp.h" +#include "cipher.h" +#include "hash-common.h" + +typedef struct { + u32 h0,h1,h2,h3,h4,h5,h6,h7; + u32 nblocks; + byte buf[64]; + int count; +} SHA256_CONTEXT; + + +static void +sha256_init (void *context) +{ + SHA256_CONTEXT *hd = context; + + hd->h0 = 0x6a09e667; + hd->h1 = 0xbb67ae85; + hd->h2 = 0x3c6ef372; + hd->h3 = 0xa54ff53a; + hd->h4 = 0x510e527f; + hd->h5 = 0x9b05688c; + hd->h6 = 0x1f83d9ab; + hd->h7 = 0x5be0cd19; + + hd->nblocks = 0; + hd->count = 0; +} + + +static void +sha224_init (void *context) +{ + SHA256_CONTEXT *hd = context; + + hd->h0 = 0xc1059ed8; + hd->h1 = 0x367cd507; + hd->h2 = 0x3070dd17; + hd->h3 = 0xf70e5939; + hd->h4 = 0xffc00b31; + hd->h5 = 0x68581511; + hd->h6 = 0x64f98fa7; + hd->h7 = 0xbefa4fa4; + + hd->nblocks = 0; + hd->count = 0; +} + + +/* + Transform the message X which consists of 16 32-bit-words. See FIPS + 180-2 for details. */ +#define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */ +#define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */ +#define R(a,b,c,d,e,f,g,h,k,w) do \ + { \ + t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + (k) + (w); \ + t2 = Sum0((a)) + Maj((a),(b),(c)); \ + h = g; \ + g = f; \ + f = e; \ + e = d + t1; \ + d = c; \ + c = b; \ + b = a; \ + a = t1 + t2; \ + } while (0) + +/* (4.2) same as SHA-1's F1. */ +static inline u32 +Cho (u32 x, u32 y, u32 z) +{ + return (z ^ (x & (y ^ z))); +} + +/* (4.3) same as SHA-1's F3 */ +static inline u32 +Maj (u32 x, u32 y, u32 z) +{ + return ((x & y) | (z & (x|y))); +} + +/* (4.4) */ +static inline u32 +Sum0 (u32 x) +{ + return (ror (x, 2) ^ ror (x, 13) ^ ror (x, 22)); +} + +/* (4.5) */ +static inline u32 +Sum1 (u32 x) +{ + return (ror (x, 6) ^ ror (x, 11) ^ ror (x, 25)); +} + + +static void +transform (SHA256_CONTEXT *hd, const unsigned char *data) +{ + static const u32 K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + + u32 a,b,c,d,e,f,g,h,t1,t2; + u32 x[16]; + u32 w[64]; + int i; + + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + f = hd->h5; + g = hd->h6; + h = hd->h7; + +#ifdef WORDS_BIGENDIAN + memcpy (x, data, 64); +#else + { + byte *p2; + + for (i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) + { + p2[3] = *data++; + p2[2] = *data++; + p2[1] = *data++; + p2[0] = *data++; + } + } +#endif + + for (i=0; i < 16; i++) + w[i] = x[i]; + for (; i < 64; i++) + w[i] = S1(w[i-2]) + w[i-7] + S0(w[i-15]) + w[i-16]; + + for (i=0; i < 64;) + { +#if 0 + R(a,b,c,d,e,f,g,h,K[i],w[i]); + i++; +#else + t1 = h + Sum1 (e) + Cho (e, f, g) + K[i] + w[i]; + t2 = Sum0 (a) + Maj (a, b, c); + d += t1; + h = t1 + t2; + + t1 = g + Sum1 (d) + Cho (d, e, f) + K[i+1] + w[i+1]; + t2 = Sum0 (h) + Maj (h, a, b); + c += t1; + g = t1 + t2; + + t1 = f + Sum1 (c) + Cho (c, d, e) + K[i+2] + w[i+2]; + t2 = Sum0 (g) + Maj (g, h, a); + b += t1; + f = t1 + t2; + + t1 = e + Sum1 (b) + Cho (b, c, d) + K[i+3] + w[i+3]; + t2 = Sum0 (f) + Maj (f, g, h); + a += t1; + e = t1 + t2; + + t1 = d + Sum1 (a) + Cho (a, b, c) + K[i+4] + w[i+4]; + t2 = Sum0 (e) + Maj (e, f, g); + h += t1; + d = t1 + t2; + + t1 = c + Sum1 (h) + Cho (h, a, b) + K[i+5] + w[i+5]; + t2 = Sum0 (d) + Maj (d, e, f); + g += t1; + c = t1 + t2; + + t1 = b + Sum1 (g) + Cho (g, h, a) + K[i+6] + w[i+6]; + t2 = Sum0 (c) + Maj (c, d, e); + f += t1; + b = t1 + t2; + + t1 = a + Sum1 (f) + Cho (f, g, h) + K[i+7] + w[i+7]; + t2 = Sum0 (b) + Maj (b, c, d); + e += t1; + a = t1 + t2; + + i += 8; +#endif + } + + hd->h0 += a; + hd->h1 += b; + hd->h2 += c; + hd->h3 += d; + hd->h4 += e; + hd->h5 += f; + hd->h6 += g; + hd->h7 += h; +} +#undef S0 +#undef S1 +#undef R + + +/* Update the message digest with the contents of INBUF with length + INLEN. */ +static void +sha256_write (void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + SHA256_CONTEXT *hd = context; + + if (hd->count == 64) + { /* flush the buffer */ + transform (hd, hd->buf); + _gcry_burn_stack (74*4+32); + hd->count = 0; + hd->nblocks++; + } + if (!inbuf) + return; + if (hd->count) + { + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; + sha256_write (hd, NULL, 0); + if (!inlen) + return; + } + + while (inlen >= 64) + { + transform (hd, inbuf); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + _gcry_burn_stack (74*4+32); + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; +} + + +/* + The routine finally terminates the computation and returns the + digest. The handle is prepared for a new cycle, but adding bytes + to the handle will the destroy the returned buffer. Returns: 32 + bytes with the message the digest. */ +static void +sha256_final(void *context) +{ + SHA256_CONTEXT *hd = context; + u32 t, msb, lsb; + byte *p; + + sha256_write (hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if ((lsb += hd->count) < t) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if (hd->count < 56) + { /* enough room */ + hd->buf[hd->count++] = 0x80; /* pad */ + while (hd->count < 56) + hd->buf[hd->count++] = 0; /* pad */ + } + else + { /* need one extra block */ + hd->buf[hd->count++] = 0x80; /* pad character */ + while (hd->count < 64) + hd->buf[hd->count++] = 0; + sha256_write (hd, NULL, 0); /* flush */; + memset (hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = msb >> 24; + hd->buf[57] = msb >> 16; + hd->buf[58] = msb >> 8; + hd->buf[59] = msb; + hd->buf[60] = lsb >> 24; + hd->buf[61] = lsb >> 16; + hd->buf[62] = lsb >> 8; + hd->buf[63] = lsb; + transform (hd, hd->buf); + _gcry_burn_stack (74*4+32); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) +#else /* little endian */ +#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ + *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) +#endif + X(0); + X(1); + X(2); + X(3); + X(4); + X(5); + X(6); + X(7); +#undef X +} + +static byte * +sha256_read (void *context) +{ + SHA256_CONTEXT *hd = context; + + return hd->buf; +} + + + +/* + Self-test section. + */ + + +static gpg_err_code_t +selftests_sha224 (int extended, selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + + what = "short string"; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA224, 0, + "abc", 3, + "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3" + "\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7", 28); + if (errtxt) + goto failed; + + if (extended) + { + what = "long string"; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA224, 0, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01\x50" + "\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25", 28); + if (errtxt) + goto failed; + + what = "one million \"a\""; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA224, 1, + NULL, 0, + "\x20\x79\x46\x55\x98\x0c\x91\xd8\xbb\xb4\xc1\xea\x97\x61\x8a\x4b" + "\xf0\x3f\x42\x58\x19\x48\xb2\xee\x4e\xe7\xad\x67", 28); + if (errtxt) + goto failed; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("digest", GCRY_MD_SHA224, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + +static gpg_err_code_t +selftests_sha256 (int extended, selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + + what = "short string"; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA256, 0, + "abc", 3, + "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23" + "\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad", 32); + if (errtxt) + goto failed; + + if (extended) + { + what = "long string"; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA256, 0, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, + "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39" + "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1", + 32); + if (errtxt) + goto failed; + + what = "one million \"a\""; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA256, 1, + NULL, 0, + "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67" + "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0", + 32); + if (errtxt) + goto failed; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("digest", GCRY_MD_SHA256, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + +/* Run a full self-test for ALGO and return 0 on success. */ +static gpg_err_code_t +run_selftests (int algo, int extended, selftest_report_func_t report) +{ + gpg_err_code_t ec; + + switch (algo) + { + case GCRY_MD_SHA224: + ec = selftests_sha224 (extended, report); + break; + case GCRY_MD_SHA256: + ec = selftests_sha256 (extended, report); + break; + default: + ec = GPG_ERR_DIGEST_ALGO; + break; + + } + return ec; +} + + + + +static byte asn224[19] = /* Object ID is 2.16.840.1.101.3.4.2.4 */ + { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, + 0x1C + }; + +static gcry_md_oid_spec_t oid_spec_sha224[] = + { + /* From RFC3874, Section 4 */ + { "2.16.840.1.101.3.4.2.4" }, + { NULL }, + }; + +static byte asn256[19] = /* Object ID is 2.16.840.1.101.3.4.2.1 */ + { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04, 0x20 }; + +static gcry_md_oid_spec_t oid_spec_sha256[] = + { + /* According to the OpenPGP draft rfc2440-bis06 */ + { "2.16.840.1.101.3.4.2.1" }, + /* PKCS#1 sha256WithRSAEncryption */ + { "1.2.840.113549.1.1.11" }, + + { NULL }, + }; + +gcry_md_spec_t _gcry_digest_spec_sha224 = + { + "SHA224", asn224, DIM (asn224), oid_spec_sha224, 28, + sha224_init, sha256_write, sha256_final, sha256_read, + sizeof (SHA256_CONTEXT) + }; +md_extra_spec_t _gcry_digest_extraspec_sha224 = + { + run_selftests + }; + +gcry_md_spec_t _gcry_digest_spec_sha256 = + { + "SHA256", asn256, DIM (asn256), oid_spec_sha256, 32, + sha256_init, sha256_write, sha256_final, sha256_read, + sizeof (SHA256_CONTEXT) + }; +md_extra_spec_t _gcry_digest_extraspec_sha256 = + { + run_selftests + }; diff --git a/grub-core/lib/libgcrypt/cipher/sha512.c b/grub-core/lib/libgcrypt/cipher/sha512.c new file mode 100644 index 0000000..2163e60 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/sha512.c @@ -0,0 +1,629 @@ +/* sha512.c - SHA384 and SHA512 hash functions + * Copyright (C) 2003, 2008, 2009 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + + +/* Test vectors from FIPS-180-2: + * + * "abc" + * 384: + * CB00753F 45A35E8B B5A03D69 9AC65007 272C32AB 0EDED163 + * 1A8B605A 43FF5BED 8086072B A1E7CC23 58BAECA1 34C825A7 + * 512: + * DDAF35A1 93617ABA CC417349 AE204131 12E6FA4E 89A97EA2 0A9EEEE6 4B55D39A + * 2192992A 274FC1A8 36BA3C23 A3FEEBBD 454D4423 643CE80E 2A9AC94F A54CA49F + * + * "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" + * 384: + * 09330C33 F71147E8 3D192FC7 82CD1B47 53111B17 3B3B05D2 + * 2FA08086 E3B0F712 FCC7C71A 557E2DB9 66C3E9FA 91746039 + * 512: + * 8E959B75 DAE313DA 8CF4F728 14FC143F 8F7779C6 EB9F7FA1 7299AEAD B6889018 + * 501D289E 4900F7E4 331B99DE C4B5433A C7D329EE B6DD2654 5E96E55B 874BE909 + * + * "a" x 1000000 + * 384: + * 9D0E1809 716474CB 086E834E 310A4A1C ED149E9C 00F24852 + * 7972CEC5 704C2A5B 07B8B3DC 38ECC4EB AE97DDD8 7F3D8985 + * 512: + * E718483D 0CE76964 4E2E42C7 BC15B463 8E1F98B1 3B204428 5632A803 AFA973EB + * DE0FF244 877EA60A 4CB0432C E577C31B EB009C5C 2C49AA2E 4EADB217 AD8CC09B + */ + + +#include <config.h> +#include <string.h> +#include "g10lib.h" +#include "bithelp.h" +#include "cipher.h" +#include "hash-common.h" + +typedef struct +{ + u64 h0, h1, h2, h3, h4, h5, h6, h7; + u64 nblocks; + byte buf[128]; + int count; +} SHA512_CONTEXT; + +static void +sha512_init (void *context) +{ + SHA512_CONTEXT *hd = context; + + hd->h0 = U64_C(0x6a09e667f3bcc908); + hd->h1 = U64_C(0xbb67ae8584caa73b); + hd->h2 = U64_C(0x3c6ef372fe94f82b); + hd->h3 = U64_C(0xa54ff53a5f1d36f1); + hd->h4 = U64_C(0x510e527fade682d1); + hd->h5 = U64_C(0x9b05688c2b3e6c1f); + hd->h6 = U64_C(0x1f83d9abfb41bd6b); + hd->h7 = U64_C(0x5be0cd19137e2179); + + hd->nblocks = 0; + hd->count = 0; +} + +static void +sha384_init (void *context) +{ + SHA512_CONTEXT *hd = context; + + hd->h0 = U64_C(0xcbbb9d5dc1059ed8); + hd->h1 = U64_C(0x629a292a367cd507); + hd->h2 = U64_C(0x9159015a3070dd17); + hd->h3 = U64_C(0x152fecd8f70e5939); + hd->h4 = U64_C(0x67332667ffc00b31); + hd->h5 = U64_C(0x8eb44a8768581511); + hd->h6 = U64_C(0xdb0c2e0d64f98fa7); + hd->h7 = U64_C(0x47b5481dbefa4fa4); + + hd->nblocks = 0; + hd->count = 0; +} + + +static inline u64 +ROTR (u64 x, u64 n) +{ + return ((x >> n) | (x << (64 - n))); +} + +static inline u64 +Ch (u64 x, u64 y, u64 z) +{ + return ((x & y) ^ ( ~x & z)); +} + +static inline u64 +Maj (u64 x, u64 y, u64 z) +{ + return ((x & y) ^ (x & z) ^ (y & z)); +} + +static inline u64 +Sum0 (u64 x) +{ + return (ROTR (x, 28) ^ ROTR (x, 34) ^ ROTR (x, 39)); +} + +static inline u64 +Sum1 (u64 x) +{ + return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41)); +} + +/**************** + * Transform the message W which consists of 16 64-bit-words + */ +static void +transform (SHA512_CONTEXT *hd, const unsigned char *data) +{ + u64 a, b, c, d, e, f, g, h; + u64 w[80]; + int t; + static const u64 k[] = + { + U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd), + U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc), + U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019), + U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118), + U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe), + U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2), + U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1), + U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694), + U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3), + U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65), + U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483), + U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5), + U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210), + U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4), + U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725), + U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70), + U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926), + U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df), + U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8), + U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b), + U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001), + U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30), + U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910), + U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8), + U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53), + U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8), + U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb), + U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3), + U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60), + U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec), + U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9), + U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b), + U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207), + U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178), + U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6), + U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b), + U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493), + U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c), + U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a), + U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817) + }; + + /* get values from the chaining vars */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + f = hd->h5; + g = hd->h6; + h = hd->h7; + +#ifdef WORDS_BIGENDIAN + memcpy (w, data, 128); +#else + { + int i; + byte *p2; + + for (i = 0, p2 = (byte *) w; i < 16; i++, p2 += 8) + { + p2[7] = *data++; + p2[6] = *data++; + p2[5] = *data++; + p2[4] = *data++; + p2[3] = *data++; + p2[2] = *data++; + p2[1] = *data++; + p2[0] = *data++; + } + } +#endif + +#define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) +#define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) + + for (t = 16; t < 80; t++) + w[t] = S1 (w[t - 2]) + w[t - 7] + S0 (w[t - 15]) + w[t - 16]; + + + for (t = 0; t < 80; ) + { + u64 t1, t2; + + /* Performance on a AMD Athlon(tm) Dual Core Processor 4050e + with gcc 4.3.3 using gcry_md_hash_buffer of each 10000 bytes + initialized to 0,1,2,3...255,0,... and 1000 iterations: + + Not unrolled with macros: 440ms + Unrolled with macros: 350ms + Unrolled with inline: 330ms + */ +#if 0 /* Not unrolled. */ + t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; + t2 = Sum0 (a) + Maj (a, b, c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + t++; +#else /* Unrolled to interweave the chain variables. */ + t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; + t2 = Sum0 (a) + Maj (a, b, c); + d += t1; + h = t1 + t2; + + t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[t+1]; + t2 = Sum0 (h) + Maj (h, a, b); + c += t1; + g = t1 + t2; + + t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[t+2]; + t2 = Sum0 (g) + Maj (g, h, a); + b += t1; + f = t1 + t2; + + t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[t+3]; + t2 = Sum0 (f) + Maj (f, g, h); + a += t1; + e = t1 + t2; + + t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[t+4]; + t2 = Sum0 (e) + Maj (e, f, g); + h += t1; + d = t1 + t2; + + t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[t+5]; + t2 = Sum0 (d) + Maj (d, e, f); + g += t1; + c = t1 + t2; + + t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[t+6]; + t2 = Sum0 (c) + Maj (c, d, e); + f += t1; + b = t1 + t2; + + t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[t+7]; + t2 = Sum0 (b) + Maj (b, c, d); + e += t1; + a = t1 + t2; + + t += 8; +#endif + } + + /* Update chaining vars. */ + hd->h0 += a; + hd->h1 += b; + hd->h2 += c; + hd->h3 += d; + hd->h4 += e; + hd->h5 += f; + hd->h6 += g; + hd->h7 += h; +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +sha512_write (void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + SHA512_CONTEXT *hd = context; + + if (hd->count == 128) + { /* flush the buffer */ + transform (hd, hd->buf); + _gcry_burn_stack (768); + hd->count = 0; + hd->nblocks++; + } + if (!inbuf) + return; + if (hd->count) + { + for (; inlen && hd->count < 128; inlen--) + hd->buf[hd->count++] = *inbuf++; + sha512_write (context, NULL, 0); + if (!inlen) + return; + } + + while (inlen >= 128) + { + transform (hd, inbuf); + hd->count = 0; + hd->nblocks++; + inlen -= 128; + inbuf += 128; + } + _gcry_burn_stack (768); + for (; inlen && hd->count < 128; inlen--) + hd->buf[hd->count++] = *inbuf++; +} + + +/* The routine final terminates the computation and + * returns the digest. + * The handle is prepared for a new cycle, but adding bytes to the + * handle will the destroy the returned buffer. + * Returns: 64 bytes representing the digest. When used for sha384, + * we take the leftmost 48 of those bytes. + */ + +static void +sha512_final (void *context) +{ + SHA512_CONTEXT *hd = context; + u64 t, msb, lsb; + byte *p; + + sha512_write (context, NULL, 0); /* flush */ ; + + t = hd->nblocks; + /* multiply by 128 to make a byte count */ + lsb = t << 7; + msb = t >> 57; + /* add the count */ + t = lsb; + if ((lsb += hd->count) < t) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 61; + + if (hd->count < 112) + { /* enough room */ + hd->buf[hd->count++] = 0x80; /* pad */ + while (hd->count < 112) + hd->buf[hd->count++] = 0; /* pad */ + } + else + { /* need one extra block */ + hd->buf[hd->count++] = 0x80; /* pad character */ + while (hd->count < 128) + hd->buf[hd->count++] = 0; + sha512_write (context, NULL, 0); /* flush */ ; + memset (hd->buf, 0, 112); /* fill next block with zeroes */ + } + /* append the 128 bit count */ + hd->buf[112] = msb >> 56; + hd->buf[113] = msb >> 48; + hd->buf[114] = msb >> 40; + hd->buf[115] = msb >> 32; + hd->buf[116] = msb >> 24; + hd->buf[117] = msb >> 16; + hd->buf[118] = msb >> 8; + hd->buf[119] = msb; + + hd->buf[120] = lsb >> 56; + hd->buf[121] = lsb >> 48; + hd->buf[122] = lsb >> 40; + hd->buf[123] = lsb >> 32; + hd->buf[124] = lsb >> 24; + hd->buf[125] = lsb >> 16; + hd->buf[126] = lsb >> 8; + hd->buf[127] = lsb; + transform (hd, hd->buf); + _gcry_burn_stack (768); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *(u64*)p = hd->h##a ; p += 8; } while (0) +#else /* little endian */ +#define X(a) do { *p++ = hd->h##a >> 56; *p++ = hd->h##a >> 48; \ + *p++ = hd->h##a >> 40; *p++ = hd->h##a >> 32; \ + *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ + *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0) +#endif + X (0); + X (1); + X (2); + X (3); + X (4); + X (5); + /* Note that these last two chunks are included even for SHA384. + We just ignore them. */ + X (6); + X (7); +#undef X +} + +static byte * +sha512_read (void *context) +{ + SHA512_CONTEXT *hd = (SHA512_CONTEXT *) context; + return hd->buf; +} + + + +/* + Self-test section. + */ + + +static gpg_err_code_t +selftests_sha384 (int extended, selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + + what = "short string"; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA384, 0, + "abc", 3, + "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07" + "\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed" + "\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7", 48); + if (errtxt) + goto failed; + + if (extended) + { + what = "long string"; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA384, 0, + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + "\x09\x33\x0C\x33\xF7\x11\x47\xE8\x3D\x19\x2F\xC7\x82\xCD\x1B\x47" + "\x53\x11\x1B\x17\x3B\x3B\x05\xD2\x2F\xA0\x80\x86\xE3\xB0\xF7\x12" + "\xFC\xC7\xC7\x1A\x55\x7E\x2D\xB9\x66\xC3\xE9\xFA\x91\x74\x60\x39", + 48); + if (errtxt) + goto failed; + + what = "one million \"a\""; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA384, 1, + NULL, 0, + "\x9D\x0E\x18\x09\x71\x64\x74\xCB\x08\x6E\x83\x4E\x31\x0A\x4A\x1C" + "\xED\x14\x9E\x9C\x00\xF2\x48\x52\x79\x72\xCE\xC5\x70\x4C\x2A\x5B" + "\x07\xB8\xB3\xDC\x38\xEC\xC4\xEB\xAE\x97\xDD\xD8\x7F\x3D\x89\x85", + 48); + if (errtxt) + goto failed; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("digest", GCRY_MD_SHA384, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + +static gpg_err_code_t +selftests_sha512 (int extended, selftest_report_func_t report) +{ + const char *what; + const char *errtxt; + + what = "short string"; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA512, 0, + "abc", 3, + "\xDD\xAF\x35\xA1\x93\x61\x7A\xBA\xCC\x41\x73\x49\xAE\x20\x41\x31" + "\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A" + "\x21\x92\x99\x2A\x27\x4F\xC1\xA8\x36\xBA\x3C\x23\xA3\xFE\xEB\xBD" + "\x45\x4D\x44\x23\x64\x3C\xE8\x0E\x2A\x9A\xC9\x4F\xA5\x4C\xA4\x9F", 64); + if (errtxt) + goto failed; + + if (extended) + { + what = "long string"; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA512, 0, + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + "\x8E\x95\x9B\x75\xDA\xE3\x13\xDA\x8C\xF4\xF7\x28\x14\xFC\x14\x3F" + "\x8F\x77\x79\xC6\xEB\x9F\x7F\xA1\x72\x99\xAE\xAD\xB6\x88\x90\x18" + "\x50\x1D\x28\x9E\x49\x00\xF7\xE4\x33\x1B\x99\xDE\xC4\xB5\x43\x3A" + "\xC7\xD3\x29\xEE\xB6\xDD\x26\x54\x5E\x96\xE5\x5B\x87\x4B\xE9\x09", + 64); + if (errtxt) + goto failed; + + what = "one million \"a\""; + errtxt = _gcry_hash_selftest_check_one + (GCRY_MD_SHA512, 1, + NULL, 0, + "\xE7\x18\x48\x3D\x0C\xE7\x69\x64\x4E\x2E\x42\xC7\xBC\x15\xB4\x63" + "\x8E\x1F\x98\xB1\x3B\x20\x44\x28\x56\x32\xA8\x03\xAF\xA9\x73\xEB" + "\xDE\x0F\xF2\x44\x87\x7E\xA6\x0A\x4C\xB0\x43\x2C\xE5\x77\xC3\x1B" + "\xEB\x00\x9C\x5C\x2C\x49\xAA\x2E\x4E\xAD\xB2\x17\xAD\x8C\xC0\x9B", + 64); + if (errtxt) + goto failed; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("digest", GCRY_MD_SHA512, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +} + + +/* Run a full self-test for ALGO and return 0 on success. */ +static gpg_err_code_t +run_selftests (int algo, int extended, selftest_report_func_t report) +{ + gpg_err_code_t ec; + + switch (algo) + { + case GCRY_MD_SHA384: + ec = selftests_sha384 (extended, report); + break; + case GCRY_MD_SHA512: + ec = selftests_sha512 (extended, report); + break; + default: + ec = GPG_ERR_DIGEST_ALGO; + break; + + } + return ec; +} + + + + +static byte sha512_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.3 */ + { + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40 + }; + +static gcry_md_oid_spec_t oid_spec_sha512[] = + { + { "2.16.840.1.101.3.4.2.3" }, + + /* PKCS#1 sha512WithRSAEncryption */ + { "1.2.840.113549.1.1.13" }, + + { NULL } + }; + +gcry_md_spec_t _gcry_digest_spec_sha512 = + { + "SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64, + sha512_init, sha512_write, sha512_final, sha512_read, + sizeof (SHA512_CONTEXT), + }; +md_extra_spec_t _gcry_digest_extraspec_sha512 = + { + run_selftests + }; + +static byte sha384_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.2 */ + { + 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, + 0x00, 0x04, 0x30 + }; + +static gcry_md_oid_spec_t oid_spec_sha384[] = + { + { "2.16.840.1.101.3.4.2.2" }, + + /* PKCS#1 sha384WithRSAEncryption */ + { "1.2.840.113549.1.1.12" }, + + { NULL }, + }; + +gcry_md_spec_t _gcry_digest_spec_sha384 = + { + "SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48, + sha384_init, sha512_write, sha512_final, sha512_read, + sizeof (SHA512_CONTEXT), + }; +md_extra_spec_t _gcry_digest_extraspec_sha384 = + { + run_selftests + }; diff --git a/grub-core/lib/libgcrypt/cipher/test-getrusage.c b/grub-core/lib/libgcrypt/cipher/test-getrusage.c new file mode 100644 index 0000000..479eaab --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/test-getrusage.c @@ -0,0 +1,105 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/resource.h> + +int +main (int argc, char **argv) +{ + struct rusage buf; + + if (argc > 1) + { + system (argv[1]); + + if (getrusage (RUSAGE_CHILDREN, &buf )) + { + perror ("getrusage"); + return 1; + } + } + else + { + if (getrusage (RUSAGE_SELF, &buf )) + { + perror ("getrusage"); + return 1; + } + } + + printf ("ru_utime = %ld.%06ld\n", + buf.ru_utime.tv_sec, buf.ru_utime.tv_usec); + printf ("ru_stime = %ld.%06ld\n", + buf.ru_stime.tv_sec, buf.ru_stime.tv_usec); + printf ("ru_maxrss = %ld\n", buf.ru_maxrss ); + printf ("ru_ixrss = %ld\n", buf.ru_ixrss ); + printf ("ru_idrss = %ld\n", buf.ru_idrss ); + printf ("ru_isrss = %ld\n", buf.ru_isrss ); + printf ("ru_minflt = %ld\n", buf.ru_minflt ); + printf ("ru_majflt = %ld\n", buf.ru_majflt ); + printf ("ru_nswap = %ld\n", buf.ru_nswap ); + printf ("ru_inblock = %ld\n", buf.ru_inblock ); + printf ("ru_oublock = %ld\n", buf.ru_oublock ); + printf ("ru_msgsnd = %ld\n", buf.ru_msgsnd ); + printf ("ru_msgrcv = %ld\n", buf.ru_msgrcv ); + printf ("ru_nsignals= %ld\n", buf.ru_nsignals ); + printf ("ru_nvcsw = %ld\n", buf.ru_nvcsw ); + printf ("ru_nivcsw = %ld\n", buf.ru_nivcsw ); + + fprintf (stderr, "ru_utime ru_stime ru_minflt ru_nccsw ru_nivcsw\n"); + fprintf (stderr, "%ld.%06ld %ld.%06ld %5ld %5ld %5ld\n"); + + + return 0; +} + + +/* Codesnippet for debugging in random.c. */ +#if 0 +static void +collect_rusage_stats (struct rusage *rb) +{ + static int idx; + static struct rusage buf[100]; + + if (!rb) + { + int i; + + fprintf (stderr, "ru_utime ru_stime ru_minflt ru_nvcsw ru_nivcsw\n"); + for (i=0; i < idx; i++) + fprintf (stderr, "%ld.%06ld %ld.%06ld %5ld %5ld %5ld\n", + buf[i].ru_utime.tv_sec, buf[i].ru_utime.tv_usec, + buf[i].ru_stime.tv_sec, buf[i].ru_stime.tv_usec, + buf[i].ru_minflt, + buf[i].ru_nvcsw, + buf[i].ru_nivcsw); + } + else if (idx < DIM(buf)) + { + buf[idx++] = *rb; + } +} +#endif +/* + void + _gcry_random_dump_stats() + { +@@ -233,8 +261,11 @@ + rndstats.naddbytes, rndstats.addbytes, + rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1, + rndstats.ngetbytes2, rndstats.getbytes2 ); ++ ++ collect_rusage_stats (NULL); + } + +======== + + getrusage (RUSAGE_SELF, &buf ); ++ collect_rusage_stats (&buf); + add_randomness( &buf, sizeof buf, 1 ); + memset( &buf, 0, sizeof buf ); + } + +*/ + + diff --git a/grub-core/lib/libgcrypt/cipher/tiger.c b/grub-core/lib/libgcrypt/cipher/tiger.c new file mode 100644 index 0000000..d4ad514 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/tiger.c @@ -0,0 +1,911 @@ +/* tiger.c - The TIGER hash function + * Copyright (C) 1998, 2001, 2002, 2003, 2010 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* See http://www.cs.technion.ac.il/~biham/Reports/Tiger/ */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "g10lib.h" +#include "cipher.h" + +/* We really need a 64 bit type for this code. */ +#ifdef HAVE_U64_TYPEDEF + +typedef struct +{ + u64 a, b, c; + byte buf[64]; + int count; + u32 nblocks; + int variant; /* 0 = old code, 1 = fixed code, 2 - TIGER2. */ +} TIGER_CONTEXT; + + +/********************************* + * Okay, okay, this is not the fastest code - improvements are welcome. + * + */ + +/* Some test vectors: + * "" 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A + * "abc" F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951 + * "Tiger" 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF + * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" + * 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386 + * "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789" + * 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197 + * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham" + * 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303 + * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" + * "eedings of Fast Software Encryption 3, Cambridge." + * EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193 + * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" + * "eedings of Fast Software Encryption 3, Cambridge, 1996." + * 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC + * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEF" + * "GHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" + * 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4 + */ + +static u64 sbox1[256] = { + U64_C(0x02aab17cf7e90c5e) /* 0 */, U64_C(0xac424b03e243a8ec) /* 1 */, + U64_C(0x72cd5be30dd5fcd3) /* 2 */, U64_C(0x6d019b93f6f97f3a) /* 3 */, + U64_C(0xcd9978ffd21f9193) /* 4 */, U64_C(0x7573a1c9708029e2) /* 5 */, + U64_C(0xb164326b922a83c3) /* 6 */, U64_C(0x46883eee04915870) /* 7 */, + U64_C(0xeaace3057103ece6) /* 8 */, U64_C(0xc54169b808a3535c) /* 9 */, + U64_C(0x4ce754918ddec47c) /* 10 */, U64_C(0x0aa2f4dfdc0df40c) /* 11 */, + U64_C(0x10b76f18a74dbefa) /* 12 */, U64_C(0xc6ccb6235ad1ab6a) /* 13 */, + U64_C(0x13726121572fe2ff) /* 14 */, U64_C(0x1a488c6f199d921e) /* 15 */, + U64_C(0x4bc9f9f4da0007ca) /* 16 */, U64_C(0x26f5e6f6e85241c7) /* 17 */, + U64_C(0x859079dbea5947b6) /* 18 */, U64_C(0x4f1885c5c99e8c92) /* 19 */, + U64_C(0xd78e761ea96f864b) /* 20 */, U64_C(0x8e36428c52b5c17d) /* 21 */, + U64_C(0x69cf6827373063c1) /* 22 */, U64_C(0xb607c93d9bb4c56e) /* 23 */, + U64_C(0x7d820e760e76b5ea) /* 24 */, U64_C(0x645c9cc6f07fdc42) /* 25 */, + U64_C(0xbf38a078243342e0) /* 26 */, U64_C(0x5f6b343c9d2e7d04) /* 27 */, + U64_C(0xf2c28aeb600b0ec6) /* 28 */, U64_C(0x6c0ed85f7254bcac) /* 29 */, + U64_C(0x71592281a4db4fe5) /* 30 */, U64_C(0x1967fa69ce0fed9f) /* 31 */, + U64_C(0xfd5293f8b96545db) /* 32 */, U64_C(0xc879e9d7f2a7600b) /* 33 */, + U64_C(0x860248920193194e) /* 34 */, U64_C(0xa4f9533b2d9cc0b3) /* 35 */, + U64_C(0x9053836c15957613) /* 36 */, U64_C(0xdb6dcf8afc357bf1) /* 37 */, + U64_C(0x18beea7a7a370f57) /* 38 */, U64_C(0x037117ca50b99066) /* 39 */, + U64_C(0x6ab30a9774424a35) /* 40 */, U64_C(0xf4e92f02e325249b) /* 41 */, + U64_C(0x7739db07061ccae1) /* 42 */, U64_C(0xd8f3b49ceca42a05) /* 43 */, + U64_C(0xbd56be3f51382f73) /* 44 */, U64_C(0x45faed5843b0bb28) /* 45 */, + U64_C(0x1c813d5c11bf1f83) /* 46 */, U64_C(0x8af0e4b6d75fa169) /* 47 */, + U64_C(0x33ee18a487ad9999) /* 48 */, U64_C(0x3c26e8eab1c94410) /* 49 */, + U64_C(0xb510102bc0a822f9) /* 50 */, U64_C(0x141eef310ce6123b) /* 51 */, + U64_C(0xfc65b90059ddb154) /* 52 */, U64_C(0xe0158640c5e0e607) /* 53 */, + U64_C(0x884e079826c3a3cf) /* 54 */, U64_C(0x930d0d9523c535fd) /* 55 */, + U64_C(0x35638d754e9a2b00) /* 56 */, U64_C(0x4085fccf40469dd5) /* 57 */, + U64_C(0xc4b17ad28be23a4c) /* 58 */, U64_C(0xcab2f0fc6a3e6a2e) /* 59 */, + U64_C(0x2860971a6b943fcd) /* 60 */, U64_C(0x3dde6ee212e30446) /* 61 */, + U64_C(0x6222f32ae01765ae) /* 62 */, U64_C(0x5d550bb5478308fe) /* 63 */, + U64_C(0xa9efa98da0eda22a) /* 64 */, U64_C(0xc351a71686c40da7) /* 65 */, + U64_C(0x1105586d9c867c84) /* 66 */, U64_C(0xdcffee85fda22853) /* 67 */, + U64_C(0xccfbd0262c5eef76) /* 68 */, U64_C(0xbaf294cb8990d201) /* 69 */, + U64_C(0xe69464f52afad975) /* 70 */, U64_C(0x94b013afdf133e14) /* 71 */, + U64_C(0x06a7d1a32823c958) /* 72 */, U64_C(0x6f95fe5130f61119) /* 73 */, + U64_C(0xd92ab34e462c06c0) /* 74 */, U64_C(0xed7bde33887c71d2) /* 75 */, + U64_C(0x79746d6e6518393e) /* 76 */, U64_C(0x5ba419385d713329) /* 77 */, + U64_C(0x7c1ba6b948a97564) /* 78 */, U64_C(0x31987c197bfdac67) /* 79 */, + U64_C(0xde6c23c44b053d02) /* 80 */, U64_C(0x581c49fed002d64d) /* 81 */, + U64_C(0xdd474d6338261571) /* 82 */, U64_C(0xaa4546c3e473d062) /* 83 */, + U64_C(0x928fce349455f860) /* 84 */, U64_C(0x48161bbacaab94d9) /* 85 */, + U64_C(0x63912430770e6f68) /* 86 */, U64_C(0x6ec8a5e602c6641c) /* 87 */, + U64_C(0x87282515337ddd2b) /* 88 */, U64_C(0x2cda6b42034b701b) /* 89 */, + U64_C(0xb03d37c181cb096d) /* 90 */, U64_C(0xe108438266c71c6f) /* 91 */, + U64_C(0x2b3180c7eb51b255) /* 92 */, U64_C(0xdf92b82f96c08bbc) /* 93 */, + U64_C(0x5c68c8c0a632f3ba) /* 94 */, U64_C(0x5504cc861c3d0556) /* 95 */, + U64_C(0xabbfa4e55fb26b8f) /* 96 */, U64_C(0x41848b0ab3baceb4) /* 97 */, + U64_C(0xb334a273aa445d32) /* 98 */, U64_C(0xbca696f0a85ad881) /* 99 */, + U64_C(0x24f6ec65b528d56c) /* 100 */, U64_C(0x0ce1512e90f4524a) /* 101 */, + U64_C(0x4e9dd79d5506d35a) /* 102 */, U64_C(0x258905fac6ce9779) /* 103 */, + U64_C(0x2019295b3e109b33) /* 104 */, U64_C(0xf8a9478b73a054cc) /* 105 */, + U64_C(0x2924f2f934417eb0) /* 106 */, U64_C(0x3993357d536d1bc4) /* 107 */, + U64_C(0x38a81ac21db6ff8b) /* 108 */, U64_C(0x47c4fbf17d6016bf) /* 109 */, + U64_C(0x1e0faadd7667e3f5) /* 110 */, U64_C(0x7abcff62938beb96) /* 111 */, + U64_C(0xa78dad948fc179c9) /* 112 */, U64_C(0x8f1f98b72911e50d) /* 113 */, + U64_C(0x61e48eae27121a91) /* 114 */, U64_C(0x4d62f7ad31859808) /* 115 */, + U64_C(0xeceba345ef5ceaeb) /* 116 */, U64_C(0xf5ceb25ebc9684ce) /* 117 */, + U64_C(0xf633e20cb7f76221) /* 118 */, U64_C(0xa32cdf06ab8293e4) /* 119 */, + U64_C(0x985a202ca5ee2ca4) /* 120 */, U64_C(0xcf0b8447cc8a8fb1) /* 121 */, + U64_C(0x9f765244979859a3) /* 122 */, U64_C(0xa8d516b1a1240017) /* 123 */, + U64_C(0x0bd7ba3ebb5dc726) /* 124 */, U64_C(0xe54bca55b86adb39) /* 125 */, + U64_C(0x1d7a3afd6c478063) /* 126 */, U64_C(0x519ec608e7669edd) /* 127 */, + U64_C(0x0e5715a2d149aa23) /* 128 */, U64_C(0x177d4571848ff194) /* 129 */, + U64_C(0xeeb55f3241014c22) /* 130 */, U64_C(0x0f5e5ca13a6e2ec2) /* 131 */, + U64_C(0x8029927b75f5c361) /* 132 */, U64_C(0xad139fabc3d6e436) /* 133 */, + U64_C(0x0d5df1a94ccf402f) /* 134 */, U64_C(0x3e8bd948bea5dfc8) /* 135 */, + U64_C(0xa5a0d357bd3ff77e) /* 136 */, U64_C(0xa2d12e251f74f645) /* 137 */, + U64_C(0x66fd9e525e81a082) /* 138 */, U64_C(0x2e0c90ce7f687a49) /* 139 */, + U64_C(0xc2e8bcbeba973bc5) /* 140 */, U64_C(0x000001bce509745f) /* 141 */, + U64_C(0x423777bbe6dab3d6) /* 142 */, U64_C(0xd1661c7eaef06eb5) /* 143 */, + U64_C(0xa1781f354daacfd8) /* 144 */, U64_C(0x2d11284a2b16affc) /* 145 */, + U64_C(0xf1fc4f67fa891d1f) /* 146 */, U64_C(0x73ecc25dcb920ada) /* 147 */, + U64_C(0xae610c22c2a12651) /* 148 */, U64_C(0x96e0a810d356b78a) /* 149 */, + U64_C(0x5a9a381f2fe7870f) /* 150 */, U64_C(0xd5ad62ede94e5530) /* 151 */, + U64_C(0xd225e5e8368d1427) /* 152 */, U64_C(0x65977b70c7af4631) /* 153 */, + U64_C(0x99f889b2de39d74f) /* 154 */, U64_C(0x233f30bf54e1d143) /* 155 */, + U64_C(0x9a9675d3d9a63c97) /* 156 */, U64_C(0x5470554ff334f9a8) /* 157 */, + U64_C(0x166acb744a4f5688) /* 158 */, U64_C(0x70c74caab2e4aead) /* 159 */, + U64_C(0xf0d091646f294d12) /* 160 */, U64_C(0x57b82a89684031d1) /* 161 */, + U64_C(0xefd95a5a61be0b6b) /* 162 */, U64_C(0x2fbd12e969f2f29a) /* 163 */, + U64_C(0x9bd37013feff9fe8) /* 164 */, U64_C(0x3f9b0404d6085a06) /* 165 */, + U64_C(0x4940c1f3166cfe15) /* 166 */, U64_C(0x09542c4dcdf3defb) /* 167 */, + U64_C(0xb4c5218385cd5ce3) /* 168 */, U64_C(0xc935b7dc4462a641) /* 169 */, + U64_C(0x3417f8a68ed3b63f) /* 170 */, U64_C(0xb80959295b215b40) /* 171 */, + U64_C(0xf99cdaef3b8c8572) /* 172 */, U64_C(0x018c0614f8fcb95d) /* 173 */, + U64_C(0x1b14accd1a3acdf3) /* 174 */, U64_C(0x84d471f200bb732d) /* 175 */, + U64_C(0xc1a3110e95e8da16) /* 176 */, U64_C(0x430a7220bf1a82b8) /* 177 */, + U64_C(0xb77e090d39df210e) /* 178 */, U64_C(0x5ef4bd9f3cd05e9d) /* 179 */, + U64_C(0x9d4ff6da7e57a444) /* 180 */, U64_C(0xda1d60e183d4a5f8) /* 181 */, + U64_C(0xb287c38417998e47) /* 182 */, U64_C(0xfe3edc121bb31886) /* 183 */, + U64_C(0xc7fe3ccc980ccbef) /* 184 */, U64_C(0xe46fb590189bfd03) /* 185 */, + U64_C(0x3732fd469a4c57dc) /* 186 */, U64_C(0x7ef700a07cf1ad65) /* 187 */, + U64_C(0x59c64468a31d8859) /* 188 */, U64_C(0x762fb0b4d45b61f6) /* 189 */, + U64_C(0x155baed099047718) /* 190 */, U64_C(0x68755e4c3d50baa6) /* 191 */, + U64_C(0xe9214e7f22d8b4df) /* 192 */, U64_C(0x2addbf532eac95f4) /* 193 */, + U64_C(0x32ae3909b4bd0109) /* 194 */, U64_C(0x834df537b08e3450) /* 195 */, + U64_C(0xfa209da84220728d) /* 196 */, U64_C(0x9e691d9b9efe23f7) /* 197 */, + U64_C(0x0446d288c4ae8d7f) /* 198 */, U64_C(0x7b4cc524e169785b) /* 199 */, + U64_C(0x21d87f0135ca1385) /* 200 */, U64_C(0xcebb400f137b8aa5) /* 201 */, + U64_C(0x272e2b66580796be) /* 202 */, U64_C(0x3612264125c2b0de) /* 203 */, + U64_C(0x057702bdad1efbb2) /* 204 */, U64_C(0xd4babb8eacf84be9) /* 205 */, + U64_C(0x91583139641bc67b) /* 206 */, U64_C(0x8bdc2de08036e024) /* 207 */, + U64_C(0x603c8156f49f68ed) /* 208 */, U64_C(0xf7d236f7dbef5111) /* 209 */, + U64_C(0x9727c4598ad21e80) /* 210 */, U64_C(0xa08a0896670a5fd7) /* 211 */, + U64_C(0xcb4a8f4309eba9cb) /* 212 */, U64_C(0x81af564b0f7036a1) /* 213 */, + U64_C(0xc0b99aa778199abd) /* 214 */, U64_C(0x959f1ec83fc8e952) /* 215 */, + U64_C(0x8c505077794a81b9) /* 216 */, U64_C(0x3acaaf8f056338f0) /* 217 */, + U64_C(0x07b43f50627a6778) /* 218 */, U64_C(0x4a44ab49f5eccc77) /* 219 */, + U64_C(0x3bc3d6e4b679ee98) /* 220 */, U64_C(0x9cc0d4d1cf14108c) /* 221 */, + U64_C(0x4406c00b206bc8a0) /* 222 */, U64_C(0x82a18854c8d72d89) /* 223 */, + U64_C(0x67e366b35c3c432c) /* 224 */, U64_C(0xb923dd61102b37f2) /* 225 */, + U64_C(0x56ab2779d884271d) /* 226 */, U64_C(0xbe83e1b0ff1525af) /* 227 */, + U64_C(0xfb7c65d4217e49a9) /* 228 */, U64_C(0x6bdbe0e76d48e7d4) /* 229 */, + U64_C(0x08df828745d9179e) /* 230 */, U64_C(0x22ea6a9add53bd34) /* 231 */, + U64_C(0xe36e141c5622200a) /* 232 */, U64_C(0x7f805d1b8cb750ee) /* 233 */, + U64_C(0xafe5c7a59f58e837) /* 234 */, U64_C(0xe27f996a4fb1c23c) /* 235 */, + U64_C(0xd3867dfb0775f0d0) /* 236 */, U64_C(0xd0e673de6e88891a) /* 237 */, + U64_C(0x123aeb9eafb86c25) /* 238 */, U64_C(0x30f1d5d5c145b895) /* 239 */, + U64_C(0xbb434a2dee7269e7) /* 240 */, U64_C(0x78cb67ecf931fa38) /* 241 */, + U64_C(0xf33b0372323bbf9c) /* 242 */, U64_C(0x52d66336fb279c74) /* 243 */, + U64_C(0x505f33ac0afb4eaa) /* 244 */, U64_C(0xe8a5cd99a2cce187) /* 245 */, + U64_C(0x534974801e2d30bb) /* 246 */, U64_C(0x8d2d5711d5876d90) /* 247 */, + U64_C(0x1f1a412891bc038e) /* 248 */, U64_C(0xd6e2e71d82e56648) /* 249 */, + U64_C(0x74036c3a497732b7) /* 250 */, U64_C(0x89b67ed96361f5ab) /* 251 */, + U64_C(0xffed95d8f1ea02a2) /* 252 */, U64_C(0xe72b3bd61464d43d) /* 253 */, + U64_C(0xa6300f170bdc4820) /* 254 */, U64_C(0xebc18760ed78a77a) /* 255 */ +}; +static u64 sbox2[256] = { + U64_C(0xe6a6be5a05a12138) /* 256 */, U64_C(0xb5a122a5b4f87c98) /* 257 */, + U64_C(0x563c6089140b6990) /* 258 */, U64_C(0x4c46cb2e391f5dd5) /* 259 */, + U64_C(0xd932addbc9b79434) /* 260 */, U64_C(0x08ea70e42015aff5) /* 261 */, + U64_C(0xd765a6673e478cf1) /* 262 */, U64_C(0xc4fb757eab278d99) /* 263 */, + U64_C(0xdf11c6862d6e0692) /* 264 */, U64_C(0xddeb84f10d7f3b16) /* 265 */, + U64_C(0x6f2ef604a665ea04) /* 266 */, U64_C(0x4a8e0f0ff0e0dfb3) /* 267 */, + U64_C(0xa5edeef83dbcba51) /* 268 */, U64_C(0xfc4f0a2a0ea4371e) /* 269 */, + U64_C(0xe83e1da85cb38429) /* 270 */, U64_C(0xdc8ff882ba1b1ce2) /* 271 */, + U64_C(0xcd45505e8353e80d) /* 272 */, U64_C(0x18d19a00d4db0717) /* 273 */, + U64_C(0x34a0cfeda5f38101) /* 274 */, U64_C(0x0be77e518887caf2) /* 275 */, + U64_C(0x1e341438b3c45136) /* 276 */, U64_C(0xe05797f49089ccf9) /* 277 */, + U64_C(0xffd23f9df2591d14) /* 278 */, U64_C(0x543dda228595c5cd) /* 279 */, + U64_C(0x661f81fd99052a33) /* 280 */, U64_C(0x8736e641db0f7b76) /* 281 */, + U64_C(0x15227725418e5307) /* 282 */, U64_C(0xe25f7f46162eb2fa) /* 283 */, + U64_C(0x48a8b2126c13d9fe) /* 284 */, U64_C(0xafdc541792e76eea) /* 285 */, + U64_C(0x03d912bfc6d1898f) /* 286 */, U64_C(0x31b1aafa1b83f51b) /* 287 */, + U64_C(0xf1ac2796e42ab7d9) /* 288 */, U64_C(0x40a3a7d7fcd2ebac) /* 289 */, + U64_C(0x1056136d0afbbcc5) /* 290 */, U64_C(0x7889e1dd9a6d0c85) /* 291 */, + U64_C(0xd33525782a7974aa) /* 292 */, U64_C(0xa7e25d09078ac09b) /* 293 */, + U64_C(0xbd4138b3eac6edd0) /* 294 */, U64_C(0x920abfbe71eb9e70) /* 295 */, + U64_C(0xa2a5d0f54fc2625c) /* 296 */, U64_C(0xc054e36b0b1290a3) /* 297 */, + U64_C(0xf6dd59ff62fe932b) /* 298 */, U64_C(0x3537354511a8ac7d) /* 299 */, + U64_C(0xca845e9172fadcd4) /* 300 */, U64_C(0x84f82b60329d20dc) /* 301 */, + U64_C(0x79c62ce1cd672f18) /* 302 */, U64_C(0x8b09a2add124642c) /* 303 */, + U64_C(0xd0c1e96a19d9e726) /* 304 */, U64_C(0x5a786a9b4ba9500c) /* 305 */, + U64_C(0x0e020336634c43f3) /* 306 */, U64_C(0xc17b474aeb66d822) /* 307 */, + U64_C(0x6a731ae3ec9baac2) /* 308 */, U64_C(0x8226667ae0840258) /* 309 */, + U64_C(0x67d4567691caeca5) /* 310 */, U64_C(0x1d94155c4875adb5) /* 311 */, + U64_C(0x6d00fd985b813fdf) /* 312 */, U64_C(0x51286efcb774cd06) /* 313 */, + U64_C(0x5e8834471fa744af) /* 314 */, U64_C(0xf72ca0aee761ae2e) /* 315 */, + U64_C(0xbe40e4cdaee8e09a) /* 316 */, U64_C(0xe9970bbb5118f665) /* 317 */, + U64_C(0x726e4beb33df1964) /* 318 */, U64_C(0x703b000729199762) /* 319 */, + U64_C(0x4631d816f5ef30a7) /* 320 */, U64_C(0xb880b5b51504a6be) /* 321 */, + U64_C(0x641793c37ed84b6c) /* 322 */, U64_C(0x7b21ed77f6e97d96) /* 323 */, + U64_C(0x776306312ef96b73) /* 324 */, U64_C(0xae528948e86ff3f4) /* 325 */, + U64_C(0x53dbd7f286a3f8f8) /* 326 */, U64_C(0x16cadce74cfc1063) /* 327 */, + U64_C(0x005c19bdfa52c6dd) /* 328 */, U64_C(0x68868f5d64d46ad3) /* 329 */, + U64_C(0x3a9d512ccf1e186a) /* 330 */, U64_C(0x367e62c2385660ae) /* 331 */, + U64_C(0xe359e7ea77dcb1d7) /* 332 */, U64_C(0x526c0773749abe6e) /* 333 */, + U64_C(0x735ae5f9d09f734b) /* 334 */, U64_C(0x493fc7cc8a558ba8) /* 335 */, + U64_C(0xb0b9c1533041ab45) /* 336 */, U64_C(0x321958ba470a59bd) /* 337 */, + U64_C(0x852db00b5f46c393) /* 338 */, U64_C(0x91209b2bd336b0e5) /* 339 */, + U64_C(0x6e604f7d659ef19f) /* 340 */, U64_C(0xb99a8ae2782ccb24) /* 341 */, + U64_C(0xccf52ab6c814c4c7) /* 342 */, U64_C(0x4727d9afbe11727b) /* 343 */, + U64_C(0x7e950d0c0121b34d) /* 344 */, U64_C(0x756f435670ad471f) /* 345 */, + U64_C(0xf5add442615a6849) /* 346 */, U64_C(0x4e87e09980b9957a) /* 347 */, + U64_C(0x2acfa1df50aee355) /* 348 */, U64_C(0xd898263afd2fd556) /* 349 */, + U64_C(0xc8f4924dd80c8fd6) /* 350 */, U64_C(0xcf99ca3d754a173a) /* 351 */, + U64_C(0xfe477bacaf91bf3c) /* 352 */, U64_C(0xed5371f6d690c12d) /* 353 */, + U64_C(0x831a5c285e687094) /* 354 */, U64_C(0xc5d3c90a3708a0a4) /* 355 */, + U64_C(0x0f7f903717d06580) /* 356 */, U64_C(0x19f9bb13b8fdf27f) /* 357 */, + U64_C(0xb1bd6f1b4d502843) /* 358 */, U64_C(0x1c761ba38fff4012) /* 359 */, + U64_C(0x0d1530c4e2e21f3b) /* 360 */, U64_C(0x8943ce69a7372c8a) /* 361 */, + U64_C(0xe5184e11feb5ce66) /* 362 */, U64_C(0x618bdb80bd736621) /* 363 */, + U64_C(0x7d29bad68b574d0b) /* 364 */, U64_C(0x81bb613e25e6fe5b) /* 365 */, + U64_C(0x071c9c10bc07913f) /* 366 */, U64_C(0xc7beeb7909ac2d97) /* 367 */, + U64_C(0xc3e58d353bc5d757) /* 368 */, U64_C(0xeb017892f38f61e8) /* 369 */, + U64_C(0xd4effb9c9b1cc21a) /* 370 */, U64_C(0x99727d26f494f7ab) /* 371 */, + U64_C(0xa3e063a2956b3e03) /* 372 */, U64_C(0x9d4a8b9a4aa09c30) /* 373 */, + U64_C(0x3f6ab7d500090fb4) /* 374 */, U64_C(0x9cc0f2a057268ac0) /* 375 */, + U64_C(0x3dee9d2dedbf42d1) /* 376 */, U64_C(0x330f49c87960a972) /* 377 */, + U64_C(0xc6b2720287421b41) /* 378 */, U64_C(0x0ac59ec07c00369c) /* 379 */, + U64_C(0xef4eac49cb353425) /* 380 */, U64_C(0xf450244eef0129d8) /* 381 */, + U64_C(0x8acc46e5caf4deb6) /* 382 */, U64_C(0x2ffeab63989263f7) /* 383 */, + U64_C(0x8f7cb9fe5d7a4578) /* 384 */, U64_C(0x5bd8f7644e634635) /* 385 */, + U64_C(0x427a7315bf2dc900) /* 386 */, U64_C(0x17d0c4aa2125261c) /* 387 */, + U64_C(0x3992486c93518e50) /* 388 */, U64_C(0xb4cbfee0a2d7d4c3) /* 389 */, + U64_C(0x7c75d6202c5ddd8d) /* 390 */, U64_C(0xdbc295d8e35b6c61) /* 391 */, + U64_C(0x60b369d302032b19) /* 392 */, U64_C(0xce42685fdce44132) /* 393 */, + U64_C(0x06f3ddb9ddf65610) /* 394 */, U64_C(0x8ea4d21db5e148f0) /* 395 */, + U64_C(0x20b0fce62fcd496f) /* 396 */, U64_C(0x2c1b912358b0ee31) /* 397 */, + U64_C(0xb28317b818f5a308) /* 398 */, U64_C(0xa89c1e189ca6d2cf) /* 399 */, + U64_C(0x0c6b18576aaadbc8) /* 400 */, U64_C(0xb65deaa91299fae3) /* 401 */, + U64_C(0xfb2b794b7f1027e7) /* 402 */, U64_C(0x04e4317f443b5beb) /* 403 */, + U64_C(0x4b852d325939d0a6) /* 404 */, U64_C(0xd5ae6beefb207ffc) /* 405 */, + U64_C(0x309682b281c7d374) /* 406 */, U64_C(0xbae309a194c3b475) /* 407 */, + U64_C(0x8cc3f97b13b49f05) /* 408 */, U64_C(0x98a9422ff8293967) /* 409 */, + U64_C(0x244b16b01076ff7c) /* 410 */, U64_C(0xf8bf571c663d67ee) /* 411 */, + U64_C(0x1f0d6758eee30da1) /* 412 */, U64_C(0xc9b611d97adeb9b7) /* 413 */, + U64_C(0xb7afd5887b6c57a2) /* 414 */, U64_C(0x6290ae846b984fe1) /* 415 */, + U64_C(0x94df4cdeacc1a5fd) /* 416 */, U64_C(0x058a5bd1c5483aff) /* 417 */, + U64_C(0x63166cc142ba3c37) /* 418 */, U64_C(0x8db8526eb2f76f40) /* 419 */, + U64_C(0xe10880036f0d6d4e) /* 420 */, U64_C(0x9e0523c9971d311d) /* 421 */, + U64_C(0x45ec2824cc7cd691) /* 422 */, U64_C(0x575b8359e62382c9) /* 423 */, + U64_C(0xfa9e400dc4889995) /* 424 */, U64_C(0xd1823ecb45721568) /* 425 */, + U64_C(0xdafd983b8206082f) /* 426 */, U64_C(0xaa7d29082386a8cb) /* 427 */, + U64_C(0x269fcd4403b87588) /* 428 */, U64_C(0x1b91f5f728bdd1e0) /* 429 */, + U64_C(0xe4669f39040201f6) /* 430 */, U64_C(0x7a1d7c218cf04ade) /* 431 */, + U64_C(0x65623c29d79ce5ce) /* 432 */, U64_C(0x2368449096c00bb1) /* 433 */, + U64_C(0xab9bf1879da503ba) /* 434 */, U64_C(0xbc23ecb1a458058e) /* 435 */, + U64_C(0x9a58df01bb401ecc) /* 436 */, U64_C(0xa070e868a85f143d) /* 437 */, + U64_C(0x4ff188307df2239e) /* 438 */, U64_C(0x14d565b41a641183) /* 439 */, + U64_C(0xee13337452701602) /* 440 */, U64_C(0x950e3dcf3f285e09) /* 441 */, + U64_C(0x59930254b9c80953) /* 442 */, U64_C(0x3bf299408930da6d) /* 443 */, + U64_C(0xa955943f53691387) /* 444 */, U64_C(0xa15edecaa9cb8784) /* 445 */, + U64_C(0x29142127352be9a0) /* 446 */, U64_C(0x76f0371fff4e7afb) /* 447 */, + U64_C(0x0239f450274f2228) /* 448 */, U64_C(0xbb073af01d5e868b) /* 449 */, + U64_C(0xbfc80571c10e96c1) /* 450 */, U64_C(0xd267088568222e23) /* 451 */, + U64_C(0x9671a3d48e80b5b0) /* 452 */, U64_C(0x55b5d38ae193bb81) /* 453 */, + U64_C(0x693ae2d0a18b04b8) /* 454 */, U64_C(0x5c48b4ecadd5335f) /* 455 */, + U64_C(0xfd743b194916a1ca) /* 456 */, U64_C(0x2577018134be98c4) /* 457 */, + U64_C(0xe77987e83c54a4ad) /* 458 */, U64_C(0x28e11014da33e1b9) /* 459 */, + U64_C(0x270cc59e226aa213) /* 460 */, U64_C(0x71495f756d1a5f60) /* 461 */, + U64_C(0x9be853fb60afef77) /* 462 */, U64_C(0xadc786a7f7443dbf) /* 463 */, + U64_C(0x0904456173b29a82) /* 464 */, U64_C(0x58bc7a66c232bd5e) /* 465 */, + U64_C(0xf306558c673ac8b2) /* 466 */, U64_C(0x41f639c6b6c9772a) /* 467 */, + U64_C(0x216defe99fda35da) /* 468 */, U64_C(0x11640cc71c7be615) /* 469 */, + U64_C(0x93c43694565c5527) /* 470 */, U64_C(0xea038e6246777839) /* 471 */, + U64_C(0xf9abf3ce5a3e2469) /* 472 */, U64_C(0x741e768d0fd312d2) /* 473 */, + U64_C(0x0144b883ced652c6) /* 474 */, U64_C(0xc20b5a5ba33f8552) /* 475 */, + U64_C(0x1ae69633c3435a9d) /* 476 */, U64_C(0x97a28ca4088cfdec) /* 477 */, + U64_C(0x8824a43c1e96f420) /* 478 */, U64_C(0x37612fa66eeea746) /* 479 */, + U64_C(0x6b4cb165f9cf0e5a) /* 480 */, U64_C(0x43aa1c06a0abfb4a) /* 481 */, + U64_C(0x7f4dc26ff162796b) /* 482 */, U64_C(0x6cbacc8e54ed9b0f) /* 483 */, + U64_C(0xa6b7ffefd2bb253e) /* 484 */, U64_C(0x2e25bc95b0a29d4f) /* 485 */, + U64_C(0x86d6a58bdef1388c) /* 486 */, U64_C(0xded74ac576b6f054) /* 487 */, + U64_C(0x8030bdbc2b45805d) /* 488 */, U64_C(0x3c81af70e94d9289) /* 489 */, + U64_C(0x3eff6dda9e3100db) /* 490 */, U64_C(0xb38dc39fdfcc8847) /* 491 */, + U64_C(0x123885528d17b87e) /* 492 */, U64_C(0xf2da0ed240b1b642) /* 493 */, + U64_C(0x44cefadcd54bf9a9) /* 494 */, U64_C(0x1312200e433c7ee6) /* 495 */, + U64_C(0x9ffcc84f3a78c748) /* 496 */, U64_C(0xf0cd1f72248576bb) /* 497 */, + U64_C(0xec6974053638cfe4) /* 498 */, U64_C(0x2ba7b67c0cec4e4c) /* 499 */, + U64_C(0xac2f4df3e5ce32ed) /* 500 */, U64_C(0xcb33d14326ea4c11) /* 501 */, + U64_C(0xa4e9044cc77e58bc) /* 502 */, U64_C(0x5f513293d934fcef) /* 503 */, + U64_C(0x5dc9645506e55444) /* 504 */, U64_C(0x50de418f317de40a) /* 505 */, + U64_C(0x388cb31a69dde259) /* 506 */, U64_C(0x2db4a83455820a86) /* 507 */, + U64_C(0x9010a91e84711ae9) /* 508 */, U64_C(0x4df7f0b7b1498371) /* 509 */, + U64_C(0xd62a2eabc0977179) /* 510 */, U64_C(0x22fac097aa8d5c0e) /* 511 */ +}; +static u64 sbox3[256] = { + U64_C(0xf49fcc2ff1daf39b) /* 512 */, U64_C(0x487fd5c66ff29281) /* 513 */, + U64_C(0xe8a30667fcdca83f) /* 514 */, U64_C(0x2c9b4be3d2fcce63) /* 515 */, + U64_C(0xda3ff74b93fbbbc2) /* 516 */, U64_C(0x2fa165d2fe70ba66) /* 517 */, + U64_C(0xa103e279970e93d4) /* 518 */, U64_C(0xbecdec77b0e45e71) /* 519 */, + U64_C(0xcfb41e723985e497) /* 520 */, U64_C(0xb70aaa025ef75017) /* 521 */, + U64_C(0xd42309f03840b8e0) /* 522 */, U64_C(0x8efc1ad035898579) /* 523 */, + U64_C(0x96c6920be2b2abc5) /* 524 */, U64_C(0x66af4163375a9172) /* 525 */, + U64_C(0x2174abdcca7127fb) /* 526 */, U64_C(0xb33ccea64a72ff41) /* 527 */, + U64_C(0xf04a4933083066a5) /* 528 */, U64_C(0x8d970acdd7289af5) /* 529 */, + U64_C(0x8f96e8e031c8c25e) /* 530 */, U64_C(0xf3fec02276875d47) /* 531 */, + U64_C(0xec7bf310056190dd) /* 532 */, U64_C(0xf5adb0aebb0f1491) /* 533 */, + U64_C(0x9b50f8850fd58892) /* 534 */, U64_C(0x4975488358b74de8) /* 535 */, + U64_C(0xa3354ff691531c61) /* 536 */, U64_C(0x0702bbe481d2c6ee) /* 537 */, + U64_C(0x89fb24057deded98) /* 538 */, U64_C(0xac3075138596e902) /* 539 */, + U64_C(0x1d2d3580172772ed) /* 540 */, U64_C(0xeb738fc28e6bc30d) /* 541 */, + U64_C(0x5854ef8f63044326) /* 542 */, U64_C(0x9e5c52325add3bbe) /* 543 */, + U64_C(0x90aa53cf325c4623) /* 544 */, U64_C(0xc1d24d51349dd067) /* 545 */, + U64_C(0x2051cfeea69ea624) /* 546 */, U64_C(0x13220f0a862e7e4f) /* 547 */, + U64_C(0xce39399404e04864) /* 548 */, U64_C(0xd9c42ca47086fcb7) /* 549 */, + U64_C(0x685ad2238a03e7cc) /* 550 */, U64_C(0x066484b2ab2ff1db) /* 551 */, + U64_C(0xfe9d5d70efbf79ec) /* 552 */, U64_C(0x5b13b9dd9c481854) /* 553 */, + U64_C(0x15f0d475ed1509ad) /* 554 */, U64_C(0x0bebcd060ec79851) /* 555 */, + U64_C(0xd58c6791183ab7f8) /* 556 */, U64_C(0xd1187c5052f3eee4) /* 557 */, + U64_C(0xc95d1192e54e82ff) /* 558 */, U64_C(0x86eea14cb9ac6ca2) /* 559 */, + U64_C(0x3485beb153677d5d) /* 560 */, U64_C(0xdd191d781f8c492a) /* 561 */, + U64_C(0xf60866baa784ebf9) /* 562 */, U64_C(0x518f643ba2d08c74) /* 563 */, + U64_C(0x8852e956e1087c22) /* 564 */, U64_C(0xa768cb8dc410ae8d) /* 565 */, + U64_C(0x38047726bfec8e1a) /* 566 */, U64_C(0xa67738b4cd3b45aa) /* 567 */, + U64_C(0xad16691cec0dde19) /* 568 */, U64_C(0xc6d4319380462e07) /* 569 */, + U64_C(0xc5a5876d0ba61938) /* 570 */, U64_C(0x16b9fa1fa58fd840) /* 571 */, + U64_C(0x188ab1173ca74f18) /* 572 */, U64_C(0xabda2f98c99c021f) /* 573 */, + U64_C(0x3e0580ab134ae816) /* 574 */, U64_C(0x5f3b05b773645abb) /* 575 */, + U64_C(0x2501a2be5575f2f6) /* 576 */, U64_C(0x1b2f74004e7e8ba9) /* 577 */, + U64_C(0x1cd7580371e8d953) /* 578 */, U64_C(0x7f6ed89562764e30) /* 579 */, + U64_C(0xb15926ff596f003d) /* 580 */, U64_C(0x9f65293da8c5d6b9) /* 581 */, + U64_C(0x6ecef04dd690f84c) /* 582 */, U64_C(0x4782275fff33af88) /* 583 */, + U64_C(0xe41433083f820801) /* 584 */, U64_C(0xfd0dfe409a1af9b5) /* 585 */, + U64_C(0x4325a3342cdb396b) /* 586 */, U64_C(0x8ae77e62b301b252) /* 587 */, + U64_C(0xc36f9e9f6655615a) /* 588 */, U64_C(0x85455a2d92d32c09) /* 589 */, + U64_C(0xf2c7dea949477485) /* 590 */, U64_C(0x63cfb4c133a39eba) /* 591 */, + U64_C(0x83b040cc6ebc5462) /* 592 */, U64_C(0x3b9454c8fdb326b0) /* 593 */, + U64_C(0x56f56a9e87ffd78c) /* 594 */, U64_C(0x2dc2940d99f42bc6) /* 595 */, + U64_C(0x98f7df096b096e2d) /* 596 */, U64_C(0x19a6e01e3ad852bf) /* 597 */, + U64_C(0x42a99ccbdbd4b40b) /* 598 */, U64_C(0xa59998af45e9c559) /* 599 */, + U64_C(0x366295e807d93186) /* 600 */, U64_C(0x6b48181bfaa1f773) /* 601 */, + U64_C(0x1fec57e2157a0a1d) /* 602 */, U64_C(0x4667446af6201ad5) /* 603 */, + U64_C(0xe615ebcacfb0f075) /* 604 */, U64_C(0xb8f31f4f68290778) /* 605 */, + U64_C(0x22713ed6ce22d11e) /* 606 */, U64_C(0x3057c1a72ec3c93b) /* 607 */, + U64_C(0xcb46acc37c3f1f2f) /* 608 */, U64_C(0xdbb893fd02aaf50e) /* 609 */, + U64_C(0x331fd92e600b9fcf) /* 610 */, U64_C(0xa498f96148ea3ad6) /* 611 */, + U64_C(0xa8d8426e8b6a83ea) /* 612 */, U64_C(0xa089b274b7735cdc) /* 613 */, + U64_C(0x87f6b3731e524a11) /* 614 */, U64_C(0x118808e5cbc96749) /* 615 */, + U64_C(0x9906e4c7b19bd394) /* 616 */, U64_C(0xafed7f7e9b24a20c) /* 617 */, + U64_C(0x6509eadeeb3644a7) /* 618 */, U64_C(0x6c1ef1d3e8ef0ede) /* 619 */, + U64_C(0xb9c97d43e9798fb4) /* 620 */, U64_C(0xa2f2d784740c28a3) /* 621 */, + U64_C(0x7b8496476197566f) /* 622 */, U64_C(0x7a5be3e6b65f069d) /* 623 */, + U64_C(0xf96330ed78be6f10) /* 624 */, U64_C(0xeee60de77a076a15) /* 625 */, + U64_C(0x2b4bee4aa08b9bd0) /* 626 */, U64_C(0x6a56a63ec7b8894e) /* 627 */, + U64_C(0x02121359ba34fef4) /* 628 */, U64_C(0x4cbf99f8283703fc) /* 629 */, + U64_C(0x398071350caf30c8) /* 630 */, U64_C(0xd0a77a89f017687a) /* 631 */, + U64_C(0xf1c1a9eb9e423569) /* 632 */, U64_C(0x8c7976282dee8199) /* 633 */, + U64_C(0x5d1737a5dd1f7abd) /* 634 */, U64_C(0x4f53433c09a9fa80) /* 635 */, + U64_C(0xfa8b0c53df7ca1d9) /* 636 */, U64_C(0x3fd9dcbc886ccb77) /* 637 */, + U64_C(0xc040917ca91b4720) /* 638 */, U64_C(0x7dd00142f9d1dcdf) /* 639 */, + U64_C(0x8476fc1d4f387b58) /* 640 */, U64_C(0x23f8e7c5f3316503) /* 641 */, + U64_C(0x032a2244e7e37339) /* 642 */, U64_C(0x5c87a5d750f5a74b) /* 643 */, + U64_C(0x082b4cc43698992e) /* 644 */, U64_C(0xdf917becb858f63c) /* 645 */, + U64_C(0x3270b8fc5bf86dda) /* 646 */, U64_C(0x10ae72bb29b5dd76) /* 647 */, + U64_C(0x576ac94e7700362b) /* 648 */, U64_C(0x1ad112dac61efb8f) /* 649 */, + U64_C(0x691bc30ec5faa427) /* 650 */, U64_C(0xff246311cc327143) /* 651 */, + U64_C(0x3142368e30e53206) /* 652 */, U64_C(0x71380e31e02ca396) /* 653 */, + U64_C(0x958d5c960aad76f1) /* 654 */, U64_C(0xf8d6f430c16da536) /* 655 */, + U64_C(0xc8ffd13f1be7e1d2) /* 656 */, U64_C(0x7578ae66004ddbe1) /* 657 */, + U64_C(0x05833f01067be646) /* 658 */, U64_C(0xbb34b5ad3bfe586d) /* 659 */, + U64_C(0x095f34c9a12b97f0) /* 660 */, U64_C(0x247ab64525d60ca8) /* 661 */, + U64_C(0xdcdbc6f3017477d1) /* 662 */, U64_C(0x4a2e14d4decad24d) /* 663 */, + U64_C(0xbdb5e6d9be0a1eeb) /* 664 */, U64_C(0x2a7e70f7794301ab) /* 665 */, + U64_C(0xdef42d8a270540fd) /* 666 */, U64_C(0x01078ec0a34c22c1) /* 667 */, + U64_C(0xe5de511af4c16387) /* 668 */, U64_C(0x7ebb3a52bd9a330a) /* 669 */, + U64_C(0x77697857aa7d6435) /* 670 */, U64_C(0x004e831603ae4c32) /* 671 */, + U64_C(0xe7a21020ad78e312) /* 672 */, U64_C(0x9d41a70c6ab420f2) /* 673 */, + U64_C(0x28e06c18ea1141e6) /* 674 */, U64_C(0xd2b28cbd984f6b28) /* 675 */, + U64_C(0x26b75f6c446e9d83) /* 676 */, U64_C(0xba47568c4d418d7f) /* 677 */, + U64_C(0xd80badbfe6183d8e) /* 678 */, U64_C(0x0e206d7f5f166044) /* 679 */, + U64_C(0xe258a43911cbca3e) /* 680 */, U64_C(0x723a1746b21dc0bc) /* 681 */, + U64_C(0xc7caa854f5d7cdd3) /* 682 */, U64_C(0x7cac32883d261d9c) /* 683 */, + U64_C(0x7690c26423ba942c) /* 684 */, U64_C(0x17e55524478042b8) /* 685 */, + U64_C(0xe0be477656a2389f) /* 686 */, U64_C(0x4d289b5e67ab2da0) /* 687 */, + U64_C(0x44862b9c8fbbfd31) /* 688 */, U64_C(0xb47cc8049d141365) /* 689 */, + U64_C(0x822c1b362b91c793) /* 690 */, U64_C(0x4eb14655fb13dfd8) /* 691 */, + U64_C(0x1ecbba0714e2a97b) /* 692 */, U64_C(0x6143459d5cde5f14) /* 693 */, + U64_C(0x53a8fbf1d5f0ac89) /* 694 */, U64_C(0x97ea04d81c5e5b00) /* 695 */, + U64_C(0x622181a8d4fdb3f3) /* 696 */, U64_C(0xe9bcd341572a1208) /* 697 */, + U64_C(0x1411258643cce58a) /* 698 */, U64_C(0x9144c5fea4c6e0a4) /* 699 */, + U64_C(0x0d33d06565cf620f) /* 700 */, U64_C(0x54a48d489f219ca1) /* 701 */, + U64_C(0xc43e5eac6d63c821) /* 702 */, U64_C(0xa9728b3a72770daf) /* 703 */, + U64_C(0xd7934e7b20df87ef) /* 704 */, U64_C(0xe35503b61a3e86e5) /* 705 */, + U64_C(0xcae321fbc819d504) /* 706 */, U64_C(0x129a50b3ac60bfa6) /* 707 */, + U64_C(0xcd5e68ea7e9fb6c3) /* 708 */, U64_C(0xb01c90199483b1c7) /* 709 */, + U64_C(0x3de93cd5c295376c) /* 710 */, U64_C(0xaed52edf2ab9ad13) /* 711 */, + U64_C(0x2e60f512c0a07884) /* 712 */, U64_C(0xbc3d86a3e36210c9) /* 713 */, + U64_C(0x35269d9b163951ce) /* 714 */, U64_C(0x0c7d6e2ad0cdb5fa) /* 715 */, + U64_C(0x59e86297d87f5733) /* 716 */, U64_C(0x298ef221898db0e7) /* 717 */, + U64_C(0x55000029d1a5aa7e) /* 718 */, U64_C(0x8bc08ae1b5061b45) /* 719 */, + U64_C(0xc2c31c2b6c92703a) /* 720 */, U64_C(0x94cc596baf25ef42) /* 721 */, + U64_C(0x0a1d73db22540456) /* 722 */, U64_C(0x04b6a0f9d9c4179a) /* 723 */, + U64_C(0xeffdafa2ae3d3c60) /* 724 */, U64_C(0xf7c8075bb49496c4) /* 725 */, + U64_C(0x9cc5c7141d1cd4e3) /* 726 */, U64_C(0x78bd1638218e5534) /* 727 */, + U64_C(0xb2f11568f850246a) /* 728 */, U64_C(0xedfabcfa9502bc29) /* 729 */, + U64_C(0x796ce5f2da23051b) /* 730 */, U64_C(0xaae128b0dc93537c) /* 731 */, + U64_C(0x3a493da0ee4b29ae) /* 732 */, U64_C(0xb5df6b2c416895d7) /* 733 */, + U64_C(0xfcabbd25122d7f37) /* 734 */, U64_C(0x70810b58105dc4b1) /* 735 */, + U64_C(0xe10fdd37f7882a90) /* 736 */, U64_C(0x524dcab5518a3f5c) /* 737 */, + U64_C(0x3c9e85878451255b) /* 738 */, U64_C(0x4029828119bd34e2) /* 739 */, + U64_C(0x74a05b6f5d3ceccb) /* 740 */, U64_C(0xb610021542e13eca) /* 741 */, + U64_C(0x0ff979d12f59e2ac) /* 742 */, U64_C(0x6037da27e4f9cc50) /* 743 */, + U64_C(0x5e92975a0df1847d) /* 744 */, U64_C(0xd66de190d3e623fe) /* 745 */, + U64_C(0x5032d6b87b568048) /* 746 */, U64_C(0x9a36b7ce8235216e) /* 747 */, + U64_C(0x80272a7a24f64b4a) /* 748 */, U64_C(0x93efed8b8c6916f7) /* 749 */, + U64_C(0x37ddbff44cce1555) /* 750 */, U64_C(0x4b95db5d4b99bd25) /* 751 */, + U64_C(0x92d3fda169812fc0) /* 752 */, U64_C(0xfb1a4a9a90660bb6) /* 753 */, + U64_C(0x730c196946a4b9b2) /* 754 */, U64_C(0x81e289aa7f49da68) /* 755 */, + U64_C(0x64669a0f83b1a05f) /* 756 */, U64_C(0x27b3ff7d9644f48b) /* 757 */, + U64_C(0xcc6b615c8db675b3) /* 758 */, U64_C(0x674f20b9bcebbe95) /* 759 */, + U64_C(0x6f31238275655982) /* 760 */, U64_C(0x5ae488713e45cf05) /* 761 */, + U64_C(0xbf619f9954c21157) /* 762 */, U64_C(0xeabac46040a8eae9) /* 763 */, + U64_C(0x454c6fe9f2c0c1cd) /* 764 */, U64_C(0x419cf6496412691c) /* 765 */, + U64_C(0xd3dc3bef265b0f70) /* 766 */, U64_C(0x6d0e60f5c3578a9e) /* 767 */ +}; +static u64 sbox4[256] = { + U64_C(0x5b0e608526323c55) /* 768 */, U64_C(0x1a46c1a9fa1b59f5) /* 769 */, + U64_C(0xa9e245a17c4c8ffa) /* 770 */, U64_C(0x65ca5159db2955d7) /* 771 */, + U64_C(0x05db0a76ce35afc2) /* 772 */, U64_C(0x81eac77ea9113d45) /* 773 */, + U64_C(0x528ef88ab6ac0a0d) /* 774 */, U64_C(0xa09ea253597be3ff) /* 775 */, + U64_C(0x430ddfb3ac48cd56) /* 776 */, U64_C(0xc4b3a67af45ce46f) /* 777 */, + U64_C(0x4ececfd8fbe2d05e) /* 778 */, U64_C(0x3ef56f10b39935f0) /* 779 */, + U64_C(0x0b22d6829cd619c6) /* 780 */, U64_C(0x17fd460a74df2069) /* 781 */, + U64_C(0x6cf8cc8e8510ed40) /* 782 */, U64_C(0xd6c824bf3a6ecaa7) /* 783 */, + U64_C(0x61243d581a817049) /* 784 */, U64_C(0x048bacb6bbc163a2) /* 785 */, + U64_C(0xd9a38ac27d44cc32) /* 786 */, U64_C(0x7fddff5baaf410ab) /* 787 */, + U64_C(0xad6d495aa804824b) /* 788 */, U64_C(0xe1a6a74f2d8c9f94) /* 789 */, + U64_C(0xd4f7851235dee8e3) /* 790 */, U64_C(0xfd4b7f886540d893) /* 791 */, + U64_C(0x247c20042aa4bfda) /* 792 */, U64_C(0x096ea1c517d1327c) /* 793 */, + U64_C(0xd56966b4361a6685) /* 794 */, U64_C(0x277da5c31221057d) /* 795 */, + U64_C(0x94d59893a43acff7) /* 796 */, U64_C(0x64f0c51ccdc02281) /* 797 */, + U64_C(0x3d33bcc4ff6189db) /* 798 */, U64_C(0xe005cb184ce66af1) /* 799 */, + U64_C(0xff5ccd1d1db99bea) /* 800 */, U64_C(0xb0b854a7fe42980f) /* 801 */, + U64_C(0x7bd46a6a718d4b9f) /* 802 */, U64_C(0xd10fa8cc22a5fd8c) /* 803 */, + U64_C(0xd31484952be4bd31) /* 804 */, U64_C(0xc7fa975fcb243847) /* 805 */, + U64_C(0x4886ed1e5846c407) /* 806 */, U64_C(0x28cddb791eb70b04) /* 807 */, + U64_C(0xc2b00be2f573417f) /* 808 */, U64_C(0x5c9590452180f877) /* 809 */, + U64_C(0x7a6bddfff370eb00) /* 810 */, U64_C(0xce509e38d6d9d6a4) /* 811 */, + U64_C(0xebeb0f00647fa702) /* 812 */, U64_C(0x1dcc06cf76606f06) /* 813 */, + U64_C(0xe4d9f28ba286ff0a) /* 814 */, U64_C(0xd85a305dc918c262) /* 815 */, + U64_C(0x475b1d8732225f54) /* 816 */, U64_C(0x2d4fb51668ccb5fe) /* 817 */, + U64_C(0xa679b9d9d72bba20) /* 818 */, U64_C(0x53841c0d912d43a5) /* 819 */, + U64_C(0x3b7eaa48bf12a4e8) /* 820 */, U64_C(0x781e0e47f22f1ddf) /* 821 */, + U64_C(0xeff20ce60ab50973) /* 822 */, U64_C(0x20d261d19dffb742) /* 823 */, + U64_C(0x16a12b03062a2e39) /* 824 */, U64_C(0x1960eb2239650495) /* 825 */, + U64_C(0x251c16fed50eb8b8) /* 826 */, U64_C(0x9ac0c330f826016e) /* 827 */, + U64_C(0xed152665953e7671) /* 828 */, U64_C(0x02d63194a6369570) /* 829 */, + U64_C(0x5074f08394b1c987) /* 830 */, U64_C(0x70ba598c90b25ce1) /* 831 */, + U64_C(0x794a15810b9742f6) /* 832 */, U64_C(0x0d5925e9fcaf8c6c) /* 833 */, + U64_C(0x3067716cd868744e) /* 834 */, U64_C(0x910ab077e8d7731b) /* 835 */, + U64_C(0x6a61bbdb5ac42f61) /* 836 */, U64_C(0x93513efbf0851567) /* 837 */, + U64_C(0xf494724b9e83e9d5) /* 838 */, U64_C(0xe887e1985c09648d) /* 839 */, + U64_C(0x34b1d3c675370cfd) /* 840 */, U64_C(0xdc35e433bc0d255d) /* 841 */, + U64_C(0xd0aab84234131be0) /* 842 */, U64_C(0x08042a50b48b7eaf) /* 843 */, + U64_C(0x9997c4ee44a3ab35) /* 844 */, U64_C(0x829a7b49201799d0) /* 845 */, + U64_C(0x263b8307b7c54441) /* 846 */, U64_C(0x752f95f4fd6a6ca6) /* 847 */, + U64_C(0x927217402c08c6e5) /* 848 */, U64_C(0x2a8ab754a795d9ee) /* 849 */, + U64_C(0xa442f7552f72943d) /* 850 */, U64_C(0x2c31334e19781208) /* 851 */, + U64_C(0x4fa98d7ceaee6291) /* 852 */, U64_C(0x55c3862f665db309) /* 853 */, + U64_C(0xbd0610175d53b1f3) /* 854 */, U64_C(0x46fe6cb840413f27) /* 855 */, + U64_C(0x3fe03792df0cfa59) /* 856 */, U64_C(0xcfe700372eb85e8f) /* 857 */, + U64_C(0xa7be29e7adbce118) /* 858 */, U64_C(0xe544ee5cde8431dd) /* 859 */, + U64_C(0x8a781b1b41f1873e) /* 860 */, U64_C(0xa5c94c78a0d2f0e7) /* 861 */, + U64_C(0x39412e2877b60728) /* 862 */, U64_C(0xa1265ef3afc9a62c) /* 863 */, + U64_C(0xbcc2770c6a2506c5) /* 864 */, U64_C(0x3ab66dd5dce1ce12) /* 865 */, + U64_C(0xe65499d04a675b37) /* 866 */, U64_C(0x7d8f523481bfd216) /* 867 */, + U64_C(0x0f6f64fcec15f389) /* 868 */, U64_C(0x74efbe618b5b13c8) /* 869 */, + U64_C(0xacdc82b714273e1d) /* 870 */, U64_C(0xdd40bfe003199d17) /* 871 */, + U64_C(0x37e99257e7e061f8) /* 872 */, U64_C(0xfa52626904775aaa) /* 873 */, + U64_C(0x8bbbf63a463d56f9) /* 874 */, U64_C(0xf0013f1543a26e64) /* 875 */, + U64_C(0xa8307e9f879ec898) /* 876 */, U64_C(0xcc4c27a4150177cc) /* 877 */, + U64_C(0x1b432f2cca1d3348) /* 878 */, U64_C(0xde1d1f8f9f6fa013) /* 879 */, + U64_C(0x606602a047a7ddd6) /* 880 */, U64_C(0xd237ab64cc1cb2c7) /* 881 */, + U64_C(0x9b938e7225fcd1d3) /* 882 */, U64_C(0xec4e03708e0ff476) /* 883 */, + U64_C(0xfeb2fbda3d03c12d) /* 884 */, U64_C(0xae0bced2ee43889a) /* 885 */, + U64_C(0x22cb8923ebfb4f43) /* 886 */, U64_C(0x69360d013cf7396d) /* 887 */, + U64_C(0x855e3602d2d4e022) /* 888 */, U64_C(0x073805bad01f784c) /* 889 */, + U64_C(0x33e17a133852f546) /* 890 */, U64_C(0xdf4874058ac7b638) /* 891 */, + U64_C(0xba92b29c678aa14a) /* 892 */, U64_C(0x0ce89fc76cfaadcd) /* 893 */, + U64_C(0x5f9d4e0908339e34) /* 894 */, U64_C(0xf1afe9291f5923b9) /* 895 */, + U64_C(0x6e3480f60f4a265f) /* 896 */, U64_C(0xeebf3a2ab29b841c) /* 897 */, + U64_C(0xe21938a88f91b4ad) /* 898 */, U64_C(0x57dfeff845c6d3c3) /* 899 */, + U64_C(0x2f006b0bf62caaf2) /* 900 */, U64_C(0x62f479ef6f75ee78) /* 901 */, + U64_C(0x11a55ad41c8916a9) /* 902 */, U64_C(0xf229d29084fed453) /* 903 */, + U64_C(0x42f1c27b16b000e6) /* 904 */, U64_C(0x2b1f76749823c074) /* 905 */, + U64_C(0x4b76eca3c2745360) /* 906 */, U64_C(0x8c98f463b91691bd) /* 907 */, + U64_C(0x14bcc93cf1ade66a) /* 908 */, U64_C(0x8885213e6d458397) /* 909 */, + U64_C(0x8e177df0274d4711) /* 910 */, U64_C(0xb49b73b5503f2951) /* 911 */, + U64_C(0x10168168c3f96b6b) /* 912 */, U64_C(0x0e3d963b63cab0ae) /* 913 */, + U64_C(0x8dfc4b5655a1db14) /* 914 */, U64_C(0xf789f1356e14de5c) /* 915 */, + U64_C(0x683e68af4e51dac1) /* 916 */, U64_C(0xc9a84f9d8d4b0fd9) /* 917 */, + U64_C(0x3691e03f52a0f9d1) /* 918 */, U64_C(0x5ed86e46e1878e80) /* 919 */, + U64_C(0x3c711a0e99d07150) /* 920 */, U64_C(0x5a0865b20c4e9310) /* 921 */, + U64_C(0x56fbfc1fe4f0682e) /* 922 */, U64_C(0xea8d5de3105edf9b) /* 923 */, + U64_C(0x71abfdb12379187a) /* 924 */, U64_C(0x2eb99de1bee77b9c) /* 925 */, + U64_C(0x21ecc0ea33cf4523) /* 926 */, U64_C(0x59a4d7521805c7a1) /* 927 */, + U64_C(0x3896f5eb56ae7c72) /* 928 */, U64_C(0xaa638f3db18f75dc) /* 929 */, + U64_C(0x9f39358dabe9808e) /* 930 */, U64_C(0xb7defa91c00b72ac) /* 931 */, + U64_C(0x6b5541fd62492d92) /* 932 */, U64_C(0x6dc6dee8f92e4d5b) /* 933 */, + U64_C(0x353f57abc4beea7e) /* 934 */, U64_C(0x735769d6da5690ce) /* 935 */, + U64_C(0x0a234aa642391484) /* 936 */, U64_C(0xf6f9508028f80d9d) /* 937 */, + U64_C(0xb8e319a27ab3f215) /* 938 */, U64_C(0x31ad9c1151341a4d) /* 939 */, + U64_C(0x773c22a57bef5805) /* 940 */, U64_C(0x45c7561a07968633) /* 941 */, + U64_C(0xf913da9e249dbe36) /* 942 */, U64_C(0xda652d9b78a64c68) /* 943 */, + U64_C(0x4c27a97f3bc334ef) /* 944 */, U64_C(0x76621220e66b17f4) /* 945 */, + U64_C(0x967743899acd7d0b) /* 946 */, U64_C(0xf3ee5bcae0ed6782) /* 947 */, + U64_C(0x409f753600c879fc) /* 948 */, U64_C(0x06d09a39b5926db6) /* 949 */, + U64_C(0x6f83aeb0317ac588) /* 950 */, U64_C(0x01e6ca4a86381f21) /* 951 */, + U64_C(0x66ff3462d19f3025) /* 952 */, U64_C(0x72207c24ddfd3bfb) /* 953 */, + U64_C(0x4af6b6d3e2ece2eb) /* 954 */, U64_C(0x9c994dbec7ea08de) /* 955 */, + U64_C(0x49ace597b09a8bc4) /* 956 */, U64_C(0xb38c4766cf0797ba) /* 957 */, + U64_C(0x131b9373c57c2a75) /* 958 */, U64_C(0xb1822cce61931e58) /* 959 */, + U64_C(0x9d7555b909ba1c0c) /* 960 */, U64_C(0x127fafdd937d11d2) /* 961 */, + U64_C(0x29da3badc66d92e4) /* 962 */, U64_C(0xa2c1d57154c2ecbc) /* 963 */, + U64_C(0x58c5134d82f6fe24) /* 964 */, U64_C(0x1c3ae3515b62274f) /* 965 */, + U64_C(0xe907c82e01cb8126) /* 966 */, U64_C(0xf8ed091913e37fcb) /* 967 */, + U64_C(0x3249d8f9c80046c9) /* 968 */, U64_C(0x80cf9bede388fb63) /* 969 */, + U64_C(0x1881539a116cf19e) /* 970 */, U64_C(0x5103f3f76bd52457) /* 971 */, + U64_C(0x15b7e6f5ae47f7a8) /* 972 */, U64_C(0xdbd7c6ded47e9ccf) /* 973 */, + U64_C(0x44e55c410228bb1a) /* 974 */, U64_C(0xb647d4255edb4e99) /* 975 */, + U64_C(0x5d11882bb8aafc30) /* 976 */, U64_C(0xf5098bbb29d3212a) /* 977 */, + U64_C(0x8fb5ea14e90296b3) /* 978 */, U64_C(0x677b942157dd025a) /* 979 */, + U64_C(0xfb58e7c0a390acb5) /* 980 */, U64_C(0x89d3674c83bd4a01) /* 981 */, + U64_C(0x9e2da4df4bf3b93b) /* 982 */, U64_C(0xfcc41e328cab4829) /* 983 */, + U64_C(0x03f38c96ba582c52) /* 984 */, U64_C(0xcad1bdbd7fd85db2) /* 985 */, + U64_C(0xbbb442c16082ae83) /* 986 */, U64_C(0xb95fe86ba5da9ab0) /* 987 */, + U64_C(0xb22e04673771a93f) /* 988 */, U64_C(0x845358c9493152d8) /* 989 */, + U64_C(0xbe2a488697b4541e) /* 990 */, U64_C(0x95a2dc2dd38e6966) /* 991 */, + U64_C(0xc02c11ac923c852b) /* 992 */, U64_C(0x2388b1990df2a87b) /* 993 */, + U64_C(0x7c8008fa1b4f37be) /* 994 */, U64_C(0x1f70d0c84d54e503) /* 995 */, + U64_C(0x5490adec7ece57d4) /* 996 */, U64_C(0x002b3c27d9063a3a) /* 997 */, + U64_C(0x7eaea3848030a2bf) /* 998 */, U64_C(0xc602326ded2003c0) /* 999 */, + U64_C(0x83a7287d69a94086) /* 1000 */, U64_C(0xc57a5fcb30f57a8a) /* 1001 */, + U64_C(0xb56844e479ebe779) /* 1002 */, U64_C(0xa373b40f05dcbce9) /* 1003 */, + U64_C(0xd71a786e88570ee2) /* 1004 */, U64_C(0x879cbacdbde8f6a0) /* 1005 */, + U64_C(0x976ad1bcc164a32f) /* 1006 */, U64_C(0xab21e25e9666d78b) /* 1007 */, + U64_C(0x901063aae5e5c33c) /* 1008 */, U64_C(0x9818b34448698d90) /* 1009 */, + U64_C(0xe36487ae3e1e8abb) /* 1010 */, U64_C(0xafbdf931893bdcb4) /* 1011 */, + U64_C(0x6345a0dc5fbbd519) /* 1012 */, U64_C(0x8628fe269b9465ca) /* 1013 */, + U64_C(0x1e5d01603f9c51ec) /* 1014 */, U64_C(0x4de44006a15049b7) /* 1015 */, + U64_C(0xbf6c70e5f776cbb1) /* 1016 */, U64_C(0x411218f2ef552bed) /* 1017 */, + U64_C(0xcb0c0708705a36a3) /* 1018 */, U64_C(0xe74d14754f986044) /* 1019 */, + U64_C(0xcd56d9430ea8280e) /* 1020 */, U64_C(0xc12591d7535f5065) /* 1021 */, + U64_C(0xc83223f1720aef96) /* 1022 */, U64_C(0xc3a0396f7363a51f) /* 1023 */ +}; + +static void +do_init (void *context, int variant) +{ + TIGER_CONTEXT *hd = context; + + hd->a = 0x0123456789abcdefLL; + hd->b = 0xfedcba9876543210LL; + hd->c = 0xf096a5b4c3b2e187LL; + hd->nblocks = 0; + hd->count = 0; + hd->variant = variant; +} + +static void +tiger_init (void *context) +{ + do_init (context, 0); +} + +static void +tiger1_init (void *context) +{ + do_init (context, 1); +} + +static void +tiger2_init (void *context) +{ + do_init (context, 2); +} + +static void +tiger_round( u64 *ra, u64 *rb, u64 *rc, u64 x, int mul ) +{ + u64 a = *ra; + u64 b = *rb; + u64 c = *rc; + + c ^= x; + a -= ( sbox1[ c & 0xff ] ^ sbox2[ (c >> 16) & 0xff ] + ^ sbox3[ (c >> 32) & 0xff ] ^ sbox4[ (c >> 48) & 0xff ]); + b += ( sbox4[ (c >> 8) & 0xff ] ^ sbox3[ (c >> 24) & 0xff ] + ^ sbox2[ (c >> 40) & 0xff ] ^ sbox1[ (c >> 56) & 0xff ]); + b *= mul; + + *ra = a; + *rb = b; + *rc = c; +} + + +static void +pass( u64 *ra, u64 *rb, u64 *rc, u64 *x, int mul ) +{ + u64 a = *ra; + u64 b = *rb; + u64 c = *rc; + + tiger_round( &a, &b, &c, x[0], mul ); + tiger_round( &b, &c, &a, x[1], mul ); + tiger_round( &c, &a, &b, x[2], mul ); + tiger_round( &a, &b, &c, x[3], mul ); + tiger_round( &b, &c, &a, x[4], mul ); + tiger_round( &c, &a, &b, x[5], mul ); + tiger_round( &a, &b, &c, x[6], mul ); + tiger_round( &b, &c, &a, x[7], mul ); + + *ra = a; + *rb = b; + *rc = c; +} + + +static void +key_schedule( u64 *x ) +{ + x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5LL; + x[1] ^= x[0]; + x[2] += x[1]; + x[3] -= x[2] ^ ((~x[1]) << 19 ); + x[4] ^= x[3]; + x[5] += x[4]; + x[6] -= x[5] ^ ((~x[4]) >> 23 ); + x[7] ^= x[6]; + x[0] += x[7]; + x[1] -= x[0] ^ ((~x[7]) << 19 ); + x[2] ^= x[1]; + x[3] += x[2]; + x[4] -= x[3] ^ ((~x[2]) >> 23 ); + x[5] ^= x[4]; + x[6] += x[5]; + x[7] -= x[6] ^ 0x0123456789abcdefLL; +} + + +/**************** + * Transform the message DATA which consists of 512 bytes (8 words) + */ +static void +transform ( TIGER_CONTEXT *hd, const unsigned char *data ) +{ + u64 a,b,c,aa,bb,cc; + u64 x[8]; +#ifdef WORDS_BIGENDIAN +#define MKWORD(d,n) \ + ( ((u64)(d)[8*(n)+7]) << 56 | ((u64)(d)[8*(n)+6]) << 48 \ + | ((u64)(d)[8*(n)+5]) << 40 | ((u64)(d)[8*(n)+4]) << 32 \ + | ((u64)(d)[8*(n)+3]) << 24 | ((u64)(d)[8*(n)+2]) << 16 \ + | ((u64)(d)[8*(n)+1]) << 8 | ((u64)(d)[8*(n) ]) ) + x[0] = MKWORD(data, 0); + x[1] = MKWORD(data, 1); + x[2] = MKWORD(data, 2); + x[3] = MKWORD(data, 3); + x[4] = MKWORD(data, 4); + x[5] = MKWORD(data, 5); + x[6] = MKWORD(data, 6); + x[7] = MKWORD(data, 7); +#undef MKWORD +#else + memcpy( &x[0], data, 64 ); +#endif + + /* save */ + a = aa = hd->a; + b = bb = hd->b; + c = cc = hd->c; + + pass( &a, &b, &c, x, 5); + key_schedule( x ); + pass( &c, &a, &b, x, 7); + key_schedule( x ); + pass( &b, &c, &a, x, 9); + + /* feedforward */ + a ^= aa; + b -= bb; + c += cc; + /* store */ + hd->a = a; + hd->b = b; + hd->c = c; +} + + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +static void +tiger_write ( void *context, const void *inbuf_arg, size_t inlen) +{ + const unsigned char *inbuf = inbuf_arg; + TIGER_CONTEXT *hd = context; + + if( hd->count == 64 ) /* flush the buffer */ + { + transform( hd, hd->buf ); + _gcry_burn_stack (21*8+11*sizeof(void*)); + hd->count = 0; + hd->nblocks++; + } + if( !inbuf ) + return; + if( hd->count ) + { + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; + tiger_write( hd, NULL, 0 ); + if( !inlen ) + return; + } + + while( inlen >= 64 ) + { + transform( hd, inbuf ); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + _gcry_burn_stack (21*8+11*sizeof(void*)); + for( ; inlen && hd->count < 64; inlen-- ) + hd->buf[hd->count++] = *inbuf++; +} + + + +/* The routine terminates the computation + */ +static void +tiger_final( void *context ) +{ + TIGER_CONTEXT *hd = context; + u32 t, msb, lsb; + byte *p; + byte pad = hd->variant == 2? 0x80 : 0x01; + + tiger_write(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if( (lsb += hd->count) < t ) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if( hd->count < 56 ) /* enough room */ + { + hd->buf[hd->count++] = pad; + while( hd->count < 56 ) + hd->buf[hd->count++] = 0; /* pad */ + } + else /* need one extra block */ + { + hd->buf[hd->count++] = pad; /* pad character */ + while( hd->count < 64 ) + hd->buf[hd->count++] = 0; + tiger_write(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = lsb ; + hd->buf[57] = lsb >> 8; + hd->buf[58] = lsb >> 16; + hd->buf[59] = lsb >> 24; + hd->buf[60] = msb ; + hd->buf[61] = msb >> 8; + hd->buf[62] = msb >> 16; + hd->buf[63] = msb >> 24; + transform( hd, hd->buf ); + _gcry_burn_stack (21*8+11*sizeof(void*)); + + p = hd->buf; +#ifdef WORDS_BIGENDIAN +#define X(a) do { *(u64*)p = hd->a ; p += 8; } while(0) +#else /* little endian */ +#define X(a) do { *p++ = hd->a >> 56; *p++ = hd->a >> 48; \ + *p++ = hd->a >> 40; *p++ = hd->a >> 32; \ + *p++ = hd->a >> 24; *p++ = hd->a >> 16; \ + *p++ = hd->a >> 8; *p++ = hd->a; } while(0) +#endif +#define Y(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ + *p++ = hd->a >> 16; *p++ = hd->a >> 24; \ + *p++ = hd->a >> 32; *p++ = hd->a >> 40; \ + *p++ = hd->a >> 48; *p++ = hd->a >> 56; } while(0) + if (hd->variant == 0) + { + X(a); + X(b); + X(c); + } + else + { + Y(a); + Y(b); + Y(c); + } +#undef X +#undef Y +} + +static byte * +tiger_read( void *context ) +{ + TIGER_CONTEXT *hd = context; + + return hd->buf; +} + + + +/* This is the old TIGER variant based on the unfixed reference + implementation. IT was used in GnupG up to 1.3.2. We don't provide + an OID anymore because that would not be correct. */ +gcry_md_spec_t _gcry_digest_spec_tiger = + { + "TIGER192", NULL, 0, NULL, 24, + tiger_init, tiger_write, tiger_final, tiger_read, + sizeof (TIGER_CONTEXT) + }; + + + +/* This is the fixed TIGER implementation. */ +static byte asn1[19] = /* Object ID is 1.3.6.1.4.1.11591.12.2 */ + { 0x30, 0x29, 0x30, 0x0d, 0x06, 0x09, 0x2b, 0x06, + 0x01, 0x04, 0x01, 0xda, 0x47, 0x0c, 0x02, + 0x05, 0x00, 0x04, 0x18 }; + +static gcry_md_oid_spec_t oid_spec_tiger1[] = + { + /* GNU.digestAlgorithm TIGER */ + { "1.3.6.1.4.1.11591.12.2" }, + { NULL } + }; + +gcry_md_spec_t _gcry_digest_spec_tiger1 = + { + "TIGER", asn1, DIM (asn1), oid_spec_tiger1, 24, + tiger1_init, tiger_write, tiger_final, tiger_read, + sizeof (TIGER_CONTEXT) + }; + + + +/* This is TIGER2 which usues a changed padding algorithm. */ +gcry_md_spec_t _gcry_digest_spec_tiger2 = + { + "TIGER2", NULL, 0, NULL, 24, + tiger2_init, tiger_write, tiger_final, tiger_read, + sizeof (TIGER_CONTEXT) + }; + +#endif /* HAVE_U64_TYPEDEF */ diff --git a/grub-core/lib/libgcrypt/cipher/twofish.c b/grub-core/lib/libgcrypt/cipher/twofish.c new file mode 100644 index 0000000..f1a93ca --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/twofish.c @@ -0,0 +1,1040 @@ +/* Twofish for GPG + * Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc. + * Written by Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998 + * 256-bit key length added March 20, 1999 + * Some modifications to reduce the text size by Werner Koch, April, 1998 + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + ******************************************************************** + * + * This code is a "clean room" implementation, written from the paper + * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey, + * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available + * through http://www.counterpane.com/twofish.html + * + * For background information on multiplication in finite fields, used for + * the matrix operations in the key schedule, see the book _Contemporary + * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the + * Third Edition. + * + * Only the 128- and 256-bit key sizes are supported. This code is intended + * for GNU C on a 32-bit system, but it should work almost anywhere. Loops + * are unrolled, precomputation tables are used, etc., for maximum speed at + * some cost in memory consumption. */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> /* for memcmp() */ + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + +/* Prototype for the self-test function. */ +static const char *selftest(void); + +/* Structure for an expanded Twofish key. s contains the key-dependent + * S-boxes composed with the MDS matrix; w contains the eight "whitening" + * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note + * that k[i] corresponds to what the Twofish paper calls K[i+8]. */ +typedef struct { + u32 s[4][256], w[8], k[32]; +} TWOFISH_context; + +/* These two tables are the q0 and q1 permutations, exactly as described in + * the Twofish paper. */ + +static const byte q0[256] = { + 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, + 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, + 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, + 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, + 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, + 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, + 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, + 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, + 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, + 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, + 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, + 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, + 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, + 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, + 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, + 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, + 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, + 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, + 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, + 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, + 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, + 0x4A, 0x5E, 0xC1, 0xE0 +}; + +static const byte q1[256] = { + 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, + 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, + 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, + 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, + 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, + 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, + 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, + 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, + 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, + 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, + 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, + 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, + 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, + 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, + 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, + 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, + 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, + 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, + 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, + 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, + 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, + 0x55, 0x09, 0xBE, 0x91 +}; + +/* These MDS tables are actually tables of MDS composed with q0 and q1, + * because it is only ever used that way and we can save some time by + * precomputing. Of course the main saving comes from precomputing the + * GF(2^8) multiplication involved in the MDS matrix multiply; by looking + * things up in these tables we reduce the matrix multiply to four lookups + * and three XORs. Semi-formally, the definition of these tables is: + * mds[0][i] = MDS (q1[i] 0 0 0)^T mds[1][i] = MDS (0 q0[i] 0 0)^T + * mds[2][i] = MDS (0 0 q1[i] 0)^T mds[3][i] = MDS (0 0 0 q0[i])^T + * where ^T means "transpose", the matrix multiply is performed in GF(2^8) + * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described + * by Schneier et al, and I'm casually glossing over the byte/word + * conversion issues. */ + +static const u32 mds[4][256] = { + {0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, + 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, + 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, + 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, + 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, + 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, + 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, + 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, + 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, + 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, + 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, + 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, + 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, + 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, + 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, + 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, + 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, + 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, + 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, + 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, + 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, + 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, + 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, + 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, + 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, + 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, + 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, + 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, + 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, + 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, + 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, + 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, + 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, + 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, + 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, + 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, + 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, + 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, + 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, + 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, + 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, + 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, + 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91}, + + {0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, + 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, + 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, + 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, + 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, + 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, + 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, + 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, + 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, + 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, + 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, + 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, + 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, + 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, + 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, + 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, + 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, + 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, + 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, + 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, + 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, + 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, + 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, + 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, + 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, + 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, + 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, + 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, + 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, + 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, + 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, + 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, + 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, + 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, + 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, + 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, + 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, + 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, + 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, + 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, + 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, + 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, + 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8}, + + {0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, + 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, + 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, + 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, + 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, + 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, + 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, + 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, + 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, + 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, + 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, + 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, + 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, + 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, + 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, + 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, + 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, + 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, + 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, + 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, + 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, + 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, + 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, + 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, + 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, + 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, + 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, + 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, + 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, + 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, + 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, + 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, + 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, + 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, + 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, + 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, + 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, + 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, + 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, + 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, + 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, + 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, + 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF}, + + {0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, + 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, + 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, + 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, + 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, + 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, + 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, + 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, + 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, + 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, + 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, + 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, + 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, + 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, + 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, + 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, + 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, + 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, + 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, + 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, + 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, + 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, + 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, + 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, + 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, + 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, + 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, + 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, + 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, + 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, + 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, + 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, + 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, + 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, + 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, + 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, + 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, + 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, + 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, + 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, + 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, + 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, + 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8} +}; + +/* The exp_to_poly and poly_to_exp tables are used to perform efficient + * operations in GF(2^8) represented as GF(2)[x]/w(x) where + * w(x)=x^8+x^6+x^3+x^2+1. We care about doing that because it's part of the + * definition of the RS matrix in the key schedule. Elements of that field + * are polynomials of degree not greater than 7 and all coefficients 0 or 1, + * which can be represented naturally by bytes (just substitute x=2). In that + * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8) + * multiplication is inefficient without hardware support. To multiply + * faster, I make use of the fact x is a generator for the nonzero elements, + * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for + * some n in 0..254. Note that that caret is exponentiation in GF(2^8), + * *not* polynomial notation. So if I want to compute pq where p and q are + * in GF(2^8), I can just say: + * 1. if p=0 or q=0 then pq=0 + * 2. otherwise, find m and n such that p=x^m and q=x^n + * 3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq + * The translations in steps 2 and 3 are looked up in the tables + * poly_to_exp (for step 2) and exp_to_poly (for step 3). To see this + * in action, look at the CALC_S macro. As additional wrinkles, note that + * one of my operands is always a constant, so the poly_to_exp lookup on it + * is done in advance; I included the original values in the comments so + * readers can have some chance of recognizing that this *is* the RS matrix + * from the Twofish paper. I've only included the table entries I actually + * need; I never do a lookup on a variable input of zero and the biggest + * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll + * never sum to more than 491. I'm repeating part of the exp_to_poly table + * so that I don't have to do mod-255 reduction in the exponent arithmetic. + * Since I know my constant operands are never zero, I only have to worry + * about zero values in the variable operand, and I do it with a simple + * conditional branch. I know conditionals are expensive, but I couldn't + * see a non-horrible way of avoiding them, and I did manage to group the + * statements so that each if covers four group multiplications. */ + +static const byte poly_to_exp[255] = { + 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, + 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, + 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, + 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, + 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, + 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, + 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, + 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, + 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, + 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, + 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, + 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, + 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, + 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, + 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, + 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, + 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, + 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, + 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, + 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, + 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, + 0x85, 0xC8, 0xA1 +}; + +static const byte exp_to_poly[492] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, + 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, + 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, + 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, + 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, + 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, + 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, + 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, + 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, + 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, + 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, + 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, + 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, + 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, + 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, + 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, + 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, + 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, + 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, + 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, + 0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, + 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, + 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, + 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, + 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, + 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, + 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, + 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, + 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, + 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, + 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, + 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, + 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, + 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, + 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, + 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, + 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, + 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, + 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, + 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB +}; + + +/* The table constants are indices of + * S-box entries, preprocessed through q0 and q1. */ +static byte calc_sb_tbl[512] = { + 0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4, + 0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8, + 0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B, + 0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B, + 0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD, + 0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1, + 0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B, + 0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F, + 0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B, + 0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D, + 0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E, + 0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5, + 0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14, + 0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3, + 0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54, + 0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51, + 0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A, + 0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96, + 0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10, + 0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C, + 0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7, + 0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70, + 0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB, + 0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8, + 0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF, + 0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC, + 0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF, + 0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2, + 0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82, + 0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9, + 0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97, + 0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17, + 0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D, + 0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3, + 0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C, + 0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E, + 0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F, + 0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49, + 0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21, + 0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9, + 0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD, + 0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01, + 0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F, + 0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48, + 0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E, + 0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19, + 0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57, + 0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64, + 0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE, + 0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5, + 0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44, + 0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69, + 0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15, + 0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E, + 0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34, + 0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC, + 0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B, + 0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB, + 0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52, + 0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9, + 0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4, + 0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2, + 0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56, + 0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91 +}; +/* Macro to perform one column of the RS matrix multiplication. The + * parameters a, b, c, and d are the four bytes of output; i is the index + * of the key bytes, and w, x, y, and z, are the column of constants from + * the RS matrix, preprocessed through the poly_to_exp table. */ + +#define CALC_S(a, b, c, d, i, w, x, y, z) \ + if (key[i]) { \ + tmp = poly_to_exp[key[i] - 1]; \ + (a) ^= exp_to_poly[tmp + (w)]; \ + (b) ^= exp_to_poly[tmp + (x)]; \ + (c) ^= exp_to_poly[tmp + (y)]; \ + (d) ^= exp_to_poly[tmp + (z)]; \ + } + +/* Macros to calculate the key-dependent S-boxes for a 128-bit key using + * the S vector from CALC_S. CALC_SB_2 computes a single entry in all + * four S-boxes, where i is the index of the entry to compute, and a and b + * are the index numbers preprocessed through the q0 and q1 tables + * respectively. CALC_SB is simply a convenience to make the code shorter; + * it calls CALC_SB_2 four times with consecutive indices from i to i+3, + * using the remaining parameters two by two. */ + +#define CALC_SB_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \ + ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \ + ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \ + ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh] + +#define CALC_SB(i, a, b, c, d, e, f, g, h) \ + CALC_SB_2 (i, a, b); CALC_SB_2 ((i)+1, c, d); \ + CALC_SB_2 ((i)+2, e, f); CALC_SB_2 ((i)+3, g, h) + +/* Macros exactly like CALC_SB and CALC_SB_2, but for 256-bit keys. */ + +#define CALC_SB256_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \ + ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \ + ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \ + ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp]; + +#define CALC_SB256(i, a, b, c, d, e, f, g, h) \ + CALC_SB256_2 (i, a, b); CALC_SB256_2 ((i)+1, c, d); \ + CALC_SB256_2 ((i)+2, e, f); CALC_SB256_2 ((i)+3, g, h) + +/* Macros to calculate the whitening and round subkeys. CALC_K_2 computes the + * last two stages of the h() function for a given index (either 2i or 2i+1). + * a, b, c, and d are the four bytes going into the last two stages. For + * 128-bit keys, this is the entire h() function and a and c are the index + * preprocessed through q0 and q1 respectively; for longer keys they are the + * output of previous stages. j is the index of the first key byte to use. + * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 + * twice, doing the Pseudo-Hadamard Transform, and doing the necessary + * rotations. Its parameters are: a, the array to write the results into, + * j, the index of the first output entry, k and l, the preprocessed indices + * for index 2i, and m and n, the preprocessed indices for index 2i+1. + * CALC_K256_2 expands CALC_K_2 to handle 256-bit keys, by doing two + * additional lookup-and-XOR stages. The parameters a and b are the index + * preprocessed through q0 and q1 respectively; j is the index of the first + * key byte to use. CALC_K256 is identical to CALC_K but for using the + * CALC_K256_2 macro instead of CALC_K_2. */ + +#define CALC_K_2(a, b, c, d, j) \ + mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \ + ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \ + ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \ + ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]] + +#define CALC_K(a, j, k, l, m, n) \ + x = CALC_K_2 (k, l, k, l, 0); \ + y = CALC_K_2 (m, n, m, n, 4); \ + y = (y << 8) + (y >> 24); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = (y << 9) + (y >> 23) + +#define CALC_K256_2(a, b, j) \ + CALC_K_2 (q0[q1[b ^ key[(j) + 24]] ^ key[(j) + 16]], \ + q1[q1[a ^ key[(j) + 25]] ^ key[(j) + 17]], \ + q0[q0[a ^ key[(j) + 26]] ^ key[(j) + 18]], \ + q1[q0[b ^ key[(j) + 27]] ^ key[(j) + 19]], j) + +#define CALC_K256(a, j, k, l, m, n) \ + x = CALC_K256_2 (k, l, 0); \ + y = CALC_K256_2 (m, n, 4); \ + y = (y << 8) + (y >> 24); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = (y << 9) + (y >> 23) + + + +/* Perform the key setup. Note that this works only with 128- and 256-bit + * keys, despite the API that looks like it might support other sizes. */ + +static gcry_err_code_t +do_twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen) +{ + int i, j, k; + + /* Temporaries for CALC_K. */ + u32 x, y; + + /* The S vector used to key the S-boxes, split up into individual bytes. + * 128-bit keys use only sa through sh; 256-bit use all of them. */ + byte sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0; + byte si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0; + + /* Temporary for CALC_S. */ + byte tmp; + + /* Flags for self-test. */ + static int initialized = 0; + static const char *selftest_failed=0; + + /* Check key length. */ + if( ( ( keylen - 16 ) | 16 ) != 16 ) + return GPG_ERR_INV_KEYLEN; + + /* Do self-test if necessary. */ + if (!initialized) + { + initialized = 1; + selftest_failed = selftest (); + if( selftest_failed ) + log_error("%s\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + /* Compute the first two words of the S vector. The magic numbers are + * the entries of the RS matrix, preprocessed through poly_to_exp. The + * numbers in the comments are the original (polynomial form) matrix + * entries. */ + CALC_S (sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + CALC_S (se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + + if (keylen == 32) /* 256-bit key */ + { + /* Calculate the remaining two words of the S vector */ + CALC_S (si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + CALC_S (sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + + /* Compute the S-boxes. */ + for(i=j=0,k=1; i < 256; i++, j += 2, k += 2 ) + { + CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } + else + { + /* Compute the S-boxes. */ + for(i=j=0,k=1; i < 256; i++, j += 2, k += 2 ) + { + CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } + + return 0; +} + +static gcry_err_code_t +twofish_setkey (void *context, const byte *key, unsigned int keylen) +{ + TWOFISH_context *ctx = context; + int rc = do_twofish_setkey (ctx, key, keylen); + _gcry_burn_stack (23+6*sizeof(void*)); + return rc; +} + + + +/* Macros to compute the g() function in the encryption and decryption + * rounds. G1 is the straight g() function; G2 includes the 8-bit + * rotation for the high 32-bit word. */ + +#define G1(a) \ + (ctx->s[0][(a) & 0xFF]) ^ (ctx->s[1][((a) >> 8) & 0xFF]) \ + ^ (ctx->s[2][((a) >> 16) & 0xFF]) ^ (ctx->s[3][(a) >> 24]) + +#define G2(b) \ + (ctx->s[1][(b) & 0xFF]) ^ (ctx->s[2][((b) >> 8) & 0xFF]) \ + ^ (ctx->s[3][((b) >> 16) & 0xFF]) ^ (ctx->s[0][(b) >> 24]) + +/* Encryption and decryption Feistel rounds. Each one calls the two g() + * macros, does the PHT, and performs the XOR and the appropriate bit + * rotations. The parameters are the round number (used to select subkeys), + * and the four 32-bit chunks of the text. */ + +#define ENCROUND(n, a, b, c, d) \ + x = G1 (a); y = G2 (b); \ + x += y; y += x + ctx->k[2 * (n) + 1]; \ + (c) ^= x + ctx->k[2 * (n)]; \ + (c) = ((c) >> 1) + ((c) << 31); \ + (d) = (((d) << 1)+((d) >> 31)) ^ y + +#define DECROUND(n, a, b, c, d) \ + x = G1 (a); y = G2 (b); \ + x += y; y += x; \ + (d) ^= y + ctx->k[2 * (n) + 1]; \ + (d) = ((d) >> 1) + ((d) << 31); \ + (c) = (((c) << 1)+((c) >> 31)); \ + (c) ^= (x + ctx->k[2 * (n)]) + +/* Encryption and decryption cycles; each one is simply two Feistel rounds + * with the 32-bit chunks re-ordered to simulate the "swap" */ + +#define ENCCYCLE(n) \ + ENCROUND (2 * (n), a, b, c, d); \ + ENCROUND (2 * (n) + 1, c, d, a, b) + +#define DECCYCLE(n) \ + DECROUND (2 * (n) + 1, c, d, a, b); \ + DECROUND (2 * (n), a, b, c, d) + +/* Macros to convert the input and output bytes into 32-bit words, + * and simultaneously perform the whitening step. INPACK packs word + * number n into the variable named by x, using whitening subkey number m. + * OUTUNPACK unpacks word number n from the variable named by x, using + * whitening subkey number m. */ + +#define INPACK(n, x, m) \ + x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ + ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] + +#define OUTUNPACK(n, x, m) \ + x ^= ctx->w[m]; \ + out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ + out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 + +/* Encrypt one block. in and out may be the same. */ + +static void +do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) +{ + /* The four 32-bit chunks of the text. */ + u32 a, b, c, d; + + /* Temporaries used by the round function. */ + u32 x, y; + + /* Input whitening and packing. */ + INPACK (0, a, 0); + INPACK (1, b, 1); + INPACK (2, c, 2); + INPACK (3, d, 3); + + /* Encryption Feistel cycles. */ + ENCCYCLE (0); + ENCCYCLE (1); + ENCCYCLE (2); + ENCCYCLE (3); + ENCCYCLE (4); + ENCCYCLE (5); + ENCCYCLE (6); + ENCCYCLE (7); + + /* Output whitening and unpacking. */ + OUTUNPACK (0, c, 4); + OUTUNPACK (1, d, 5); + OUTUNPACK (2, a, 6); + OUTUNPACK (3, b, 7); +} + +static void +twofish_encrypt (void *context, byte *out, const byte *in) +{ + TWOFISH_context *ctx = context; + do_twofish_encrypt (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + + +/* Decrypt one block. in and out may be the same. */ + +static void +do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) +{ + /* The four 32-bit chunks of the text. */ + u32 a, b, c, d; + + /* Temporaries used by the round function. */ + u32 x, y; + + /* Input whitening and packing. */ + INPACK (0, c, 4); + INPACK (1, d, 5); + INPACK (2, a, 6); + INPACK (3, b, 7); + + /* Encryption Feistel cycles. */ + DECCYCLE (7); + DECCYCLE (6); + DECCYCLE (5); + DECCYCLE (4); + DECCYCLE (3); + DECCYCLE (2); + DECCYCLE (1); + DECCYCLE (0); + + /* Output whitening and unpacking. */ + OUTUNPACK (0, a, 0); + OUTUNPACK (1, b, 1); + OUTUNPACK (2, c, 2); + OUTUNPACK (3, d, 3); +} + +static void +twofish_decrypt (void *context, byte *out, const byte *in) +{ + TWOFISH_context *ctx = context; + + do_twofish_decrypt (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + + +/* Test a single encryption and decryption with each key size. */ + +static const char* +selftest (void) +{ + TWOFISH_context ctx; /* Expanded key. */ + byte scratch[16]; /* Encryption/decryption result buffer. */ + + /* Test vectors for single encryption/decryption. Note that I am using + * the vectors from the Twofish paper's "known answer test", I=3 for + * 128-bit and I=4 for 256-bit, instead of the all-0 vectors from the + * "intermediate value test", because an all-0 key would trigger all the + * special cases in the RS matrix multiply, leaving the math untested. */ + static byte plaintext[16] = { + 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, + 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 + }; + static byte key[16] = { + 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, + 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A + }; + static const byte ciphertext[16] = { + 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, + 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 + }; + static byte plaintext_256[16] = { + 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, + 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 + }; + static byte key_256[32] = { + 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, + 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, + 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, + 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F + }; + static const byte ciphertext_256[16] = { + 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, + 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA + }; + + twofish_setkey (&ctx, key, sizeof(key)); + twofish_encrypt (&ctx, scratch, plaintext); + if (memcmp (scratch, ciphertext, sizeof (ciphertext))) + return "Twofish-128 test encryption failed."; + twofish_decrypt (&ctx, scratch, scratch); + if (memcmp (scratch, plaintext, sizeof (plaintext))) + return "Twofish-128 test decryption failed."; + + twofish_setkey (&ctx, key_256, sizeof(key_256)); + twofish_encrypt (&ctx, scratch, plaintext_256); + if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256))) + return "Twofish-256 test encryption failed."; + twofish_decrypt (&ctx, scratch, scratch); + if (memcmp (scratch, plaintext_256, sizeof (plaintext_256))) + return "Twofish-256 test decryption failed."; + + return NULL; +} + +/* More complete test program. This does 1000 encryptions and decryptions + * with each of 250 128-bit keys and 2000 encryptions and decryptions with + * each of 125 256-bit keys, using a feedback scheme similar to a Feistel + * cipher, so as to be sure of testing all the table entries pretty + * thoroughly. We keep changing the keys so as to get a more meaningful + * performance number, since the key setup is non-trivial for Twofish. */ + +#ifdef TEST + +#include <stdio.h> +#include <string.h> +#include <time.h> + +int +main() +{ + TWOFISH_context ctx; /* Expanded key. */ + int i, j; /* Loop counters. */ + + const char *encrypt_msg; /* Message to print regarding encryption test; + * the printf is done outside the loop to avoid + * stuffing up the timing. */ + clock_t timer; /* For computing elapsed time. */ + + /* Test buffer. */ + byte buffer[4][16] = { + {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, + {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, + 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, + {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, + 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} + }; + + /* Expected outputs for the million-operation test */ + static const byte test_encrypt[4][16] = { + {0xC8, 0x23, 0xB8, 0xB7, 0x6B, 0xFE, 0x91, 0x13, + 0x2F, 0xA7, 0x5E, 0xE6, 0x94, 0x77, 0x6F, 0x6B}, + {0x90, 0x36, 0xD8, 0x29, 0xD5, 0x96, 0xC2, 0x8E, + 0xE4, 0xFF, 0x76, 0xBC, 0xE5, 0x77, 0x88, 0x27}, + {0xB8, 0x78, 0x69, 0xAF, 0x42, 0x8B, 0x48, 0x64, + 0xF7, 0xE9, 0xF3, 0x9C, 0x42, 0x18, 0x7B, 0x73}, + {0x7A, 0x88, 0xFB, 0xEB, 0x90, 0xA4, 0xB4, 0xA8, + 0x43, 0xA3, 0x1D, 0xF1, 0x26, 0xC4, 0x53, 0x57} + }; + static const byte test_decrypt[4][16] = { + {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, + {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, + 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, + {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, + 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} + }; + + /* Start the timer ticking. */ + timer = clock (); + + /* Encryption test. */ + for (i = 0; i < 125; i++) + { + twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); + for (j = 0; j < 1000; j++) + twofish_encrypt (&ctx, buffer[2], buffer[2]); + twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); + for (j = 0; j < 1000; j++) + twofish_encrypt (&ctx, buffer[3], buffer[3]); + twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); + for (j = 0; j < 1000; j++) { + twofish_encrypt (&ctx, buffer[0], buffer[0]); + twofish_encrypt (&ctx, buffer[1], buffer[1]); + } + } + encrypt_msg = memcmp (buffer, test_encrypt, sizeof (test_encrypt)) ? + "encryption failure!\n" : "encryption OK!\n"; + + /* Decryption test. */ + for (i = 0; i < 125; i++) + { + twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); + for (j = 0; j < 1000; j++) { + twofish_decrypt (&ctx, buffer[0], buffer[0]); + twofish_decrypt (&ctx, buffer[1], buffer[1]); + } + twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); + for (j = 0; j < 1000; j++) + twofish_decrypt (&ctx, buffer[3], buffer[3]); + twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); + for (j = 0; j < 1000; j++) + twofish_decrypt (&ctx, buffer[2], buffer[2]); + } + + /* Stop the timer, and print results. */ + timer = clock () - timer; + printf (encrypt_msg); + printf (memcmp (buffer, test_decrypt, sizeof (test_decrypt)) ? + "decryption failure!\n" : "decryption OK!\n"); + printf ("elapsed time: %.1f s.\n", (float) timer / CLOCKS_PER_SEC); + + return 0; +} + +#endif /* TEST */ + + + +gcry_cipher_spec_t _gcry_cipher_spec_twofish = + { + "TWOFISH", NULL, NULL, 16, 256, sizeof (TWOFISH_context), + twofish_setkey, twofish_encrypt, twofish_decrypt + }; + +gcry_cipher_spec_t _gcry_cipher_spec_twofish128 = + { + "TWOFISH128", NULL, NULL, 16, 128, sizeof (TWOFISH_context), + twofish_setkey, twofish_encrypt, twofish_decrypt + }; diff --git a/grub-core/lib/libgcrypt/cipher/whirlpool.c b/grub-core/lib/libgcrypt/cipher/whirlpool.c new file mode 100644 index 0000000..c89a572 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/whirlpool.c @@ -0,0 +1,1405 @@ +/* whirlpool.c - Whirlpool hashing algorithm + * Copyright (C) 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + +/* This is an implementation of the Whirlpool hashing algorithm, which + has been developed by Vincent Rijmen and Paulo S. L. M. Barreto; + it's homepage is located at: + http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html. + + The S-Boxes and the structure of the main transformation function, + which implements an optimized version of the algorithm, is taken + from the reference implementation available from + http://planeta.terra.com.br/informatica/paulobarreto/whirlpool.zip. */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "types.h" +#include "g10lib.h" +#include "cipher.h" + +#include "bithelp.h" + +/* Size of a whirlpool block (in bytes). */ +#define BLOCK_SIZE 64 + +/* Number of rounds. */ +#define R 10 + + + +/* Types. */ +typedef u64 whirlpool_block_t[BLOCK_SIZE / 8]; + +typedef struct { + whirlpool_block_t hash_state; + unsigned char buffer[BLOCK_SIZE]; + size_t count; + unsigned char length[32]; +} whirlpool_context_t; + + + +/* Macros. */ + +/* Convert the the buffer BUFFER into a block BLOCK, using I as + counter. */ +#define buffer_to_block(buffer, block, i) \ + for (i = 0; i < 8; i++) \ + (block)[i] = ((u64) (0 \ + | (((u64) (buffer)[i * 8 + 0]) << 56) \ + | (((u64) (buffer)[i * 8 + 1]) << 48) \ + | (((u64) (buffer)[i * 8 + 2]) << 40) \ + | (((u64) (buffer)[i * 8 + 3]) << 32) \ + | (((u64) (buffer)[i * 8 + 4]) << 24) \ + | (((u64) (buffer)[i * 8 + 5]) << 16) \ + | (((u64) (buffer)[i * 8 + 6]) << 8) \ + | (((u64) (buffer)[i * 8 + 7]) << 0))); + +/* Convert the block BLOCK into a buffer BUFFER, using I as + counter. */ +#define block_to_buffer(buffer, block, i) \ + for (i = 0; i < 8; i++) \ + { \ + (buffer)[i * 8 + 0] = (block[i] >> 56) & 0xFF; \ + (buffer)[i * 8 + 1] = (block[i] >> 48) & 0xFF; \ + (buffer)[i * 8 + 2] = (block[i] >> 40) & 0xFF; \ + (buffer)[i * 8 + 3] = (block[i] >> 32) & 0xFF; \ + (buffer)[i * 8 + 4] = (block[i] >> 24) & 0xFF; \ + (buffer)[i * 8 + 5] = (block[i] >> 16) & 0xFF; \ + (buffer)[i * 8 + 6] = (block[i] >> 8) & 0xFF; \ + (buffer)[i * 8 + 7] = (block[i] >> 0) & 0xFF; \ + } + +/* Copy the block BLOCK_SRC to BLOCK_DST, using I as counter. */ +#define block_copy(block_dst, block_src, i) \ + for (i = 0; i < 8; i++) \ + block_dst[i] = block_src[i]; + +/* XOR the block BLOCK_SRC into BLOCK_DST, using I as counter. */ +#define block_xor(block_dst, block_src, i) \ + for (i = 0; i < 8; i++) \ + block_dst[i] ^= block_src[i]; + + + +/* Round constants. */ +static const u64 rc[R] = + { + U64_C (0x1823c6e887b8014f), + U64_C (0x36a6d2f5796f9152), + U64_C (0x60bc9b8ea30c7b35), + U64_C (0x1de0d7c22e4bfe57), + U64_C (0x157737e59ff04ada), + U64_C (0x58c9290ab1a06b85), + U64_C (0xbd5d10f4cb3e0567), + U64_C (0xe427418ba77d95d8), + U64_C (0xfbee7c66dd17479e), + U64_C (0xca2dbf07ad5a8333), + }; + + + +/* Main lookup boxes. */ +static const u64 C0[256] = + { + U64_C (0x18186018c07830d8), U64_C (0x23238c2305af4626), + U64_C (0xc6c63fc67ef991b8), U64_C (0xe8e887e8136fcdfb), + U64_C (0x878726874ca113cb), U64_C (0xb8b8dab8a9626d11), + U64_C (0x0101040108050209), U64_C (0x4f4f214f426e9e0d), + U64_C (0x3636d836adee6c9b), U64_C (0xa6a6a2a6590451ff), + U64_C (0xd2d26fd2debdb90c), U64_C (0xf5f5f3f5fb06f70e), + U64_C (0x7979f979ef80f296), U64_C (0x6f6fa16f5fcede30), + U64_C (0x91917e91fcef3f6d), U64_C (0x52525552aa07a4f8), + U64_C (0x60609d6027fdc047), U64_C (0xbcbccabc89766535), + U64_C (0x9b9b569baccd2b37), U64_C (0x8e8e028e048c018a), + U64_C (0xa3a3b6a371155bd2), U64_C (0x0c0c300c603c186c), + U64_C (0x7b7bf17bff8af684), U64_C (0x3535d435b5e16a80), + U64_C (0x1d1d741de8693af5), U64_C (0xe0e0a7e05347ddb3), + U64_C (0xd7d77bd7f6acb321), U64_C (0xc2c22fc25eed999c), + U64_C (0x2e2eb82e6d965c43), U64_C (0x4b4b314b627a9629), + U64_C (0xfefedffea321e15d), U64_C (0x575741578216aed5), + U64_C (0x15155415a8412abd), U64_C (0x7777c1779fb6eee8), + U64_C (0x3737dc37a5eb6e92), U64_C (0xe5e5b3e57b56d79e), + U64_C (0x9f9f469f8cd92313), U64_C (0xf0f0e7f0d317fd23), + U64_C (0x4a4a354a6a7f9420), U64_C (0xdada4fda9e95a944), + U64_C (0x58587d58fa25b0a2), U64_C (0xc9c903c906ca8fcf), + U64_C (0x2929a429558d527c), U64_C (0x0a0a280a5022145a), + U64_C (0xb1b1feb1e14f7f50), U64_C (0xa0a0baa0691a5dc9), + U64_C (0x6b6bb16b7fdad614), U64_C (0x85852e855cab17d9), + U64_C (0xbdbdcebd8173673c), U64_C (0x5d5d695dd234ba8f), + U64_C (0x1010401080502090), U64_C (0xf4f4f7f4f303f507), + U64_C (0xcbcb0bcb16c08bdd), U64_C (0x3e3ef83eedc67cd3), + U64_C (0x0505140528110a2d), U64_C (0x676781671fe6ce78), + U64_C (0xe4e4b7e47353d597), U64_C (0x27279c2725bb4e02), + U64_C (0x4141194132588273), U64_C (0x8b8b168b2c9d0ba7), + U64_C (0xa7a7a6a7510153f6), U64_C (0x7d7de97dcf94fab2), + U64_C (0x95956e95dcfb3749), U64_C (0xd8d847d88e9fad56), + U64_C (0xfbfbcbfb8b30eb70), U64_C (0xeeee9fee2371c1cd), + U64_C (0x7c7ced7cc791f8bb), U64_C (0x6666856617e3cc71), + U64_C (0xdddd53dda68ea77b), U64_C (0x17175c17b84b2eaf), + U64_C (0x4747014702468e45), U64_C (0x9e9e429e84dc211a), + U64_C (0xcaca0fca1ec589d4), U64_C (0x2d2db42d75995a58), + U64_C (0xbfbfc6bf9179632e), U64_C (0x07071c07381b0e3f), + U64_C (0xadad8ead012347ac), U64_C (0x5a5a755aea2fb4b0), + U64_C (0x838336836cb51bef), U64_C (0x3333cc3385ff66b6), + U64_C (0x636391633ff2c65c), U64_C (0x02020802100a0412), + U64_C (0xaaaa92aa39384993), U64_C (0x7171d971afa8e2de), + U64_C (0xc8c807c80ecf8dc6), U64_C (0x19196419c87d32d1), + U64_C (0x494939497270923b), U64_C (0xd9d943d9869aaf5f), + U64_C (0xf2f2eff2c31df931), U64_C (0xe3e3abe34b48dba8), + U64_C (0x5b5b715be22ab6b9), U64_C (0x88881a8834920dbc), + U64_C (0x9a9a529aa4c8293e), U64_C (0x262698262dbe4c0b), + U64_C (0x3232c8328dfa64bf), U64_C (0xb0b0fab0e94a7d59), + U64_C (0xe9e983e91b6acff2), U64_C (0x0f0f3c0f78331e77), + U64_C (0xd5d573d5e6a6b733), U64_C (0x80803a8074ba1df4), + U64_C (0xbebec2be997c6127), U64_C (0xcdcd13cd26de87eb), + U64_C (0x3434d034bde46889), U64_C (0x48483d487a759032), + U64_C (0xffffdbffab24e354), U64_C (0x7a7af57af78ff48d), + U64_C (0x90907a90f4ea3d64), U64_C (0x5f5f615fc23ebe9d), + U64_C (0x202080201da0403d), U64_C (0x6868bd6867d5d00f), + U64_C (0x1a1a681ad07234ca), U64_C (0xaeae82ae192c41b7), + U64_C (0xb4b4eab4c95e757d), U64_C (0x54544d549a19a8ce), + U64_C (0x93937693ece53b7f), U64_C (0x222288220daa442f), + U64_C (0x64648d6407e9c863), U64_C (0xf1f1e3f1db12ff2a), + U64_C (0x7373d173bfa2e6cc), U64_C (0x12124812905a2482), + U64_C (0x40401d403a5d807a), U64_C (0x0808200840281048), + U64_C (0xc3c32bc356e89b95), U64_C (0xecec97ec337bc5df), + U64_C (0xdbdb4bdb9690ab4d), U64_C (0xa1a1bea1611f5fc0), + U64_C (0x8d8d0e8d1c830791), U64_C (0x3d3df43df5c97ac8), + U64_C (0x97976697ccf1335b), U64_C (0x0000000000000000), + U64_C (0xcfcf1bcf36d483f9), U64_C (0x2b2bac2b4587566e), + U64_C (0x7676c57697b3ece1), U64_C (0x8282328264b019e6), + U64_C (0xd6d67fd6fea9b128), U64_C (0x1b1b6c1bd87736c3), + U64_C (0xb5b5eeb5c15b7774), U64_C (0xafaf86af112943be), + U64_C (0x6a6ab56a77dfd41d), U64_C (0x50505d50ba0da0ea), + U64_C (0x45450945124c8a57), U64_C (0xf3f3ebf3cb18fb38), + U64_C (0x3030c0309df060ad), U64_C (0xefef9bef2b74c3c4), + U64_C (0x3f3ffc3fe5c37eda), U64_C (0x55554955921caac7), + U64_C (0xa2a2b2a2791059db), U64_C (0xeaea8fea0365c9e9), + U64_C (0x656589650fecca6a), U64_C (0xbabad2bab9686903), + U64_C (0x2f2fbc2f65935e4a), U64_C (0xc0c027c04ee79d8e), + U64_C (0xdede5fdebe81a160), U64_C (0x1c1c701ce06c38fc), + U64_C (0xfdfdd3fdbb2ee746), U64_C (0x4d4d294d52649a1f), + U64_C (0x92927292e4e03976), U64_C (0x7575c9758fbceafa), + U64_C (0x06061806301e0c36), U64_C (0x8a8a128a249809ae), + U64_C (0xb2b2f2b2f940794b), U64_C (0xe6e6bfe66359d185), + U64_C (0x0e0e380e70361c7e), U64_C (0x1f1f7c1ff8633ee7), + U64_C (0x6262956237f7c455), U64_C (0xd4d477d4eea3b53a), + U64_C (0xa8a89aa829324d81), U64_C (0x96966296c4f43152), + U64_C (0xf9f9c3f99b3aef62), U64_C (0xc5c533c566f697a3), + U64_C (0x2525942535b14a10), U64_C (0x59597959f220b2ab), + U64_C (0x84842a8454ae15d0), U64_C (0x7272d572b7a7e4c5), + U64_C (0x3939e439d5dd72ec), U64_C (0x4c4c2d4c5a619816), + U64_C (0x5e5e655eca3bbc94), U64_C (0x7878fd78e785f09f), + U64_C (0x3838e038ddd870e5), U64_C (0x8c8c0a8c14860598), + U64_C (0xd1d163d1c6b2bf17), U64_C (0xa5a5aea5410b57e4), + U64_C (0xe2e2afe2434dd9a1), U64_C (0x616199612ff8c24e), + U64_C (0xb3b3f6b3f1457b42), U64_C (0x2121842115a54234), + U64_C (0x9c9c4a9c94d62508), U64_C (0x1e1e781ef0663cee), + U64_C (0x4343114322528661), U64_C (0xc7c73bc776fc93b1), + U64_C (0xfcfcd7fcb32be54f), U64_C (0x0404100420140824), + U64_C (0x51515951b208a2e3), U64_C (0x99995e99bcc72f25), + U64_C (0x6d6da96d4fc4da22), U64_C (0x0d0d340d68391a65), + U64_C (0xfafacffa8335e979), U64_C (0xdfdf5bdfb684a369), + U64_C (0x7e7ee57ed79bfca9), U64_C (0x242490243db44819), + U64_C (0x3b3bec3bc5d776fe), U64_C (0xabab96ab313d4b9a), + U64_C (0xcece1fce3ed181f0), U64_C (0x1111441188552299), + U64_C (0x8f8f068f0c890383), U64_C (0x4e4e254e4a6b9c04), + U64_C (0xb7b7e6b7d1517366), U64_C (0xebeb8beb0b60cbe0), + U64_C (0x3c3cf03cfdcc78c1), U64_C (0x81813e817cbf1ffd), + U64_C (0x94946a94d4fe3540), U64_C (0xf7f7fbf7eb0cf31c), + U64_C (0xb9b9deb9a1676f18), U64_C (0x13134c13985f268b), + U64_C (0x2c2cb02c7d9c5851), U64_C (0xd3d36bd3d6b8bb05), + U64_C (0xe7e7bbe76b5cd38c), U64_C (0x6e6ea56e57cbdc39), + U64_C (0xc4c437c46ef395aa), U64_C (0x03030c03180f061b), + U64_C (0x565645568a13acdc), U64_C (0x44440d441a49885e), + U64_C (0x7f7fe17fdf9efea0), U64_C (0xa9a99ea921374f88), + U64_C (0x2a2aa82a4d825467), U64_C (0xbbbbd6bbb16d6b0a), + U64_C (0xc1c123c146e29f87), U64_C (0x53535153a202a6f1), + U64_C (0xdcdc57dcae8ba572), U64_C (0x0b0b2c0b58271653), + U64_C (0x9d9d4e9d9cd32701), U64_C (0x6c6cad6c47c1d82b), + U64_C (0x3131c43195f562a4), U64_C (0x7474cd7487b9e8f3), + U64_C (0xf6f6fff6e309f115), U64_C (0x464605460a438c4c), + U64_C (0xacac8aac092645a5), U64_C (0x89891e893c970fb5), + U64_C (0x14145014a04428b4), U64_C (0xe1e1a3e15b42dfba), + U64_C (0x16165816b04e2ca6), U64_C (0x3a3ae83acdd274f7), + U64_C (0x6969b9696fd0d206), U64_C (0x09092409482d1241), + U64_C (0x7070dd70a7ade0d7), U64_C (0xb6b6e2b6d954716f), + U64_C (0xd0d067d0ceb7bd1e), U64_C (0xeded93ed3b7ec7d6), + U64_C (0xcccc17cc2edb85e2), U64_C (0x424215422a578468), + U64_C (0x98985a98b4c22d2c), U64_C (0xa4a4aaa4490e55ed), + U64_C (0x2828a0285d885075), U64_C (0x5c5c6d5cda31b886), + U64_C (0xf8f8c7f8933fed6b), U64_C (0x8686228644a411c2), + }; + +static const u64 C1[256] = + { + U64_C (0xd818186018c07830), U64_C (0x2623238c2305af46), + U64_C (0xb8c6c63fc67ef991), U64_C (0xfbe8e887e8136fcd), + U64_C (0xcb878726874ca113), U64_C (0x11b8b8dab8a9626d), + U64_C (0x0901010401080502), U64_C (0x0d4f4f214f426e9e), + U64_C (0x9b3636d836adee6c), U64_C (0xffa6a6a2a6590451), + U64_C (0x0cd2d26fd2debdb9), U64_C (0x0ef5f5f3f5fb06f7), + U64_C (0x967979f979ef80f2), U64_C (0x306f6fa16f5fcede), + U64_C (0x6d91917e91fcef3f), U64_C (0xf852525552aa07a4), + U64_C (0x4760609d6027fdc0), U64_C (0x35bcbccabc897665), + U64_C (0x379b9b569baccd2b), U64_C (0x8a8e8e028e048c01), + U64_C (0xd2a3a3b6a371155b), U64_C (0x6c0c0c300c603c18), + U64_C (0x847b7bf17bff8af6), U64_C (0x803535d435b5e16a), + U64_C (0xf51d1d741de8693a), U64_C (0xb3e0e0a7e05347dd), + U64_C (0x21d7d77bd7f6acb3), U64_C (0x9cc2c22fc25eed99), + U64_C (0x432e2eb82e6d965c), U64_C (0x294b4b314b627a96), + U64_C (0x5dfefedffea321e1), U64_C (0xd5575741578216ae), + U64_C (0xbd15155415a8412a), U64_C (0xe87777c1779fb6ee), + U64_C (0x923737dc37a5eb6e), U64_C (0x9ee5e5b3e57b56d7), + U64_C (0x139f9f469f8cd923), U64_C (0x23f0f0e7f0d317fd), + U64_C (0x204a4a354a6a7f94), U64_C (0x44dada4fda9e95a9), + U64_C (0xa258587d58fa25b0), U64_C (0xcfc9c903c906ca8f), + U64_C (0x7c2929a429558d52), U64_C (0x5a0a0a280a502214), + U64_C (0x50b1b1feb1e14f7f), U64_C (0xc9a0a0baa0691a5d), + U64_C (0x146b6bb16b7fdad6), U64_C (0xd985852e855cab17), + U64_C (0x3cbdbdcebd817367), U64_C (0x8f5d5d695dd234ba), + U64_C (0x9010104010805020), U64_C (0x07f4f4f7f4f303f5), + U64_C (0xddcbcb0bcb16c08b), U64_C (0xd33e3ef83eedc67c), + U64_C (0x2d0505140528110a), U64_C (0x78676781671fe6ce), + U64_C (0x97e4e4b7e47353d5), U64_C (0x0227279c2725bb4e), + U64_C (0x7341411941325882), U64_C (0xa78b8b168b2c9d0b), + U64_C (0xf6a7a7a6a7510153), U64_C (0xb27d7de97dcf94fa), + U64_C (0x4995956e95dcfb37), U64_C (0x56d8d847d88e9fad), + U64_C (0x70fbfbcbfb8b30eb), U64_C (0xcdeeee9fee2371c1), + U64_C (0xbb7c7ced7cc791f8), U64_C (0x716666856617e3cc), + U64_C (0x7bdddd53dda68ea7), U64_C (0xaf17175c17b84b2e), + U64_C (0x454747014702468e), U64_C (0x1a9e9e429e84dc21), + U64_C (0xd4caca0fca1ec589), U64_C (0x582d2db42d75995a), + U64_C (0x2ebfbfc6bf917963), U64_C (0x3f07071c07381b0e), + U64_C (0xacadad8ead012347), U64_C (0xb05a5a755aea2fb4), + U64_C (0xef838336836cb51b), U64_C (0xb63333cc3385ff66), + U64_C (0x5c636391633ff2c6), U64_C (0x1202020802100a04), + U64_C (0x93aaaa92aa393849), U64_C (0xde7171d971afa8e2), + U64_C (0xc6c8c807c80ecf8d), U64_C (0xd119196419c87d32), + U64_C (0x3b49493949727092), U64_C (0x5fd9d943d9869aaf), + U64_C (0x31f2f2eff2c31df9), U64_C (0xa8e3e3abe34b48db), + U64_C (0xb95b5b715be22ab6), U64_C (0xbc88881a8834920d), + U64_C (0x3e9a9a529aa4c829), U64_C (0x0b262698262dbe4c), + U64_C (0xbf3232c8328dfa64), U64_C (0x59b0b0fab0e94a7d), + U64_C (0xf2e9e983e91b6acf), U64_C (0x770f0f3c0f78331e), + U64_C (0x33d5d573d5e6a6b7), U64_C (0xf480803a8074ba1d), + U64_C (0x27bebec2be997c61), U64_C (0xebcdcd13cd26de87), + U64_C (0x893434d034bde468), U64_C (0x3248483d487a7590), + U64_C (0x54ffffdbffab24e3), U64_C (0x8d7a7af57af78ff4), + U64_C (0x6490907a90f4ea3d), U64_C (0x9d5f5f615fc23ebe), + U64_C (0x3d202080201da040), U64_C (0x0f6868bd6867d5d0), + U64_C (0xca1a1a681ad07234), U64_C (0xb7aeae82ae192c41), + U64_C (0x7db4b4eab4c95e75), U64_C (0xce54544d549a19a8), + U64_C (0x7f93937693ece53b), U64_C (0x2f222288220daa44), + U64_C (0x6364648d6407e9c8), U64_C (0x2af1f1e3f1db12ff), + U64_C (0xcc7373d173bfa2e6), U64_C (0x8212124812905a24), + U64_C (0x7a40401d403a5d80), U64_C (0x4808082008402810), + U64_C (0x95c3c32bc356e89b), U64_C (0xdfecec97ec337bc5), + U64_C (0x4ddbdb4bdb9690ab), U64_C (0xc0a1a1bea1611f5f), + U64_C (0x918d8d0e8d1c8307), U64_C (0xc83d3df43df5c97a), + U64_C (0x5b97976697ccf133), U64_C (0x0000000000000000), + U64_C (0xf9cfcf1bcf36d483), U64_C (0x6e2b2bac2b458756), + U64_C (0xe17676c57697b3ec), U64_C (0xe68282328264b019), + U64_C (0x28d6d67fd6fea9b1), U64_C (0xc31b1b6c1bd87736), + U64_C (0x74b5b5eeb5c15b77), U64_C (0xbeafaf86af112943), + U64_C (0x1d6a6ab56a77dfd4), U64_C (0xea50505d50ba0da0), + U64_C (0x5745450945124c8a), U64_C (0x38f3f3ebf3cb18fb), + U64_C (0xad3030c0309df060), U64_C (0xc4efef9bef2b74c3), + U64_C (0xda3f3ffc3fe5c37e), U64_C (0xc755554955921caa), + U64_C (0xdba2a2b2a2791059), U64_C (0xe9eaea8fea0365c9), + U64_C (0x6a656589650fecca), U64_C (0x03babad2bab96869), + U64_C (0x4a2f2fbc2f65935e), U64_C (0x8ec0c027c04ee79d), + U64_C (0x60dede5fdebe81a1), U64_C (0xfc1c1c701ce06c38), + U64_C (0x46fdfdd3fdbb2ee7), U64_C (0x1f4d4d294d52649a), + U64_C (0x7692927292e4e039), U64_C (0xfa7575c9758fbcea), + U64_C (0x3606061806301e0c), U64_C (0xae8a8a128a249809), + U64_C (0x4bb2b2f2b2f94079), U64_C (0x85e6e6bfe66359d1), + U64_C (0x7e0e0e380e70361c), U64_C (0xe71f1f7c1ff8633e), + U64_C (0x556262956237f7c4), U64_C (0x3ad4d477d4eea3b5), + U64_C (0x81a8a89aa829324d), U64_C (0x5296966296c4f431), + U64_C (0x62f9f9c3f99b3aef), U64_C (0xa3c5c533c566f697), + U64_C (0x102525942535b14a), U64_C (0xab59597959f220b2), + U64_C (0xd084842a8454ae15), U64_C (0xc57272d572b7a7e4), + U64_C (0xec3939e439d5dd72), U64_C (0x164c4c2d4c5a6198), + U64_C (0x945e5e655eca3bbc), U64_C (0x9f7878fd78e785f0), + U64_C (0xe53838e038ddd870), U64_C (0x988c8c0a8c148605), + U64_C (0x17d1d163d1c6b2bf), U64_C (0xe4a5a5aea5410b57), + U64_C (0xa1e2e2afe2434dd9), U64_C (0x4e616199612ff8c2), + U64_C (0x42b3b3f6b3f1457b), U64_C (0x342121842115a542), + U64_C (0x089c9c4a9c94d625), U64_C (0xee1e1e781ef0663c), + U64_C (0x6143431143225286), U64_C (0xb1c7c73bc776fc93), + U64_C (0x4ffcfcd7fcb32be5), U64_C (0x2404041004201408), + U64_C (0xe351515951b208a2), U64_C (0x2599995e99bcc72f), + U64_C (0x226d6da96d4fc4da), U64_C (0x650d0d340d68391a), + U64_C (0x79fafacffa8335e9), U64_C (0x69dfdf5bdfb684a3), + U64_C (0xa97e7ee57ed79bfc), U64_C (0x19242490243db448), + U64_C (0xfe3b3bec3bc5d776), U64_C (0x9aabab96ab313d4b), + U64_C (0xf0cece1fce3ed181), U64_C (0x9911114411885522), + U64_C (0x838f8f068f0c8903), U64_C (0x044e4e254e4a6b9c), + U64_C (0x66b7b7e6b7d15173), U64_C (0xe0ebeb8beb0b60cb), + U64_C (0xc13c3cf03cfdcc78), U64_C (0xfd81813e817cbf1f), + U64_C (0x4094946a94d4fe35), U64_C (0x1cf7f7fbf7eb0cf3), + U64_C (0x18b9b9deb9a1676f), U64_C (0x8b13134c13985f26), + U64_C (0x512c2cb02c7d9c58), U64_C (0x05d3d36bd3d6b8bb), + U64_C (0x8ce7e7bbe76b5cd3), U64_C (0x396e6ea56e57cbdc), + U64_C (0xaac4c437c46ef395), U64_C (0x1b03030c03180f06), + U64_C (0xdc565645568a13ac), U64_C (0x5e44440d441a4988), + U64_C (0xa07f7fe17fdf9efe), U64_C (0x88a9a99ea921374f), + U64_C (0x672a2aa82a4d8254), U64_C (0x0abbbbd6bbb16d6b), + U64_C (0x87c1c123c146e29f), U64_C (0xf153535153a202a6), + U64_C (0x72dcdc57dcae8ba5), U64_C (0x530b0b2c0b582716), + U64_C (0x019d9d4e9d9cd327), U64_C (0x2b6c6cad6c47c1d8), + U64_C (0xa43131c43195f562), U64_C (0xf37474cd7487b9e8), + U64_C (0x15f6f6fff6e309f1), U64_C (0x4c464605460a438c), + U64_C (0xa5acac8aac092645), U64_C (0xb589891e893c970f), + U64_C (0xb414145014a04428), U64_C (0xbae1e1a3e15b42df), + U64_C (0xa616165816b04e2c), U64_C (0xf73a3ae83acdd274), + U64_C (0x066969b9696fd0d2), U64_C (0x4109092409482d12), + U64_C (0xd77070dd70a7ade0), U64_C (0x6fb6b6e2b6d95471), + U64_C (0x1ed0d067d0ceb7bd), U64_C (0xd6eded93ed3b7ec7), + U64_C (0xe2cccc17cc2edb85), U64_C (0x68424215422a5784), + U64_C (0x2c98985a98b4c22d), U64_C (0xeda4a4aaa4490e55), + U64_C (0x752828a0285d8850), U64_C (0x865c5c6d5cda31b8), + U64_C (0x6bf8f8c7f8933fed), U64_C (0xc28686228644a411), + }; + +static const u64 C2[256] = + { + U64_C (0x30d818186018c078), U64_C (0x462623238c2305af), + U64_C (0x91b8c6c63fc67ef9), U64_C (0xcdfbe8e887e8136f), + U64_C (0x13cb878726874ca1), U64_C (0x6d11b8b8dab8a962), + U64_C (0x0209010104010805), U64_C (0x9e0d4f4f214f426e), + U64_C (0x6c9b3636d836adee), U64_C (0x51ffa6a6a2a65904), + U64_C (0xb90cd2d26fd2debd), U64_C (0xf70ef5f5f3f5fb06), + U64_C (0xf2967979f979ef80), U64_C (0xde306f6fa16f5fce), + U64_C (0x3f6d91917e91fcef), U64_C (0xa4f852525552aa07), + U64_C (0xc04760609d6027fd), U64_C (0x6535bcbccabc8976), + U64_C (0x2b379b9b569baccd), U64_C (0x018a8e8e028e048c), + U64_C (0x5bd2a3a3b6a37115), U64_C (0x186c0c0c300c603c), + U64_C (0xf6847b7bf17bff8a), U64_C (0x6a803535d435b5e1), + U64_C (0x3af51d1d741de869), U64_C (0xddb3e0e0a7e05347), + U64_C (0xb321d7d77bd7f6ac), U64_C (0x999cc2c22fc25eed), + U64_C (0x5c432e2eb82e6d96), U64_C (0x96294b4b314b627a), + U64_C (0xe15dfefedffea321), U64_C (0xaed5575741578216), + U64_C (0x2abd15155415a841), U64_C (0xeee87777c1779fb6), + U64_C (0x6e923737dc37a5eb), U64_C (0xd79ee5e5b3e57b56), + U64_C (0x23139f9f469f8cd9), U64_C (0xfd23f0f0e7f0d317), + U64_C (0x94204a4a354a6a7f), U64_C (0xa944dada4fda9e95), + U64_C (0xb0a258587d58fa25), U64_C (0x8fcfc9c903c906ca), + U64_C (0x527c2929a429558d), U64_C (0x145a0a0a280a5022), + U64_C (0x7f50b1b1feb1e14f), U64_C (0x5dc9a0a0baa0691a), + U64_C (0xd6146b6bb16b7fda), U64_C (0x17d985852e855cab), + U64_C (0x673cbdbdcebd8173), U64_C (0xba8f5d5d695dd234), + U64_C (0x2090101040108050), U64_C (0xf507f4f4f7f4f303), + U64_C (0x8bddcbcb0bcb16c0), U64_C (0x7cd33e3ef83eedc6), + U64_C (0x0a2d050514052811), U64_C (0xce78676781671fe6), + U64_C (0xd597e4e4b7e47353), U64_C (0x4e0227279c2725bb), + U64_C (0x8273414119413258), U64_C (0x0ba78b8b168b2c9d), + U64_C (0x53f6a7a7a6a75101), U64_C (0xfab27d7de97dcf94), + U64_C (0x374995956e95dcfb), U64_C (0xad56d8d847d88e9f), + U64_C (0xeb70fbfbcbfb8b30), U64_C (0xc1cdeeee9fee2371), + U64_C (0xf8bb7c7ced7cc791), U64_C (0xcc716666856617e3), + U64_C (0xa77bdddd53dda68e), U64_C (0x2eaf17175c17b84b), + U64_C (0x8e45474701470246), U64_C (0x211a9e9e429e84dc), + U64_C (0x89d4caca0fca1ec5), U64_C (0x5a582d2db42d7599), + U64_C (0x632ebfbfc6bf9179), U64_C (0x0e3f07071c07381b), + U64_C (0x47acadad8ead0123), U64_C (0xb4b05a5a755aea2f), + U64_C (0x1bef838336836cb5), U64_C (0x66b63333cc3385ff), + U64_C (0xc65c636391633ff2), U64_C (0x041202020802100a), + U64_C (0x4993aaaa92aa3938), U64_C (0xe2de7171d971afa8), + U64_C (0x8dc6c8c807c80ecf), U64_C (0x32d119196419c87d), + U64_C (0x923b494939497270), U64_C (0xaf5fd9d943d9869a), + U64_C (0xf931f2f2eff2c31d), U64_C (0xdba8e3e3abe34b48), + U64_C (0xb6b95b5b715be22a), U64_C (0x0dbc88881a883492), + U64_C (0x293e9a9a529aa4c8), U64_C (0x4c0b262698262dbe), + U64_C (0x64bf3232c8328dfa), U64_C (0x7d59b0b0fab0e94a), + U64_C (0xcff2e9e983e91b6a), U64_C (0x1e770f0f3c0f7833), + U64_C (0xb733d5d573d5e6a6), U64_C (0x1df480803a8074ba), + U64_C (0x6127bebec2be997c), U64_C (0x87ebcdcd13cd26de), + U64_C (0x68893434d034bde4), U64_C (0x903248483d487a75), + U64_C (0xe354ffffdbffab24), U64_C (0xf48d7a7af57af78f), + U64_C (0x3d6490907a90f4ea), U64_C (0xbe9d5f5f615fc23e), + U64_C (0x403d202080201da0), U64_C (0xd00f6868bd6867d5), + U64_C (0x34ca1a1a681ad072), U64_C (0x41b7aeae82ae192c), + U64_C (0x757db4b4eab4c95e), U64_C (0xa8ce54544d549a19), + U64_C (0x3b7f93937693ece5), U64_C (0x442f222288220daa), + U64_C (0xc86364648d6407e9), U64_C (0xff2af1f1e3f1db12), + U64_C (0xe6cc7373d173bfa2), U64_C (0x248212124812905a), + U64_C (0x807a40401d403a5d), U64_C (0x1048080820084028), + U64_C (0x9b95c3c32bc356e8), U64_C (0xc5dfecec97ec337b), + U64_C (0xab4ddbdb4bdb9690), U64_C (0x5fc0a1a1bea1611f), + U64_C (0x07918d8d0e8d1c83), U64_C (0x7ac83d3df43df5c9), + U64_C (0x335b97976697ccf1), U64_C (0x0000000000000000), + U64_C (0x83f9cfcf1bcf36d4), U64_C (0x566e2b2bac2b4587), + U64_C (0xece17676c57697b3), U64_C (0x19e68282328264b0), + U64_C (0xb128d6d67fd6fea9), U64_C (0x36c31b1b6c1bd877), + U64_C (0x7774b5b5eeb5c15b), U64_C (0x43beafaf86af1129), + U64_C (0xd41d6a6ab56a77df), U64_C (0xa0ea50505d50ba0d), + U64_C (0x8a5745450945124c), U64_C (0xfb38f3f3ebf3cb18), + U64_C (0x60ad3030c0309df0), U64_C (0xc3c4efef9bef2b74), + U64_C (0x7eda3f3ffc3fe5c3), U64_C (0xaac755554955921c), + U64_C (0x59dba2a2b2a27910), U64_C (0xc9e9eaea8fea0365), + U64_C (0xca6a656589650fec), U64_C (0x6903babad2bab968), + U64_C (0x5e4a2f2fbc2f6593), U64_C (0x9d8ec0c027c04ee7), + U64_C (0xa160dede5fdebe81), U64_C (0x38fc1c1c701ce06c), + U64_C (0xe746fdfdd3fdbb2e), U64_C (0x9a1f4d4d294d5264), + U64_C (0x397692927292e4e0), U64_C (0xeafa7575c9758fbc), + U64_C (0x0c3606061806301e), U64_C (0x09ae8a8a128a2498), + U64_C (0x794bb2b2f2b2f940), U64_C (0xd185e6e6bfe66359), + U64_C (0x1c7e0e0e380e7036), U64_C (0x3ee71f1f7c1ff863), + U64_C (0xc4556262956237f7), U64_C (0xb53ad4d477d4eea3), + U64_C (0x4d81a8a89aa82932), U64_C (0x315296966296c4f4), + U64_C (0xef62f9f9c3f99b3a), U64_C (0x97a3c5c533c566f6), + U64_C (0x4a102525942535b1), U64_C (0xb2ab59597959f220), + U64_C (0x15d084842a8454ae), U64_C (0xe4c57272d572b7a7), + U64_C (0x72ec3939e439d5dd), U64_C (0x98164c4c2d4c5a61), + U64_C (0xbc945e5e655eca3b), U64_C (0xf09f7878fd78e785), + U64_C (0x70e53838e038ddd8), U64_C (0x05988c8c0a8c1486), + U64_C (0xbf17d1d163d1c6b2), U64_C (0x57e4a5a5aea5410b), + U64_C (0xd9a1e2e2afe2434d), U64_C (0xc24e616199612ff8), + U64_C (0x7b42b3b3f6b3f145), U64_C (0x42342121842115a5), + U64_C (0x25089c9c4a9c94d6), U64_C (0x3cee1e1e781ef066), + U64_C (0x8661434311432252), U64_C (0x93b1c7c73bc776fc), + U64_C (0xe54ffcfcd7fcb32b), U64_C (0x0824040410042014), + U64_C (0xa2e351515951b208), U64_C (0x2f2599995e99bcc7), + U64_C (0xda226d6da96d4fc4), U64_C (0x1a650d0d340d6839), + U64_C (0xe979fafacffa8335), U64_C (0xa369dfdf5bdfb684), + U64_C (0xfca97e7ee57ed79b), U64_C (0x4819242490243db4), + U64_C (0x76fe3b3bec3bc5d7), U64_C (0x4b9aabab96ab313d), + U64_C (0x81f0cece1fce3ed1), U64_C (0x2299111144118855), + U64_C (0x03838f8f068f0c89), U64_C (0x9c044e4e254e4a6b), + U64_C (0x7366b7b7e6b7d151), U64_C (0xcbe0ebeb8beb0b60), + U64_C (0x78c13c3cf03cfdcc), U64_C (0x1ffd81813e817cbf), + U64_C (0x354094946a94d4fe), U64_C (0xf31cf7f7fbf7eb0c), + U64_C (0x6f18b9b9deb9a167), U64_C (0x268b13134c13985f), + U64_C (0x58512c2cb02c7d9c), U64_C (0xbb05d3d36bd3d6b8), + U64_C (0xd38ce7e7bbe76b5c), U64_C (0xdc396e6ea56e57cb), + U64_C (0x95aac4c437c46ef3), U64_C (0x061b03030c03180f), + U64_C (0xacdc565645568a13), U64_C (0x885e44440d441a49), + U64_C (0xfea07f7fe17fdf9e), U64_C (0x4f88a9a99ea92137), + U64_C (0x54672a2aa82a4d82), U64_C (0x6b0abbbbd6bbb16d), + U64_C (0x9f87c1c123c146e2), U64_C (0xa6f153535153a202), + U64_C (0xa572dcdc57dcae8b), U64_C (0x16530b0b2c0b5827), + U64_C (0x27019d9d4e9d9cd3), U64_C (0xd82b6c6cad6c47c1), + U64_C (0x62a43131c43195f5), U64_C (0xe8f37474cd7487b9), + U64_C (0xf115f6f6fff6e309), U64_C (0x8c4c464605460a43), + U64_C (0x45a5acac8aac0926), U64_C (0x0fb589891e893c97), + U64_C (0x28b414145014a044), U64_C (0xdfbae1e1a3e15b42), + U64_C (0x2ca616165816b04e), U64_C (0x74f73a3ae83acdd2), + U64_C (0xd2066969b9696fd0), U64_C (0x124109092409482d), + U64_C (0xe0d77070dd70a7ad), U64_C (0x716fb6b6e2b6d954), + U64_C (0xbd1ed0d067d0ceb7), U64_C (0xc7d6eded93ed3b7e), + U64_C (0x85e2cccc17cc2edb), U64_C (0x8468424215422a57), + U64_C (0x2d2c98985a98b4c2), U64_C (0x55eda4a4aaa4490e), + U64_C (0x50752828a0285d88), U64_C (0xb8865c5c6d5cda31), + U64_C (0xed6bf8f8c7f8933f), U64_C (0x11c28686228644a4), + }; + +static const u64 C3[256] = + { + U64_C (0x7830d818186018c0), U64_C (0xaf462623238c2305), + U64_C (0xf991b8c6c63fc67e), U64_C (0x6fcdfbe8e887e813), + U64_C (0xa113cb878726874c), U64_C (0x626d11b8b8dab8a9), + U64_C (0x0502090101040108), U64_C (0x6e9e0d4f4f214f42), + U64_C (0xee6c9b3636d836ad), U64_C (0x0451ffa6a6a2a659), + U64_C (0xbdb90cd2d26fd2de), U64_C (0x06f70ef5f5f3f5fb), + U64_C (0x80f2967979f979ef), U64_C (0xcede306f6fa16f5f), + U64_C (0xef3f6d91917e91fc), U64_C (0x07a4f852525552aa), + U64_C (0xfdc04760609d6027), U64_C (0x766535bcbccabc89), + U64_C (0xcd2b379b9b569bac), U64_C (0x8c018a8e8e028e04), + U64_C (0x155bd2a3a3b6a371), U64_C (0x3c186c0c0c300c60), + U64_C (0x8af6847b7bf17bff), U64_C (0xe16a803535d435b5), + U64_C (0x693af51d1d741de8), U64_C (0x47ddb3e0e0a7e053), + U64_C (0xacb321d7d77bd7f6), U64_C (0xed999cc2c22fc25e), + U64_C (0x965c432e2eb82e6d), U64_C (0x7a96294b4b314b62), + U64_C (0x21e15dfefedffea3), U64_C (0x16aed55757415782), + U64_C (0x412abd15155415a8), U64_C (0xb6eee87777c1779f), + U64_C (0xeb6e923737dc37a5), U64_C (0x56d79ee5e5b3e57b), + U64_C (0xd923139f9f469f8c), U64_C (0x17fd23f0f0e7f0d3), + U64_C (0x7f94204a4a354a6a), U64_C (0x95a944dada4fda9e), + U64_C (0x25b0a258587d58fa), U64_C (0xca8fcfc9c903c906), + U64_C (0x8d527c2929a42955), U64_C (0x22145a0a0a280a50), + U64_C (0x4f7f50b1b1feb1e1), U64_C (0x1a5dc9a0a0baa069), + U64_C (0xdad6146b6bb16b7f), U64_C (0xab17d985852e855c), + U64_C (0x73673cbdbdcebd81), U64_C (0x34ba8f5d5d695dd2), + U64_C (0x5020901010401080), U64_C (0x03f507f4f4f7f4f3), + U64_C (0xc08bddcbcb0bcb16), U64_C (0xc67cd33e3ef83eed), + U64_C (0x110a2d0505140528), U64_C (0xe6ce78676781671f), + U64_C (0x53d597e4e4b7e473), U64_C (0xbb4e0227279c2725), + U64_C (0x5882734141194132), U64_C (0x9d0ba78b8b168b2c), + U64_C (0x0153f6a7a7a6a751), U64_C (0x94fab27d7de97dcf), + U64_C (0xfb374995956e95dc), U64_C (0x9fad56d8d847d88e), + U64_C (0x30eb70fbfbcbfb8b), U64_C (0x71c1cdeeee9fee23), + U64_C (0x91f8bb7c7ced7cc7), U64_C (0xe3cc716666856617), + U64_C (0x8ea77bdddd53dda6), U64_C (0x4b2eaf17175c17b8), + U64_C (0x468e454747014702), U64_C (0xdc211a9e9e429e84), + U64_C (0xc589d4caca0fca1e), U64_C (0x995a582d2db42d75), + U64_C (0x79632ebfbfc6bf91), U64_C (0x1b0e3f07071c0738), + U64_C (0x2347acadad8ead01), U64_C (0x2fb4b05a5a755aea), + U64_C (0xb51bef838336836c), U64_C (0xff66b63333cc3385), + U64_C (0xf2c65c636391633f), U64_C (0x0a04120202080210), + U64_C (0x384993aaaa92aa39), U64_C (0xa8e2de7171d971af), + U64_C (0xcf8dc6c8c807c80e), U64_C (0x7d32d119196419c8), + U64_C (0x70923b4949394972), U64_C (0x9aaf5fd9d943d986), + U64_C (0x1df931f2f2eff2c3), U64_C (0x48dba8e3e3abe34b), + U64_C (0x2ab6b95b5b715be2), U64_C (0x920dbc88881a8834), + U64_C (0xc8293e9a9a529aa4), U64_C (0xbe4c0b262698262d), + U64_C (0xfa64bf3232c8328d), U64_C (0x4a7d59b0b0fab0e9), + U64_C (0x6acff2e9e983e91b), U64_C (0x331e770f0f3c0f78), + U64_C (0xa6b733d5d573d5e6), U64_C (0xba1df480803a8074), + U64_C (0x7c6127bebec2be99), U64_C (0xde87ebcdcd13cd26), + U64_C (0xe468893434d034bd), U64_C (0x75903248483d487a), + U64_C (0x24e354ffffdbffab), U64_C (0x8ff48d7a7af57af7), + U64_C (0xea3d6490907a90f4), U64_C (0x3ebe9d5f5f615fc2), + U64_C (0xa0403d202080201d), U64_C (0xd5d00f6868bd6867), + U64_C (0x7234ca1a1a681ad0), U64_C (0x2c41b7aeae82ae19), + U64_C (0x5e757db4b4eab4c9), U64_C (0x19a8ce54544d549a), + U64_C (0xe53b7f93937693ec), U64_C (0xaa442f222288220d), + U64_C (0xe9c86364648d6407), U64_C (0x12ff2af1f1e3f1db), + U64_C (0xa2e6cc7373d173bf), U64_C (0x5a24821212481290), + U64_C (0x5d807a40401d403a), U64_C (0x2810480808200840), + U64_C (0xe89b95c3c32bc356), U64_C (0x7bc5dfecec97ec33), + U64_C (0x90ab4ddbdb4bdb96), U64_C (0x1f5fc0a1a1bea161), + U64_C (0x8307918d8d0e8d1c), U64_C (0xc97ac83d3df43df5), + U64_C (0xf1335b97976697cc), U64_C (0x0000000000000000), + U64_C (0xd483f9cfcf1bcf36), U64_C (0x87566e2b2bac2b45), + U64_C (0xb3ece17676c57697), U64_C (0xb019e68282328264), + U64_C (0xa9b128d6d67fd6fe), U64_C (0x7736c31b1b6c1bd8), + U64_C (0x5b7774b5b5eeb5c1), U64_C (0x2943beafaf86af11), + U64_C (0xdfd41d6a6ab56a77), U64_C (0x0da0ea50505d50ba), + U64_C (0x4c8a574545094512), U64_C (0x18fb38f3f3ebf3cb), + U64_C (0xf060ad3030c0309d), U64_C (0x74c3c4efef9bef2b), + U64_C (0xc37eda3f3ffc3fe5), U64_C (0x1caac75555495592), + U64_C (0x1059dba2a2b2a279), U64_C (0x65c9e9eaea8fea03), + U64_C (0xecca6a656589650f), U64_C (0x686903babad2bab9), + U64_C (0x935e4a2f2fbc2f65), U64_C (0xe79d8ec0c027c04e), + U64_C (0x81a160dede5fdebe), U64_C (0x6c38fc1c1c701ce0), + U64_C (0x2ee746fdfdd3fdbb), U64_C (0x649a1f4d4d294d52), + U64_C (0xe0397692927292e4), U64_C (0xbceafa7575c9758f), + U64_C (0x1e0c360606180630), U64_C (0x9809ae8a8a128a24), + U64_C (0x40794bb2b2f2b2f9), U64_C (0x59d185e6e6bfe663), + U64_C (0x361c7e0e0e380e70), U64_C (0x633ee71f1f7c1ff8), + U64_C (0xf7c4556262956237), U64_C (0xa3b53ad4d477d4ee), + U64_C (0x324d81a8a89aa829), U64_C (0xf4315296966296c4), + U64_C (0x3aef62f9f9c3f99b), U64_C (0xf697a3c5c533c566), + U64_C (0xb14a102525942535), U64_C (0x20b2ab59597959f2), + U64_C (0xae15d084842a8454), U64_C (0xa7e4c57272d572b7), + U64_C (0xdd72ec3939e439d5), U64_C (0x6198164c4c2d4c5a), + U64_C (0x3bbc945e5e655eca), U64_C (0x85f09f7878fd78e7), + U64_C (0xd870e53838e038dd), U64_C (0x8605988c8c0a8c14), + U64_C (0xb2bf17d1d163d1c6), U64_C (0x0b57e4a5a5aea541), + U64_C (0x4dd9a1e2e2afe243), U64_C (0xf8c24e616199612f), + U64_C (0x457b42b3b3f6b3f1), U64_C (0xa542342121842115), + U64_C (0xd625089c9c4a9c94), U64_C (0x663cee1e1e781ef0), + U64_C (0x5286614343114322), U64_C (0xfc93b1c7c73bc776), + U64_C (0x2be54ffcfcd7fcb3), U64_C (0x1408240404100420), + U64_C (0x08a2e351515951b2), U64_C (0xc72f2599995e99bc), + U64_C (0xc4da226d6da96d4f), U64_C (0x391a650d0d340d68), + U64_C (0x35e979fafacffa83), U64_C (0x84a369dfdf5bdfb6), + U64_C (0x9bfca97e7ee57ed7), U64_C (0xb44819242490243d), + U64_C (0xd776fe3b3bec3bc5), U64_C (0x3d4b9aabab96ab31), + U64_C (0xd181f0cece1fce3e), U64_C (0x5522991111441188), + U64_C (0x8903838f8f068f0c), U64_C (0x6b9c044e4e254e4a), + U64_C (0x517366b7b7e6b7d1), U64_C (0x60cbe0ebeb8beb0b), + U64_C (0xcc78c13c3cf03cfd), U64_C (0xbf1ffd81813e817c), + U64_C (0xfe354094946a94d4), U64_C (0x0cf31cf7f7fbf7eb), + U64_C (0x676f18b9b9deb9a1), U64_C (0x5f268b13134c1398), + U64_C (0x9c58512c2cb02c7d), U64_C (0xb8bb05d3d36bd3d6), + U64_C (0x5cd38ce7e7bbe76b), U64_C (0xcbdc396e6ea56e57), + U64_C (0xf395aac4c437c46e), U64_C (0x0f061b03030c0318), + U64_C (0x13acdc565645568a), U64_C (0x49885e44440d441a), + U64_C (0x9efea07f7fe17fdf), U64_C (0x374f88a9a99ea921), + U64_C (0x8254672a2aa82a4d), U64_C (0x6d6b0abbbbd6bbb1), + U64_C (0xe29f87c1c123c146), U64_C (0x02a6f153535153a2), + U64_C (0x8ba572dcdc57dcae), U64_C (0x2716530b0b2c0b58), + U64_C (0xd327019d9d4e9d9c), U64_C (0xc1d82b6c6cad6c47), + U64_C (0xf562a43131c43195), U64_C (0xb9e8f37474cd7487), + U64_C (0x09f115f6f6fff6e3), U64_C (0x438c4c464605460a), + U64_C (0x2645a5acac8aac09), U64_C (0x970fb589891e893c), + U64_C (0x4428b414145014a0), U64_C (0x42dfbae1e1a3e15b), + U64_C (0x4e2ca616165816b0), U64_C (0xd274f73a3ae83acd), + U64_C (0xd0d2066969b9696f), U64_C (0x2d12410909240948), + U64_C (0xade0d77070dd70a7), U64_C (0x54716fb6b6e2b6d9), + U64_C (0xb7bd1ed0d067d0ce), U64_C (0x7ec7d6eded93ed3b), + U64_C (0xdb85e2cccc17cc2e), U64_C (0x578468424215422a), + U64_C (0xc22d2c98985a98b4), U64_C (0x0e55eda4a4aaa449), + U64_C (0x8850752828a0285d), U64_C (0x31b8865c5c6d5cda), + U64_C (0x3fed6bf8f8c7f893), U64_C (0xa411c28686228644), + }; + +static const u64 C4[256] = + { + U64_C (0xc07830d818186018), U64_C (0x05af462623238c23), + U64_C (0x7ef991b8c6c63fc6), U64_C (0x136fcdfbe8e887e8), + U64_C (0x4ca113cb87872687), U64_C (0xa9626d11b8b8dab8), + U64_C (0x0805020901010401), U64_C (0x426e9e0d4f4f214f), + U64_C (0xadee6c9b3636d836), U64_C (0x590451ffa6a6a2a6), + U64_C (0xdebdb90cd2d26fd2), U64_C (0xfb06f70ef5f5f3f5), + U64_C (0xef80f2967979f979), U64_C (0x5fcede306f6fa16f), + U64_C (0xfcef3f6d91917e91), U64_C (0xaa07a4f852525552), + U64_C (0x27fdc04760609d60), U64_C (0x89766535bcbccabc), + U64_C (0xaccd2b379b9b569b), U64_C (0x048c018a8e8e028e), + U64_C (0x71155bd2a3a3b6a3), U64_C (0x603c186c0c0c300c), + U64_C (0xff8af6847b7bf17b), U64_C (0xb5e16a803535d435), + U64_C (0xe8693af51d1d741d), U64_C (0x5347ddb3e0e0a7e0), + U64_C (0xf6acb321d7d77bd7), U64_C (0x5eed999cc2c22fc2), + U64_C (0x6d965c432e2eb82e), U64_C (0x627a96294b4b314b), + U64_C (0xa321e15dfefedffe), U64_C (0x8216aed557574157), + U64_C (0xa8412abd15155415), U64_C (0x9fb6eee87777c177), + U64_C (0xa5eb6e923737dc37), U64_C (0x7b56d79ee5e5b3e5), + U64_C (0x8cd923139f9f469f), U64_C (0xd317fd23f0f0e7f0), + U64_C (0x6a7f94204a4a354a), U64_C (0x9e95a944dada4fda), + U64_C (0xfa25b0a258587d58), U64_C (0x06ca8fcfc9c903c9), + U64_C (0x558d527c2929a429), U64_C (0x5022145a0a0a280a), + U64_C (0xe14f7f50b1b1feb1), U64_C (0x691a5dc9a0a0baa0), + U64_C (0x7fdad6146b6bb16b), U64_C (0x5cab17d985852e85), + U64_C (0x8173673cbdbdcebd), U64_C (0xd234ba8f5d5d695d), + U64_C (0x8050209010104010), U64_C (0xf303f507f4f4f7f4), + U64_C (0x16c08bddcbcb0bcb), U64_C (0xedc67cd33e3ef83e), + U64_C (0x28110a2d05051405), U64_C (0x1fe6ce7867678167), + U64_C (0x7353d597e4e4b7e4), U64_C (0x25bb4e0227279c27), + U64_C (0x3258827341411941), U64_C (0x2c9d0ba78b8b168b), + U64_C (0x510153f6a7a7a6a7), U64_C (0xcf94fab27d7de97d), + U64_C (0xdcfb374995956e95), U64_C (0x8e9fad56d8d847d8), + U64_C (0x8b30eb70fbfbcbfb), U64_C (0x2371c1cdeeee9fee), + U64_C (0xc791f8bb7c7ced7c), U64_C (0x17e3cc7166668566), + U64_C (0xa68ea77bdddd53dd), U64_C (0xb84b2eaf17175c17), + U64_C (0x02468e4547470147), U64_C (0x84dc211a9e9e429e), + U64_C (0x1ec589d4caca0fca), U64_C (0x75995a582d2db42d), + U64_C (0x9179632ebfbfc6bf), U64_C (0x381b0e3f07071c07), + U64_C (0x012347acadad8ead), U64_C (0xea2fb4b05a5a755a), + U64_C (0x6cb51bef83833683), U64_C (0x85ff66b63333cc33), + U64_C (0x3ff2c65c63639163), U64_C (0x100a041202020802), + U64_C (0x39384993aaaa92aa), U64_C (0xafa8e2de7171d971), + U64_C (0x0ecf8dc6c8c807c8), U64_C (0xc87d32d119196419), + U64_C (0x7270923b49493949), U64_C (0x869aaf5fd9d943d9), + U64_C (0xc31df931f2f2eff2), U64_C (0x4b48dba8e3e3abe3), + U64_C (0xe22ab6b95b5b715b), U64_C (0x34920dbc88881a88), + U64_C (0xa4c8293e9a9a529a), U64_C (0x2dbe4c0b26269826), + U64_C (0x8dfa64bf3232c832), U64_C (0xe94a7d59b0b0fab0), + U64_C (0x1b6acff2e9e983e9), U64_C (0x78331e770f0f3c0f), + U64_C (0xe6a6b733d5d573d5), U64_C (0x74ba1df480803a80), + U64_C (0x997c6127bebec2be), U64_C (0x26de87ebcdcd13cd), + U64_C (0xbde468893434d034), U64_C (0x7a75903248483d48), + U64_C (0xab24e354ffffdbff), U64_C (0xf78ff48d7a7af57a), + U64_C (0xf4ea3d6490907a90), U64_C (0xc23ebe9d5f5f615f), + U64_C (0x1da0403d20208020), U64_C (0x67d5d00f6868bd68), + U64_C (0xd07234ca1a1a681a), U64_C (0x192c41b7aeae82ae), + U64_C (0xc95e757db4b4eab4), U64_C (0x9a19a8ce54544d54), + U64_C (0xece53b7f93937693), U64_C (0x0daa442f22228822), + U64_C (0x07e9c86364648d64), U64_C (0xdb12ff2af1f1e3f1), + U64_C (0xbfa2e6cc7373d173), U64_C (0x905a248212124812), + U64_C (0x3a5d807a40401d40), U64_C (0x4028104808082008), + U64_C (0x56e89b95c3c32bc3), U64_C (0x337bc5dfecec97ec), + U64_C (0x9690ab4ddbdb4bdb), U64_C (0x611f5fc0a1a1bea1), + U64_C (0x1c8307918d8d0e8d), U64_C (0xf5c97ac83d3df43d), + U64_C (0xccf1335b97976697), U64_C (0x0000000000000000), + U64_C (0x36d483f9cfcf1bcf), U64_C (0x4587566e2b2bac2b), + U64_C (0x97b3ece17676c576), U64_C (0x64b019e682823282), + U64_C (0xfea9b128d6d67fd6), U64_C (0xd87736c31b1b6c1b), + U64_C (0xc15b7774b5b5eeb5), U64_C (0x112943beafaf86af), + U64_C (0x77dfd41d6a6ab56a), U64_C (0xba0da0ea50505d50), + U64_C (0x124c8a5745450945), U64_C (0xcb18fb38f3f3ebf3), + U64_C (0x9df060ad3030c030), U64_C (0x2b74c3c4efef9bef), + U64_C (0xe5c37eda3f3ffc3f), U64_C (0x921caac755554955), + U64_C (0x791059dba2a2b2a2), U64_C (0x0365c9e9eaea8fea), + U64_C (0x0fecca6a65658965), U64_C (0xb9686903babad2ba), + U64_C (0x65935e4a2f2fbc2f), U64_C (0x4ee79d8ec0c027c0), + U64_C (0xbe81a160dede5fde), U64_C (0xe06c38fc1c1c701c), + U64_C (0xbb2ee746fdfdd3fd), U64_C (0x52649a1f4d4d294d), + U64_C (0xe4e0397692927292), U64_C (0x8fbceafa7575c975), + U64_C (0x301e0c3606061806), U64_C (0x249809ae8a8a128a), + U64_C (0xf940794bb2b2f2b2), U64_C (0x6359d185e6e6bfe6), + U64_C (0x70361c7e0e0e380e), U64_C (0xf8633ee71f1f7c1f), + U64_C (0x37f7c45562629562), U64_C (0xeea3b53ad4d477d4), + U64_C (0x29324d81a8a89aa8), U64_C (0xc4f4315296966296), + U64_C (0x9b3aef62f9f9c3f9), U64_C (0x66f697a3c5c533c5), + U64_C (0x35b14a1025259425), U64_C (0xf220b2ab59597959), + U64_C (0x54ae15d084842a84), U64_C (0xb7a7e4c57272d572), + U64_C (0xd5dd72ec3939e439), U64_C (0x5a6198164c4c2d4c), + U64_C (0xca3bbc945e5e655e), U64_C (0xe785f09f7878fd78), + U64_C (0xddd870e53838e038), U64_C (0x148605988c8c0a8c), + U64_C (0xc6b2bf17d1d163d1), U64_C (0x410b57e4a5a5aea5), + U64_C (0x434dd9a1e2e2afe2), U64_C (0x2ff8c24e61619961), + U64_C (0xf1457b42b3b3f6b3), U64_C (0x15a5423421218421), + U64_C (0x94d625089c9c4a9c), U64_C (0xf0663cee1e1e781e), + U64_C (0x2252866143431143), U64_C (0x76fc93b1c7c73bc7), + U64_C (0xb32be54ffcfcd7fc), U64_C (0x2014082404041004), + U64_C (0xb208a2e351515951), U64_C (0xbcc72f2599995e99), + U64_C (0x4fc4da226d6da96d), U64_C (0x68391a650d0d340d), + U64_C (0x8335e979fafacffa), U64_C (0xb684a369dfdf5bdf), + U64_C (0xd79bfca97e7ee57e), U64_C (0x3db4481924249024), + U64_C (0xc5d776fe3b3bec3b), U64_C (0x313d4b9aabab96ab), + U64_C (0x3ed181f0cece1fce), U64_C (0x8855229911114411), + U64_C (0x0c8903838f8f068f), U64_C (0x4a6b9c044e4e254e), + U64_C (0xd1517366b7b7e6b7), U64_C (0x0b60cbe0ebeb8beb), + U64_C (0xfdcc78c13c3cf03c), U64_C (0x7cbf1ffd81813e81), + U64_C (0xd4fe354094946a94), U64_C (0xeb0cf31cf7f7fbf7), + U64_C (0xa1676f18b9b9deb9), U64_C (0x985f268b13134c13), + U64_C (0x7d9c58512c2cb02c), U64_C (0xd6b8bb05d3d36bd3), + U64_C (0x6b5cd38ce7e7bbe7), U64_C (0x57cbdc396e6ea56e), + U64_C (0x6ef395aac4c437c4), U64_C (0x180f061b03030c03), + U64_C (0x8a13acdc56564556), U64_C (0x1a49885e44440d44), + U64_C (0xdf9efea07f7fe17f), U64_C (0x21374f88a9a99ea9), + U64_C (0x4d8254672a2aa82a), U64_C (0xb16d6b0abbbbd6bb), + U64_C (0x46e29f87c1c123c1), U64_C (0xa202a6f153535153), + U64_C (0xae8ba572dcdc57dc), U64_C (0x582716530b0b2c0b), + U64_C (0x9cd327019d9d4e9d), U64_C (0x47c1d82b6c6cad6c), + U64_C (0x95f562a43131c431), U64_C (0x87b9e8f37474cd74), + U64_C (0xe309f115f6f6fff6), U64_C (0x0a438c4c46460546), + U64_C (0x092645a5acac8aac), U64_C (0x3c970fb589891e89), + U64_C (0xa04428b414145014), U64_C (0x5b42dfbae1e1a3e1), + U64_C (0xb04e2ca616165816), U64_C (0xcdd274f73a3ae83a), + U64_C (0x6fd0d2066969b969), U64_C (0x482d124109092409), + U64_C (0xa7ade0d77070dd70), U64_C (0xd954716fb6b6e2b6), + U64_C (0xceb7bd1ed0d067d0), U64_C (0x3b7ec7d6eded93ed), + U64_C (0x2edb85e2cccc17cc), U64_C (0x2a57846842421542), + U64_C (0xb4c22d2c98985a98), U64_C (0x490e55eda4a4aaa4), + U64_C (0x5d8850752828a028), U64_C (0xda31b8865c5c6d5c), + U64_C (0x933fed6bf8f8c7f8), U64_C (0x44a411c286862286), + }; + +static const u64 C5[256] = + { + U64_C (0x18c07830d8181860), U64_C (0x2305af462623238c), + U64_C (0xc67ef991b8c6c63f), U64_C (0xe8136fcdfbe8e887), + U64_C (0x874ca113cb878726), U64_C (0xb8a9626d11b8b8da), + U64_C (0x0108050209010104), U64_C (0x4f426e9e0d4f4f21), + U64_C (0x36adee6c9b3636d8), U64_C (0xa6590451ffa6a6a2), + U64_C (0xd2debdb90cd2d26f), U64_C (0xf5fb06f70ef5f5f3), + U64_C (0x79ef80f2967979f9), U64_C (0x6f5fcede306f6fa1), + U64_C (0x91fcef3f6d91917e), U64_C (0x52aa07a4f8525255), + U64_C (0x6027fdc04760609d), U64_C (0xbc89766535bcbcca), + U64_C (0x9baccd2b379b9b56), U64_C (0x8e048c018a8e8e02), + U64_C (0xa371155bd2a3a3b6), U64_C (0x0c603c186c0c0c30), + U64_C (0x7bff8af6847b7bf1), U64_C (0x35b5e16a803535d4), + U64_C (0x1de8693af51d1d74), U64_C (0xe05347ddb3e0e0a7), + U64_C (0xd7f6acb321d7d77b), U64_C (0xc25eed999cc2c22f), + U64_C (0x2e6d965c432e2eb8), U64_C (0x4b627a96294b4b31), + U64_C (0xfea321e15dfefedf), U64_C (0x578216aed5575741), + U64_C (0x15a8412abd151554), U64_C (0x779fb6eee87777c1), + U64_C (0x37a5eb6e923737dc), U64_C (0xe57b56d79ee5e5b3), + U64_C (0x9f8cd923139f9f46), U64_C (0xf0d317fd23f0f0e7), + U64_C (0x4a6a7f94204a4a35), U64_C (0xda9e95a944dada4f), + U64_C (0x58fa25b0a258587d), U64_C (0xc906ca8fcfc9c903), + U64_C (0x29558d527c2929a4), U64_C (0x0a5022145a0a0a28), + U64_C (0xb1e14f7f50b1b1fe), U64_C (0xa0691a5dc9a0a0ba), + U64_C (0x6b7fdad6146b6bb1), U64_C (0x855cab17d985852e), + U64_C (0xbd8173673cbdbdce), U64_C (0x5dd234ba8f5d5d69), + U64_C (0x1080502090101040), U64_C (0xf4f303f507f4f4f7), + U64_C (0xcb16c08bddcbcb0b), U64_C (0x3eedc67cd33e3ef8), + U64_C (0x0528110a2d050514), U64_C (0x671fe6ce78676781), + U64_C (0xe47353d597e4e4b7), U64_C (0x2725bb4e0227279c), + U64_C (0x4132588273414119), U64_C (0x8b2c9d0ba78b8b16), + U64_C (0xa7510153f6a7a7a6), U64_C (0x7dcf94fab27d7de9), + U64_C (0x95dcfb374995956e), U64_C (0xd88e9fad56d8d847), + U64_C (0xfb8b30eb70fbfbcb), U64_C (0xee2371c1cdeeee9f), + U64_C (0x7cc791f8bb7c7ced), U64_C (0x6617e3cc71666685), + U64_C (0xdda68ea77bdddd53), U64_C (0x17b84b2eaf17175c), + U64_C (0x4702468e45474701), U64_C (0x9e84dc211a9e9e42), + U64_C (0xca1ec589d4caca0f), U64_C (0x2d75995a582d2db4), + U64_C (0xbf9179632ebfbfc6), U64_C (0x07381b0e3f07071c), + U64_C (0xad012347acadad8e), U64_C (0x5aea2fb4b05a5a75), + U64_C (0x836cb51bef838336), U64_C (0x3385ff66b63333cc), + U64_C (0x633ff2c65c636391), U64_C (0x02100a0412020208), + U64_C (0xaa39384993aaaa92), U64_C (0x71afa8e2de7171d9), + U64_C (0xc80ecf8dc6c8c807), U64_C (0x19c87d32d1191964), + U64_C (0x497270923b494939), U64_C (0xd9869aaf5fd9d943), + U64_C (0xf2c31df931f2f2ef), U64_C (0xe34b48dba8e3e3ab), + U64_C (0x5be22ab6b95b5b71), U64_C (0x8834920dbc88881a), + U64_C (0x9aa4c8293e9a9a52), U64_C (0x262dbe4c0b262698), + U64_C (0x328dfa64bf3232c8), U64_C (0xb0e94a7d59b0b0fa), + U64_C (0xe91b6acff2e9e983), U64_C (0x0f78331e770f0f3c), + U64_C (0xd5e6a6b733d5d573), U64_C (0x8074ba1df480803a), + U64_C (0xbe997c6127bebec2), U64_C (0xcd26de87ebcdcd13), + U64_C (0x34bde468893434d0), U64_C (0x487a75903248483d), + U64_C (0xffab24e354ffffdb), U64_C (0x7af78ff48d7a7af5), + U64_C (0x90f4ea3d6490907a), U64_C (0x5fc23ebe9d5f5f61), + U64_C (0x201da0403d202080), U64_C (0x6867d5d00f6868bd), + U64_C (0x1ad07234ca1a1a68), U64_C (0xae192c41b7aeae82), + U64_C (0xb4c95e757db4b4ea), U64_C (0x549a19a8ce54544d), + U64_C (0x93ece53b7f939376), U64_C (0x220daa442f222288), + U64_C (0x6407e9c86364648d), U64_C (0xf1db12ff2af1f1e3), + U64_C (0x73bfa2e6cc7373d1), U64_C (0x12905a2482121248), + U64_C (0x403a5d807a40401d), U64_C (0x0840281048080820), + U64_C (0xc356e89b95c3c32b), U64_C (0xec337bc5dfecec97), + U64_C (0xdb9690ab4ddbdb4b), U64_C (0xa1611f5fc0a1a1be), + U64_C (0x8d1c8307918d8d0e), U64_C (0x3df5c97ac83d3df4), + U64_C (0x97ccf1335b979766), U64_C (0x0000000000000000), + U64_C (0xcf36d483f9cfcf1b), U64_C (0x2b4587566e2b2bac), + U64_C (0x7697b3ece17676c5), U64_C (0x8264b019e6828232), + U64_C (0xd6fea9b128d6d67f), U64_C (0x1bd87736c31b1b6c), + U64_C (0xb5c15b7774b5b5ee), U64_C (0xaf112943beafaf86), + U64_C (0x6a77dfd41d6a6ab5), U64_C (0x50ba0da0ea50505d), + U64_C (0x45124c8a57454509), U64_C (0xf3cb18fb38f3f3eb), + U64_C (0x309df060ad3030c0), U64_C (0xef2b74c3c4efef9b), + U64_C (0x3fe5c37eda3f3ffc), U64_C (0x55921caac7555549), + U64_C (0xa2791059dba2a2b2), U64_C (0xea0365c9e9eaea8f), + U64_C (0x650fecca6a656589), U64_C (0xbab9686903babad2), + U64_C (0x2f65935e4a2f2fbc), U64_C (0xc04ee79d8ec0c027), + U64_C (0xdebe81a160dede5f), U64_C (0x1ce06c38fc1c1c70), + U64_C (0xfdbb2ee746fdfdd3), U64_C (0x4d52649a1f4d4d29), + U64_C (0x92e4e03976929272), U64_C (0x758fbceafa7575c9), + U64_C (0x06301e0c36060618), U64_C (0x8a249809ae8a8a12), + U64_C (0xb2f940794bb2b2f2), U64_C (0xe66359d185e6e6bf), + U64_C (0x0e70361c7e0e0e38), U64_C (0x1ff8633ee71f1f7c), + U64_C (0x6237f7c455626295), U64_C (0xd4eea3b53ad4d477), + U64_C (0xa829324d81a8a89a), U64_C (0x96c4f43152969662), + U64_C (0xf99b3aef62f9f9c3), U64_C (0xc566f697a3c5c533), + U64_C (0x2535b14a10252594), U64_C (0x59f220b2ab595979), + U64_C (0x8454ae15d084842a), U64_C (0x72b7a7e4c57272d5), + U64_C (0x39d5dd72ec3939e4), U64_C (0x4c5a6198164c4c2d), + U64_C (0x5eca3bbc945e5e65), U64_C (0x78e785f09f7878fd), + U64_C (0x38ddd870e53838e0), U64_C (0x8c148605988c8c0a), + U64_C (0xd1c6b2bf17d1d163), U64_C (0xa5410b57e4a5a5ae), + U64_C (0xe2434dd9a1e2e2af), U64_C (0x612ff8c24e616199), + U64_C (0xb3f1457b42b3b3f6), U64_C (0x2115a54234212184), + U64_C (0x9c94d625089c9c4a), U64_C (0x1ef0663cee1e1e78), + U64_C (0x4322528661434311), U64_C (0xc776fc93b1c7c73b), + U64_C (0xfcb32be54ffcfcd7), U64_C (0x0420140824040410), + U64_C (0x51b208a2e3515159), U64_C (0x99bcc72f2599995e), + U64_C (0x6d4fc4da226d6da9), U64_C (0x0d68391a650d0d34), + U64_C (0xfa8335e979fafacf), U64_C (0xdfb684a369dfdf5b), + U64_C (0x7ed79bfca97e7ee5), U64_C (0x243db44819242490), + U64_C (0x3bc5d776fe3b3bec), U64_C (0xab313d4b9aabab96), + U64_C (0xce3ed181f0cece1f), U64_C (0x1188552299111144), + U64_C (0x8f0c8903838f8f06), U64_C (0x4e4a6b9c044e4e25), + U64_C (0xb7d1517366b7b7e6), U64_C (0xeb0b60cbe0ebeb8b), + U64_C (0x3cfdcc78c13c3cf0), U64_C (0x817cbf1ffd81813e), + U64_C (0x94d4fe354094946a), U64_C (0xf7eb0cf31cf7f7fb), + U64_C (0xb9a1676f18b9b9de), U64_C (0x13985f268b13134c), + U64_C (0x2c7d9c58512c2cb0), U64_C (0xd3d6b8bb05d3d36b), + U64_C (0xe76b5cd38ce7e7bb), U64_C (0x6e57cbdc396e6ea5), + U64_C (0xc46ef395aac4c437), U64_C (0x03180f061b03030c), + U64_C (0x568a13acdc565645), U64_C (0x441a49885e44440d), + U64_C (0x7fdf9efea07f7fe1), U64_C (0xa921374f88a9a99e), + U64_C (0x2a4d8254672a2aa8), U64_C (0xbbb16d6b0abbbbd6), + U64_C (0xc146e29f87c1c123), U64_C (0x53a202a6f1535351), + U64_C (0xdcae8ba572dcdc57), U64_C (0x0b582716530b0b2c), + U64_C (0x9d9cd327019d9d4e), U64_C (0x6c47c1d82b6c6cad), + U64_C (0x3195f562a43131c4), U64_C (0x7487b9e8f37474cd), + U64_C (0xf6e309f115f6f6ff), U64_C (0x460a438c4c464605), + U64_C (0xac092645a5acac8a), U64_C (0x893c970fb589891e), + U64_C (0x14a04428b4141450), U64_C (0xe15b42dfbae1e1a3), + U64_C (0x16b04e2ca6161658), U64_C (0x3acdd274f73a3ae8), + U64_C (0x696fd0d2066969b9), U64_C (0x09482d1241090924), + U64_C (0x70a7ade0d77070dd), U64_C (0xb6d954716fb6b6e2), + U64_C (0xd0ceb7bd1ed0d067), U64_C (0xed3b7ec7d6eded93), + U64_C (0xcc2edb85e2cccc17), U64_C (0x422a578468424215), + U64_C (0x98b4c22d2c98985a), U64_C (0xa4490e55eda4a4aa), + U64_C (0x285d8850752828a0), U64_C (0x5cda31b8865c5c6d), + U64_C (0xf8933fed6bf8f8c7), U64_C (0x8644a411c2868622), + }; + +static const u64 C6[256] = + { + U64_C (0x6018c07830d81818), U64_C (0x8c2305af46262323), + U64_C (0x3fc67ef991b8c6c6), U64_C (0x87e8136fcdfbe8e8), + U64_C (0x26874ca113cb8787), U64_C (0xdab8a9626d11b8b8), + U64_C (0x0401080502090101), U64_C (0x214f426e9e0d4f4f), + U64_C (0xd836adee6c9b3636), U64_C (0xa2a6590451ffa6a6), + U64_C (0x6fd2debdb90cd2d2), U64_C (0xf3f5fb06f70ef5f5), + U64_C (0xf979ef80f2967979), U64_C (0xa16f5fcede306f6f), + U64_C (0x7e91fcef3f6d9191), U64_C (0x5552aa07a4f85252), + U64_C (0x9d6027fdc0476060), U64_C (0xcabc89766535bcbc), + U64_C (0x569baccd2b379b9b), U64_C (0x028e048c018a8e8e), + U64_C (0xb6a371155bd2a3a3), U64_C (0x300c603c186c0c0c), + U64_C (0xf17bff8af6847b7b), U64_C (0xd435b5e16a803535), + U64_C (0x741de8693af51d1d), U64_C (0xa7e05347ddb3e0e0), + U64_C (0x7bd7f6acb321d7d7), U64_C (0x2fc25eed999cc2c2), + U64_C (0xb82e6d965c432e2e), U64_C (0x314b627a96294b4b), + U64_C (0xdffea321e15dfefe), U64_C (0x41578216aed55757), + U64_C (0x5415a8412abd1515), U64_C (0xc1779fb6eee87777), + U64_C (0xdc37a5eb6e923737), U64_C (0xb3e57b56d79ee5e5), + U64_C (0x469f8cd923139f9f), U64_C (0xe7f0d317fd23f0f0), + U64_C (0x354a6a7f94204a4a), U64_C (0x4fda9e95a944dada), + U64_C (0x7d58fa25b0a25858), U64_C (0x03c906ca8fcfc9c9), + U64_C (0xa429558d527c2929), U64_C (0x280a5022145a0a0a), + U64_C (0xfeb1e14f7f50b1b1), U64_C (0xbaa0691a5dc9a0a0), + U64_C (0xb16b7fdad6146b6b), U64_C (0x2e855cab17d98585), + U64_C (0xcebd8173673cbdbd), U64_C (0x695dd234ba8f5d5d), + U64_C (0x4010805020901010), U64_C (0xf7f4f303f507f4f4), + U64_C (0x0bcb16c08bddcbcb), U64_C (0xf83eedc67cd33e3e), + U64_C (0x140528110a2d0505), U64_C (0x81671fe6ce786767), + U64_C (0xb7e47353d597e4e4), U64_C (0x9c2725bb4e022727), + U64_C (0x1941325882734141), U64_C (0x168b2c9d0ba78b8b), + U64_C (0xa6a7510153f6a7a7), U64_C (0xe97dcf94fab27d7d), + U64_C (0x6e95dcfb37499595), U64_C (0x47d88e9fad56d8d8), + U64_C (0xcbfb8b30eb70fbfb), U64_C (0x9fee2371c1cdeeee), + U64_C (0xed7cc791f8bb7c7c), U64_C (0x856617e3cc716666), + U64_C (0x53dda68ea77bdddd), U64_C (0x5c17b84b2eaf1717), + U64_C (0x014702468e454747), U64_C (0x429e84dc211a9e9e), + U64_C (0x0fca1ec589d4caca), U64_C (0xb42d75995a582d2d), + U64_C (0xc6bf9179632ebfbf), U64_C (0x1c07381b0e3f0707), + U64_C (0x8ead012347acadad), U64_C (0x755aea2fb4b05a5a), + U64_C (0x36836cb51bef8383), U64_C (0xcc3385ff66b63333), + U64_C (0x91633ff2c65c6363), U64_C (0x0802100a04120202), + U64_C (0x92aa39384993aaaa), U64_C (0xd971afa8e2de7171), + U64_C (0x07c80ecf8dc6c8c8), U64_C (0x6419c87d32d11919), + U64_C (0x39497270923b4949), U64_C (0x43d9869aaf5fd9d9), + U64_C (0xeff2c31df931f2f2), U64_C (0xabe34b48dba8e3e3), + U64_C (0x715be22ab6b95b5b), U64_C (0x1a8834920dbc8888), + U64_C (0x529aa4c8293e9a9a), U64_C (0x98262dbe4c0b2626), + U64_C (0xc8328dfa64bf3232), U64_C (0xfab0e94a7d59b0b0), + U64_C (0x83e91b6acff2e9e9), U64_C (0x3c0f78331e770f0f), + U64_C (0x73d5e6a6b733d5d5), U64_C (0x3a8074ba1df48080), + U64_C (0xc2be997c6127bebe), U64_C (0x13cd26de87ebcdcd), + U64_C (0xd034bde468893434), U64_C (0x3d487a7590324848), + U64_C (0xdbffab24e354ffff), U64_C (0xf57af78ff48d7a7a), + U64_C (0x7a90f4ea3d649090), U64_C (0x615fc23ebe9d5f5f), + U64_C (0x80201da0403d2020), U64_C (0xbd6867d5d00f6868), + U64_C (0x681ad07234ca1a1a), U64_C (0x82ae192c41b7aeae), + U64_C (0xeab4c95e757db4b4), U64_C (0x4d549a19a8ce5454), + U64_C (0x7693ece53b7f9393), U64_C (0x88220daa442f2222), + U64_C (0x8d6407e9c8636464), U64_C (0xe3f1db12ff2af1f1), + U64_C (0xd173bfa2e6cc7373), U64_C (0x4812905a24821212), + U64_C (0x1d403a5d807a4040), U64_C (0x2008402810480808), + U64_C (0x2bc356e89b95c3c3), U64_C (0x97ec337bc5dfecec), + U64_C (0x4bdb9690ab4ddbdb), U64_C (0xbea1611f5fc0a1a1), + U64_C (0x0e8d1c8307918d8d), U64_C (0xf43df5c97ac83d3d), + U64_C (0x6697ccf1335b9797), U64_C (0x0000000000000000), + U64_C (0x1bcf36d483f9cfcf), U64_C (0xac2b4587566e2b2b), + U64_C (0xc57697b3ece17676), U64_C (0x328264b019e68282), + U64_C (0x7fd6fea9b128d6d6), U64_C (0x6c1bd87736c31b1b), + U64_C (0xeeb5c15b7774b5b5), U64_C (0x86af112943beafaf), + U64_C (0xb56a77dfd41d6a6a), U64_C (0x5d50ba0da0ea5050), + U64_C (0x0945124c8a574545), U64_C (0xebf3cb18fb38f3f3), + U64_C (0xc0309df060ad3030), U64_C (0x9bef2b74c3c4efef), + U64_C (0xfc3fe5c37eda3f3f), U64_C (0x4955921caac75555), + U64_C (0xb2a2791059dba2a2), U64_C (0x8fea0365c9e9eaea), + U64_C (0x89650fecca6a6565), U64_C (0xd2bab9686903baba), + U64_C (0xbc2f65935e4a2f2f), U64_C (0x27c04ee79d8ec0c0), + U64_C (0x5fdebe81a160dede), U64_C (0x701ce06c38fc1c1c), + U64_C (0xd3fdbb2ee746fdfd), U64_C (0x294d52649a1f4d4d), + U64_C (0x7292e4e039769292), U64_C (0xc9758fbceafa7575), + U64_C (0x1806301e0c360606), U64_C (0x128a249809ae8a8a), + U64_C (0xf2b2f940794bb2b2), U64_C (0xbfe66359d185e6e6), + U64_C (0x380e70361c7e0e0e), U64_C (0x7c1ff8633ee71f1f), + U64_C (0x956237f7c4556262), U64_C (0x77d4eea3b53ad4d4), + U64_C (0x9aa829324d81a8a8), U64_C (0x6296c4f431529696), + U64_C (0xc3f99b3aef62f9f9), U64_C (0x33c566f697a3c5c5), + U64_C (0x942535b14a102525), U64_C (0x7959f220b2ab5959), + U64_C (0x2a8454ae15d08484), U64_C (0xd572b7a7e4c57272), + U64_C (0xe439d5dd72ec3939), U64_C (0x2d4c5a6198164c4c), + U64_C (0x655eca3bbc945e5e), U64_C (0xfd78e785f09f7878), + U64_C (0xe038ddd870e53838), U64_C (0x0a8c148605988c8c), + U64_C (0x63d1c6b2bf17d1d1), U64_C (0xaea5410b57e4a5a5), + U64_C (0xafe2434dd9a1e2e2), U64_C (0x99612ff8c24e6161), + U64_C (0xf6b3f1457b42b3b3), U64_C (0x842115a542342121), + U64_C (0x4a9c94d625089c9c), U64_C (0x781ef0663cee1e1e), + U64_C (0x1143225286614343), U64_C (0x3bc776fc93b1c7c7), + U64_C (0xd7fcb32be54ffcfc), U64_C (0x1004201408240404), + U64_C (0x5951b208a2e35151), U64_C (0x5e99bcc72f259999), + U64_C (0xa96d4fc4da226d6d), U64_C (0x340d68391a650d0d), + U64_C (0xcffa8335e979fafa), U64_C (0x5bdfb684a369dfdf), + U64_C (0xe57ed79bfca97e7e), U64_C (0x90243db448192424), + U64_C (0xec3bc5d776fe3b3b), U64_C (0x96ab313d4b9aabab), + U64_C (0x1fce3ed181f0cece), U64_C (0x4411885522991111), + U64_C (0x068f0c8903838f8f), U64_C (0x254e4a6b9c044e4e), + U64_C (0xe6b7d1517366b7b7), U64_C (0x8beb0b60cbe0ebeb), + U64_C (0xf03cfdcc78c13c3c), U64_C (0x3e817cbf1ffd8181), + U64_C (0x6a94d4fe35409494), U64_C (0xfbf7eb0cf31cf7f7), + U64_C (0xdeb9a1676f18b9b9), U64_C (0x4c13985f268b1313), + U64_C (0xb02c7d9c58512c2c), U64_C (0x6bd3d6b8bb05d3d3), + U64_C (0xbbe76b5cd38ce7e7), U64_C (0xa56e57cbdc396e6e), + U64_C (0x37c46ef395aac4c4), U64_C (0x0c03180f061b0303), + U64_C (0x45568a13acdc5656), U64_C (0x0d441a49885e4444), + U64_C (0xe17fdf9efea07f7f), U64_C (0x9ea921374f88a9a9), + U64_C (0xa82a4d8254672a2a), U64_C (0xd6bbb16d6b0abbbb), + U64_C (0x23c146e29f87c1c1), U64_C (0x5153a202a6f15353), + U64_C (0x57dcae8ba572dcdc), U64_C (0x2c0b582716530b0b), + U64_C (0x4e9d9cd327019d9d), U64_C (0xad6c47c1d82b6c6c), + U64_C (0xc43195f562a43131), U64_C (0xcd7487b9e8f37474), + U64_C (0xfff6e309f115f6f6), U64_C (0x05460a438c4c4646), + U64_C (0x8aac092645a5acac), U64_C (0x1e893c970fb58989), + U64_C (0x5014a04428b41414), U64_C (0xa3e15b42dfbae1e1), + U64_C (0x5816b04e2ca61616), U64_C (0xe83acdd274f73a3a), + U64_C (0xb9696fd0d2066969), U64_C (0x2409482d12410909), + U64_C (0xdd70a7ade0d77070), U64_C (0xe2b6d954716fb6b6), + U64_C (0x67d0ceb7bd1ed0d0), U64_C (0x93ed3b7ec7d6eded), + U64_C (0x17cc2edb85e2cccc), U64_C (0x15422a5784684242), + U64_C (0x5a98b4c22d2c9898), U64_C (0xaaa4490e55eda4a4), + U64_C (0xa0285d8850752828), U64_C (0x6d5cda31b8865c5c), + U64_C (0xc7f8933fed6bf8f8), U64_C (0x228644a411c28686), + }; + +static const u64 C7[256] = + { + U64_C (0x186018c07830d818), U64_C (0x238c2305af462623), + U64_C (0xc63fc67ef991b8c6), U64_C (0xe887e8136fcdfbe8), + U64_C (0x8726874ca113cb87), U64_C (0xb8dab8a9626d11b8), + U64_C (0x0104010805020901), U64_C (0x4f214f426e9e0d4f), + U64_C (0x36d836adee6c9b36), U64_C (0xa6a2a6590451ffa6), + U64_C (0xd26fd2debdb90cd2), U64_C (0xf5f3f5fb06f70ef5), + U64_C (0x79f979ef80f29679), U64_C (0x6fa16f5fcede306f), + U64_C (0x917e91fcef3f6d91), U64_C (0x525552aa07a4f852), + U64_C (0x609d6027fdc04760), U64_C (0xbccabc89766535bc), + U64_C (0x9b569baccd2b379b), U64_C (0x8e028e048c018a8e), + U64_C (0xa3b6a371155bd2a3), U64_C (0x0c300c603c186c0c), + U64_C (0x7bf17bff8af6847b), U64_C (0x35d435b5e16a8035), + U64_C (0x1d741de8693af51d), U64_C (0xe0a7e05347ddb3e0), + U64_C (0xd77bd7f6acb321d7), U64_C (0xc22fc25eed999cc2), + U64_C (0x2eb82e6d965c432e), U64_C (0x4b314b627a96294b), + U64_C (0xfedffea321e15dfe), U64_C (0x5741578216aed557), + U64_C (0x155415a8412abd15), U64_C (0x77c1779fb6eee877), + U64_C (0x37dc37a5eb6e9237), U64_C (0xe5b3e57b56d79ee5), + U64_C (0x9f469f8cd923139f), U64_C (0xf0e7f0d317fd23f0), + U64_C (0x4a354a6a7f94204a), U64_C (0xda4fda9e95a944da), + U64_C (0x587d58fa25b0a258), U64_C (0xc903c906ca8fcfc9), + U64_C (0x29a429558d527c29), U64_C (0x0a280a5022145a0a), + U64_C (0xb1feb1e14f7f50b1), U64_C (0xa0baa0691a5dc9a0), + U64_C (0x6bb16b7fdad6146b), U64_C (0x852e855cab17d985), + U64_C (0xbdcebd8173673cbd), U64_C (0x5d695dd234ba8f5d), + U64_C (0x1040108050209010), U64_C (0xf4f7f4f303f507f4), + U64_C (0xcb0bcb16c08bddcb), U64_C (0x3ef83eedc67cd33e), + U64_C (0x05140528110a2d05), U64_C (0x6781671fe6ce7867), + U64_C (0xe4b7e47353d597e4), U64_C (0x279c2725bb4e0227), + U64_C (0x4119413258827341), U64_C (0x8b168b2c9d0ba78b), + U64_C (0xa7a6a7510153f6a7), U64_C (0x7de97dcf94fab27d), + U64_C (0x956e95dcfb374995), U64_C (0xd847d88e9fad56d8), + U64_C (0xfbcbfb8b30eb70fb), U64_C (0xee9fee2371c1cdee), + U64_C (0x7ced7cc791f8bb7c), U64_C (0x66856617e3cc7166), + U64_C (0xdd53dda68ea77bdd), U64_C (0x175c17b84b2eaf17), + U64_C (0x47014702468e4547), U64_C (0x9e429e84dc211a9e), + U64_C (0xca0fca1ec589d4ca), U64_C (0x2db42d75995a582d), + U64_C (0xbfc6bf9179632ebf), U64_C (0x071c07381b0e3f07), + U64_C (0xad8ead012347acad), U64_C (0x5a755aea2fb4b05a), + U64_C (0x8336836cb51bef83), U64_C (0x33cc3385ff66b633), + U64_C (0x6391633ff2c65c63), U64_C (0x020802100a041202), + U64_C (0xaa92aa39384993aa), U64_C (0x71d971afa8e2de71), + U64_C (0xc807c80ecf8dc6c8), U64_C (0x196419c87d32d119), + U64_C (0x4939497270923b49), U64_C (0xd943d9869aaf5fd9), + U64_C (0xf2eff2c31df931f2), U64_C (0xe3abe34b48dba8e3), + U64_C (0x5b715be22ab6b95b), U64_C (0x881a8834920dbc88), + U64_C (0x9a529aa4c8293e9a), U64_C (0x2698262dbe4c0b26), + U64_C (0x32c8328dfa64bf32), U64_C (0xb0fab0e94a7d59b0), + U64_C (0xe983e91b6acff2e9), U64_C (0x0f3c0f78331e770f), + U64_C (0xd573d5e6a6b733d5), U64_C (0x803a8074ba1df480), + U64_C (0xbec2be997c6127be), U64_C (0xcd13cd26de87ebcd), + U64_C (0x34d034bde4688934), U64_C (0x483d487a75903248), + U64_C (0xffdbffab24e354ff), U64_C (0x7af57af78ff48d7a), + U64_C (0x907a90f4ea3d6490), U64_C (0x5f615fc23ebe9d5f), + U64_C (0x2080201da0403d20), U64_C (0x68bd6867d5d00f68), + U64_C (0x1a681ad07234ca1a), U64_C (0xae82ae192c41b7ae), + U64_C (0xb4eab4c95e757db4), U64_C (0x544d549a19a8ce54), + U64_C (0x937693ece53b7f93), U64_C (0x2288220daa442f22), + U64_C (0x648d6407e9c86364), U64_C (0xf1e3f1db12ff2af1), + U64_C (0x73d173bfa2e6cc73), U64_C (0x124812905a248212), + U64_C (0x401d403a5d807a40), U64_C (0x0820084028104808), + U64_C (0xc32bc356e89b95c3), U64_C (0xec97ec337bc5dfec), + U64_C (0xdb4bdb9690ab4ddb), U64_C (0xa1bea1611f5fc0a1), + U64_C (0x8d0e8d1c8307918d), U64_C (0x3df43df5c97ac83d), + U64_C (0x976697ccf1335b97), U64_C (0x0000000000000000), + U64_C (0xcf1bcf36d483f9cf), U64_C (0x2bac2b4587566e2b), + U64_C (0x76c57697b3ece176), U64_C (0x82328264b019e682), + U64_C (0xd67fd6fea9b128d6), U64_C (0x1b6c1bd87736c31b), + U64_C (0xb5eeb5c15b7774b5), U64_C (0xaf86af112943beaf), + U64_C (0x6ab56a77dfd41d6a), U64_C (0x505d50ba0da0ea50), + U64_C (0x450945124c8a5745), U64_C (0xf3ebf3cb18fb38f3), + U64_C (0x30c0309df060ad30), U64_C (0xef9bef2b74c3c4ef), + U64_C (0x3ffc3fe5c37eda3f), U64_C (0x554955921caac755), + U64_C (0xa2b2a2791059dba2), U64_C (0xea8fea0365c9e9ea), + U64_C (0x6589650fecca6a65), U64_C (0xbad2bab9686903ba), + U64_C (0x2fbc2f65935e4a2f), U64_C (0xc027c04ee79d8ec0), + U64_C (0xde5fdebe81a160de), U64_C (0x1c701ce06c38fc1c), + U64_C (0xfdd3fdbb2ee746fd), U64_C (0x4d294d52649a1f4d), + U64_C (0x927292e4e0397692), U64_C (0x75c9758fbceafa75), + U64_C (0x061806301e0c3606), U64_C (0x8a128a249809ae8a), + U64_C (0xb2f2b2f940794bb2), U64_C (0xe6bfe66359d185e6), + U64_C (0x0e380e70361c7e0e), U64_C (0x1f7c1ff8633ee71f), + U64_C (0x62956237f7c45562), U64_C (0xd477d4eea3b53ad4), + U64_C (0xa89aa829324d81a8), U64_C (0x966296c4f4315296), + U64_C (0xf9c3f99b3aef62f9), U64_C (0xc533c566f697a3c5), + U64_C (0x25942535b14a1025), U64_C (0x597959f220b2ab59), + U64_C (0x842a8454ae15d084), U64_C (0x72d572b7a7e4c572), + U64_C (0x39e439d5dd72ec39), U64_C (0x4c2d4c5a6198164c), + U64_C (0x5e655eca3bbc945e), U64_C (0x78fd78e785f09f78), + U64_C (0x38e038ddd870e538), U64_C (0x8c0a8c148605988c), + U64_C (0xd163d1c6b2bf17d1), U64_C (0xa5aea5410b57e4a5), + U64_C (0xe2afe2434dd9a1e2), U64_C (0x6199612ff8c24e61), + U64_C (0xb3f6b3f1457b42b3), U64_C (0x21842115a5423421), + U64_C (0x9c4a9c94d625089c), U64_C (0x1e781ef0663cee1e), + U64_C (0x4311432252866143), U64_C (0xc73bc776fc93b1c7), + U64_C (0xfcd7fcb32be54ffc), U64_C (0x0410042014082404), + U64_C (0x515951b208a2e351), U64_C (0x995e99bcc72f2599), + U64_C (0x6da96d4fc4da226d), U64_C (0x0d340d68391a650d), + U64_C (0xfacffa8335e979fa), U64_C (0xdf5bdfb684a369df), + U64_C (0x7ee57ed79bfca97e), U64_C (0x2490243db4481924), + U64_C (0x3bec3bc5d776fe3b), U64_C (0xab96ab313d4b9aab), + U64_C (0xce1fce3ed181f0ce), U64_C (0x1144118855229911), + U64_C (0x8f068f0c8903838f), U64_C (0x4e254e4a6b9c044e), + U64_C (0xb7e6b7d1517366b7), U64_C (0xeb8beb0b60cbe0eb), + U64_C (0x3cf03cfdcc78c13c), U64_C (0x813e817cbf1ffd81), + U64_C (0x946a94d4fe354094), U64_C (0xf7fbf7eb0cf31cf7), + U64_C (0xb9deb9a1676f18b9), U64_C (0x134c13985f268b13), + U64_C (0x2cb02c7d9c58512c), U64_C (0xd36bd3d6b8bb05d3), + U64_C (0xe7bbe76b5cd38ce7), U64_C (0x6ea56e57cbdc396e), + U64_C (0xc437c46ef395aac4), U64_C (0x030c03180f061b03), + U64_C (0x5645568a13acdc56), U64_C (0x440d441a49885e44), + U64_C (0x7fe17fdf9efea07f), U64_C (0xa99ea921374f88a9), + U64_C (0x2aa82a4d8254672a), U64_C (0xbbd6bbb16d6b0abb), + U64_C (0xc123c146e29f87c1), U64_C (0x535153a202a6f153), + U64_C (0xdc57dcae8ba572dc), U64_C (0x0b2c0b582716530b), + U64_C (0x9d4e9d9cd327019d), U64_C (0x6cad6c47c1d82b6c), + U64_C (0x31c43195f562a431), U64_C (0x74cd7487b9e8f374), + U64_C (0xf6fff6e309f115f6), U64_C (0x4605460a438c4c46), + U64_C (0xac8aac092645a5ac), U64_C (0x891e893c970fb589), + U64_C (0x145014a04428b414), U64_C (0xe1a3e15b42dfbae1), + U64_C (0x165816b04e2ca616), U64_C (0x3ae83acdd274f73a), + U64_C (0x69b9696fd0d20669), U64_C (0x092409482d124109), + U64_C (0x70dd70a7ade0d770), U64_C (0xb6e2b6d954716fb6), + U64_C (0xd067d0ceb7bd1ed0), U64_C (0xed93ed3b7ec7d6ed), + U64_C (0xcc17cc2edb85e2cc), U64_C (0x4215422a57846842), + U64_C (0x985a98b4c22d2c98), U64_C (0xa4aaa4490e55eda4), + U64_C (0x28a0285d88507528), U64_C (0x5c6d5cda31b8865c), + U64_C (0xf8c7f8933fed6bf8), U64_C (0x86228644a411c286), + }; + + + +static void +whirlpool_init (void *ctx) +{ + whirlpool_context_t *context = ctx; + + memset (context, 0, sizeof (*context)); +} + + +/* + * Transform block. + */ +static void +whirlpool_transform (whirlpool_context_t *context, const unsigned char *data) +{ + whirlpool_block_t data_block; + whirlpool_block_t key; + whirlpool_block_t state; + whirlpool_block_t block; + unsigned int r; + unsigned int i; + + buffer_to_block (data, data_block, i); + block_copy (key, context->hash_state, i); + block_copy (state, context->hash_state, i); + block_xor (state, data_block, i); + + for (r = 0; r < R; r++) + { + /* Compute round key K^r. */ + + block[0] = (C0[(key[0] >> 56) & 0xFF] ^ C1[(key[7] >> 48) & 0xFF] ^ + C2[(key[6] >> 40) & 0xFF] ^ C3[(key[5] >> 32) & 0xFF] ^ + C4[(key[4] >> 24) & 0xFF] ^ C5[(key[3] >> 16) & 0xFF] ^ + C6[(key[2] >> 8) & 0xFF] ^ C7[(key[1] >> 0) & 0xFF] ^ rc[r]); + block[1] = (C0[(key[1] >> 56) & 0xFF] ^ C1[(key[0] >> 48) & 0xFF] ^ + C2[(key[7] >> 40) & 0xFF] ^ C3[(key[6] >> 32) & 0xFF] ^ + C4[(key[5] >> 24) & 0xFF] ^ C5[(key[4] >> 16) & 0xFF] ^ + C6[(key[3] >> 8) & 0xFF] ^ C7[(key[2] >> 0) & 0xFF]); + block[2] = (C0[(key[2] >> 56) & 0xFF] ^ C1[(key[1] >> 48) & 0xFF] ^ + C2[(key[0] >> 40) & 0xFF] ^ C3[(key[7] >> 32) & 0xFF] ^ + C4[(key[6] >> 24) & 0xFF] ^ C5[(key[5] >> 16) & 0xFF] ^ + C6[(key[4] >> 8) & 0xFF] ^ C7[(key[3] >> 0) & 0xFF]); + block[3] = (C0[(key[3] >> 56) & 0xFF] ^ C1[(key[2] >> 48) & 0xFF] ^ + C2[(key[1] >> 40) & 0xFF] ^ C3[(key[0] >> 32) & 0xFF] ^ + C4[(key[7] >> 24) & 0xFF] ^ C5[(key[6] >> 16) & 0xFF] ^ + C6[(key[5] >> 8) & 0xFF] ^ C7[(key[4] >> 0) & 0xFF]); + block[4] = (C0[(key[4] >> 56) & 0xFF] ^ C1[(key[3] >> 48) & 0xFF] ^ + C2[(key[2] >> 40) & 0xFF] ^ C3[(key[1] >> 32) & 0xFF] ^ + C4[(key[0] >> 24) & 0xFF] ^ C5[(key[7] >> 16) & 0xFF] ^ + C6[(key[6] >> 8) & 0xFF] ^ C7[(key[5] >> 0) & 0xFF]); + block[5] = (C0[(key[5] >> 56) & 0xFF] ^ C1[(key[4] >> 48) & 0xFF] ^ + C2[(key[3] >> 40) & 0xFF] ^ C3[(key[2] >> 32) & 0xFF] ^ + C4[(key[1] >> 24) & 0xFF] ^ C5[(key[0] >> 16) & 0xFF] ^ + C6[(key[7] >> 8) & 0xFF] ^ C7[(key[6] >> 0) & 0xFF]); + block[6] = (C0[(key[6] >> 56) & 0xFF] ^ C1[(key[5] >> 48) & 0xFF] ^ + C2[(key[4] >> 40) & 0xFF] ^ C3[(key[3] >> 32) & 0xFF] ^ + C4[(key[2] >> 24) & 0xFF] ^ C5[(key[1] >> 16) & 0xFF] ^ + C6[(key[0] >> 8) & 0xFF] ^ C7[(key[7] >> 0) & 0xFF]); + block[7] = (C0[(key[7] >> 56) & 0xFF] ^ C1[(key[6] >> 48) & 0xFF] ^ + C2[(key[5] >> 40) & 0xFF] ^ C3[(key[4] >> 32) & 0xFF] ^ + C4[(key[3] >> 24) & 0xFF] ^ C5[(key[2] >> 16) & 0xFF] ^ + C6[(key[1] >> 8) & 0xFF] ^ C7[(key[0] >> 0) & 0xFF]); + block_copy (key, block, i); + + /* Apply r-th round transformation. */ + + block[0] = (C0[(state[0] >> 56) & 0xFF] ^ C1[(state[7] >> 48) & 0xFF] ^ + C2[(state[6] >> 40) & 0xFF] ^ C3[(state[5] >> 32) & 0xFF] ^ + C4[(state[4] >> 24) & 0xFF] ^ C5[(state[3] >> 16) & 0xFF] ^ + C6[(state[2] >> 8) & 0xFF] ^ C7[(state[1] >> 0) & 0xFF] ^ key[0]); + block[1] = (C0[(state[1] >> 56) & 0xFF] ^ C1[(state[0] >> 48) & 0xFF] ^ + C2[(state[7] >> 40) & 0xFF] ^ C3[(state[6] >> 32) & 0xFF] ^ + C4[(state[5] >> 24) & 0xFF] ^ C5[(state[4] >> 16) & 0xFF] ^ + C6[(state[3] >> 8) & 0xFF] ^ C7[(state[2] >> 0) & 0xFF] ^ key[1]); + block[2] = (C0[(state[2] >> 56) & 0xFF] ^ C1[(state[1] >> 48) & 0xFF] ^ + C2[(state[0] >> 40) & 0xFF] ^ C3[(state[7] >> 32) & 0xFF] ^ + C4[(state[6] >> 24) & 0xFF] ^ C5[(state[5] >> 16) & 0xFF] ^ + C6[(state[4] >> 8) & 0xFF] ^ C7[(state[3] >> 0) & 0xFF] ^ key[2]); + block[3] = (C0[(state[3] >> 56) & 0xFF] ^ C1[(state[2] >> 48) & 0xFF] ^ + C2[(state[1] >> 40) & 0xFF] ^ C3[(state[0] >> 32) & 0xFF] ^ + C4[(state[7] >> 24) & 0xFF] ^ C5[(state[6] >> 16) & 0xFF] ^ + C6[(state[5] >> 8) & 0xFF] ^ C7[(state[4] >> 0) & 0xFF] ^ key[3]); + block[4] = (C0[(state[4] >> 56) & 0xFF] ^ C1[(state[3] >> 48) & 0xFF] ^ + C2[(state[2] >> 40) & 0xFF] ^ C3[(state[1] >> 32) & 0xFF] ^ + C4[(state[0] >> 24) & 0xFF] ^ C5[(state[7] >> 16) & 0xFF] ^ + C6[(state[6] >> 8) & 0xFF] ^ C7[(state[5] >> 0) & 0xFF] ^ key[4]); + block[5] = (C0[(state[5] >> 56) & 0xFF] ^ C1[(state[4] >> 48) & 0xFF] ^ + C2[(state[3] >> 40) & 0xFF] ^ C3[(state[2] >> 32) & 0xFF] ^ + C4[(state[1] >> 24) & 0xFF] ^ C5[(state[0] >> 16) & 0xFF] ^ + C6[(state[7] >> 8) & 0xFF] ^ C7[(state[6] >> 0) & 0xFF] ^ key[5]); + block[6] = (C0[(state[6] >> 56) & 0xFF] ^ C1[(state[5] >> 48) & 0xFF] ^ + C2[(state[4] >> 40) & 0xFF] ^ C3[(state[3] >> 32) & 0xFF] ^ + C4[(state[2] >> 24) & 0xFF] ^ C5[(state[1] >> 16) & 0xFF] ^ + C6[(state[0] >> 8) & 0xFF] ^ C7[(state[7] >> 0) & 0xFF] ^ key[6]); + block[7] = (C0[(state[7] >> 56) & 0xFF] ^ C1[(state[6] >> 48) & 0xFF] ^ + C2[(state[5] >> 40) & 0xFF] ^ C3[(state[4] >> 32) & 0xFF] ^ + C4[(state[3] >> 24) & 0xFF] ^ C5[(state[2] >> 16) & 0xFF] ^ + C6[(state[1] >> 8) & 0xFF] ^ C7[(state[0] >> 0) & 0xFF] ^ key[7]); + block_copy (state, block, i); + } + + /* Compression. */ + + block_xor (context->hash_state, data_block, i); + block_xor (context->hash_state, state, i); +} + +static void +whirlpool_add (whirlpool_context_t *context, + const void *buffer_arg, size_t buffer_n) +{ + const unsigned char *buffer = buffer_arg; + u64 buffer_size; + unsigned int carry; + unsigned int i; + + buffer_size = buffer_n; + + if (context->count == BLOCK_SIZE) + { + /* Flush the buffer. */ + whirlpool_transform (context, context->buffer); + /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ + context->count = 0; + } + if (! buffer) + return; /* Nothing to add. */ + + if (context->count) + { + while (buffer_n && (context->count < BLOCK_SIZE)) + { + context->buffer[context->count++] = *buffer++; + buffer_n--; + } + whirlpool_add (context, NULL, 0); + if (!buffer_n) + /* Done. */ + return; + } + /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ + + while (buffer_n >= BLOCK_SIZE) + { + whirlpool_transform (context, buffer); + context->count = 0; + buffer_n -= BLOCK_SIZE; + buffer += BLOCK_SIZE; + } + while (buffer_n && (context->count < BLOCK_SIZE)) + { + context->buffer[context->count++] = *buffer++; + buffer_n--; + } + + /* Update bit counter. */ + carry = 0; + buffer_size <<= 3; + for (i = 1; i <= 32; i++) + { + if (! (buffer_size || carry)) + break; + + carry += context->length[32 - i] + (buffer_size & 0xFF); + context->length[32 - i] = carry; + buffer_size >>= 8; + carry >>= 8; + } + gcry_assert (! (buffer_size || carry)); +} + +static void +whirlpool_write (void *ctx, const void *buffer, size_t buffer_n) +{ + whirlpool_context_t *context = ctx; + + whirlpool_add (context, buffer, buffer_n); +} + +static void +whirlpool_final (void *ctx) +{ + whirlpool_context_t *context = ctx; + unsigned int i; + + /* Flush. */ + whirlpool_add (context, NULL, 0); + + /* Pad. */ + context->buffer[context->count++] = 0x80; + + if (context->count > 32) + { + /* An extra block is necessary. */ + while (context->count < 64) + context->buffer[context->count++] = 0; + whirlpool_add (context, NULL, 0); + } + while (context->count < 32) + context->buffer[context->count++] = 0; + + /* Add length of message. */ + memcpy (context->buffer + context->count, context->length, 32); + context->count += 32; + whirlpool_add (context, NULL, 0); + + block_to_buffer (context->buffer, context->hash_state, i); +} + +static byte * +whirlpool_read (void *ctx) +{ + whirlpool_context_t *context = ctx; + + return context->buffer; +} + +gcry_md_spec_t _gcry_digest_spec_whirlpool = + { + "WHIRLPOOL", NULL, 0, NULL, 64, + whirlpool_init, whirlpool_write, whirlpool_final, whirlpool_read, + sizeof (whirlpool_context_t) + }; diff --git a/grub-core/lib/libgcrypt/mpi/ChangeLog-2011 b/grub-core/lib/libgcrypt/mpi/ChangeLog-2011 new file mode 100644 index 0000000..9307171 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/ChangeLog-2011 @@ -0,0 +1,822 @@ +2011-12-01 Werner Koch <wk@g10code.com> + + NB: ChangeLog files are no longer manually maintained. Starting + on December 1st, 2011 we put change information only in the GIT + commit log, and generate a top-level ChangeLog file from logs at + "make dist". See doc/HACKING for details. + +2011-03-28 Werner Koch <wk@g10code.com> + + * mpi-pow.c (gcry_mpi_powm): Remove unused var RSEC. + +2011-02-01 Werner Koch <wk@g10code.com> + + * mpi-cmp.c (gcry_mpi_cmp): Allow comparing of opaque MPIs. + +2010-04-12 Brad Hards <bradh@frogmouth.net> (wk) + + Spelling fixes. + +2010-02-22 Aurelien Jarno <aurel32@debian.org> (wk) + + * longlong.h (umul_ppmm) <mips> [__GNUC__ >= 4.4]: Patch according + to recommended gcc 4.4 changes. + +2009-12-09 Werner Koch <wk@g10code.com> + + * config.links: Remove asm modules for all sparc64. This is + debian#560028. + +2009-05-26 Werner Koch <wk@g10code.com> + + * mpicoder.c (mpi_read_from_buffer): Allow zero-sized MPIs (i.e a + zero). + +2009-02-16 Werner Koch <wk@g10code.com> + + * mpiutil.c: Remove memory.h. + +2008-12-05 Werner Koch <wk@g10code.com> + + * mpicoder.c (mpi_read_from_buffer): Do not bail out if the mpi is + larger than the buffer (potential problem). Do not print error + messages. + (mpi_fromstr): Return an error instead of hitting an assert. + (gcry_mpi_scan) <PGP>: Fix potential double free problem. + (gcry_mpi_scan) <HEX>: Fix potential memory leak. + (do_get_buffer): Return NULL on memory allocation failure. + (gcry_mpi_print): Check result of do_get_buffer. + (gcry_mpi_aprint): Return error on a memory allocation failure. + + * mpicoder.c: Re-indent. + +2008-12-03 Werner Koch <wk@g10code.com> + + * mpi-pow.c (gcry_mpi_powm): Fix last change. Asserts are really + useful! + +2008-12-02 Werner Koch <wk@g10code.com> + + * mpi-pow.c (gcry_mpi_powm): Re-indent. + (gcry_mpi_powm): Simplified allocation of the result to fix a + double free bug. This is bug#977. Reported by Haakon Ringberg. + +2008-08-20 Werner Koch <wk@g10code.com> + + * mpi-bit.c (gcry_mpi_lshift): Actually implement. + +2008-08-19 Werner Koch <wk@g10code.com> + + * mpi-bit.c (gcry_mpi_lshift): New. + +2007-10-31 Werner Koch <wk@g10code.com> + + * mpi-mod.c (gcry_mpi_mod): Remove + * mpi-inv.c (_gcry_mpi_invm): Remove _ prefix. + * mpiutil.c (_gcry_mpi_swap): Remove. + (_gcry_mpi_new): Remove. + (_gcry_mpi_snew): Remove. + (gcry_mpi_invm): Remove. + (gcry_mpi_copy): Remove and rename _version to this. + (gcry_mpi_set, gcry_mpi_set_ui): Merge with _ version. + * mpi-inv.c (gcry_mpi_invm): Remove _ prefix and return 1. + * mpi-mul.c (gcry_mpi_mul_2exp): Remove and rename _ version to this. + +2007-10-29 Werner Koch <wk@g10code.com> + + * config.links: No Candadian Cross here, thus use $host instead of + $target. + +2007-10-26 Werner Koch <wk@g10code.com> + + * config.links (mpi_optional_modules): Special rules for Apple + Darwin on ia32 from Gregor Riepl. + +2007-05-09 Marcus Brinkmann <marcus@g10code.de> + + * config.links: Rename assembler file links by suffixing "-asm". + * Makefile.am (CCASCOMPILE, LTCCASCOMPILE, CLEANFILES, + libmpi_la_LIBADD, libmpi_la_DEPENDENCIES, SUFFIXES, .S.o, .S.obj, + .S.lo): Removed variables and targets. + (mpih_add1, mpih_sub1, mpih_mul1, mpih_mul2, mpih_mul3, + mpih_lshift, mpih_rshift, mpih_udiv, mpih_udiv_qrnnd, + nodist_libmpi_la_SOURCES): New variables. + (DISTCLEANFILES): Rename assembler file links by suffixing "-asm". + Add variants for C file links. + +2007-05-04 Werner Koch <wk@g10code.com> + + * config.links (path): Allowthe sue of colons as delimiters. + +2007-05-03 Werner Koch <wk@g10code.com> + + * pentium4/distfiles: Fixed. + +2007-04-30 Werner Koch <wk@g10code.com> + + * config.links: Create a file mod-source-info.h. + * Makefile.am (DISTCLEANFILES): Add that file. + * mpiutil.c (_gcry_mpi_get_hw_config): New. + +2007-04-28 Marcus Brinkmann <marcus@g10code.de> + + * config.links: Add additional assembler search directories. + +2007-03-28 Werner Koch <wk@g10code.com> + + * ec.c: New. + +2007-03-23 Werner Koch <wk@g10code.com> + + * mpi-bit.c (_gcry_mpi_lshift_limbs): Assign AP after the resize. + + * mpi-div.c (gcry_mpi_mod, _gcry_mpi_mod): Moved to .. + * mpi-mod.c: .. new file. + (_gcry_mpi_barrett_init, _gcry_mpi_barrett_free): New. + (_gcry_mpi_mod_barrett): New. + (_gcry_mpi_mul_barrett): New. + +2007-03-22 Werner Koch <wk@g10code.com> + + * mpi-div.c (_gcry_mpi_mod): New. + * mpiutil.c (_gcry_mpi_new, _gcry_mpi_snew): New. + +2007-03-13 Werner Dittmann <Werner.Dittmann@t-online.de> (wk) + + * amd64/mpih-add1.S, amd64/mpih-add1.S, amd64/mpih-lshift.S + * amd64/mpih-mul1.S, amd64/mpih-mul2.S, amd64/mpih-mul3.S + * amd64/mpih-rshift.S, amd64/mpih-sub1.S: New. + * config.links: Add case for x86_64. + +2007-02-23 Werner Koch <wk@g10code.com> + + * mpi-pow.c (gcry_mpi_powm): Remove unused var ESIGN. + + * mpiutil.c (gcry_mpi_get_flag): Let it return a value to silent + MIPSpro cc warning. + +2007-02-21 Werner Koch <wk@g10code.com> + + * mpicoder.c (_gcry_mpi_set_buffer): Made BUFFER a void*. + +2006-11-15 Werner Koch <wk@g10code.com> + + * Makefile.am (.S.o): Check for srcdir also in in CPP pass. + (INCLUDES): Removed. + (AM_CPPFLAGS, AM_CFLAGS): New, modified. Merged with Moritz' + changes. + +2006-11-05 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (AM_CFLAGS): Added -I$(top_builddir)/src so that the + new gcrypt.h is used, not the one installed in the system. + +2006-10-23 Werner Koch <wk@g10code.com> + + * config.links (mpi_optional_modules): Make sure that powerpc64 is + matched before a generic powerpc. Reported by Andreas Metzler. + Should fix Debian bug 284609. + +2006-08-25 Werner Koch <wk@g10code.com> + + * mpi-bit.c (gcry_mpi_rshift): Don't shift if N == 0 but do a + plain copy. + +2006-08-04 Werner Koch <wk@g10code.com> + + * mpi-bit.c (gcry_mpi_rshift): Rewritten to remove the limitation + on N (which used to be less than BITS_PER_MPI_LIMB). + +2006-08-03 Werner Koch <wk@g10code.com> + + * mpi-bit.c (gcry_mpi_set_bit, gcry_mpi_set_highbit): Fixed + allocation. Reported by bpgcrypt at itaparica.org. + * mpiutil.c (_gcry_mpi_resize): Clear the new part of the resized + limb space. + +2006-07-26 Werner Koch <wk@g10code.com> + + * mpiutil.c (gcry_mpi_randomize): Changed P to unsigned char*. + + * mpicoder.c (gcry_mpi_scan): Changed arg BUFFER to void*. + (mpi_read_from_buffer): Made BUFFER arg const. + (gcry_mpi_scan): Removed now needless cast. Add cast for arg to + mpi_fromstr. + (gcry_mpi_print): Made TMP unsigned. + + * Makefile.am (AM_CCASFLAGS): New. + +2005-10-09 Moritz Schulte <moritz@g10code.com> + + * mpi-cmp.c (gcry_mpi_cmp_ui): Rewritten; correctly handle case of + zero limbs in U. + +2005-04-27 Moritz Schulte <moritz@g10code.com> + + * mpiutil.c (gcry_mpi_randomize): Store random data in secure + memory if the given MPI is secure - not the other way around (argl). + +2005-04-23 Moritz Schulte <moritz@g10code.com> + + * Makefile.am: Don't assume the compiler will pre-process the .S + files. Some compilers, like those from HP and IBM, don't do + this. So, we use the same solution gnupg-1.4.0 does. Preprocess + first and then compile. + + * hppa1.1/mpih-mul3.S: Add "level 1.1" directive to disable + warning about using PA-RISC1.1 opcodes. + * hppa1.1/mpih-mul2.S: Likewise. + * hppa1.1/mpih-mul1.S: Likewise. + * hppa1.1/udiv-qrnnd.S: Likewise. + +2005-02-16 Moritz Schulte <moritz@g10code.com> + + * mpiutil.c (_gcry_mpi_alloc_limb_space): Rewritten, fixed memory + corruption. + +2005-02-06 Moritz Schulte <moritz@g10code.com> + + * mpiutil.c (_gcry_mpi_get_ui, gcry_mpi_get_ui): New functions. + +2005-01-05 Werner Koch <wk@g10code.com> + + * hppa1.1/udiv-qrnnd.S: Reverted change of 2004-03-02 but kept the + .align directive. + +2004-12-16 Werner Koch <wk@g10code.com> + + * config.links (mpi_optional_modules): Move entry for powerpc64 + before generic powerpc. Suggested by Rafael Ãvila de EspÃndola. + +2004-03-02 Werner Koch <wk@gnupg.org> + + * hppa1.1/udiv-qrnnd.S: Alignment fix from Lamont Jones for + Debian. Taken from gnupg-1.3. + + * longlong.h: Added PowerPC 64 bit code from GPM-4.1.2 but didn't + enable it yet. Some whitespace changes in HPPA to fix assembler + problems on HP-UX. From gnupg 1.3 + + * mpiutil.c (_gcry_mpi_alloc_limb_space): Better allocate + something even if NLIMBS is passed as 0. + + * config.links: Updated system list to match gnupg 1.3. + +2003-12-19 Werner Koch <wk@gnupg.org> + + * mpi-internal.h [M_DEBUG]: Removed this unused code. + (struct karatsuba_ctx): Added TSPACE_NLIMBS and TP_NLIMBS. + * mpiutil.c (_gcry_mpi_free_limb_space): Add arg NLIMBS and wipe + out the memory. Changed all callers. + * mpih-mul.c (_gcry_mpih_mul_karatsuba_case): Keep track of + allocated limbs. + * mpi-div.c (_gcry_mpi_tdiv_qr): Keep track of allocated limbs. + * mpi-mul.c (gcry_mpi_mul): Ditto. + * mpi-pow.c (gcry_mpi_powm): Ditto. + + * Manifest: Empty new file. Also add Manifest files to all CPU + specific directories. + * Makefile.am: Added. + + * mpiutil.c (gcry_mpi_randomize): Use gcry_create_nonce if WEAK + random has been requested. + +2003-10-31 Werner Koch <wk@gnupg.org> + + * i386/mpih-rshift.S, i386/mpih-lshift.S: Use %dl and not %edx for + testb; this avoids an assembler warning. + + * mpi-pow.c (gcry_mpi_powm): s/exp/expo/ to avoid shadowing warning. + +2003-08-19 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (SUFFIXES): New variable. + (.S.o, .S.lo, .S.obj): Rewritten. + +2003-07-30 Moritz Schulte <moritz@g10code.com> + + * longlong.h (__clz_tab): Renamed to _gcry_clz_tab. + * mpi-bit.c (__clz_tab): Likewise. + +2003-07-27 Werner Koch <wk@gnupg.org> + + * mpicoder.c (gcry_mpi_scan): New argument BUFLEN to replace the + use of the intial value of NBYTES. Changed BUFFER to unsigned. + (gcry_mpi_print): Likewise. + (gcry_mpi_dump): New. + (_gcry_log_mpidump): Make use of gcry_mpi_dump. + (mpi_print): Removed. + (gcry_mpi_scan): Allocated mpi in secure memory when required. + (gcry_mpi_aprint): Changed BUFFER to unsigned char*. + +2003-07-14 Moritz Schulte <moritz@g10code.com> + + * mpicoder.c: Used gcry_err* wrappers for libgpg-error symbols. + +2003-06-16 Moritz Schulte <moritz@g10code.com> + + * mpi-add.c: Replace last occurences of old type names with newer + names (i.e. replace MPI with gcry_mpi_t). + * mpi-bit.c: Likewise. + * mpi-cmp.c: Likewise. + * mpi-div.c: Likewise. + * mpi-gcd.c: Likewise. + * mpi-internal.h: Likewise. + * mpi-inv.c: Likewise. + * mpi-mpow.c: Likewise. + * mpi-mul.c: Likewise. + * mpi-pow.c: Likewise. + * mpi-scan.c: Likewise. + * mpicoder.c: Likewise. + * mpiutil.c: Likewise. + +2003-06-09 Moritz Schulte <moritz@g10code.com> + + * mpicoder.c (gcry_mpi_scan): Adjust for libgpg-error. + (gcry_mpi_print): Likewise. + (gcry_mpi_aprint): Likewise. + +2003-06-07 Moritz Schulte <moritz@g10code.com> + + * longlong.h, mpi-add.c, mpi-bit.c, mpi-cmp.c, mpi-div.c, + mpi-gcd.c, mpi-inline.c, mpi-inline.h, mpi-internal.h, mpi-inv.c, + mpi-mpow.c, mpi-mul.c, mpi-pow.c, mpi-scan.c, mpicoder.c, + mpih-div.c, mpih-mul.c, mpiutil.c, generic/mpi-asm-defs.h, + generic/mpih-add1.c, generic/mpih-lshift.c, generic/mpih-mul1.c, + generic/mpih-mul2.c, generic/mpih-mul3.c, generic/mpih-rshift.c, + generic/mpih-sub1.c, generic/udiv-w-sdiv.c, i386/syntax.h, + m68k/syntax.h, mips3/mpi-asm-defs.h, powerpc32/syntax.h: Edited + all preprocessor instructions to remove whitespace before the '#'. + This is not required by C89, but there are some compilers out + there that don't like it. Replaced any occurence of the now + deprecated type names with the new ones. + +2003-05-21 Moritz Schulte <moritz@g10code.com> + + * mpiutil.c (_gcry_mpi_alloc_limb_space): Only try to allocate + memory in case the amount of bytes to allocate is non-zero. + +2003-04-27 Moritz Schulte <moritz@g10code.com> + + * mpiutil.c (_gcry_mpi_resize): Allocate secure memory, in case + bit zero of `flags' is set. + + * mpi-add.c (gcry_mpi_sub): Simplify function; always use a + temporary variable now. + +2003-04-15 Werner Koch <wk@gnupg.org> + + * longlong.h (umul_ppmm): Support SH3 and SH4. Thanks to + kazuya.s@jp.yokogawa.com. + +2003-04-02 Werner Koch <wk@gnupg.org> + + * mpicoder.c (gcry_mpi_print): Fixed testing against possible + uninitialized LEN. Valgrinded by Nikos Mavroyanopoulos. + +2003-01-15 Werner Koch <wk@gnupg.org> + + * longlong.h: Removed some spaces between backslashes and newlines. + +2002-09-20 Werner Koch <wk@gnupg.org> + + * mpi-mul.c (gcry_mpi_mul_2exp): New. This was declared in + gcrypt.h but only implemented as internal function. Noted by Timo + but a few minutes to late for today's release. + + * Makefile.am (DISTCLEANFILES): Include mpi-asm-defs.h + +2002-09-18 Werner Koch <wk@gnupg.org> + + * Makefile.am (.S.lo): Pass -DPIC. i386, PPC and Sparc code + require it. It worked for me because I am using the i586 code. + +2002-08-23 Werner Koch <wk@gnupg.org> + + * Makefile.am (.S.lo): Fixed for libtool build with --disable-shared. + +2002-07-24 Werner Koch <wk@gnupg.org> + + * longlong.h: Replaced all K&R multiline strings by ISO ones for + the sake of modern compilers. Suggested by Marco Parrone. + +2002-06-24 Werner Koch <wk@gnupg.org> + + * mpiutil.c (gcry_mpi_swap): New. + + * mpi-div.c (gcry_mpi_div): New. + (gcry_mpi_mod): New. + * mpi-inv.c (gcry_mpi_invm): New. + + * mpicoder.c (do_get_buffer): Make sure that we allocate at least + one byte. + +2002-06-12 Werner Koch <wk@gnupg.org> + + * hppa1.1/udiv-qrnnd.S: Changes for PIC by Randolph Chung. + +2002-05-15 Werner Koch <wk@gnupg.org> + + * config.links: Chnage the way the mpi modules are determined. + * Makefile.am: Revamped to better handle modules + +2002-05-14 Werner Koch <wk@gnupg.org> + + Changed license of all files to the LGPL. + +2002-04-18 Werner Koch <wk@gnupg.org> + + * mpicoder.c (gcry_mpi_scan): Don't use normalize on a NULL MPI. + +2002-03-20 Werner Koch <wk@gnupg.org> + + * mpicoder.c (mpi_read_from_buffer): Bail out on a zero length + buffer because we can't eventually do an malloc of this size. + Reported by Timo. + +2002-01-14 Werner Koch <wk@gnupg.org> + + * mpi-inv.c (_gcry_mpi_invm): Typo fixes, noted by Carlo Perassi. + +2001-11-01 Werner Koch <wk@gnupg.org> + + * mpicoder.c (gcry_mpi_scan): Allow to pass a nbytes as NULL or + with value 0 for format GCRY_FMT_SSH, so that the length is not + used for any checks, only the length stored in the bufer is used. + This is a nice format becuase we can just pass a buffer around and + don't need to care about its length. + +2001-08-03 Werner Koch <wk@gnupg.org> + + * config.links: Changed the way the list of files to be + symlinked is returned. + +2001-05-31 Werner Koch <wk@gnupg.org> + + * mpih-cmp.c: Removed and moved mpihelp_cmp to .. + * mpi-inline.h: .. here. + + Major function renaming. All global functions are now prefixed + with _gcry_ or gcry_. Renamed also all mpihelp_ to just mpih_ so + that functions names are not getting to long an unreadable and for + better matching with the filenames. + +2001-05-28 Werner Koch <wk@gnupg.org> + + * mpicoder.c (mpi_fromstr): Made static and assume that all input + is in hexformat. + + Updated all CPU specific code with the one from GnuPG-1.0.5. This + is just a change of text formatting and the use of .label + instead of labels for hppa and pa7100. + + * longlong.h: Fixes for ARM by Phil Blundell. + +2001-03-29 Werner Koch <wk@gnupg.org> + + * mpi-mul.c (mpi_mul): Make sure that secret temporary results are + not stored in w. Suggested by Florian Weimer. + + * config.links: Use i386 code for i386. According to tests by + Kevin Ryde the i586 code runs slow on i386 CPUs. Ditto for i786. + +2001-01-11 Werner Koch <wk@gnupg.org> + + * Makefile.am: Removed mpi.h. + +2000-12-19 Werner Koch <wk@gnupg.org> + + * mpi-internal.h: Put limb_t definition in an ifdef. + + Major change: + Removed all GnuPG stuff and renamed this piece of software + to gcrypt. + +2000-11-14 Werner Koch <wk@gnupg.org> + + * mpi-internal.h, mpi.h: Changed the way they are called and + introduced DID_MPI_LIMP_TYPEDEF hack. Very ugly, should all be + revamped. + + * Makefile.am (OMIT_DEPENDENCIES): Hack to work around dependency + problems. + +2000-10-11 Werner Koch <wk@gnupg.org> + + * generic/mpi-asm-defs.h: New. + * mips3/mpi-asm-defs.h: New. + * config.links: Create a link to one of the above files. + +Fri Jul 28 18:19:11 CEST 2000 Werner Koch <wk@openit.de> + + * mpicoder.c (gcry_mpi_scan): Normalize the returned MPI. + +Tue Jul 25 17:44:15 CEST 2000 Werner Koch <wk@openit.de> + + * config.links: Support for powerpc--netbsd by Gabriel Rosenkoetter. + +Mon Jul 17 16:35:47 CEST 2000 Werner Koch <wk@> + + * power/: Add all files from GMP for this CPU. Converted comments to + CPP comments because some ASes complain about ' in comments. + + * config.links: Support for BSDI 4.x; by Wayne Chapeskie. Add support + for FreeBSD 5 and made the case stmt looking nicer; by Jun Kuriyama. + Add support for NetBSD. + (sparc8): Made the search path the same as sparc9 + (sparc64-unknown-linux-gnu): use udiv module; by Adam Mitchell. + + * Makefile.am: c/SFLAGS/ASFLAGS/. This has only been used by the + powerpc and actually never passed the -Wa,foo to the cc. + + * mpih-div.c (mpihelp_divrem): The MPN_COPY_DECR copied one element + too many. This is a gmp2.0.2p9.txt patch. + + * longlong.h (umul_ppmm): Fixes for ARM-4. By Sean MacLennan. + + * mpi-internal.h (karatsuba_ctx): New. + * mpih-mul.c (mpihelp_release_karatsuba_ctx): New. + (mpihelp_mul_karatsuba_case): New. + (mpihelp_mul): Splitted to make use of the new functions. + * mpi-pow.c (mpi_powm): Make use of the new splitted function to avoid + multiple allocation of temporary memory during the karatsuba operations. + * mpi_mpow.c: Removed the unused Barrett code. + +2000-03-21 16:17:30 Werner Koch (wk@habibti.openit.de) + + * config.links: Add support for FreeBSD 5. + +Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de> + + * mpicoder.c (gcry_mpi_aprint): Now really returns the length. + +Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de> + + * mpiutil.c: Removed all memory debugging code. + + * mpicoder.c (gcry_mpi_aprint): New. + + * Replaced all m_ memory functions by g10_ ones. + +Fri Dec 31 14:06:56 CET 1999 Werner Koch <wk@gnupg.de> + + * mpi-bit.c (gcry_mpi_get_nbits): New. + + * mpiutil.c (mpi_set_secure): made static. + (gcry_mpi_get_flag): New. + (gcry_mpi_set_flag): New. + (gcry_mpi_clear_flag): New. + (mpi_set_opaque): renamed to gcry_mpi_set_opaque. + (mpi_get_opaque): renamed to gcry_mpi_get_opaque. + +Fri Dec 31 12:48:31 CET 1999 Werner Koch <wk@gnupg.de> + + * mpicoder.c (mpi_read_from_buffer): Made static. + (gcry_mpi_print): A buffer of NULL is now allowed to get the required + length back. + (mpi_get_keyid): Removed. + (mpi_print): Made static - should be removed. + +Wed Dec 8 21:58:32 CET 1999 Werner Koch <wk@gnupg.de> + + * Makefile.am (INCLUDES): Add ../gcrypt. + + * g10m.c : Removed. + + * mpicoder.c (mpi_write): Removed. + (mpi_read): Removed. + (gcry_mpi_scan): New. Taken from ../gcrypt/mpiapi.c. + (gcry_mpi_print): Ditto. + + * mpi-pow.c (mpi_powm): Renamed to ... + (gcry_mpi_powm): ... this. + + * mpiutil.c (gcry_mpi_new): New as a wrapper around the old function. + Taken from ../gcrypt/mpiapi.c. + (gcry_mpi_snew): Ditto. + (gcry_mpi_release): Ditto. + (gcry_mpi_copy): Ditto. + (gcry_mpi_set): Ditto. + (gcry_mpi_set_ui): Ditto. + (gcry_mpi_cmp): Ditto. + (gcry_mpi_cmp_ui): Ditto. + (gcry_mpi_randomize): Ditto. + + * mpicoder.c (mpi_print): Removed the nbit_info kludge. + * mpi-bits.c (mpi_get_nbits): Replaced the is_protected stuff by + checking whether it is an opaque mpi and then returns it's length + in bits. + * mpiutil.c (mpi_set_opaque): Changed the interface to take a number + of bits for the length. Adjusted all users. + (mpi_get_opaque): Ditto. + +Fri Nov 19 17:15:20 CET 1999 Werner Koch <wk@gnupg.de> + + * mpicoder.c (g10_log_mpidump): Add a temporary workaround + + * mpih-mul.c (mpihelp_mul_n): s/m_is_ecure/g10_is_secure/ + + * mpiutil.c (mpi_alloc): Remved the debug mode because it has turned + out, that this feature was not very useful in the past. Use the + new alloc functions. + (mpi_alloc_secure): Ditto. + (mpi_alloc_limb_space): Ditto. + (mpi_free_limb_space): Ditto. + (mpi_resize): Ditto. + (mpi_free): Ditto. + (mpi_set_secure): Removed the debug stuff. + (mpi_set_opaque): Ditto. + (mpi_copy): Ditto. + (mpi_alloc_set_ui): Ditto. + (mpi_m_check): Use g10_ wrapper. + +Mon Aug 30 20:38:33 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * config.links: Add case label for DJGPP + +Wed Jul 14 19:42:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * Makefile.am: Use .s files as temporaries, disabled other .S rules. + +Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * mpicoder.c (g10_log_mpidump): New. + + * Makefile.am: Support for libtool. + +Fri Jul 2 11:45:54 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * mpi-bit.c (mpi_lshift_limbs,mpi_rshift_limbs): New. + * mpi-mpow.c (barrett_mulm): New but diabled. + +Tue Jun 1 16:01:46 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * config.links (i[56]86*-*-freebsdelf*): New. + +Sun May 23 14:20:22 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * config.links (sysdep.h): Not any more conditionally created. + +Tue May 4 15:47:53 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mpiutil.c (mpi_alloc_like): New. + +Mon Apr 26 17:48:15 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mpih-add.c, mpih-sub.c: Removed + * mpi-inline.c: New. + * mpi-inline.h: Make it usable by mpi-inline.c. + +Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mpih-mul.c (mpihelp_mul_n): Fixed use of memory region. + (mpihelp_mul): Ditto. + +Wed Apr 7 20:51:39 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Explicit rules to invoke cpp on *.S + +Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * config.links: Take advantage of the with_symbol_underscore macro. + Add support for freebsd 4. + +Wed Feb 24 11:07:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mips3/mpih-sub1.S: Removed left over junk in last line. (Should I + blame me or my editor?). + +Sat Feb 13 12:04:43 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Removed the +=. Add MPI_OPT_FLAGS. + +Sat Jan 9 16:02:23 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mpi-cmp.c (mpi_cmp_ui): Normalized the arg. + +Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mpi-bit.c (mpi_normalize): New. + (mpi_get_nbits): Normalize the MPI. + * mpi-bit.c (mpi_cmp): Normalize the MPI before the compare. + + +Tue Dec 8 13:15:16 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * config.links: Moved the case for powerpc*linux + * powerpcp32/*.S: Removed some underscores. + +Thu Nov 26 07:27:52 1998 Werner Koch <werner.koch@guug.de> + + * config.links: Support for ppc with ELF + * powerpc32/syntax.h: New. + * powerpc32/*.S: Applied ELF patches (glibc patches) + +Tue Nov 10 19:31:37 1998 Werner Koch (wk@isil.d.shuttle.de) + + * power*/ : Started with stuff for PPC + * config.links: Some stuff for PPC. + * generic/udiv-w-sdiv.c: New but disabled. + +Tue Oct 27 12:37:46 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links (freebsd): Fixes for FreeBSD 3.0 + +Wed Oct 14 09:59:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links (freebsd): ELF patches from Jun Kuriyama. + +Thu Oct 8 13:28:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpi-mpow.c (mpi_mulpowm): Fixed mem leak (m_free/mpi_free). + +Thu Sep 17 18:08:50 1998 Werner Koch (wk@(none)) + + * hppa1.1/udiv-qrnnd.S: Fix from Steffen Zahn for HPUX 10.20 + +Thu Aug 6 16:39:28 1998 Werner Koch,mobil,,, (wk@tobold) + + * mpi-bit.c (mpi_set_bytes): Removed. + +Wed Aug 5 15:11:12 1998 Werner Koch (wk@(none)) + + * mpicoder.c (mpi_read_from_buffer): New. + + * mpiutil.c (mpi_set_opaque): New. + (mpi_get_opaque): New. + (mpi_copy): Changed to support opauqe flag + (mpi_free): Ditto. + +Sat Jul 4 10:11:11 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpiutil.c (mpi_clear): Reset flags. + (mpi_set): Ditto. + (mpi_alloc_secure): Set flag to 1 and not ored the 1 in, tsss.. + +Fri Jun 26 11:19:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpiutil.c (mpi_alloc): set nbits to 0. + (mpi_alloc_secure): Ditto. + (mpi_clear): Ditto. + +Thu Jun 25 11:50:01 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mips3/*.S: New + +Mon May 18 13:47:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links: split mpih-shift into mpih-[lr]shift and + changed all implementations. + * mpi/alpha: add some new assembler stuff. + +Wed May 13 11:04:29 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links: Add support for MIPS + +Thu Apr 9 11:31:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpicoder.c (mpi_get_secure_buffer): New. + +Wed Apr 8 09:44:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links: Applied small fix from Ulf Möller. + +Mon Apr 6 12:38:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpicoder.c (mpi_get_buffer): Removed returned leading zeroes + and changed all callers. + +Tue Mar 10 13:40:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpi-bit.c (mpi_clear_highbit): New. + +Mon Mar 2 19:29:00 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am (DISTCLEANFILES): New + +Thu Feb 26 06:48:54 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links (X86_BROKEN_ALIGN): Added for some systems. + +Mon Feb 23 12:21:40 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpi/m68k/mpih-shift.S (Lspecial): Changed duplicate symbol. + +Mon Feb 16 13:00:27 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links : Add detection of m68k cpus + + + Copyright 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/grub-core/lib/libgcrypt/mpi/Makefile.am b/grub-core/lib/libgcrypt/mpi/Makefile.am new file mode 100644 index 0000000..e900539 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/Makefile.am @@ -0,0 +1,177 @@ +## Process this file with automake to produce Makefile.in +# Copyright (C) 1992, 1999, 2000, 2002 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +# 1.5 leads to a combinatorial explosion due to all the conditionals +# I was not able to build it with 64Megs - 1.6 fixes this. +# not anymore required: AUTOMAKE_OPTIONS = 1.6 + +# Need to include ../src in addition to top_srcdir because gcrypt.h is +# a built header. +AM_CPPFLAGS = -I../src -I$(top_srcdir)/src +AM_CFLAGS = $(GPG_ERROR_CFLAGS) + +AM_ASFLAGS = $(MPI_SFLAGS) +AM_CCASFLAGS = $(NOEXECSTACK_FLAGS) + +EXTRA_DIST = Manifest config.links +DISTCLEANFILES = mpi-asm-defs.h \ + mpih-add1-asm.S mpih-mul1-asm.S mpih-mul2-asm.S mpih-mul3-asm.S \ + mpih-lshift-asm.S mpih-rshift-asm.S mpih-sub1-asm.S asm-syntax.h \ + mpih-add1.c mpih-mul1.c mpih-mul2.c mpih-mul3.c \ + mpih-lshift.c mpih-rshift.c mpih-sub1.c \ + sysdep.h mod-source-info.h + +# Beware: The following list is not a comment but grepped by +# config.links to get the list of symlinked modules +# Optional modules are marked with an O in the second column. +#BEGIN_ASM_LIST +# mpih-add1 C +# mpih-sub1 C +# mpih-mul1 C +# mpih-mul2 C +# mpih-mul3 C +# mpih-lshift C +# mpih-rshift C +# udiv O +# udiv-qrnnd O +#END_ASM_LIST + +# Note: This function has not yet been implemented. There is only a dummy in +# generic/ +# udiv-w-sdiv O + +# And we need to have conditionals for all modules because +# we don't know whether they are .c or .S. Very ugly; I know. +# Remember to define them all in configure.ac +if MPI_MOD_ASM_MPIH_ADD1 +mpih_add1 = mpih-add1-asm.S +else +if MPI_MOD_C_MPIH_ADD1 +mpih_add1 = mpih-add1.c +else +mpih_add1 = +endif +endif + +if MPI_MOD_ASM_MPIH_SUB1 +mpih_sub1 = mpih-sub1-asm.S +else +if MPI_MOD_C_MPIH_SUB1 +mpih_sub1 = mpih-sub1.c +else +mpih_sub1 = +endif +endif + +if MPI_MOD_ASM_MPIH_MUL1 +mpih_mul1 = mpih-mul1-asm.S +else +if MPI_MOD_C_MPIH_MUL1 +mpih_mul1 = mpih-mul1.c +else +mpih_mul1 = +endif +endif + +if MPI_MOD_ASM_MPIH_MUL2 +mpih_mul2 = mpih-mul2-asm.S +else +if MPI_MOD_C_MPIH_MUL2 +mpih_mul2 = mpih-mul2.c +else +mpih_mul2 = +endif +endif + +if MPI_MOD_ASM_MPIH_MUL3 +mpih_mul3 = mpih-mul3-asm.S +else +if MPI_MOD_C_MPIH_MUL3 +mpih_mul3 = mpih-mul3.c +else +mpih_mul3 = +endif +endif + +if MPI_MOD_ASM_MPIH_LSHIFT +mpih_lshift = mpih-lshift-asm.S +else +if MPI_MOD_C_MPIH_LSHIFT +mpih_lshift = mpih-lshift.c +else +mpih_lshift = +endif +endif + +if MPI_MOD_ASM_MPIH_RSHIFT +mpih_rshift = mpih-rshift-asm.S +else +if MPI_MOD_C_MPIH_RSHIFT +mpih_rshift = mpih-rshift.c +else +mpih_rshift = +endif +endif + +if MPI_MOD_ASM_UDIV +udiv = udiv-asm.S +else +if MPI_MOD_C_UDIV +udiv = udiv.c +else +udiv = +endif +endif + +if MPI_MOD_ASM_UDIV_QRNND +udiv_qrnnd = udiv-qrnnd-asm.S +else +if MPI_MOD_C_UDIV_QRNND +udiv_qrnnd = udiv-qrnnd.c +else +udiv_qrnnd = +endif +endif + +noinst_LTLIBRARIES = libmpi.la + +libmpi_la_LDFLAGS = +nodist_libmpi_la_SOURCES = $(mpih_add1) $(mpih_sub1) $(mpih_mul1) \ + $(mpih_mul2) $(mpih_mul3) $(mpih_lshift) $(mpih_rshift) \ + $(udiv) $(udiv_qrnnd) +libmpi_la_SOURCES = longlong.h \ + mpi-add.c \ + mpi-bit.c \ + mpi-cmp.c \ + mpi-div.c \ + mpi-gcd.c \ + mpi-internal.h \ + mpi-inline.h \ + mpi-inline.c \ + mpi-inv.c \ + mpi-mul.c \ + mpi-mod.c \ + mpi-pow.c \ + mpi-mpow.c \ + mpi-scan.c \ + mpicoder.c \ + mpih-div.c \ + mpih-mul.c \ + mpiutil.c \ + ec.c diff --git a/grub-core/lib/libgcrypt/mpi/Manifest b/grub-core/lib/libgcrypt/mpi/Manifest new file mode 100644 index 0000000..3b0d673 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/Manifest @@ -0,0 +1,41 @@ +# Manifest - checksums of the mpi directory +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +Makefile.am +config.links +longlong.h +mpi-add.c +mpi-bit.c +mpi-cmp.c +mpi-div.c +mpi-gcd.c +mpi-inline.c +mpi-inline.h +mpi-internal.h +mpi-inv.c +mpi-mpow.c +mpi-mul.c +mpi-pow.c +mpi-scan.c +mpicoder.c +mpih-div.c +mpih-mul.c +mpiutil.c +$names$ iQCVAwUAP+LmfDEAnp832S/7AQKZJQQAkR/gQITUM+6Ygy9WAOAO17btyKAlCtGTXp5XSZ+J3X0o/rYneRdSCW89IJvwFRJjAOcFJd52MXs6ZVFF/RQBC8MvJzuQChbEzvihK8o2VgK34YWjU+6XH9sFgRMIgzkHs/51ZZxeQUOPy1XF7TyKB0WE7YBUVisFiRaqB1qGIOs==Z3qB + diff --git a/grub-core/lib/libgcrypt/mpi/alpha/README b/grub-core/lib/libgcrypt/mpi/alpha/README new file mode 100644 index 0000000..55c0a29 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/alpha/README @@ -0,0 +1,53 @@ +This directory contains mpn functions optimized for DEC Alpha processors. + +RELEVANT OPTIMIZATION ISSUES + +EV4 + +1. This chip has very limited store bandwidth. The on-chip L1 cache is +write-through, and a cache line is transfered from the store buffer to the +off-chip L2 in as much 15 cycles on most systems. This delay hurts +mpn_add_n, mpn_sub_n, mpn_lshift, and mpn_rshift. + +2. Pairing is possible between memory instructions and integer arithmetic +instructions. + +3. mulq and umulh is documented to have a latency of 23 cycles, but 2 of +these cycles are pipelined. Thus, multiply instructions can be issued at a +rate of one each 21nd cycle. + +EV5 + +1. The memory bandwidth of this chip seems excellent, both for loads and +stores. Even when the working set is larger than the on-chip L1 and L2 +caches, the perfromance remain almost unaffected. + +2. mulq has a measured latency of 13 cycles and an issue rate of 1 each 8th +cycle. umulh has a measured latency of 15 cycles and an issue rate of 1 +each 10th cycle. But the exact timing is somewhat confusing. + +3. mpn_add_n. With 4-fold unrolling, we need 37 instructions, whereof 12 + are memory operations. This will take at least + ceil(37/2) [dual issue] + 1 [taken branch] = 20 cycles + We have 12 memory cycles, plus 4 after-store conflict cycles, or 16 data + cache cycles, which should be completely hidden in the 20 issue cycles. + The computation is inherently serial, with these dependencies: + addq + / \ + addq cmpult + | | + cmpult | + \ / + or + I.e., there is a 4 cycle path for each limb, making 16 cycles the absolute + minimum. We could replace the `or' with a cmoveq/cmovne, which would save + a cycle on EV5, but that might waste a cycle on EV4. Also, cmov takes 2 + cycles. + addq + / \ + addq cmpult + | \ + cmpult -> cmovne + +STATUS + diff --git a/grub-core/lib/libgcrypt/mpi/alpha/distfiles b/grub-core/lib/libgcrypt/mpi/alpha/distfiles new file mode 100644 index 0000000..f2ab9fc --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/alpha/distfiles @@ -0,0 +1,11 @@ +README +mpih-add1.S +mpih-sub1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S + +udiv-qrnnd.S + diff --git a/grub-core/lib/libgcrypt/mpi/alpha/mpih-add1.S b/grub-core/lib/libgcrypt/mpi/alpha/mpih-add1.S new file mode 100644 index 0000000..50dbb2b --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/alpha/mpih-add1.S @@ -0,0 +1,124 @@ +/* alpha add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * Copyright (C) 1995, 1998, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + +/******************* + * mpi_limb_t + * _gcry_mpih_add_n( mpi_ptr_t res_ptr, ($16) + * mpi_ptr_t s1_ptr, ($17) + * mpi_ptr_t s2_ptr, ($18) + * mpi_size_t size) ($19) + */ + + + .set noreorder + .set noat +.text + .align 3 + .globl _gcry_mpih_add_n + .ent _gcry_mpih_add_n +_gcry_mpih_add_n: + .frame $30,0,$26,0 + + ldq $3,0($17) + ldq $4,0($18) + + subq $19,1,$19 + and $19,4-1,$2 # number of limbs in first loop + bis $31,$31,$0 + beq $2,.L0 # if multiple of 4 limbs, skip first loop + + subq $19,$2,$19 + +.Loop0: subq $2,1,$2 + ldq $5,8($17) + addq $4,$0,$4 + ldq $6,8($18) + cmpult $4,$0,$1 + addq $3,$4,$4 + cmpult $4,$3,$0 + stq $4,0($16) + or $0,$1,$0 + + addq $17,8,$17 + addq $18,8,$18 + bis $5,$5,$3 + bis $6,$6,$4 + addq $16,8,$16 + bne $2,.Loop0 + +.L0: beq $19,.Lend + + .align 3 +.Loop: subq $19,4,$19 + + ldq $5,8($17) + addq $4,$0,$4 + ldq $6,8($18) + cmpult $4,$0,$1 + addq $3,$4,$4 + cmpult $4,$3,$0 + stq $4,0($16) + or $0,$1,$0 + + ldq $3,16($17) + addq $6,$0,$6 + ldq $4,16($18) + cmpult $6,$0,$1 + addq $5,$6,$6 + cmpult $6,$5,$0 + stq $6,8($16) + or $0,$1,$0 + + ldq $5,24($17) + addq $4,$0,$4 + ldq $6,24($18) + cmpult $4,$0,$1 + addq $3,$4,$4 + cmpult $4,$3,$0 + stq $4,16($16) + or $0,$1,$0 + + ldq $3,32($17) + addq $6,$0,$6 + ldq $4,32($18) + cmpult $6,$0,$1 + addq $5,$6,$6 + cmpult $6,$5,$0 + stq $6,24($16) + or $0,$1,$0 + + addq $17,32,$17 + addq $18,32,$18 + addq $16,32,$16 + bne $19,.Loop + +.Lend: addq $4,$0,$4 + cmpult $4,$0,$1 + addq $3,$4,$4 + cmpult $4,$3,$0 + stq $4,0($16) + or $0,$1,$0 + ret $31,($26),1 + + .end _gcry_mpih_add_n + diff --git a/grub-core/lib/libgcrypt/mpi/alpha/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/alpha/mpih-lshift.S new file mode 100644 index 0000000..ded4b15 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/alpha/mpih-lshift.S @@ -0,0 +1,122 @@ +/* alpha - left shift + * + * Copyright (C) 1994, 1995, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + + +/******************* + * mpi_limb_t + * _gcry_mpih_lshift( mpi_ptr_t wp, (r16) + * mpi_ptr_t up, (r17) + * mpi_size_t usize, (r18) + * unsigned cnt) (r19) + * + * This code runs at 4.8 cycles/limb on the 21064. With infinite unrolling, + * it would take 4 cycles/limb. It should be possible to get down to 3 + * cycles/limb since both ldq and stq can be paired with the other used + * instructions. But there are many restrictions in the 21064 pipeline that + * makes it hard, if not impossible, to get down to 3 cycles/limb: + * + * 1. ldq has a 3 cycle delay, srl and sll have a 2 cycle delay. + * 2. Only aligned instruction pairs can be paired. + * 3. The store buffer or silo might not be able to deal with the bandwidth. + */ + + .set noreorder + .set noat +.text + .align 3 + .globl _gcry_mpih_lshift + .ent _gcry_mpih_lshift +_gcry_mpih_lshift: + .frame $30,0,$26,0 + + s8addq $18,$17,$17 # make r17 point at end of s1 + ldq $4,-8($17) # load first limb + subq $17,8,$17 + subq $31,$19,$7 + s8addq $18,$16,$16 # make r16 point at end of RES + subq $18,1,$18 + and $18,4-1,$20 # number of limbs in first loop + srl $4,$7,$0 # compute function result + + beq $20,.L0 + subq $18,$20,$18 + + .align 3 +.Loop0: + ldq $3,-8($17) + subq $16,8,$16 + subq $17,8,$17 + subq $20,1,$20 + sll $4,$19,$5 + srl $3,$7,$6 + bis $3,$3,$4 + bis $5,$6,$8 + stq $8,0($16) + bne $20,.Loop0 + +.L0: beq $18,.Lend + + .align 3 +.Loop: ldq $3,-8($17) + subq $16,32,$16 + subq $18,4,$18 + sll $4,$19,$5 + srl $3,$7,$6 + + ldq $4,-16($17) + sll $3,$19,$1 + bis $5,$6,$8 + stq $8,24($16) + srl $4,$7,$2 + + ldq $3,-24($17) + sll $4,$19,$5 + bis $1,$2,$8 + stq $8,16($16) + srl $3,$7,$6 + + ldq $4,-32($17) + sll $3,$19,$1 + bis $5,$6,$8 + stq $8,8($16) + srl $4,$7,$2 + + subq $17,32,$17 + bis $1,$2,$8 + stq $8,0($16) + + bgt $18,.Loop + +.Lend: sll $4,$19,$8 + stq $8,-8($16) + ret $31,($26),1 + .end _gcry_mpih_lshift + + diff --git a/grub-core/lib/libgcrypt/mpi/alpha/mpih-mul1.S b/grub-core/lib/libgcrypt/mpi/alpha/mpih-mul1.S new file mode 100644 index 0000000..cd91b10 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/alpha/mpih-mul1.S @@ -0,0 +1,90 @@ +/* Alpha 21064 mpih-mul1.S -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * _gcry_mpih_mul_1( mpi_ptr_t res_ptr, (r16) + * mpi_ptr_t s1_ptr, (r17) + * mpi_size_t s1_size, (r18) + * mpi_limb_t s2_limb) (r19) + * + * This code runs at 42 cycles/limb on the EV4 and 18 cycles/limb on the EV5. + * + * To improve performance for long multiplications, we would use + * 'fetch' for S1 and 'fetch_m' for RES. It's not obvious how to use + * these instructions without slowing down the general code: 1. We can + * only have two prefetches in operation at any time in the Alpha + * architecture. 2. There will seldom be any special alignment + * between RES_PTR and S1_PTR. Maybe we can simply divide the current + * loop into an inner and outer loop, having the inner loop handle + * exactly one prefetch block? + */ + + .set noreorder + .set noat +.text + .align 3 + .globl _gcry_mpih_mul_1 + .ent _gcry_mpih_mul_1 2 +_gcry_mpih_mul_1: + .frame $30,0,$26 + + ldq $2,0($17) # $2 = s1_limb + subq $18,1,$18 # size-- + mulq $2,$19,$3 # $3 = prod_low + bic $31,$31,$4 # clear cy_limb + umulh $2,$19,$0 # $0 = prod_high + beq $18,Lend1 # jump if size was == 1 + ldq $2,8($17) # $2 = s1_limb + subq $18,1,$18 # size-- + stq $3,0($16) + beq $18,Lend2 # jump if size was == 2 + + .align 3 +Loop: mulq $2,$19,$3 # $3 = prod_low + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + subq $18,1,$18 # size-- + umulh $2,$19,$4 # $4 = cy_limb + ldq $2,16($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + addq $3,$0,$3 # $3 = cy_limb + prod_low + stq $3,8($16) + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + addq $16,8,$16 # res_ptr++ + bne $18,Loop + +Lend2: mulq $2,$19,$3 # $3 = prod_low + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + umulh $2,$19,$4 # $4 = cy_limb + addq $3,$0,$3 # $3 = cy_limb + prod_low + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + stq $3,8($16) + addq $4,$0,$0 # cy_limb = prod_high + cy + ret $31,($26),1 +Lend1: stq $3,0($16) + ret $31,($26),1 + + .end _gcry_mpih_mul_1 + + diff --git a/grub-core/lib/libgcrypt/mpi/alpha/mpih-mul2.S b/grub-core/lib/libgcrypt/mpi/alpha/mpih-mul2.S new file mode 100644 index 0000000..5eb6b98 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/alpha/mpih-mul2.S @@ -0,0 +1,97 @@ +/* Alpha 21064 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, (r16) + * mpi_ptr_t s1_ptr, (r17) + * mpi_size_t s1_size, (r18) + * mpi_limb_t s2_limb) (r19) + * + * This code runs at 42 cycles/limb on EV4 and 18 cycles/limb on EV5. + */ + + + .set noreorder + .set noat +.text + .align 3 + .globl _gcry_mpih_addmul_1 + .ent _gcry_mpih_addmul_1 2 +_gcry_mpih_addmul_1: + .frame $30,0,$26 + + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + subq $18,1,$18 # size-- + mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + umulh $2,$19,$0 # $0 = prod_high + beq $18,.Lend1 # jump if size was == 1 + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + subq $18,1,$18 # size-- + addq $5,$3,$3 + cmpult $3,$5,$4 + stq $3,0($16) + addq $16,8,$16 # res_ptr++ + beq $18,.Lend2 # jump if size was == 2 + + .align 3 +.Loop: mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + subq $18,1,$18 # size-- + umulh $2,$19,$4 # $4 = cy_limb + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + addq $3,$0,$3 # $3 = cy_limb + prod_low + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + addq $5,$3,$3 + cmpult $3,$5,$5 + stq $3,0($16) + addq $16,8,$16 # res_ptr++ + addq $5,$0,$0 # combine carries + bne $18,.Loop + +.Lend2: mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + umulh $2,$19,$4 # $4 = cy_limb + addq $3,$0,$3 # $3 = cy_limb + prod_low + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + addq $5,$3,$3 + cmpult $3,$5,$5 + stq $3,0($16) + addq $5,$0,$0 # combine carries + addq $4,$0,$0 # cy_limb = prod_high + cy + ret $31,($26),1 +.Lend1: addq $5,$3,$3 + cmpult $3,$5,$5 + stq $3,0($16) + addq $0,$5,$0 + ret $31,($26),1 + + .end _gcry_mpih_addmul_1 + diff --git a/grub-core/lib/libgcrypt/mpi/alpha/mpih-mul3.S b/grub-core/lib/libgcrypt/mpi/alpha/mpih-mul3.S new file mode 100644 index 0000000..7d5d2af --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/alpha/mpih-mul3.S @@ -0,0 +1,95 @@ +/* Alpha 21064 submul_1 -- Multiply a limb vector with a limb and + * subtract the result from a second limb vector. + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * _gcry_mpih_submul_1( mpi_ptr_t res_ptr, (r16 ) + * mpi_ptr_t s1_ptr, (r17 ) + * mpi_size_t s1_size, (r18 ) + * mpi_limb_t s2_limb) (r19 ) + * + * This code runs at 42 cycles/limb on EV4 and 18 cycles/limb on EV5. + */ + + .set noreorder + .set noat +.text + .align 3 + .globl _gcry_mpih_submul_1 + .ent _gcry_mpih_submul_1 2 +_gcry_mpih_submul_1: + .frame $30,0,$26 + + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + subq $18,1,$18 # size-- + mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + umulh $2,$19,$0 # $0 = prod_high + beq $18,.Lend1 # jump if size was == 1 + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + subq $18,1,$18 # size-- + subq $5,$3,$3 + cmpult $5,$3,$4 + stq $3,0($16) + addq $16,8,$16 # res_ptr++ + beq $18,.Lend2 # jump if size was == 2 + + .align 3 +.Loop: mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + subq $18,1,$18 # size-- + umulh $2,$19,$4 # $4 = cy_limb + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + addq $3,$0,$3 # $3 = cy_limb + prod_low + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + subq $5,$3,$3 + cmpult $5,$3,$5 + stq $3,0($16) + addq $16,8,$16 # res_ptr++ + addq $5,$0,$0 # combine carries + bne $18,.Loop + +.Lend2: mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + umulh $2,$19,$4 # $4 = cy_limb + addq $3,$0,$3 # $3 = cy_limb + prod_low + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + subq $5,$3,$3 + cmpult $5,$3,$5 + stq $3,0($16) + addq $5,$0,$0 # combine carries + addq $4,$0,$0 # cy_limb = prod_high + cy + ret $31,($26),1 +.Lend1: subq $5,$3,$3 + cmpult $5,$3,$5 + stq $3,0($16) + addq $0,$5,$0 + ret $31,($26),1 + + .end _gcry_mpih_submul_1 + diff --git a/grub-core/lib/libgcrypt/mpi/alpha/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/alpha/mpih-rshift.S new file mode 100644 index 0000000..f0c9814 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/alpha/mpih-rshift.S @@ -0,0 +1,118 @@ +/* alpha rshift + * Copyright (C) 1994, 1995, 1998, 1999, + * 2000, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + + + +/******************* + * mpi_limb_t + * _gcry_mpih_rshift( mpi_ptr_t wp, (r16) + * mpi_ptr_t up, (r17) + * mpi_size_t usize, (r18) + * unsigned cnt) (r19) + * + * This code runs at 4.8 cycles/limb on the 21064. With infinite unrolling, + * it would take 4 cycles/limb. It should be possible to get down to 3 + * cycles/limb since both ldq and stq can be paired with the other used + * instructions. But there are many restrictions in the 21064 pipeline that + * makes it hard, if not impossible, to get down to 3 cycles/limb: + * + * 1. ldq has a 3 cycle delay, srl and sll have a 2 cycle delay. + * 2. Only aligned instruction pairs can be paired. + * 3. The store buffer or silo might not be able to deal with the bandwidth. + */ + + .set noreorder + .set noat +.text + .align 3 + .globl _gcry_mpih_rshift + .ent _gcry_mpih_rshift +_gcry_mpih_rshift: + .frame $30,0,$26,0 + + ldq $4,0($17) # load first limb + addq $17,8,$17 + subq $31,$19,$7 + subq $18,1,$18 + and $18,4-1,$20 # number of limbs in first loop + sll $4,$7,$0 # compute function result + + beq $20,.R0 + subq $18,$20,$18 + + .align 3 +.Roop0: + ldq $3,0($17) + addq $16,8,$16 + addq $17,8,$17 + subq $20,1,$20 + srl $4,$19,$5 + sll $3,$7,$6 + bis $3,$3,$4 + bis $5,$6,$8 + stq $8,-8($16) + bne $20,.Roop0 + +.R0: beq $18,.Rend + + .align 3 +.Roop: ldq $3,0($17) + addq $16,32,$16 + subq $18,4,$18 + srl $4,$19,$5 + sll $3,$7,$6 + + ldq $4,8($17) + srl $3,$19,$1 + bis $5,$6,$8 + stq $8,-32($16) + sll $4,$7,$2 + + ldq $3,16($17) + srl $4,$19,$5 + bis $1,$2,$8 + stq $8,-24($16) + sll $3,$7,$6 + + ldq $4,24($17) + srl $3,$19,$1 + bis $5,$6,$8 + stq $8,-16($16) + sll $4,$7,$2 + + addq $17,32,$17 + bis $1,$2,$8 + stq $8,-8($16) + + bgt $18,.Roop + +.Rend: srl $4,$19,$8 + stq $8,0($16) + ret $31,($26),1 + .end _gcry_mpih_rshift + diff --git a/grub-core/lib/libgcrypt/mpi/alpha/mpih-sub1.S b/grub-core/lib/libgcrypt/mpi/alpha/mpih-sub1.S new file mode 100644 index 0000000..9a64446 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/alpha/mpih-sub1.S @@ -0,0 +1,124 @@ +/* Alpha sub_n -- Subtract two limb vectors of the same length > 0 and + * store difference in a third limb vector. + * Copyright (C) 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * _gcry_mpih_sub_n( mpi_ptr_t res_ptr, (r16) + * mpi_ptr_t s1_ptr, (r17) + * mpi_ptr_t s2_ptr, (r18) + * mpi_size_t size) (r19) + */ + + .set noreorder + .set noat +.text + .align 3 + .globl _gcry_mpih_sub_n + .ent _gcry_mpih_sub_n +_gcry_mpih_sub_n: + .frame $30,0,$26,0 + + ldq $3,0($17) + ldq $4,0($18) + + subq $19,1,$19 + and $19,4-1,$2 # number of limbs in first loop + bis $31,$31,$0 + beq $2,.L0 # if multiple of 4 limbs, skip first loop + + subq $19,$2,$19 + +.Loop0: subq $2,1,$2 + ldq $5,8($17) + addq $4,$0,$4 + ldq $6,8($18) + cmpult $4,$0,$1 + subq $3,$4,$4 + cmpult $3,$4,$0 + stq $4,0($16) + or $0,$1,$0 + + addq $17,8,$17 + addq $18,8,$18 + bis $5,$5,$3 + bis $6,$6,$4 + addq $16,8,$16 + bne $2,.Loop0 + +.L0: beq $19,.Lend + + .align 3 +.Loop: subq $19,4,$19 + + ldq $5,8($17) + addq $4,$0,$4 + ldq $6,8($18) + cmpult $4,$0,$1 + subq $3,$4,$4 + cmpult $3,$4,$0 + stq $4,0($16) + or $0,$1,$0 + + ldq $3,16($17) + addq $6,$0,$6 + ldq $4,16($18) + cmpult $6,$0,$1 + subq $5,$6,$6 + cmpult $5,$6,$0 + stq $6,8($16) + or $0,$1,$0 + + ldq $5,24($17) + addq $4,$0,$4 + ldq $6,24($18) + cmpult $4,$0,$1 + subq $3,$4,$4 + cmpult $3,$4,$0 + stq $4,16($16) + or $0,$1,$0 + + ldq $3,32($17) + addq $6,$0,$6 + ldq $4,32($18) + cmpult $6,$0,$1 + subq $5,$6,$6 + cmpult $5,$6,$0 + stq $6,24($16) + or $0,$1,$0 + + addq $17,32,$17 + addq $18,32,$18 + addq $16,32,$16 + bne $19,.Loop + +.Lend: addq $4,$0,$4 + cmpult $4,$0,$1 + subq $3,$4,$4 + cmpult $3,$4,$0 + stq $4,0($16) + or $0,$1,$0 + ret $31,($26),1 + + .end _gcry_mpih_sub_n + + diff --git a/grub-core/lib/libgcrypt/mpi/alpha/udiv-qrnnd.S b/grub-core/lib/libgcrypt/mpi/alpha/udiv-qrnnd.S new file mode 100644 index 0000000..dd0c52d --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/alpha/udiv-qrnnd.S @@ -0,0 +1,159 @@ +/* Alpha 21064 __udiv_qrnnd + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + + + .set noreorder + .set noat +.text + .align 3 + .globl __udiv_qrnnd + .ent __udiv_qrnnd +__udiv_qrnnd: + .frame $30,0,$26,0 + .prologue 0 +#define cnt $2 +#define tmp $3 +#define rem_ptr $16 +#define n1 $17 +#define n0 $18 +#define d $19 +#define qb $20 + + ldiq cnt,16 + blt d,.Largedivisor + +.Loop1: cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule d,n1,qb + subq n1,d,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule d,n1,qb + subq n1,d,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule d,n1,qb + subq n1,d,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule d,n1,qb + subq n1,d,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + subq cnt,1,cnt + bgt cnt,.Loop1 + stq n1,0(rem_ptr) + bis $31,n0,$0 + ret $31,($26),1 + +.Largedivisor: + and n0,1,$4 + + srl n0,1,n0 + sll n1,63,tmp + or tmp,n0,n0 + srl n1,1,n1 + + and d,1,$6 + srl d,1,$5 + addq $5,$6,$5 + +.Loop2: cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule $5,n1,qb + subq n1,$5,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule $5,n1,qb + subq n1,$5,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule $5,n1,qb + subq n1,$5,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule $5,n1,qb + subq n1,$5,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + subq cnt,1,cnt + bgt cnt,.Loop2 + + addq n1,n1,n1 + addq $4,n1,n1 + bne $6,.LOdd + stq n1,0(rem_ptr) + bis $31,n0,$0 + ret $31,($26),1 + +.LOdd: + /* q' in n0. r' in n1 */ + addq n1,n0,n1 + cmpult n1,n0,tmp # tmp := carry from addq + beq tmp,.LLp6 + addq n0,1,n0 + subq n1,d,n1 +.LLp6: cmpult n1,d,tmp + bne tmp,.LLp7 + addq n0,1,n0 + subq n1,d,n1 +.LLp7: + stq n1,0(rem_ptr) + bis $31,n0,$0 + ret $31,($26),1 + + .end __udiv_qrnnd diff --git a/grub-core/lib/libgcrypt/mpi/amd64/distfiles b/grub-core/lib/libgcrypt/mpi/amd64/distfiles new file mode 100644 index 0000000..634e36f --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/amd64/distfiles @@ -0,0 +1,8 @@ +mpih-add1.S +mpih-lshift.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-rshift.S +mpih-sub1.S +mpi-asm-defs.h diff --git a/grub-core/lib/libgcrypt/mpi/amd64/mpi-asm-defs.h b/grub-core/lib/libgcrypt/mpi/amd64/mpi-asm-defs.h new file mode 100644 index 0000000..17de1c1 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/amd64/mpi-asm-defs.h @@ -0,0 +1,4 @@ +/* This file defines some basic constants for the MPI machinery. We + * need to define the types on a per-CPU basis, so it is done with + * this file here. */ +#define BYTES_PER_MPI_LIMB 8 diff --git a/grub-core/lib/libgcrypt/mpi/amd64/mpih-add1.S b/grub-core/lib/libgcrypt/mpi/amd64/mpih-add1.S new file mode 100644 index 0000000..f0ec89c --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/amd64/mpih-add1.S @@ -0,0 +1,63 @@ +/* AMD64 (x86_64) add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002, 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_add_n( mpi_ptr_t res_ptr, rdi + * mpi_ptr_t s1_ptr, rsi + * mpi_ptr_t s2_ptr, rdx + * mpi_size_t size) rcx + */ + +.text + .globl C_SYMBOL_NAME(_gcry_mpih_add_n) +C_SYMBOL_NAME(_gcry_mpih_add_n:) + leaq (%rsi,%rcx,8), %rsi + leaq (%rdi,%rcx,8), %rdi + leaq (%rdx,%rcx,8), %rdx + negq %rcx + xorl %eax, %eax /* clear cy */ + + ALIGN(4) /* minimal alignment for claimed speed */ +.Loop: movq (%rsi,%rcx,8), %rax + movq (%rdx,%rcx,8), %r10 + adcq %r10, %rax + movq %rax, (%rdi,%rcx,8) + incq %rcx + jne .Loop + + movq %rcx, %rax /* zero %rax */ + adcq %rax, %rax + ret +
\ No newline at end of file diff --git a/grub-core/lib/libgcrypt/mpi/amd64/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/amd64/mpih-lshift.S new file mode 100644 index 0000000..e87dd1a --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/amd64/mpih-lshift.S @@ -0,0 +1,77 @@ +/* AMD64 (x86_64) lshift -- Left shift a limb vector and store + * result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002, 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * _gcry_mpih_lshift( mpi_ptr_t wp, rdi + * mpi_ptr_t up, rsi + * mpi_size_t usize, rdx + * unsigned cnt) rcx + */ + +.text + .globl C_SYMBOL_NAME(_gcry_mpih_lshift) +C_SYMBOL_NAME(_gcry_mpih_lshift:) + movq -8(%rsi,%rdx,8), %mm7 + movd %ecx, %mm1 + movl $64, %eax + subl %ecx, %eax + movd %eax, %mm0 + movq %mm7, %mm3 + psrlq %mm0, %mm7 + movd %mm7, %rax + subq $2, %rdx + jl .Lendo + + ALIGN(4) /* minimal alignment for claimed speed */ +.Loop: movq (%rsi,%rdx,8), %mm6 + movq %mm6, %mm2 + psrlq %mm0, %mm6 + psllq %mm1, %mm3 + por %mm6, %mm3 + movq %mm3, 8(%rdi,%rdx,8) + je .Lende + movq -8(%rsi,%rdx,8), %mm7 + movq %mm7, %mm3 + psrlq %mm0, %mm7 + psllq %mm1, %mm2 + por %mm7, %mm2 + movq %mm2, (%rdi,%rdx,8) + subq $2, %rdx + jge .Loop + +.Lendo: movq %mm3, %mm2 +.Lende: psllq %mm1, %mm2 + movq %mm2, (%rdi) + emms + ret diff --git a/grub-core/lib/libgcrypt/mpi/amd64/mpih-mul1.S b/grub-core/lib/libgcrypt/mpi/amd64/mpih-mul1.S new file mode 100644 index 0000000..54b0ab4 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/amd64/mpih-mul1.S @@ -0,0 +1,65 @@ +/* AMD64 mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002, 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * _gcry_mpih_mul_1( mpi_ptr_t res_ptr, (rdi) + * mpi_ptr_t s1_ptr, (rsi) + * mpi_size_t s1_size, (rdx) + * mpi_limb_t s2_limb) (rcx) + */ + + + TEXT + ALIGN(5) + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + GLOBL C_SYMBOL_NAME(_gcry_mpih_mul_1) +C_SYMBOL_NAME(_gcry_mpih_mul_1:) + + movq %rdx, %r11 + leaq (%rsi,%rdx,8), %rsi + leaq (%rdi,%rdx,8), %rdi + negq %r11 + xorl %r8d, %r8d + +.Loop: movq (%rsi,%r11,8), %rax + mulq %rcx + addq %r8, %rax + movl $0, %r8d + adcq %rdx, %r8 + movq %rax, (%rdi,%r11,8) + incq %r11 + jne .Loop + + movq %r8, %rax + ret diff --git a/grub-core/lib/libgcrypt/mpi/amd64/mpih-mul2.S b/grub-core/lib/libgcrypt/mpi/amd64/mpih-mul2.S new file mode 100644 index 0000000..1180f76 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/amd64/mpih-mul2.S @@ -0,0 +1,107 @@ +/* AMD64 addmul2 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002, 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_addmul_2( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + + /* i80386 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, (rdi) + * mpi_ptr_t s1_ptr, (rsi) + * mpi_size_t s1_size, (rdx) + * mpi_limb_t s2_limb) (rcx) + */ + TEXT + GLOBL C_SYMBOL_NAME(_gcry_mpih_addmul_1) +C_SYMBOL_NAME(_gcry_mpih_addmul_1:) + movq %rdx, %r11 + leaq (%rsi,%rdx,8), %rsi + leaq (%rdi,%rdx,8), %rdi + negq %r11 + xorl %r8d, %r8d + xorl %r10d, %r10d + + ALIGN(3) /* minimal alignment for claimed speed */ +.Loop: movq (%rsi,%r11,8), %rax + mulq %rcx + addq (%rdi,%r11,8), %rax + adcq %r10, %rdx + addq %r8, %rax + movq %r10, %r8 + movq %rax, (%rdi,%r11,8) + adcq %rdx, %r8 + incq %r11 + jne .Loop + + movq %r8, %rax + ret diff --git a/grub-core/lib/libgcrypt/mpi/amd64/mpih-mul3.S b/grub-core/lib/libgcrypt/mpi/amd64/mpih-mul3.S new file mode 100644 index 0000000..4d458a7 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/amd64/mpih-mul3.S @@ -0,0 +1,66 @@ +/* AMD64 submul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002, 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_submul_1( mpi_ptr_t res_ptr, (rdi) + * mpi_ptr_t s1_ptr, (rsi) + * mpi_size_t s1_size, (rdx) + * mpi_limb_t s2_limb) (rcx) + */ + TEXT + GLOBL C_SYMBOL_NAME(_gcry_mpih_submul_1) +C_SYMBOL_NAME(_gcry_mpih_submul_1:) + + movq %rdx, %r11 + leaq (%rsi,%r11,8), %rsi + leaq (%rdi,%r11,8), %rdi + negq %r11 + xorl %r8d, %r8d + + ALIGN(3) /* minimal alignment for claimed speed */ +.Loop: movq (%rsi,%r11,8), %rax + movq (%rdi,%r11,8), %r10 + mulq %rcx + subq %r8, %r10 + movl $0, %r8d + adcl %r8d, %r8d + subq %rax, %r10 + adcq %rdx, %r8 + movq %r10, (%rdi,%r11,8) + incq %r11 + jne .Loop + + movq %r8, %rax + ret diff --git a/grub-core/lib/libgcrypt/mpi/amd64/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/amd64/mpih-rshift.S new file mode 100644 index 0000000..4cfc8f6 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/amd64/mpih-rshift.S @@ -0,0 +1,80 @@ +/* AMD64 (x86_64) rshift -- Right shift a limb vector and store + * result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002, 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * _gcry_mpih_rshift( mpi_ptr_t wp, rdi + * mpi_ptr_t up, rsi + * mpi_size_t usize, rdx + * unsigned cnt) rcx + */ + +.text + .globl C_SYMBOL_NAME(_gcry_mpih_rshift) +C_SYMBOL_NAME(_gcry_mpih_rshift:) + movq (%rsi), %mm7 + movd %ecx, %mm1 + movl $64, %eax + subl %ecx, %eax + movd %eax, %mm0 + movq %mm7, %mm3 + psllq %mm0, %mm7 + movd %mm7, %rax + leaq (%rsi,%rdx,8), %rsi + leaq (%rdi,%rdx,8), %rdi + negq %rdx + addq $2, %rdx + jg .Lendo + + ALIGN(8) /* minimal alignment for claimed speed */ +.Loop: movq -8(%rsi,%rdx,8), %mm6 + movq %mm6, %mm2 + psllq %mm0, %mm6 + psrlq %mm1, %mm3 + por %mm6, %mm3 + movq %mm3, -16(%rdi,%rdx,8) + je .Lende + movq (%rsi,%rdx,8), %mm7 + movq %mm7, %mm3 + psllq %mm0, %mm7 + psrlq %mm1, %mm2 + por %mm7, %mm2 + movq %mm2, -8(%rdi,%rdx,8) + addq $2, %rdx + jle .Loop + +.Lendo: movq %mm3, %mm2 +.Lende: psrlq %mm1, %mm2 + movq %mm2, -8(%rdi) + emms + ret diff --git a/grub-core/lib/libgcrypt/mpi/amd64/mpih-sub1.S b/grub-core/lib/libgcrypt/mpi/amd64/mpih-sub1.S new file mode 100644 index 0000000..b3609b0 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/amd64/mpih-sub1.S @@ -0,0 +1,61 @@ +/* AMD64 (x86_64) sub_n -- Subtract two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002, 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_sub_n( mpi_ptr_t res_ptr, rdi + * mpi_ptr_t s1_ptr, rsi + * mpi_ptr_t s2_ptr, rdx + * mpi_size_t size) rcx + */ +.text + .globl C_SYMBOL_NAME(_gcry_mpih_sub_n) +C_SYMBOL_NAME(_gcry_mpih_sub_n:) + leaq (%rsi,%rcx,8), %rsi + leaq (%rdi,%rcx,8), %rdi + leaq (%rdx,%rcx,8), %rdx + negq %rcx + xorl %eax, %eax /* clear cy */ + + ALIGN(4) /* minimal alignment for claimed speed */ +.Loop: movq (%rsi,%rcx,8), %rax + movq (%rdx,%rcx,8), %r10 + sbbq %r10, %rax + movq %rax, (%rdi,%rcx,8) + incq %rcx + jne .Loop + + movq %rcx, %rax /* zero %rax */ + adcq %rax, %rax + ret diff --git a/grub-core/lib/libgcrypt/mpi/config.links b/grub-core/lib/libgcrypt/mpi/config.links new file mode 100644 index 0000000..7e910ee --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/config.links @@ -0,0 +1,360 @@ +# config.links - helper for ../configure -*- mode: sh -*- +# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +# +# sourced by ../configure to get the list of files to link +# this should set $mpi_ln_list. +# Note: this is called from the above directory. + +mpi_sflags= +mpi_extra_modules= + +test -d ./mpi || mkdir ./mpi + +# We grep the list of modules from the Makefile so that +# we don't need to maintain them here. +mpi_standard_modules=`$AWK '/^#BEGIN_ASM_LIST/,/^#END_ASM_LIST/ { + if( $3 != "O" ) print $2 }' $srcdir/mpi/Makefile.am` +mpi_optional_modules=`$AWK '/^#BEGIN_ASM_LIST/,/^#END_ASM_LIST/ { + if( $3 == "O" ) print $2 }' $srcdir/mpi/Makefile.am` + + +echo '/* created by config.links - do not edit */' >./mpi/asm-syntax.h +echo "/* Host: ${host} */" >>./mpi/asm-syntax.h + +if test "$try_asm_modules" = "yes" ; then +case "${host}" in + powerpc-apple-darwin* | \ + i[34567]86*-*-openbsd[12]* | \ + i[34567]86*-*-openbsd3.[0123]*) + echo '/* No working assembler modules available */' >>./mpi/asm-syntax.h + path="" + ;; + i[3467]86*-*-openbsd* | \ + i[3467]86*-*-freebsd*-elf | \ + i[3467]86*-*-freebsd[3-9]* | \ + i[3467]86*-*-freebsdelf* | \ + i[3467]86*-*-netbsd* | \ + i[3467]86*-*-k*bsd*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-*-openbsd* | \ + i586*-*-freebsd*-elf | \ + i586*-*-freebsd[3-9]* | \ + i586*-*-freebsdelf* | \ + i586*-*-netbsd* | \ + i586*-*-k*bsd* | \ + pentium-*-netbsd* | \ + pentiumpro-*-netbsd*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + i[34]86*-*-bsdi4*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i[3467]86*-*-linuxaout* | \ + i[3467]86*-*-linuxoldld* | \ + i[3467]86*-*-*bsd*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-*-linuxaout* | \ + i586*-*-linuxoldld* | \ + i586*-*-*bsd*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + i[3467]86*-msdosdjgpp* | \ + i[34]86*-apple-darwin*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-msdosdjgpp* | \ + i[567]86*-apple-darwin*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + i[3467]86*-*-*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-*-* | \ + pentium-*-* | \ + pentiumpro-*-*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + x86_64-*-*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="amd64" + ;; + alpha*-*-*) + echo '/* configured for alpha */' >>./mpi/asm-syntax.h + path="alpha" + mpi_extra_modules="udiv-qrnnd" + ;; + hppa7000*-*-*) + echo '/* configured for HPPA (pa7000) */' >>./mpi/asm-syntax.h + path="hppa1.1 hppa" + mpi_extra_modules="udiv-qrnnd" + ;; + hppa1.0*-*-*) + echo '/* configured for HPPA 1.0 */' >>./mpi/asm-syntax.h + path="hppa" + mpi_extra_modules="udiv-qrnnd" + ;; + hppa*-*-*) # assume pa7100 + echo '/* configured for HPPA (pa7100) */' >>./mpi/asm-syntax.h + path="pa7100 hppa1.1 hppa" + mpi_extra_modules="udiv-qrnnd" + ;; + sparc64-*-linux-gnu) + echo '/* No working assembler modules available */' >>./mpi/asm-syntax.h + path="" + ;; + sparc64-sun-solaris2*) + echo '/* No working assembler modules available */' >>./mpi/asm-syntax.h + path="" + ;; + sparc64-*-netbsd* | sparc64-*-freebsd* | sparc64-*-openbsd*) + # There are no sparc64 assembler modules that work on the + # *BSDs, so use the generic C functions. + echo '/* No working assembler modules available */' >>./mpi/asm-syntax.h + path="" + ;; + sparc64*-*-*) + echo '/* No working assembler modules available */' >>./mpi/asm-syntax.h + path="" + ;; + sparc9*-*-* | \ + ultrasparc*-*-* ) + echo '/* configured for sparc9 or higher */' >>./mpi/asm-syntax.h + path="sparc32v8 sparc32" + ;; + sparc8*-*-* | \ + microsparc*-*-*) + echo '/* configured for sparc8 */' >>./mpi/asm-syntax.h + path="sparc32v8 sparc32" + ;; + supersparc*-*-*) + echo '/* configured for supersparc */' >>./mpi/asm-syntax.h + path="supersparc sparc32v8 sparc32" + mpi_extra_modules="udiv" + ;; + sparc*-*-*) + echo '/* configured for sparc */' >>./mpi/asm-syntax.h + path="sparc32" + mpi_extra_modules="udiv" + ;; + mips[34]*-*-* | \ + mips*-*-irix6*) + echo '/* configured for MIPS3 */' >>./mpi/asm-syntax.h + path="mips3" + ;; + mips*-*-*) + echo '/* configured for MIPS2 */' >>./mpi/asm-syntax.h + path="mips2" + ;; + + # Motorola 68k configurations. Let m68k mean 68020-68040. + # mc68000 or mc68060 configurations need to be specified explicitly + m680[234]0*-*-linuxaout* | \ + m68k*-*-linuxaout*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68020 m68k" + ;; + m68060*-*-linuxaout*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k" + ;; + m680[234]0*-*-linux* | \ + m68k*-*-linux*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + ;; + m68060*-*-linux*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k" + ;; + m68k-atari-mint) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68020 m68k" + ;; + m68000*-*-* | \ + m68060*-*-*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68000" + ;; + m680[234]0*-*-* | \ + m68k*-*-*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68020 m68k" + ;; + + powerpc*-*-netbsd* | powerpc*-*-openbsd*) + echo '/* configured {Open,Net}BSD on powerpc */' >>./mpi/asm-syntax.h + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/powerpc32/syntax.h >>./mpi/asm-syntax.h + mpi_sflags="-Wa,-mppc" + path="powerpc32" + ;; + + ppc620-*-* | \ + powerpc64*-*-*) + mpi_sflags="-Wa,-mppc" + path="powerpc64" + ;; + powerpc*-*-linux*) + echo '/* configured for powerpc/ELF */' >>./mpi/asm-syntax.h + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/powerpc32/syntax.h >>./mpi/asm-syntax.h + path="powerpc32" + ;; + + rs6000-*-aix[456789]* | \ + rs6000-*-aix3.2.[456789]) + mpi_sflags="-Wa,-mpwr" + path="power" + mpi_extra_modules="udiv-w-sdiv" + ;; + rs6000-*-* | \ + power-*-* | \ + power2-*-*) + mpi_sflags="-Wa,-mppc" + path="power" + mpi_extra_modules="udiv-w-sdiv" + ;; + powerpc-ibm-aix4.2.* ) + # I am not sure about this one but a machine identified by + # powerpc-ibm-aix4.2.1.0 cannot use the powerpc32 code. + mpi_sflags="-Wa,-mpwr" + path="power" + mpi_extra_modules="udiv-w-sdiv" + ;; + ppc601-*-*) + mpi_sflags="-Wa,-mppc" + path="power powerpc32" + ;; + ppc60[234]*-*-*) + mpi_sflags="-Wa,-mppc" + path="powerpc32" + ;; + powerpc*-*-*) + mpi_sflags="-Wa,-mppc" + path="powerpc32" + ;; + *) + echo '/* No assembler modules configured */' >>./mpi/asm-syntax.h + path="" + ;; +esac +else + echo '/* Assembler modules disabled on request */' >>./mpi/asm-syntax.h + path="" +fi + + +# Make sysdep.h +echo '/* created by config.links - do not edit */' >./mpi/sysdep.h +if test x$ac_cv_sys_symbol_underscore = xyes; then + cat <<EOF >>./mpi/sysdep.h +#if __STDC__ +#define C_SYMBOL_NAME(name) _##name +#else +#define C_SYMBOL_NAME(name) _/**/name +#endif +EOF +else + cat <<EOF >>./mpi/sysdep.h +#define C_SYMBOL_NAME(name) name +EOF +fi + + +# Figure the required modules out +mpi_required_modules=$mpi_standard_modules +if test "$mpi_extra_modules" != ""; then + for fn in $mpi_extra_modules; do + for i in $mpi_optional_modules; do + if test "$fn" = "$i" ; then + mpi_required_modules="$mpi_required_modules $fn" + fi + done + done +fi + +# Try to get file to link from the assembler subdirectory and +# if this fails get it from the generic subdirectory. +mpi_ln_list= +mpi_mod_list= +path=`echo "$mpi_extra_path $path generic" | tr ':' ' '` +echo '/* Created by config.links - do not edit */' >./mpi/mod-source-info.h +echo "/* Host: ${host} */" >>./mpi/mod-source-info.h +echo "static char mod_source_info[] =" >>./mpi/mod-source-info.h +for fn in $mpi_required_modules ; do + fnu=`echo $fn | sed 's/-/_/g'` + eval mpi_mod_c_${fnu}=no + eval mpi_mod_asm_${fnu}=no + for dir in $path ; do + rm -f $srcdir/mpi/$fn.[Sc] + if test -f $srcdir/mpi/$dir/$fn.S ; then + echo " \":$dir/$fn.S\"" >>./mpi/mod-source-info.h + mpi_ln_list="$mpi_ln_list mpi/$fn-asm.S:mpi/$dir/$fn.S" + eval mpi_mod_asm_${fnu}=yes + mpi_mod_list="$mpi_mod_list $fn" + break; + elif test -f $srcdir/mpi/$dir/$fn.c ; then + echo " \":$dir/$fn.c\"" >>./mpi/mod-source-info.h + mpi_ln_list="$mpi_ln_list mpi/$fn.c:mpi/$dir/$fn.c" + eval mpi_mod_c_${fnu}=yes + mpi_mod_list="$mpi_mod_list $fn" + break; + fi + done +done +echo " ;" >>./mpi/mod-source-info.h + +# Same thing for the file which defines the limb size +path=`echo "$path generic" | tr ':' ' '` +for dir in $path ; do + rm -f $srcdir/mpi/mpi-asm-defs.h + if test -f $srcdir/mpi/$dir/mpi-asm-defs.h ; then + mpi_ln_list="$mpi_ln_list mpi/mpi-asm-defs.h:mpi/$dir/mpi-asm-defs.h" + break; + fi +done diff --git a/grub-core/lib/libgcrypt/mpi/ec.c b/grub-core/lib/libgcrypt/mpi/ec.c new file mode 100644 index 0000000..fa00818 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/ec.c @@ -0,0 +1,721 @@ +/* ec.c - Elliptic Curve functions + Copyright (C) 2007 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "mpi-internal.h" +#include "longlong.h" +#include "g10lib.h" + + +#define point_init(a) _gcry_mpi_ec_point_init ((a)) +#define point_free(a) _gcry_mpi_ec_point_free ((a)) + + +/* Object to represent a point in projective coordinates. */ +/* Currently defined in mpi.h */ + +/* This context is used with all our EC functions. */ +struct mpi_ec_ctx_s +{ + /* Domain parameters. */ + gcry_mpi_t p; /* Prime specifying the field GF(p). */ + gcry_mpi_t a; /* First coefficient of the Weierstrass equation. */ + + int a_is_pminus3; /* True if A = P - 3. */ + + /* Some often used constants. */ + gcry_mpi_t one; + gcry_mpi_t two; + gcry_mpi_t three; + gcry_mpi_t four; + gcry_mpi_t eight; + gcry_mpi_t two_inv_p; + + /* Scratch variables. */ + gcry_mpi_t scratch[11]; + + /* Helper for fast reduction. */ +/* int nist_nbits; /\* If this is a NIST curve, the number of bits. *\/ */ +/* gcry_mpi_t s[10]; */ +/* gcry_mpi_t c; */ + +}; + + + +/* Initialized a point object. gcry_mpi_ec_point_free shall be used + to release this object. */ +void +_gcry_mpi_ec_point_init (mpi_point_t *p) +{ + p->x = mpi_new (0); + p->y = mpi_new (0); + p->z = mpi_new (0); +} + + +/* Release a point object. */ +void +_gcry_mpi_ec_point_free (mpi_point_t *p) +{ + mpi_free (p->x); p->x = NULL; + mpi_free (p->y); p->y = NULL; + mpi_free (p->z); p->z = NULL; +} + +/* Set the value from S into D. */ +static void +point_set (mpi_point_t *d, mpi_point_t *s) +{ + mpi_set (d->x, s->x); + mpi_set (d->y, s->y); + mpi_set (d->z, s->z); +} + + + +static void +ec_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) +{ + mpi_addm (w, u, v, ctx->p); +} + +static void +ec_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) +{ + mpi_subm (w, u, v, ctx->p); +} + +static void +ec_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) +{ +#if 0 + /* NOTE: This code works only for limb sizes of 32 bit. */ + mpi_limb_t *wp, *sp; + + if (ctx->nist_nbits == 192) + { + mpi_mul (w, u, v); + mpi_resize (w, 12); + wp = w->d; + + sp = ctx->s[0]->d; + sp[0*2+0] = wp[0*2+0]; + sp[0*2+1] = wp[0*2+1]; + sp[1*2+0] = wp[1*2+0]; + sp[1*2+1] = wp[1*2+1]; + sp[2*2+0] = wp[2*2+0]; + sp[2*2+1] = wp[2*2+1]; + + sp = ctx->s[1]->d; + sp[0*2+0] = wp[3*2+0]; + sp[0*2+1] = wp[3*2+1]; + sp[1*2+0] = wp[3*2+0]; + sp[1*2+1] = wp[3*2+1]; + sp[2*2+0] = 0; + sp[2*2+1] = 0; + + sp = ctx->s[2]->d; + sp[0*2+0] = 0; + sp[0*2+1] = 0; + sp[1*2+0] = wp[4*2+0]; + sp[1*2+1] = wp[4*2+1]; + sp[2*2+0] = wp[4*2+0]; + sp[2*2+1] = wp[4*2+1]; + + sp = ctx->s[3]->d; + sp[0*2+0] = wp[5*2+0]; + sp[0*2+1] = wp[5*2+1]; + sp[1*2+0] = wp[5*2+0]; + sp[1*2+1] = wp[5*2+1]; + sp[2*2+0] = wp[5*2+0]; + sp[2*2+1] = wp[5*2+1]; + + ctx->s[0]->nlimbs = 6; + ctx->s[1]->nlimbs = 6; + ctx->s[2]->nlimbs = 6; + ctx->s[3]->nlimbs = 6; + + mpi_add (ctx->c, ctx->s[0], ctx->s[1]); + mpi_add (ctx->c, ctx->c, ctx->s[2]); + mpi_add (ctx->c, ctx->c, ctx->s[3]); + + while ( mpi_cmp (ctx->c, ctx->p ) >= 0 ) + mpi_sub ( ctx->c, ctx->c, ctx->p ); + mpi_set (w, ctx->c); + } + else if (ctx->nist_nbits == 384) + { + int i; + mpi_mul (w, u, v); + mpi_resize (w, 24); + wp = w->d; + +#define NEXT(a) do { ctx->s[(a)]->nlimbs = 12; \ + sp = ctx->s[(a)]->d; \ + i = 0; } while (0) +#define X(a) do { sp[i++] = wp[(a)];} while (0) +#define X0(a) do { sp[i++] = 0; } while (0) + NEXT(0); + X(0);X(1);X(2);X(3);X(4);X(5);X(6);X(7);X(8);X(9);X(10);X(11); + NEXT(1); + X0();X0();X0();X0();X(21);X(22);X(23);X0();X0();X0();X0();X0(); + NEXT(2); + X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20);X(21);X(22);X(23); + NEXT(3); + X(21);X(22);X(23);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20); + NEXT(4); + X0();X(23);X0();X(20);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19); + NEXT(5); + X0();X0();X0();X0();X(20);X(21);X(22);X(23);X0();X0();X0();X0(); + NEXT(6); + X(20);X0();X0();X(21);X(22);X(23);X0();X0();X0();X0();X0();X0(); + NEXT(7); + X(23);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20);X(21);X(22); + NEXT(8); + X0();X(20);X(21);X(22);X(23);X0();X0();X0();X0();X0();X0();X0(); + NEXT(9); + X0();X0();X0();X(23);X(23);X0();X0();X0();X0();X0();X0();X0(); +#undef X0 +#undef X +#undef NEXT + mpi_add (ctx->c, ctx->s[0], ctx->s[1]); + mpi_add (ctx->c, ctx->c, ctx->s[1]); + mpi_add (ctx->c, ctx->c, ctx->s[2]); + mpi_add (ctx->c, ctx->c, ctx->s[3]); + mpi_add (ctx->c, ctx->c, ctx->s[4]); + mpi_add (ctx->c, ctx->c, ctx->s[5]); + mpi_add (ctx->c, ctx->c, ctx->s[6]); + mpi_sub (ctx->c, ctx->c, ctx->s[7]); + mpi_sub (ctx->c, ctx->c, ctx->s[8]); + mpi_sub (ctx->c, ctx->c, ctx->s[9]); + + while ( mpi_cmp (ctx->c, ctx->p ) >= 0 ) + mpi_sub ( ctx->c, ctx->c, ctx->p ); + while ( ctx->c->sign ) + mpi_add ( ctx->c, ctx->c, ctx->p ); + mpi_set (w, ctx->c); + } + else +#endif /*0*/ + mpi_mulm (w, u, v, ctx->p); +} + +static void +ec_powm (gcry_mpi_t w, const gcry_mpi_t b, const gcry_mpi_t e, + mpi_ec_t ctx) +{ + mpi_powm (w, b, e, ctx->p); +} + +static void +ec_invm (gcry_mpi_t x, gcry_mpi_t a, mpi_ec_t ctx) +{ + mpi_invm (x, a, ctx->p); +} + + + +/* This function returns a new context for elliptic curve based on the + field GF(p). P is the prime specifying thuis field, A is the first + coefficient. + + This context needs to be released using _gcry_mpi_ec_free. */ +mpi_ec_t +_gcry_mpi_ec_init (gcry_mpi_t p, gcry_mpi_t a) +{ + int i; + mpi_ec_t ctx; + gcry_mpi_t tmp; + + mpi_normalize (p); + mpi_normalize (a); + + /* Fixme: Do we want to check some constraints? e.g. + a < p + */ + + ctx = gcry_xcalloc (1, sizeof *ctx); + + ctx->p = mpi_copy (p); + ctx->a = mpi_copy (a); + + tmp = mpi_alloc_like (ctx->p); + mpi_sub_ui (tmp, ctx->p, 3); + ctx->a_is_pminus3 = !mpi_cmp (ctx->a, tmp); + mpi_free (tmp); + + + /* Allocate constants. */ + ctx->one = mpi_alloc_set_ui (1); + ctx->two = mpi_alloc_set_ui (2); + ctx->three = mpi_alloc_set_ui (3); + ctx->four = mpi_alloc_set_ui (4); + ctx->eight = mpi_alloc_set_ui (8); + ctx->two_inv_p = mpi_alloc (0); + ec_invm (ctx->two_inv_p, ctx->two, ctx); + + /* Allocate scratch variables. */ + for (i=0; i< DIM(ctx->scratch); i++) + ctx->scratch[i] = mpi_alloc_like (ctx->p); + + /* Prepare for fast reduction. */ + /* FIXME: need a test for NIST values. However it does not gain us + any real advantage, for 384 bits it is actually slower than using + mpi_mulm. */ +/* ctx->nist_nbits = mpi_get_nbits (ctx->p); */ +/* if (ctx->nist_nbits == 192) */ +/* { */ +/* for (i=0; i < 4; i++) */ +/* ctx->s[i] = mpi_new (192); */ +/* ctx->c = mpi_new (192*2); */ +/* } */ +/* else if (ctx->nist_nbits == 384) */ +/* { */ +/* for (i=0; i < 10; i++) */ +/* ctx->s[i] = mpi_new (384); */ +/* ctx->c = mpi_new (384*2); */ +/* } */ + + return ctx; +} + +void +_gcry_mpi_ec_free (mpi_ec_t ctx) +{ + int i; + + if (!ctx) + return; + + mpi_free (ctx->p); + mpi_free (ctx->a); + + mpi_free (ctx->one); + mpi_free (ctx->two); + mpi_free (ctx->three); + mpi_free (ctx->four); + mpi_free (ctx->eight); + + mpi_free (ctx->two_inv_p); + + for (i=0; i< DIM(ctx->scratch); i++) + mpi_free (ctx->scratch[i]); + +/* if (ctx->nist_nbits == 192) */ +/* { */ +/* for (i=0; i < 4; i++) */ +/* mpi_free (ctx->s[i]); */ +/* mpi_free (ctx->c); */ +/* } */ +/* else if (ctx->nist_nbits == 384) */ +/* { */ +/* for (i=0; i < 10; i++) */ +/* mpi_free (ctx->s[i]); */ +/* mpi_free (ctx->c); */ +/* } */ + + gcry_free (ctx); +} + +/* Compute the affine coordinates from the projective coordinates in + POINT. Set them into X and Y. If one coordinate is not required, + X or Y may be passed as NULL. CTX is the usual context. Returns: 0 + on success or !0 if POINT is at infinity. */ +int +_gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t *point, + mpi_ec_t ctx) +{ + gcry_mpi_t z1, z2, z3; + + if (!mpi_cmp_ui (point->z, 0)) + return -1; + + z1 = mpi_new (0); + z2 = mpi_new (0); + ec_invm (z1, point->z, ctx); /* z1 = z^(-1) mod p */ + ec_mulm (z2, z1, z1, ctx); /* z2 = z^(-2) mod p */ + + if (x) + ec_mulm (x, point->x, z2, ctx); + + if (y) + { + z3 = mpi_new (0); + ec_mulm (z3, z2, z1, ctx); /* z3 = z^(-3) mod p */ + ec_mulm (y, point->y, z3, ctx); + mpi_free (z3); + } + + mpi_free (z2); + mpi_free (z1); + return 0; +} + + + + + +/* RESULT = 2 * POINT */ +void +_gcry_mpi_ec_dup_point (mpi_point_t *result, mpi_point_t *point, mpi_ec_t ctx) +{ +#define x3 (result->x) +#define y3 (result->y) +#define z3 (result->z) +#define t1 (ctx->scratch[0]) +#define t2 (ctx->scratch[1]) +#define t3 (ctx->scratch[2]) +#define l1 (ctx->scratch[3]) +#define l2 (ctx->scratch[4]) +#define l3 (ctx->scratch[5]) + + if (!mpi_cmp_ui (point->y, 0) || !mpi_cmp_ui (point->z, 0)) + { + /* P_y == 0 || P_z == 0 => [1:1:0] */ + mpi_set_ui (x3, 1); + mpi_set_ui (y3, 1); + mpi_set_ui (z3, 0); + } + else + { + if (ctx->a_is_pminus3) /* Use the faster case. */ + { + /* L1 = 3(X - Z^2)(X + Z^2) */ + /* T1: used for Z^2. */ + /* T2: used for the right term. */ + ec_powm (t1, point->z, ctx->two, ctx); + ec_subm (l1, point->x, t1, ctx); + ec_mulm (l1, l1, ctx->three, ctx); + ec_addm (t2, point->x, t1, ctx); + ec_mulm (l1, l1, t2, ctx); + } + else /* Standard case. */ + { + /* L1 = 3X^2 + aZ^4 */ + /* T1: used for aZ^4. */ + ec_powm (l1, point->x, ctx->two, ctx); + ec_mulm (l1, l1, ctx->three, ctx); + ec_powm (t1, point->z, ctx->four, ctx); + ec_mulm (t1, t1, ctx->a, ctx); + ec_addm (l1, l1, t1, ctx); + } + /* Z3 = 2YZ */ + ec_mulm (z3, point->y, point->z, ctx); + ec_mulm (z3, z3, ctx->two, ctx); + + /* L2 = 4XY^2 */ + /* T2: used for Y2; required later. */ + ec_powm (t2, point->y, ctx->two, ctx); + ec_mulm (l2, t2, point->x, ctx); + ec_mulm (l2, l2, ctx->four, ctx); + + /* X3 = L1^2 - 2L2 */ + /* T1: used for L2^2. */ + ec_powm (x3, l1, ctx->two, ctx); + ec_mulm (t1, l2, ctx->two, ctx); + ec_subm (x3, x3, t1, ctx); + + /* L3 = 8Y^4 */ + /* T2: taken from above. */ + ec_powm (t2, t2, ctx->two, ctx); + ec_mulm (l3, t2, ctx->eight, ctx); + + /* Y3 = L1(L2 - X3) - L3 */ + ec_subm (y3, l2, x3, ctx); + ec_mulm (y3, y3, l1, ctx); + ec_subm (y3, y3, l3, ctx); + } + +#undef x3 +#undef y3 +#undef z3 +#undef t1 +#undef t2 +#undef t3 +#undef l1 +#undef l2 +#undef l3 +} + + + +/* RESULT = P1 + P2 */ +void +_gcry_mpi_ec_add_points (mpi_point_t *result, + mpi_point_t *p1, mpi_point_t *p2, + mpi_ec_t ctx) +{ +#define x1 (p1->x ) +#define y1 (p1->y ) +#define z1 (p1->z ) +#define x2 (p2->x ) +#define y2 (p2->y ) +#define z2 (p2->z ) +#define x3 (result->x) +#define y3 (result->y) +#define z3 (result->z) +#define l1 (ctx->scratch[0]) +#define l2 (ctx->scratch[1]) +#define l3 (ctx->scratch[2]) +#define l4 (ctx->scratch[3]) +#define l5 (ctx->scratch[4]) +#define l6 (ctx->scratch[5]) +#define l7 (ctx->scratch[6]) +#define l8 (ctx->scratch[7]) +#define l9 (ctx->scratch[8]) +#define t1 (ctx->scratch[9]) +#define t2 (ctx->scratch[10]) + + if ( (!mpi_cmp (x1, x2)) && (!mpi_cmp (y1, y2)) && (!mpi_cmp (z1, z2)) ) + { + /* Same point; need to call the duplicate function. */ + _gcry_mpi_ec_dup_point (result, p1, ctx); + } + else if (!mpi_cmp_ui (z1, 0)) + { + /* P1 is at infinity. */ + mpi_set (x3, p2->x); + mpi_set (y3, p2->y); + mpi_set (z3, p2->z); + } + else if (!mpi_cmp_ui (z2, 0)) + { + /* P2 is at infinity. */ + mpi_set (x3, p1->x); + mpi_set (y3, p1->y); + mpi_set (z3, p1->z); + } + else + { + int z1_is_one = !mpi_cmp_ui (z1, 1); + int z2_is_one = !mpi_cmp_ui (z2, 1); + + /* l1 = x1 z2^2 */ + /* l2 = x2 z1^2 */ + if (z2_is_one) + mpi_set (l1, x1); + else + { + ec_powm (l1, z2, ctx->two, ctx); + ec_mulm (l1, l1, x1, ctx); + } + if (z1_is_one) + mpi_set (l2, x2); + else + { + ec_powm (l2, z1, ctx->two, ctx); + ec_mulm (l2, l2, x2, ctx); + } + /* l3 = l1 - l2 */ + ec_subm (l3, l1, l2, ctx); + /* l4 = y1 z2^3 */ + ec_powm (l4, z2, ctx->three, ctx); + ec_mulm (l4, l4, y1, ctx); + /* l5 = y2 z1^3 */ + ec_powm (l5, z1, ctx->three, ctx); + ec_mulm (l5, l5, y2, ctx); + /* l6 = l4 - l5 */ + ec_subm (l6, l4, l5, ctx); + + if (!mpi_cmp_ui (l3, 0)) + { + if (!mpi_cmp_ui (l6, 0)) + { + /* P1 and P2 are the same - use duplicate function. */ + _gcry_mpi_ec_dup_point (result, p1, ctx); + } + else + { + /* P1 is the inverse of P2. */ + mpi_set_ui (x3, 1); + mpi_set_ui (y3, 1); + mpi_set_ui (z3, 0); + } + } + else + { + /* l7 = l1 + l2 */ + ec_addm (l7, l1, l2, ctx); + /* l8 = l4 + l5 */ + ec_addm (l8, l4, l5, ctx); + /* z3 = z1 z2 l3 */ + ec_mulm (z3, z1, z2, ctx); + ec_mulm (z3, z3, l3, ctx); + /* x3 = l6^2 - l7 l3^2 */ + ec_powm (t1, l6, ctx->two, ctx); + ec_powm (t2, l3, ctx->two, ctx); + ec_mulm (t2, t2, l7, ctx); + ec_subm (x3, t1, t2, ctx); + /* l9 = l7 l3^2 - 2 x3 */ + ec_mulm (t1, x3, ctx->two, ctx); + ec_subm (l9, t2, t1, ctx); + /* y3 = (l9 l6 - l8 l3^3)/2 */ + ec_mulm (l9, l9, l6, ctx); + ec_powm (t1, l3, ctx->three, ctx); /* fixme: Use saved value*/ + ec_mulm (t1, t1, l8, ctx); + ec_subm (y3, l9, t1, ctx); + ec_mulm (y3, y3, ctx->two_inv_p, ctx); + } + } + +#undef x1 +#undef y1 +#undef z1 +#undef x2 +#undef y2 +#undef z2 +#undef x3 +#undef y3 +#undef z3 +#undef l1 +#undef l2 +#undef l3 +#undef l4 +#undef l5 +#undef l6 +#undef l7 +#undef l8 +#undef l9 +#undef t1 +#undef t2 +} + + + +/* Scalar point multiplication - the main function for ECC. If takes + an integer SCALAR and a POINT as well as the usual context CTX. + RESULT will be set to the resulting point. */ +void +_gcry_mpi_ec_mul_point (mpi_point_t *result, + gcry_mpi_t scalar, mpi_point_t *point, + mpi_ec_t ctx) +{ +#if 0 + /* Simple left to right binary method. GECC Algorithm 3.27 */ + unsigned int nbits; + int i; + + nbits = mpi_get_nbits (scalar); + mpi_set_ui (result->x, 1); + mpi_set_ui (result->y, 1); + mpi_set_ui (result->z, 0); + + for (i=nbits-1; i >= 0; i--) + { + _gcry_mpi_ec_dup_point (result, result, ctx); + if (mpi_test_bit (scalar, i) == 1) + _gcry_mpi_ec_add_points (result, result, point, ctx); + } + +#else + gcry_mpi_t x1, y1, z1, k, h, yy; + unsigned int i, loops; + mpi_point_t p1, p2, p1inv; + + x1 = mpi_alloc_like (ctx->p); + y1 = mpi_alloc_like (ctx->p); + h = mpi_alloc_like (ctx->p); + k = mpi_copy (scalar); + yy = mpi_copy (point->y); + + if ( mpi_is_neg (k) ) + { + k->sign = 0; + ec_invm (yy, yy, ctx); + } + + if (!mpi_cmp_ui (point->z, 1)) + { + mpi_set (x1, point->x); + mpi_set (y1, yy); + } + else + { + gcry_mpi_t z2, z3; + + z2 = mpi_alloc_like (ctx->p); + z3 = mpi_alloc_like (ctx->p); + ec_mulm (z2, point->z, point->z, ctx); + ec_mulm (z3, point->z, z2, ctx); + ec_invm (z2, z2, ctx); + ec_mulm (x1, point->x, z2, ctx); + ec_invm (z3, z3, ctx); + ec_mulm (y1, yy, z3, ctx); + mpi_free (z2); + mpi_free (z3); + } + z1 = mpi_copy (ctx->one); + + mpi_mul (h, k, ctx->three); /* h = 3k */ + loops = mpi_get_nbits (h); + if (loops < 2) + { + /* If SCALAR is zero, the above mpi_mul sets H to zero and thus + LOOPs will be zero. To avoid an underflow of I in the main + loop we set LOOP to 2 and the result to (0,0,0). */ + loops = 2; + mpi_clear (result->x); + mpi_clear (result->y); + mpi_clear (result->z); + } + else + { + mpi_set (result->x, point->x); + mpi_set (result->y, yy); + mpi_set (result->z, point->z); + } + mpi_free (yy); yy = NULL; + + p1.x = x1; x1 = NULL; + p1.y = y1; y1 = NULL; + p1.z = z1; z1 = NULL; + point_init (&p2); + point_init (&p1inv); + + for (i=loops-2; i > 0; i--) + { + _gcry_mpi_ec_dup_point (result, result, ctx); + if (mpi_test_bit (h, i) == 1 && mpi_test_bit (k, i) == 0) + { + point_set (&p2, result); + _gcry_mpi_ec_add_points (result, &p2, &p1, ctx); + } + if (mpi_test_bit (h, i) == 0 && mpi_test_bit (k, i) == 1) + { + point_set (&p2, result); + /* Invert point: y = p - y mod p */ + point_set (&p1inv, &p1); + ec_subm (p1inv.y, ctx->p, p1inv.y, ctx); + _gcry_mpi_ec_add_points (result, &p2, &p1inv, ctx); + } + } + + point_free (&p1); + point_free (&p2); + point_free (&p1inv); + mpi_free (h); + mpi_free (k); +#endif +} diff --git a/grub-core/lib/libgcrypt/mpi/generic/Manifest b/grub-core/lib/libgcrypt/mpi/generic/Manifest new file mode 100644 index 0000000..c429fde --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/generic/Manifest @@ -0,0 +1,29 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +mpih-add1.c iQCVAwUAP+Lj2DEAnp832S/7AQKn/AQAwQLWggl6zNQ5EZ+lE+jKV8W3FsogW3/6tp9T5rrSR5JnlWyoHQ9/Pu4knOcLjS6nIfVOiAEifu3nuIysQr9jDSSSJA2LylSUBSXKLKDamPsOCwXOLxiZODslJT3CCGAUtLvXJrWDbTZQrkEuwnLnjQFDzuA7iY9JLrG9kAoXD6Q==WoWm +mpih-mul1.c iQCVAwUAP+LkCTEAnp832S/7AQKFVQP+MhBNjcY73JtnsHZfnaVZq3TiKwN151cWV51nDc1RnTaMhSIFeuNlj3vNML2W0Gn8n+GnyiWE2XXdQEaik6BL02eekUn9aq7I/rdpnTHuOjQPK1uwjuNl8RuJ9YrERBAxq4oB71f+iwMab8dsMSUlVC+NdeAocRqLLgnR/efkdLc==2Tkb +mpih-mul2.c iQCVAwUAP+LkMjEAnp832S/7AQLPeAQAqmRzxFe/mDqTdZr/pTXT8RVyB1vKB0Ei2THV05BxmI4OPv39uysfFpLMt/INsX7AGqdOlj4jOZ/qNaFXR1ceMrlSXvo8u/epk6rCXFp82kM7Qs983LjoP//PrMCkYkXwblaVrgUGiBUCbuPMliWTK6qKkxxXtEfqZ7nVbEWdBx8==Kwhl +mpih-mul3.c iQCVAwUAP+LkVDEAnp832S/7AQL91gP/Qd5iZWxRiN5DdEIVHAedoNvl23NPrT2UUdXvnSK49DpplTxkLiMBj0WqCayG/YIET2NpMRCeLvAZNcSt6lOm0bSZDYo1Hv/N+UoqD3V1McjY16REBv/nnPaMWMZcx7rl5yKTVZiX2PgV6oQOL7Yfrt5ZIOlrHBRs9S2/zcCaVz0==9BQe +mpih-lshift.c iQCVAwUAP+LlATEAnp832S/7AQIACAQAhMrpx0SRXE/LN1NkjMO9n74nMrvmzYJyru0gw2O4BYrUPvD/LWGju2FZaggKV0IBjmi0cDoCrNeK9EGjKOO1lfgODbX2IZ1LUhr9jDuMj0QRqj6T9YkAFYTNUk4GfpwIf7T6Ybo7c78Jx93PidCJt7d39eMMEalooC7LZ4IU3NM==nZ4k +mpih-rshift.c iQCVAwUAP+LlIjEAnp832S/7AQKiuAP/eYC2ZScd+taBx/kNzRvGjA0eAXvORMkMLV6Ot+OXVzVUi04eoP2yXdxSNFKwUj12p8GWXkdoMG3aOGBKg2a7bY5Q5RUho3hUWb9UsVYVUfXLf7IOTt/3a6MLh2CmV5dFPWJmSlbCyQRcn6n/fLDeJ3A2bWTS/BhqGfpOXUIU1ws==jCf8 +mpih-sub1.c iQCVAwUAP+LlZzEAnp832S/7AQIEPgP/dLHTDRbPrYJhsLp9SjGstU1M8/IC5XytcDtO3NQeu4mx6vaXjpujtsTvKIbX4QL5IahNntVVKv1xFLEm2yFg7L2ns0uD/mfwGgOhCG1j2o/SaTAWP5KxP7ae5UDcZl2w6NWvEuMj9t32zmziAZjP8W73A37FUspeRDYiL9sQzkI==QQzk +udiv-w-sdiv.c iQCVAwUAP+Lk0TEAnp832S/7AQICXAQAsxe1SQD4+xZaZTqBC0V9Cyuo0mrdccnRFzthOtm0ARwKFXU2cuLW/ZBOkmeWOVmOFhBp22/I8dEGYnMA3gcfmOMCpNu9i9zk/XHfptdunA1MnOe3GsoWgfHL0rhpAyPhp/X043ICB41NElnnuxADuQQlD4Z1fca5ygYxMr2crJg==EI/6 +mpi-asm-defs.h iQCVAwUAP+LkgDEAnp832S/7AQK0FgQAxJZ7xvXhoZa33GWe23LRb3asrno/loZSyAIXrntqtVH8M3pEsCY0OyW4ry4hX2RnxpuhRCM/PdRNLG3xXyMSVIhkHU8WVRLqzF2LLjEkyU3cAmHnnTQ9aO/XpUWtJGTZ8q2bv7ZsAEi4aPl0p6KhPXcPgM9vQ2XcyOPn3Dl0d6Q==xpjI +$names$ iQCVAwUAP+LmNDEAnp832S/7AQJa+gP+KQNJpbNOgc+s2UX+Ya2gDaOFcAROImIllhg3ej8EaBF8xxdHmWT1zaKwTwi3moEEleykMR104YAGWyQeMbFYiuPPBW+ohrT6KxRBVJpIA9auOOqqJMyglZyoR3Hv7gduVYUW1h/DebnqiKXKEfzQDFqYuT0ayuteoOR4B5NICbE==nLSh diff --git a/grub-core/lib/libgcrypt/mpi/generic/distfiles b/grub-core/lib/libgcrypt/mpi/generic/distfiles new file mode 100644 index 0000000..9810eef --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/generic/distfiles @@ -0,0 +1,11 @@ +Manifest +mpih-add1.c +mpih-mul1.c +mpih-mul2.c +mpih-mul3.c +mpih-lshift.c +mpih-rshift.c +mpih-sub1.c +udiv-w-sdiv.c +mpi-asm-defs.h + diff --git a/grub-core/lib/libgcrypt/mpi/generic/mpi-asm-defs.h b/grub-core/lib/libgcrypt/mpi/generic/mpi-asm-defs.h new file mode 100644 index 0000000..13424e2 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/generic/mpi-asm-defs.h @@ -0,0 +1,10 @@ +/* This file defines some basic constants for the MPI machinery. We + * need to define the types on a per-CPU basis, so it is done with + * this file here. */ +#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG) + + + + + + diff --git a/grub-core/lib/libgcrypt/mpi/generic/mpih-add1.c b/grub-core/lib/libgcrypt/mpi/generic/mpih-add1.c new file mode 100644 index 0000000..4a84df6 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/generic/mpih-add1.c @@ -0,0 +1,65 @@ +/* mpihelp-add_1.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, + * 2000, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +_gcry_mpih_add_n (mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size) +{ + mpi_limb_t x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to one addend */ + cy = y < cy; /* get out carry from that addition */ + y += x; /* add other addend */ + cy += y < x; /* get out carry from that add, combine */ + res_ptr[j] = y; + } + while ( ++j ); + + return cy; +} + diff --git a/grub-core/lib/libgcrypt/mpi/generic/mpih-lshift.c b/grub-core/lib/libgcrypt/mpi/generic/mpih-lshift.c new file mode 100644 index 0000000..f48c12c --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/generic/mpih-lshift.c @@ -0,0 +1,68 @@ +/* mpi-lshift.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + +/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left + * and store the USIZE least significant digits of the result at WP. + * Return the bits shifted out from the most significant digit. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be >= UP. + */ + +mpi_limb_t +_gcry_mpih_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned int cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp += 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + i = usize - 1; + low_limb = up[i]; + retval = low_limb >> sh_2; + high_limb = low_limb; + while ( --i >= 0 ) + { + low_limb = up[i]; + wp[i] = (high_limb << sh_1) | (low_limb >> sh_2); + high_limb = low_limb; + } + wp[i] = high_limb << sh_1; + + return retval; +} + + diff --git a/grub-core/lib/libgcrypt/mpi/generic/mpih-mul1.c b/grub-core/lib/libgcrypt/mpi/generic/mpih-mul1.c new file mode 100644 index 0000000..0e8197d --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/generic/mpih-mul1.c @@ -0,0 +1,62 @@ +/* mpihelp-mul_1.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +_gcry_mpih_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + + /* The loop counter and index J goes from -S1_SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + res_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + res_ptr[j] = prod_low; + } + while( ++j ); + + return cy_limb; +} + diff --git a/grub-core/lib/libgcrypt/mpi/generic/mpih-mul2.c b/grub-core/lib/libgcrypt/mpi/generic/mpih-mul2.c new file mode 100644 index 0000000..3b75496 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/generic/mpih-mul2.c @@ -0,0 +1,68 @@ +/* mpih-mul2.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +mpi_limb_t +_gcry_mpih_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x + prod_low; + cy_limb += prod_low < x?1:0; + res_ptr[j] = prod_low; + } + while ( ++j ); + + return cy_limb; +} + + diff --git a/grub-core/lib/libgcrypt/mpi/generic/mpih-mul3.c b/grub-core/lib/libgcrypt/mpi/generic/mpih-mul3.c new file mode 100644 index 0000000..5e84f94 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/generic/mpih-mul3.c @@ -0,0 +1,68 @@ +/* mpih-mul3.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +mpi_limb_t +_gcry_mpih_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do + { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x - prod_low; + cy_limb += prod_low > x?1:0; + res_ptr[j] = prod_low; + } + while( ++j ); + + return cy_limb; +} + + diff --git a/grub-core/lib/libgcrypt/mpi/generic/mpih-rshift.c b/grub-core/lib/libgcrypt/mpi/generic/mpih-rshift.c new file mode 100644 index 0000000..e40794f --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/generic/mpih-rshift.c @@ -0,0 +1,67 @@ +/* mpih-rshift.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 1999, + * 2000, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + + +/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right + * and store the USIZE least significant limbs of the result at WP. + * The bits shifted out to the right are returned. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be <= UP. + */ + +mpi_limb_t +_gcry_mpih_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp -= 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + high_limb = up[0]; + retval = high_limb << sh_2; + low_limb = high_limb; + for (i=1; i < usize; i++) + { + high_limb = up[i]; + wp[i] = (low_limb >> sh_1) | (high_limb << sh_2); + low_limb = high_limb; + } + wp[i] = low_limb >> sh_1; + + return retval; +} + diff --git a/grub-core/lib/libgcrypt/mpi/generic/mpih-sub1.c b/grub-core/lib/libgcrypt/mpi/generic/mpih-sub1.c new file mode 100644 index 0000000..e88821b --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/generic/mpih-sub1.c @@ -0,0 +1,66 @@ +/* mpihelp-add_2.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +_gcry_mpih_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size) +{ + mpi_limb_t x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do + { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to subtrahend */ + cy = y < cy; /* get out carry from that addition */ + y = x - y; /* main subtract */ + cy += y > x; /* get out carry from the subtract, combine */ + res_ptr[j] = y; + } + while( ++j ); + + return cy; +} + + diff --git a/grub-core/lib/libgcrypt/mpi/generic/udiv-w-sdiv.c b/grub-core/lib/libgcrypt/mpi/generic/udiv-w-sdiv.c new file mode 100644 index 0000000..e80d98b --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/generic/udiv-w-sdiv.c @@ -0,0 +1,133 @@ +/* mpih-w-sdiv -- implement udiv_qrnnd on machines with only signed + * division. + * Copyright (C) 1992, 1994, 1996, 1998, 2002 Free Software Foundation, Inc. + * Contributed by Peter L. Montgomery. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +#if 0 /* not yet ported to MPI */ + +mpi_limb_t +mpihelp_udiv_w_sdiv( mpi_limp_t *rp, + mpi_limp_t *a1, + mpi_limp_t *a0, + mpi_limp_t *d ) +{ + mp_limb_t q, r; + mp_limb_t c0, c1, b1; + + if ((mpi_limb_signed_t) d >= 0) + { + if (a1 < d - a1 - (a0 >> (BITS_PER_MP_LIMB - 1))) + { + /* dividend, divisor, and quotient are nonnegative */ + sdiv_qrnnd (q, r, a1, a0, d); + } + else + { + /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ + sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (BITS_PER_MP_LIMB - 1)); + /* Divide (c1*2^32 + c0) by d */ + sdiv_qrnnd (q, r, c1, c0, d); + /* Add 2^31 to quotient */ + q += (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1); + } + } + else + { + b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */ + c1 = a1 >> 1; /* A/2 */ + c0 = (a1 << (BITS_PER_MP_LIMB - 1)) + (a0 >> 1); + + if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */ + { + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */ + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */ + { + c1 = (b1 - 1) - c1; + c0 = ~c0; /* logical NOT */ + + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + q = ~q; /* (A/2)/b1 */ + r = (b1 - 1) - r; + + r = 2*r + (a0 & 1); /* A/(2*b1) */ + + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else /* Implies c1 = b1 */ + { /* Hence a1 = d - 1 = 2*b1 - 1 */ + if (a0 >= -d) + { + q = -1; + r = a0 + d; + } + else + { + q = -2; + r = a0 + 2*d; + } + } + } + + *rp = r; + return q; +} + +#endif + diff --git a/grub-core/lib/libgcrypt/mpi/hppa/README b/grub-core/lib/libgcrypt/mpi/hppa/README new file mode 100644 index 0000000..5a2d5fd --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/hppa/README @@ -0,0 +1,84 @@ +This directory contains mpn functions for various HP PA-RISC chips. Code +that runs faster on the PA7100 and later implementations, is in the pa7100 +directory. + +RELEVANT OPTIMIZATION ISSUES + + Load and Store timing + +On the PA7000 no memory instructions can issue the two cycles after a store. +For the PA7100, this is reduced to one cycle. + +The PA7100 has a lookup-free cache, so it helps to schedule loads and the +dependent instruction really far from each other. + +STATUS + +1. mpn_mul_1 could be improved to 6.5 cycles/limb on the PA7100, using the + instructions bwlow (but some sw pipelining is needed to avoid the + xmpyu-fstds delay): + + fldds s1_ptr + + xmpyu + fstds N(%r30) + xmpyu + fstds N(%r30) + + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + + addc + stws res_ptr + addc + stws res_ptr + + addib Loop + +2. mpn_addmul_1 could be improved from the current 10 to 7.5 cycles/limb + (asymptotically) on the PA7100, using the instructions below. With proper + sw pipelining and the unrolling level below, the speed becomes 8 + cycles/limb. + + fldds s1_ptr + fldds s1_ptr + + xmpyu + fstds N(%r30) + xmpyu + fstds N(%r30) + xmpyu + fstds N(%r30) + xmpyu + fstds N(%r30) + + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + addc + addc + addc + addc + addc %r0,%r0,cy-limb + + ldws res_ptr + ldws res_ptr + ldws res_ptr + ldws res_ptr + add + stws res_ptr + addc + stws res_ptr + addc + stws res_ptr + addc + stws res_ptr + + addib diff --git a/grub-core/lib/libgcrypt/mpi/hppa/distfiles b/grub-core/lib/libgcrypt/mpi/hppa/distfiles new file mode 100644 index 0000000..7f24205 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/hppa/distfiles @@ -0,0 +1,7 @@ +README +udiv-qrnnd.S +mpih-add1.S +mpih-sub1.S +mpih-lshift.S +mpih-rshift.S + diff --git a/grub-core/lib/libgcrypt/mpi/hppa/mpih-add1.S b/grub-core/lib/libgcrypt/mpi/hppa/mpih-add1.S new file mode 100644 index 0000000..3bc0e5e --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/hppa/mpih-add1.S @@ -0,0 +1,70 @@ +/* hppa add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Fee Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + + +/******************* + * mpi_limb_t + * _gcry_mpih_add_n( mpi_ptr_t res_ptr, (gr26) + * mpi_ptr_t s1_ptr, (gr25) + * mpi_ptr_t s2_ptr, (gr24) + * mpi_size_t size) (gr23) + * + * One might want to unroll this as for other processors, but it turns + * out that the data cache contention after a store makes such + * unrolling useless. We can't come under 5 cycles/limb anyway. + */ + + .code + .export _gcry_mpih_add_n + .label _gcry_mpih_add_n + .proc + .callinfo frame=0,no_calls + .entry + + ldws,ma 4(0,%r25),%r20 + ldws,ma 4(0,%r24),%r19 + + addib,= -1,%r23,L$end ; check for (SIZE == 1) + add %r20,%r19,%r28 ; add first limbs ignoring cy + + .label L$loop + ldws,ma 4(0,%r25),%r20 + ldws,ma 4(0,%r24),%r19 + stws,ma %r28,4(0,%r26) + addib,<> -1,%r23,L$loop + addc %r20,%r19,%r28 + + .label L$end + stws %r28,0(0,%r26) + bv 0(%r2) + addc %r0,%r0,%r28 + + .exit + .procend diff --git a/grub-core/lib/libgcrypt/mpi/hppa/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/hppa/mpih-lshift.S new file mode 100644 index 0000000..91b29bb --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/hppa/mpih-lshift.S @@ -0,0 +1,77 @@ +/* hppa lshift + * + * Copyright (C) 1992, 1994, 1998 + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + +/******************* + * mpi_limb_t + * _gcry_mpih_lshift( mpi_ptr_t wp, (gr26) + * mpi_ptr_t up, (gr25) + * mpi_size_t usize, (gr24) + * unsigned cnt) (gr23) + */ + + .code + .export _gcry_mpih_lshift + .label _gcry_mpih_lshift + .proc + .callinfo frame=64,no_calls + .entry + + sh2add %r24,%r25,%r25 + sh2add %r24,%r26,%r26 + ldws,mb -4(0,%r25),%r22 + subi 32,%r23,%r1 + mtsar %r1 + addib,= -1,%r24,L$0004 + vshd %r0,%r22,%r28 ; compute carry out limb + ldws,mb -4(0,%r25),%r29 + addib,= -1,%r24,L$0002 + vshd %r22,%r29,%r20 + + .label L$loop + ldws,mb -4(0,%r25),%r22 + stws,mb %r20,-4(0,%r26) + addib,= -1,%r24,L$0003 + vshd %r29,%r22,%r20 + ldws,mb -4(0,%r25),%r29 + stws,mb %r20,-4(0,%r26) + addib,<> -1,%r24,L$loop + vshd %r22,%r29,%r20 + + .label L$0002 + stws,mb %r20,-4(0,%r26) + vshd %r29,%r0,%r20 + bv 0(%r2) + stw %r20,-4(0,%r26) + .label L$0003 + stws,mb %r20,-4(0,%r26) + .label L$0004 + vshd %r22,%r0,%r20 + bv 0(%r2) + stw %r20,-4(0,%r26) + + .exit + .procend + + + diff --git a/grub-core/lib/libgcrypt/mpi/hppa/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/hppa/mpih-rshift.S new file mode 100644 index 0000000..37a9d4e --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/hppa/mpih-rshift.S @@ -0,0 +1,73 @@ +/* hppa rshift + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + + +/******************* + * mpi_limb_t + * _gcry_mpih_rshift( mpi_ptr_t wp, (gr26) + * mpi_ptr_t up, (gr25) + * mpi_size_t usize, (gr24) + * unsigned cnt) (gr23) + */ + + .code + .export _gcry_mpih_rshift + .label _gcry_mpih_rshift + .proc + .callinfo frame=64,no_calls + .entry + + ldws,ma 4(0,%r25),%r22 + mtsar %r23 + addib,= -1,%r24,L$r004 + vshd %r22,%r0,%r28 ; compute carry out limb + ldws,ma 4(0,%r25),%r29 + addib,= -1,%r24,L$r002 + vshd %r29,%r22,%r20 + + .label L$roop + ldws,ma 4(0,%r25),%r22 + stws,ma %r20,4(0,%r26) + addib,= -1,%r24,L$r003 + vshd %r22,%r29,%r20 + ldws,ma 4(0,%r25),%r29 + stws,ma %r20,4(0,%r26) + addib,<> -1,%r24,L$roop + vshd %r29,%r22,%r20 + + .label L$r002 + stws,ma %r20,4(0,%r26) + vshd %r0,%r29,%r20 + bv 0(%r2) + stw %r20,0(0,%r26) + .label L$r003 + stws,ma %r20,4(0,%r26) + .label L$r004 + vshd %r0,%r22,%r20 + bv 0(%r2) + stw %r20,0(0,%r26) + + .exit + .procend + diff --git a/grub-core/lib/libgcrypt/mpi/hppa/mpih-sub1.S b/grub-core/lib/libgcrypt/mpi/hppa/mpih-sub1.S new file mode 100644 index 0000000..8d197e4 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/hppa/mpih-sub1.S @@ -0,0 +1,78 @@ +/* hppa sub_n -- Sub two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_sub_n( mpi_ptr_t res_ptr, (gr26) + * mpi_ptr_t s1_ptr, (gr25) + * mpi_ptr_t s2_ptr, (gr24) + * mpi_size_t size) (gr23) + * + * One might want to unroll this as for other processors, but it turns + * out that the data cache contention after a store makes such + * unrolling useless. We can't come under 5 cycles/limb anyway. + */ + + + .code + .export _gcry_mpih_sub_n + .label _gcry_mpih_sub_n + .proc + .callinfo frame=0,no_calls + .entry + + ldws,ma 4(0,%r25),%r20 + ldws,ma 4(0,%r24),%r19 + + addib,= -1,%r23,L$end ; check for (SIZE == 1) + sub %r20,%r19,%r28 ; subtract first limbs ignoring cy + + .label L$loop + ldws,ma 4(0,%r25),%r20 + ldws,ma 4(0,%r24),%r19 + stws,ma %r28,4(0,%r26) + addib,<> -1,%r23,L$loop + subb %r20,%r19,%r28 + + .label L$end + stws %r28,0(0,%r26) + addc %r0,%r0,%r28 + bv 0(%r2) + subi 1,%r28,%r28 + + .exit + .procend + + + diff --git a/grub-core/lib/libgcrypt/mpi/hppa/udiv-qrnnd.S b/grub-core/lib/libgcrypt/mpi/hppa/udiv-qrnnd.S new file mode 100644 index 0000000..59ebf7a --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/hppa/udiv-qrnnd.S @@ -0,0 +1,297 @@ +/* HP-PA __udiv_qrnnd division support, used from longlong.h. + * This version runs fast on pre-PA7000 CPUs. + * + * Copyright (C) 1993, 1994, 1998, 2001, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + + +/* INPUT PARAMETERS + * rem_ptr gr26 + * n1 gr25 + * n0 gr24 + * d gr23 + * + * The code size is a bit excessive. We could merge the last two ds;addc + * sequences by simply moving the "bb,< Odd" instruction down. The only + * trouble is the FFFFFFFF code that would need some hacking. + */ + + .code + .export __udiv_qrnnd + .label __udiv_qrnnd + .proc + .callinfo frame=0,no_calls + .entry + + comb,< %r23,0,L$largedivisor + sub %r0,%r23,%r1 ; clear cy as side-effect + ds %r0,%r1,%r0 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r28 + ds %r25,%r23,%r25 + comclr,>= %r25,%r0,%r0 + addl %r25,%r23,%r25 + stws %r25,0(0,%r26) + bv 0(%r2) + addc %r28,%r28,%r28 + + .label L$largedivisor + extru %r24,31,1,%r19 ; r19 = n0 & 1 + bb,< %r23,31,L$odd + extru %r23,30,31,%r22 ; r22 = d >> 1 + shd %r25,%r24,1,%r24 ; r24 = new n0 + extru %r25,30,31,%r25 ; r25 = new n1 + sub %r0,%r22,%r21 + ds %r0,%r21,%r0 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + comclr,>= %r25,%r0,%r0 + addl %r25,%r22,%r25 + sh1addl %r25,%r19,%r25 + stws %r25,0(0,%r26) + bv 0(%r2) + addc %r24,%r24,%r28 + + .label L$odd + addib,sv,n 1,%r22,L$FF.. ; r22 = (d / 2 + 1) + shd %r25,%r24,1,%r24 ; r24 = new n0 + extru %r25,30,31,%r25 ; r25 = new n1 + sub %r0,%r22,%r21 + ds %r0,%r21,%r0 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r28 + comclr,>= %r25,%r0,%r0 + addl %r25,%r22,%r25 + sh1addl %r25,%r19,%r25 +; We have computed (n1,,n0) / (d + 1), q' = r28, r' = r25 + add,nuv %r28,%r25,%r25 + addl %r25,%r1,%r25 + addc %r0,%r28,%r28 + sub,<< %r25,%r23,%r0 + addl %r25,%r1,%r25 + stws %r25,0(0,%r26) + bv 0(%r2) + addc %r0,%r28,%r28 + +; This is just a special case of the code above. +; We come here when d == 0xFFFFFFFF + .label L$FF.. + add,uv %r25,%r24,%r24 + sub,<< %r24,%r23,%r0 + ldo 1(%r24),%r24 + stws %r24,0(0,%r26) + bv 0(%r2) + addc %r0,%r25,%r28 + + .exit + .procend diff --git a/grub-core/lib/libgcrypt/mpi/i386/Manifest b/grub-core/lib/libgcrypt/mpi/i386/Manifest new file mode 100644 index 0000000..812bc8a --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i386/Manifest @@ -0,0 +1,28 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +mpih-add1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +mpih-sub1.S +syntax.h +$names$ iQCVAwUAP+LmOTEAnp832S/7AQJZmgQA1+GIl7rXiEY00y5xD2kG5Lm2QD6c9aBME8hTl812OEcj0ul/QSpdv8E2NEKooifr4SiLVhEVfLNaLqAgN3cIsttn3rRX3/pMC5JwSKHDJPsUbpN9tzb5dr2YC9GG9m8xngAQrN11IQPnGfvFLJK+oDnEMIAeHDpOnX9NeQPDAQA==bnOy diff --git a/grub-core/lib/libgcrypt/mpi/i386/distfiles b/grub-core/lib/libgcrypt/mpi/i386/distfiles new file mode 100644 index 0000000..22b9979 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i386/distfiles @@ -0,0 +1,10 @@ +Manifest +mpih-add1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +mpih-sub1.S +syntax.h + diff --git a/grub-core/lib/libgcrypt/mpi/i386/mpih-add1.S b/grub-core/lib/libgcrypt/mpi/i386/mpih-add1.S new file mode 100644 index 0000000..652b232 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i386/mpih-add1.S @@ -0,0 +1,116 @@ +/* i80386 add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_add_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(_gcry_mpih_add_n) +C_SYMBOL_NAME(_gcry_mpih_add_n:) + pushl %edi + pushl %esi + + movl 12(%esp),%edi /* res_ptr */ + movl 16(%esp),%esi /* s1_ptr */ + movl 20(%esp),%edx /* s2_ptr */ + movl 24(%esp),%ecx /* size */ + + movl %ecx,%eax + shrl $3,%ecx /* compute count for unrolled loop */ + negl %eax + andl $7,%eax /* get index where to start loop */ + jz Loop /* necessary special case for 0 */ + incl %ecx /* adjust loop count */ + shll $2,%eax /* adjustment for pointers... */ + subl %eax,%edi /* ... since they are offset ... */ + subl %eax,%esi /* ... by a constant when we ... */ + subl %eax,%edx /* ... enter the loop */ + shrl $2,%eax /* restore previous value */ +#ifdef PIC +/* Calculate start address in loop for PIC. Due to limitations in some + assemblers, Loop-L0-3 cannot be put into the leal */ + call L0 +L0: leal (%eax,%eax,8),%eax + addl (%esp),%eax + addl $(Loop-L0-3),%eax + addl $4,%esp +#else +/* Calculate start address in loop for non-PIC. */ + leal (Loop - 3)(%eax,%eax,8),%eax +#endif + jmp *%eax /* jump into loop */ + ALIGN (3) +Loop: movl (%esi),%eax + adcl (%edx),%eax + movl %eax,(%edi) + movl 4(%esi),%eax + adcl 4(%edx),%eax + movl %eax,4(%edi) + movl 8(%esi),%eax + adcl 8(%edx),%eax + movl %eax,8(%edi) + movl 12(%esi),%eax + adcl 12(%edx),%eax + movl %eax,12(%edi) + movl 16(%esi),%eax + adcl 16(%edx),%eax + movl %eax,16(%edi) + movl 20(%esi),%eax + adcl 20(%edx),%eax + movl %eax,20(%edi) + movl 24(%esi),%eax + adcl 24(%edx),%eax + movl %eax,24(%edi) + movl 28(%esi),%eax + adcl 28(%edx),%eax + movl %eax,28(%edi) + leal 32(%edi),%edi + leal 32(%esi),%esi + leal 32(%edx),%edx + decl %ecx + jnz Loop + + sbbl %eax,%eax + negl %eax + + popl %esi + popl %edi + ret + diff --git a/grub-core/lib/libgcrypt/mpi/i386/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/i386/mpih-lshift.S new file mode 100644 index 0000000..bf8ed9d --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i386/mpih-lshift.S @@ -0,0 +1,94 @@ +/* i80386 lshift + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_lshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(_gcry_mpih_lshift) +C_SYMBOL_NAME(_gcry_mpih_lshift:) + pushl %edi + pushl %esi + pushl %ebx + + movl 16(%esp),%edi /* res_ptr */ + movl 20(%esp),%esi /* s_ptr */ + movl 24(%esp),%edx /* size */ + movl 28(%esp),%ecx /* cnt */ + + subl $4,%esi /* adjust s_ptr */ + + movl (%esi,%edx,4),%ebx /* read most significant limb */ + xorl %eax,%eax + shldl %cl,%ebx,%eax /* compute carry limb */ + decl %edx + jz Lend + pushl %eax /* push carry limb onto stack */ + testb $1,%dl + jnz L1 /* enter loop in the middle */ + movl %ebx,%eax + + ALIGN (3) +Loop: movl (%esi,%edx,4),%ebx /* load next lower limb */ + shldl %cl,%ebx,%eax /* compute result limb */ + movl %eax,(%edi,%edx,4) /* store it */ + decl %edx +L1: movl (%esi,%edx,4),%eax + shldl %cl,%eax,%ebx + movl %ebx,(%edi,%edx,4) + decl %edx + jnz Loop + + shll %cl,%eax /* compute least significant limb */ + movl %eax,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebx + popl %esi + popl %edi + ret + +Lend: shll %cl,%ebx /* compute least significant limb */ + movl %ebx,(%edi) /* store it */ + + popl %ebx + popl %esi + popl %edi + ret + diff --git a/grub-core/lib/libgcrypt/mpi/i386/mpih-mul1.S b/grub-core/lib/libgcrypt/mpi/i386/mpih-mul1.S new file mode 100644 index 0000000..c9760ef --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i386/mpih-mul1.S @@ -0,0 +1,84 @@ +/* i80386 mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_mul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(_gcry_mpih_mul_1) +C_SYMBOL_NAME(_gcry_mpih_mul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/grub-core/lib/libgcrypt/mpi/i386/mpih-mul2.S b/grub-core/lib/libgcrypt/mpi/i386/mpih-mul2.S new file mode 100644 index 0000000..9794e11 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i386/mpih-mul2.S @@ -0,0 +1,86 @@ +/* i80386 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(_gcry_mpih_addmul_1) +C_SYMBOL_NAME(_gcry_mpih_addmul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(adc,l ,R(edx),$0) + INSN2(add,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/grub-core/lib/libgcrypt/mpi/i386/mpih-mul3.S b/grub-core/lib/libgcrypt/mpi/i386/mpih-mul3.S new file mode 100644 index 0000000..6df2017 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i386/mpih-mul3.S @@ -0,0 +1,86 @@ +/* i80386 submul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_submul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(_gcry_mpih_submul_1) +C_SYMBOL_NAME(_gcry_mpih_submul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(adc,l ,R(edx),$0) + INSN2(sub,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/grub-core/lib/libgcrypt/mpi/i386/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/i386/mpih-rshift.S new file mode 100644 index 0000000..2920e55 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i386/mpih-rshift.S @@ -0,0 +1,97 @@ +/* i80386 rshift + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_rshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(_gcry_mpih_rshift) +C_SYMBOL_NAME(_gcry_mpih_rshift:) + pushl %edi + pushl %esi + pushl %ebx + + movl 16(%esp),%edi /* wp */ + movl 20(%esp),%esi /* up */ + movl 24(%esp),%edx /* usize */ + movl 28(%esp),%ecx /* cnt */ + + leal -4(%edi,%edx,4),%edi + leal (%esi,%edx,4),%esi + negl %edx + + movl (%esi,%edx,4),%ebx /* read least significant limb */ + xorl %eax,%eax + shrdl %cl,%ebx,%eax /* compute carry limb */ + incl %edx + jz Lend2 + pushl %eax /* push carry limb onto stack */ + testb $1,%dl + jnz L2 /* enter loop in the middle */ + movl %ebx,%eax + + ALIGN (3) +Loop2: movl (%esi,%edx,4),%ebx /* load next higher limb */ + shrdl %cl,%ebx,%eax /* compute result limb */ + movl %eax,(%edi,%edx,4) /* store it */ + incl %edx +L2: movl (%esi,%edx,4),%eax + shrdl %cl,%eax,%ebx + movl %ebx,(%edi,%edx,4) + incl %edx + jnz Loop2 + + shrl %cl,%eax /* compute most significant limb */ + movl %eax,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebx + popl %esi + popl %edi + ret + +Lend2: shrl %cl,%ebx /* compute most significant limb */ + movl %ebx,(%edi) /* store it */ + + popl %ebx + popl %esi + popl %edi + ret + diff --git a/grub-core/lib/libgcrypt/mpi/i386/mpih-sub1.S b/grub-core/lib/libgcrypt/mpi/i386/mpih-sub1.S new file mode 100644 index 0000000..f447f7a --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i386/mpih-sub1.S @@ -0,0 +1,117 @@ +/* i80386 sub_n -- Sub two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_sub_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(_gcry_mpih_sub_n) +C_SYMBOL_NAME(_gcry_mpih_sub_n:) + pushl %edi + pushl %esi + + movl 12(%esp),%edi /* res_ptr */ + movl 16(%esp),%esi /* s1_ptr */ + movl 20(%esp),%edx /* s2_ptr */ + movl 24(%esp),%ecx /* size */ + + movl %ecx,%eax + shrl $3,%ecx /* compute count for unrolled loop */ + negl %eax + andl $7,%eax /* get index where to start loop */ + jz Loop /* necessary special case for 0 */ + incl %ecx /* adjust loop count */ + shll $2,%eax /* adjustment for pointers... */ + subl %eax,%edi /* ... since they are offset ... */ + subl %eax,%esi /* ... by a constant when we ... */ + subl %eax,%edx /* ... enter the loop */ + shrl $2,%eax /* restore previous value */ +#ifdef PIC +/* Calculate start address in loop for PIC. Due to limitations in some + assemblers, Loop-L0-3 cannot be put into the leal */ + call L0 +L0: leal (%eax,%eax,8),%eax + addl (%esp),%eax + addl $(Loop-L0-3),%eax + addl $4,%esp +#else +/* Calculate start address in loop for non-PIC. */ + leal (Loop - 3)(%eax,%eax,8),%eax +#endif + jmp *%eax /* jump into loop */ + ALIGN (3) +Loop: movl (%esi),%eax + sbbl (%edx),%eax + movl %eax,(%edi) + movl 4(%esi),%eax + sbbl 4(%edx),%eax + movl %eax,4(%edi) + movl 8(%esi),%eax + sbbl 8(%edx),%eax + movl %eax,8(%edi) + movl 12(%esi),%eax + sbbl 12(%edx),%eax + movl %eax,12(%edi) + movl 16(%esi),%eax + sbbl 16(%edx),%eax + movl %eax,16(%edi) + movl 20(%esi),%eax + sbbl 20(%edx),%eax + movl %eax,20(%edi) + movl 24(%esi),%eax + sbbl 24(%edx),%eax + movl %eax,24(%edi) + movl 28(%esi),%eax + sbbl 28(%edx),%eax + movl %eax,28(%edi) + leal 32(%edi),%edi + leal 32(%esi),%esi + leal 32(%edx),%edx + decl %ecx + jnz Loop + + sbbl %eax,%eax + negl %eax + + popl %esi + popl %edi + ret + diff --git a/grub-core/lib/libgcrypt/mpi/i386/syntax.h b/grub-core/lib/libgcrypt/mpi/i386/syntax.h new file mode 100644 index 0000000..39ede98 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i386/syntax.h @@ -0,0 +1,68 @@ +/* syntax.h -- Definitions for x86 syntax variations. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#undef ALIGN + +#if defined (BSD_SYNTAX) || defined (ELF_SYNTAX) +#define R(r) %r +#define MEM(base)(base) +#define MEM_DISP(base,displacement)displacement(R(base)) +#define MEM_INDEX(base,index,size)(R(base),R(index),size) +#ifdef __STDC__ +#define INSN1(mnemonic,size_suffix,dst)mnemonic##size_suffix dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic##size_suffix src,dst +#else +#define INSN1(mnemonic,size_suffix,dst)mnemonic/**/size_suffix dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic/**/size_suffix src,dst +#endif +#define TEXT .text +#if defined (BSD_SYNTAX) +#define ALIGN(log) .align log +#endif +#if defined (ELF_SYNTAX) +#define ALIGN(log) .align 1<<(log) +#endif +#define GLOBL .globl +#endif + +#ifdef INTEL_SYNTAX +#define R(r) r +#define MEM(base)[base] +#define MEM_DISP(base,displacement)[base+(displacement)] +#define MEM_INDEX(base,index,size)[base+index*size] +#define INSN1(mnemonic,size_suffix,dst)mnemonic dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic dst,src +#define TEXT .text +#define ALIGN(log) .align log +#define GLOBL .globl +#endif + +#ifdef X86_BROKEN_ALIGN +#undef ALIGN +#define ALIGN(log) .align log,0x90 +#endif diff --git a/grub-core/lib/libgcrypt/mpi/i586/Manifest b/grub-core/lib/libgcrypt/mpi/i586/Manifest new file mode 100644 index 0000000..6d1d7f8 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i586/Manifest @@ -0,0 +1,27 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +mpih-add1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +mpih-sub1.S +$names$ iQCVAwUAP+LmQDEAnp832S/7AQKCmgQAhG+E7X0KB4qdVf3sMb6Qr+Iv5Jlehzoub/5vxTRgePKzRuOHidCnTzSSoyzA++UcHrOjHQQDMsXnO6PqpS1d/TKkxjnGN7rE8mvMYlFAT8RsawTozSfh14mCzI0HTDbaKL9Z8pcMJtadB3XqAuqWJNO8kyECJFwurt3DRWXSWS8==Rug5 diff --git a/grub-core/lib/libgcrypt/mpi/i586/README b/grub-core/lib/libgcrypt/mpi/i586/README new file mode 100644 index 0000000..d73b082 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i586/README @@ -0,0 +1,26 @@ +This directory contains mpn functions optimized for Intel Pentium +processors. + +RELEVANT OPTIMIZATION ISSUES + +1. Pentium doesn't allocate cache lines on writes, unlike most other modern +processors. Since the functions in the mpn class do array writes, we have to +handle allocating the destination cache lines by reading a word from it in the +loops, to achieve the best performance. + +2. Pairing of memory operations requires that the two issued operations refer +to different cache banks. The simplest way to insure this is to read/write +two words from the same object. If we make operations on different objects, +they might or might not be to the same cache bank. + +STATUS + +1. mpn_lshift and mpn_rshift run at about 6 cycles/limb, but the Pentium +documentation indicates that they should take only 43/8 = 5.375 cycles/limb, +or 5 cycles/limb asymptotically. + +2. mpn_add_n and mpn_sub_n run at asymptotically 2 cycles/limb. Due to loop +overhead and other delays (cache refill?), they run at or near 2.5 cycles/limb. + +3. mpn_mul_1, mpn_addmul_1, mpn_submul_1 all run 1 cycle faster than they +should... diff --git a/grub-core/lib/libgcrypt/mpi/i586/distfiles b/grub-core/lib/libgcrypt/mpi/i586/distfiles new file mode 100644 index 0000000..546f777 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i586/distfiles @@ -0,0 +1,10 @@ +Manifest +mpih-add1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +mpih-sub1.S +README + diff --git a/grub-core/lib/libgcrypt/mpi/i586/mpih-add1.S b/grub-core/lib/libgcrypt/mpi/i586/mpih-add1.S new file mode 100644 index 0000000..7436d59 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i586/mpih-add1.S @@ -0,0 +1,135 @@ +/* i80586 add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_add_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(_gcry_mpih_add_n) +C_SYMBOL_NAME(_gcry_mpih_add_n:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s1_ptr */ + movl 28(%esp),%ebp /* s2_ptr */ + movl 32(%esp),%ecx /* size */ + + movl (%ebp),%ebx + + decl %ecx + movl %ecx,%edx + shrl $3,%ecx + andl $7,%edx + testl %ecx,%ecx /* zero carry flag */ + jz Lend + pushl %edx + + ALIGN (3) +Loop: movl 28(%edi),%eax /* fetch destination cache line */ + leal 32(%edi),%edi + +L1: movl (%esi),%eax + movl 4(%esi),%edx + adcl %ebx,%eax + movl 4(%ebp),%ebx + adcl %ebx,%edx + movl 8(%ebp),%ebx + movl %eax,-32(%edi) + movl %edx,-28(%edi) + +L2: movl 8(%esi),%eax + movl 12(%esi),%edx + adcl %ebx,%eax + movl 12(%ebp),%ebx + adcl %ebx,%edx + movl 16(%ebp),%ebx + movl %eax,-24(%edi) + movl %edx,-20(%edi) + +L3: movl 16(%esi),%eax + movl 20(%esi),%edx + adcl %ebx,%eax + movl 20(%ebp),%ebx + adcl %ebx,%edx + movl 24(%ebp),%ebx + movl %eax,-16(%edi) + movl %edx,-12(%edi) + +L4: movl 24(%esi),%eax + movl 28(%esi),%edx + adcl %ebx,%eax + movl 28(%ebp),%ebx + adcl %ebx,%edx + movl 32(%ebp),%ebx + movl %eax,-8(%edi) + movl %edx,-4(%edi) + + leal 32(%esi),%esi + leal 32(%ebp),%ebp + decl %ecx + jnz Loop + + popl %edx +Lend: + decl %edx /* test %edx w/o clobbering carry */ + js Lend2 + incl %edx +Loop2: + leal 4(%edi),%edi + movl (%esi),%eax + adcl %ebx,%eax + movl 4(%ebp),%ebx + movl %eax,-4(%edi) + leal 4(%esi),%esi + leal 4(%ebp),%ebp + decl %edx + jnz Loop2 +Lend2: + movl (%esi),%eax + adcl %ebx,%eax + movl %eax,(%edi) + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + + diff --git a/grub-core/lib/libgcrypt/mpi/i586/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/i586/mpih-lshift.S new file mode 100644 index 0000000..9d25fe9 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i586/mpih-lshift.S @@ -0,0 +1,229 @@ +/* i80586 lshift + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_lshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(_gcry_mpih_lshift) +C_SYMBOL_NAME(_gcry_mpih_lshift:) + + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s_ptr */ + movl 28(%esp),%ebp /* size */ + movl 32(%esp),%ecx /* cnt */ + +/* We can use faster code for shift-by-1 under certain conditions. */ + cmp $1,%ecx + jne Lnormal + leal 4(%esi),%eax + cmpl %edi,%eax + jnc Lspecial /* jump if s_ptr + 1 >= res_ptr */ + leal (%esi,%ebp,4),%eax + cmpl %eax,%edi + jnc Lspecial /* jump if res_ptr >= s_ptr + size */ + +Lnormal: + leal -4(%edi,%ebp,4),%edi + leal -4(%esi,%ebp,4),%esi + + movl (%esi),%edx + subl $4,%esi + xorl %eax,%eax + shldl %cl,%edx,%eax /* compute carry limb */ + pushl %eax /* push carry limb onto stack */ + + decl %ebp + pushl %ebp + shrl $3,%ebp + jz Lend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +Loop: movl -28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl -4(%esi),%edx + shldl %cl,%eax,%ebx + shldl %cl,%edx,%eax + movl %ebx,(%edi) + movl %eax,-4(%edi) + + movl -8(%esi),%ebx + movl -12(%esi),%eax + shldl %cl,%ebx,%edx + shldl %cl,%eax,%ebx + movl %edx,-8(%edi) + movl %ebx,-12(%edi) + + movl -16(%esi),%edx + movl -20(%esi),%ebx + shldl %cl,%edx,%eax + shldl %cl,%ebx,%edx + movl %eax,-16(%edi) + movl %edx,-20(%edi) + + movl -24(%esi),%eax + movl -28(%esi),%edx + shldl %cl,%eax,%ebx + shldl %cl,%edx,%eax + movl %ebx,-24(%edi) + movl %eax,-28(%edi) + + subl $32,%esi + subl $32,%edi + decl %ebp + jnz Loop + +Lend: popl %ebp + andl $7,%ebp + jz Lend2 +Loop2: movl (%esi),%eax + shldl %cl,%eax,%edx + movl %edx,(%edi) + movl %eax,%edx + subl $4,%esi + subl $4,%edi + decl %ebp + jnz Loop2 + +Lend2: shll %cl,%edx /* compute least significant limb */ + movl %edx,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. +*/ + +Lspecial: + movl (%esi),%edx + addl $4,%esi + + decl %ebp + pushl %ebp + shrl $3,%ebp + + addl %edx,%edx + incl %ebp + decl %ebp + jz LLend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +LLoop: movl 28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl 4(%esi),%edx + adcl %eax,%eax + movl %ebx,(%edi) + adcl %edx,%edx + movl %eax,4(%edi) + + movl 8(%esi),%ebx + movl 12(%esi),%eax + adcl %ebx,%ebx + movl %edx,8(%edi) + adcl %eax,%eax + movl %ebx,12(%edi) + + movl 16(%esi),%edx + movl 20(%esi),%ebx + adcl %edx,%edx + movl %eax,16(%edi) + adcl %ebx,%ebx + movl %edx,20(%edi) + + movl 24(%esi),%eax + movl 28(%esi),%edx + adcl %eax,%eax + movl %ebx,24(%edi) + adcl %edx,%edx + movl %eax,28(%edi) + + leal 32(%esi),%esi /* use leal not to clobber carry */ + leal 32(%edi),%edi + decl %ebp + jnz LLoop + +LLend: popl %ebp + sbbl %eax,%eax /* save carry in %eax */ + andl $7,%ebp + jz LLend2 + addl %eax,%eax /* restore carry from eax */ +LLoop2: movl %edx,%ebx + movl (%esi),%edx + adcl %edx,%edx + movl %ebx,(%edi) + + leal 4(%esi),%esi /* use leal not to clobber carry */ + leal 4(%edi),%edi + decl %ebp + jnz LLoop2 + + jmp LL1 +LLend2: addl %eax,%eax /* restore carry from eax */ +LL1: movl %edx,(%edi) /* store last limb */ + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + + diff --git a/grub-core/lib/libgcrypt/mpi/i586/mpih-mul1.S b/grub-core/lib/libgcrypt/mpi/i586/mpih-mul1.S new file mode 100644 index 0000000..3601d96 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i586/mpih-mul1.S @@ -0,0 +1,89 @@ +/* i80586 mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_mul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(_gcry_mpih_mul_1) +C_SYMBOL_NAME(_gcry_mpih_mul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/grub-core/lib/libgcrypt/mpi/i586/mpih-mul2.S b/grub-core/lib/libgcrypt/mpi/i586/mpih-mul2.S new file mode 100644 index 0000000..f32d363 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i586/mpih-mul2.S @@ -0,0 +1,93 @@ +/* i80586 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(_gcry_mpih_addmul_1) +C_SYMBOL_NAME(_gcry_mpih_addmul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) + + INSN2(adc,l ,R(edx),$0) + INSN2(add,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/grub-core/lib/libgcrypt/mpi/i586/mpih-mul3.S b/grub-core/lib/libgcrypt/mpi/i586/mpih-mul3.S new file mode 100644 index 0000000..fa27d4e --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i586/mpih-mul3.S @@ -0,0 +1,93 @@ +/* i80586 submul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_submul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(_gcry_mpih_submul_1) +C_SYMBOL_NAME(_gcry_mpih_submul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) + + INSN2(adc,l ,R(edx),$0) + INSN2(sub,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/grub-core/lib/libgcrypt/mpi/i586/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/i586/mpih-rshift.S new file mode 100644 index 0000000..c661e3d --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i586/mpih-rshift.S @@ -0,0 +1,228 @@ +/* i80586 rshift + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + + +/******************* + * mpi_limb_t + * _gcry_mpih_rshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(_gcry_mpih_rshift) +C_SYMBOL_NAME(_gcry_mpih_rshift:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s_ptr */ + movl 28(%esp),%ebp /* size */ + movl 32(%esp),%ecx /* cnt */ + +/* We can use faster code for shift-by-1 under certain conditions. */ + cmp $1,%ecx + jne Rnormal + leal 4(%edi),%eax + cmpl %esi,%eax + jnc Rspecial /* jump if res_ptr + 1 >= s_ptr */ + leal (%edi,%ebp,4),%eax + cmpl %eax,%esi + jnc Rspecial /* jump if s_ptr >= res_ptr + size */ + +Rnormal: + movl (%esi),%edx + addl $4,%esi + xorl %eax,%eax + shrdl %cl,%edx,%eax /* compute carry limb */ + pushl %eax /* push carry limb onto stack */ + + decl %ebp + pushl %ebp + shrl $3,%ebp + jz Rend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +Roop: movl 28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl 4(%esi),%edx + shrdl %cl,%eax,%ebx + shrdl %cl,%edx,%eax + movl %ebx,(%edi) + movl %eax,4(%edi) + + movl 8(%esi),%ebx + movl 12(%esi),%eax + shrdl %cl,%ebx,%edx + shrdl %cl,%eax,%ebx + movl %edx,8(%edi) + movl %ebx,12(%edi) + + movl 16(%esi),%edx + movl 20(%esi),%ebx + shrdl %cl,%edx,%eax + shrdl %cl,%ebx,%edx + movl %eax,16(%edi) + movl %edx,20(%edi) + + movl 24(%esi),%eax + movl 28(%esi),%edx + shrdl %cl,%eax,%ebx + shrdl %cl,%edx,%eax + movl %ebx,24(%edi) + movl %eax,28(%edi) + + addl $32,%esi + addl $32,%edi + decl %ebp + jnz Roop + +Rend: popl %ebp + andl $7,%ebp + jz Rend2 +Roop2: movl (%esi),%eax + shrdl %cl,%eax,%edx /* compute result limb */ + movl %edx,(%edi) + movl %eax,%edx + addl $4,%esi + addl $4,%edi + decl %ebp + jnz Roop2 + +Rend2: shrl %cl,%edx /* compute most significant limb */ + movl %edx,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. +*/ + +Rspecial: + leal -4(%edi,%ebp,4),%edi + leal -4(%esi,%ebp,4),%esi + + movl (%esi),%edx + subl $4,%esi + + decl %ebp + pushl %ebp + shrl $3,%ebp + + shrl $1,%edx + incl %ebp + decl %ebp + jz RLend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +RLoop: movl -28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl -4(%esi),%edx + rcrl $1,%eax + movl %ebx,(%edi) + rcrl $1,%edx + movl %eax,-4(%edi) + + movl -8(%esi),%ebx + movl -12(%esi),%eax + rcrl $1,%ebx + movl %edx,-8(%edi) + rcrl $1,%eax + movl %ebx,-12(%edi) + + movl -16(%esi),%edx + movl -20(%esi),%ebx + rcrl $1,%edx + movl %eax,-16(%edi) + rcrl $1,%ebx + movl %edx,-20(%edi) + + movl -24(%esi),%eax + movl -28(%esi),%edx + rcrl $1,%eax + movl %ebx,-24(%edi) + rcrl $1,%edx + movl %eax,-28(%edi) + + leal -32(%esi),%esi /* use leal not to clobber carry */ + leal -32(%edi),%edi + decl %ebp + jnz RLoop + +RLend: popl %ebp + sbbl %eax,%eax /* save carry in %eax */ + andl $7,%ebp + jz RLend2 + addl %eax,%eax /* restore carry from eax */ +RLoop2: movl %edx,%ebx + movl (%esi),%edx + rcrl $1,%edx + movl %ebx,(%edi) + + leal -4(%esi),%esi /* use leal not to clobber carry */ + leal -4(%edi),%edi + decl %ebp + jnz RLoop2 + + jmp RL1 +RLend2: addl %eax,%eax /* restore carry from eax */ +RL1: movl %edx,(%edi) /* store last limb */ + + movl $0,%eax + rcrl $1,%eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + diff --git a/grub-core/lib/libgcrypt/mpi/i586/mpih-sub1.S b/grub-core/lib/libgcrypt/mpi/i586/mpih-sub1.S new file mode 100644 index 0000000..ef2d580 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/i586/mpih-sub1.S @@ -0,0 +1,142 @@ +/* i80586 sub_n -- Sub two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_sub_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(_gcry_mpih_sub_n) +C_SYMBOL_NAME(_gcry_mpih_sub_n:) + + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s1_ptr */ + movl 28(%esp),%ebp /* s2_ptr */ + movl 32(%esp),%ecx /* size */ + + movl (%ebp),%ebx + + decl %ecx + movl %ecx,%edx + shrl $3,%ecx + andl $7,%edx + testl %ecx,%ecx /* zero carry flag */ + jz Lend + pushl %edx + + ALIGN (3) +Loop: movl 28(%edi),%eax /* fetch destination cache line */ + leal 32(%edi),%edi + +L1: movl (%esi),%eax + movl 4(%esi),%edx + sbbl %ebx,%eax + movl 4(%ebp),%ebx + sbbl %ebx,%edx + movl 8(%ebp),%ebx + movl %eax,-32(%edi) + movl %edx,-28(%edi) + +L2: movl 8(%esi),%eax + movl 12(%esi),%edx + sbbl %ebx,%eax + movl 12(%ebp),%ebx + sbbl %ebx,%edx + movl 16(%ebp),%ebx + movl %eax,-24(%edi) + movl %edx,-20(%edi) + +L3: movl 16(%esi),%eax + movl 20(%esi),%edx + sbbl %ebx,%eax + movl 20(%ebp),%ebx + sbbl %ebx,%edx + movl 24(%ebp),%ebx + movl %eax,-16(%edi) + movl %edx,-12(%edi) + +L4: movl 24(%esi),%eax + movl 28(%esi),%edx + sbbl %ebx,%eax + movl 28(%ebp),%ebx + sbbl %ebx,%edx + movl 32(%ebp),%ebx + movl %eax,-8(%edi) + movl %edx,-4(%edi) + + leal 32(%esi),%esi + leal 32(%ebp),%ebp + decl %ecx + jnz Loop + + popl %edx +Lend: + decl %edx /* test %edx w/o clobbering carry */ + js Lend2 + incl %edx +Loop2: + leal 4(%edi),%edi + movl (%esi),%eax + sbbl %ebx,%eax + movl 4(%ebp),%ebx + movl %eax,-4(%edi) + leal 4(%esi),%esi + leal 4(%ebp),%ebp + decl %edx + jnz Loop2 +Lend2: + movl (%esi),%eax + sbbl %ebx,%eax + movl %eax,(%edi) + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + diff --git a/grub-core/lib/libgcrypt/mpi/longlong.h b/grub-core/lib/libgcrypt/mpi/longlong.h new file mode 100644 index 0000000..b3fce09 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/longlong.h @@ -0,0 +1,1613 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Note: I added some stuff for use with gnupg + +Copyright (C) 1991, 1992, 1993, 1994, 1996, 1998, + 2000, 2001, 2002, 2003, 2004, 2011 Free Software Foundation, Inc. + +This file is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with this file; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. +*/ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +/* This is used to make sure no undesirable sharing between different libraries + that use this file takes place. */ +#ifndef __MPN +#define __MPN(x) __##x +#endif + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two + UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first non-zero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! */ + +#ifdef __riscos__ +#pragma continue_after_hash_error +#else /* !__riscos__ */ +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + + +/*************************************** + ************** A29K ***************** + ***************************************/ +#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %1,%4,%5\n" \ + "addc %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %1,%4,%5\n" \ + "subc %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("multiplu %0,%1,%2" \ + : "=r" ((USItype)(xl)) \ + : "r" (__m0), \ + "r" (__m1)); \ + __asm__ ("multmu %0,%1,%2" \ + : "=r" ((USItype)(xh)) \ + : "r" (__m0), \ + "r" (__m1)); \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("dividu %0,%3,%4" \ + : "=r" ((USItype)(q)), \ + "=q" ((USItype)(r)) \ + : "1" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))) +#define COUNT_LEADING_ZEROS_0 32 +#endif /* __a29k__ */ + + +#if defined (__alpha) && W_TYPE_SIZE == 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("umulh %r1,%2,%0" \ + : "=r" ((UDItype) ph) \ + : "%rJ" (__m0), \ + "rI" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 46 +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UDItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UDItype __udiv_qrnnd (); +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ +#endif /* __alpha */ + +/*************************************** + ************** ARM ****************** + ***************************************/ +#if defined (__arm__) && W_TYPE_SIZE == 32 && \ + (!defined (__thumb__) || defined (__thumb2__)) +/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */ +#ifndef __ARM_ARCH +# ifdef __ARM_ARCH_2__ +# define __ARM_ARCH 2 +# elif defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__) +# define __ARM_ARCH 3 +# elif defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__) +# define __ARM_ARCH 4 +# elif defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5E__) \ + || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) +# define __ARM_ARCH 5 +# elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ + || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) +# define __ARM_ARCH 6 +# elif defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7EM__) +# define __ARM_ARCH 7 +# else + /* could not detect? */ +# endif +#endif +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds %1, %4, %5\n" \ + "adc %0, %2, %3" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "%r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl)) __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs %1, %4, %5\n" \ + "sbc %0, %2, %3" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "r" ((USItype)(al)), \ + "rI" ((USItype)(bl)) __CLOBBER_CC) +#if (defined __ARM_ARCH && __ARM_ARCH <= 3) +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("@ Inlined umul_ppmm\n" \ + "mov %|r0, %2, lsr #16 @ AAAA\n" \ + "mov %|r2, %3, lsr #16 @ BBBB\n" \ + "bic %|r1, %2, %|r0, lsl #16 @ aaaa\n" \ + "bic %0, %3, %|r2, lsl #16 @ bbbb\n" \ + "mul %1, %|r1, %|r2 @ aaaa * BBBB\n" \ + "mul %|r2, %|r0, %|r2 @ AAAA * BBBB\n" \ + "mul %|r1, %0, %|r1 @ aaaa * bbbb\n" \ + "mul %0, %|r0, %0 @ AAAA * bbbb\n" \ + "adds %|r0, %1, %0 @ central sum\n" \ + "addcs %|r2, %|r2, #65536\n" \ + "adds %1, %|r1, %|r0, lsl #16\n" \ + "adc %0, %|r2, %|r0, lsr #16" \ + : "=&r" ((xh)), \ + "=r" ((xl)) \ + : "r" ((USItype)(a)), \ + "r" ((USItype)(b)) \ + : "r0", "r1", "r2" __AND_CLOBBER_CC) +#else /* __ARM_ARCH >= 4 */ +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("@ Inlined umul_ppmm\n" \ + "umull %1, %0, %2, %3" \ + : "=&r" ((xh)), \ + "=r" ((xl)) \ + : "r" ((USItype)(a)), \ + "r" ((USItype)(b))) +#endif /* __ARM_ARCH >= 4 */ +#define UMUL_TIME 20 +#define UDIV_TIME 100 +#if (defined __ARM_ARCH && __ARM_ARCH >= 5) +#define count_leading_zeros(count, x) \ + __asm__ ("clz %0, %1" \ + : "=r" ((count)) \ + : "r" ((USItype)(x))) +#endif /* __ARM_ARCH >= 5 */ +#endif /* __arm__ */ + +/*************************************** + ************** CLIPPER ************** + ***************************************/ +#if defined (__clipper__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__xx.__ll) \ + : "%0" ((USItype)(u)), \ + "r" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define smul_ppmm(w1, w0, u, v) \ + ({union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("mulwx %2,%0" \ + : "=r" (__xx.__ll) \ + : "%0" ((SItype)(u)), \ + "r" ((SItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__w) \ + : "%0" ((USItype)(u)), \ + "r" ((USItype)(v))); \ + __w; }) +#endif /* __clipper__ */ + + +/*************************************** + ************** GMICRO *************** + ***************************************/ +#if defined (__gmicro__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.w %5,%1\n" \ + "addx %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.w %5,%1\n" \ + "subx %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + __asm__ ("mulx %3,%0,%1" \ + : "=g" ((USItype)(ph)), \ + "=r" ((USItype)(pl)) \ + : "%0" ((USItype)(m0)), \ + "g" ((USItype)(m1))) +#define udiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("divx %4,%0,%1" \ + : "=g" ((USItype)(q)), \ + "=r" ((USItype)(r)) \ + : "1" ((USItype)(nh)), \ + "0" ((USItype)(nl)), \ + "g" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("bsch/1 %1,%0" \ + : "=g" (count) \ + : "g" ((USItype)(x)), \ + "0" ((USItype)0)) +#endif + + +/*************************************** + ************** HPPA ***************** + ***************************************/ +#if defined (__hppa) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ (" add %4,%5,%1\n" \ + " addc %2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rM" ((USItype)(ah)), \ + "rM" ((USItype)(bh)), \ + "%rM" ((USItype)(al)), \ + "rM" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ (" sub %4,%5,%1\n" \ + " subb %2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rM" ((USItype)(ah)), \ + "rM" ((USItype)(bh)), \ + "rM" ((USItype)(al)), \ + "rM" ((USItype)(bl))) +#if defined (_PA_RISC1_1) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ (" xmpyu %1,%2,%0" \ + : "=*f" (__xx.__ll) \ + : "*f" ((USItype)(u)), \ + "*f" ((USItype)(v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define UMUL_TIME 8 +#define UDIV_TIME 60 +#else +#define UMUL_TIME 40 +#define UDIV_TIME 80 +#endif +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { USItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern USItype __udiv_qrnnd (); +#endif /* LONGLONG_STANDALONE */ +#define count_leading_zeros(count, x) \ + do { \ + USItype __tmp; \ + __asm__ ( \ + " ldi 1,%0 \n" \ + " extru,= %1,15,16,%%r0 ; Bits 31..16 zero? \n" \ + " extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ + " ldo 16(%0),%0 ; Yes. Perform add. \n" \ + " extru,= %1,23,8,%%r0 ; Bits 15..8 zero? \n" \ + " extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ + " ldo 8(%0),%0 ; Yes. Perform add. \n" \ + " extru,= %1,27,4,%%r0 ; Bits 7..4 zero? \n" \ + " extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ + " ldo 4(%0),%0 ; Yes. Perform add. \n" \ + " extru,= %1,29,2,%%r0 ; Bits 3..2 zero? \n" \ + " extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ + " ldo 2(%0),%0 ; Yes. Perform add. \n" \ + " extru %1,30,1,%1 ; Extract bit 1. \n" \ + " sub %0,%1,%0 ; Subtract it. " \ + : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif /* hppa */ + + +/*************************************** + ************** I370 ***************** + ***************************************/ +#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32 +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "r" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (m0), \ + "r" (m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("dr %0,%2" \ + : "=r" (__xx.__ll) \ + : "0" (__xx.__ll), "r" (d)); \ + (q) = __xx.__i.__l; (r) = __xx.__i.__h; \ + } while (0) +#endif + + +/*************************************** + ************** I386 ***************** + ***************************************/ +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl %5,%1\n" \ + "adcl %3,%0" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%1\n" \ + "sbbl %3,%0" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl)) \ + __CLOBBER_CC) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mull %3" \ + : "=a" ((w0)), \ + "=d" ((w1)) \ + : "%0" ((USItype)(u)), \ + "rm" ((USItype)(v)) \ + __CLOBBER_CC) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divl %4" \ + : "=a" ((q)), \ + "=d" ((r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "rm" ((USItype)(d)) \ + __CLOBBER_CC) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("bsrl %1,%0" \ + : "=r" (__cbtmp) : "rm" ((USItype)(x)) \ + __CLOBBER_CC); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define count_trailing_zeros(count, x) \ + __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)) __CLOBBER_CC) +#ifndef UMUL_TIME +#define UMUL_TIME 40 +#endif +#ifndef UDIV_TIME +#define UDIV_TIME 40 +#endif +#endif /* 80x86 */ + + +/*************************************** + ************** I860 ***************** + ***************************************/ +#if defined (__i860__) && W_TYPE_SIZE == 32 +#define rshift_rhlc(r,h,l,c) \ + __asm__ ("shr %3,r0,r0\n" \ + "shrd %1,%2,%0" \ + "=r" (r) : "r" (h), "r" (l), "rn" (c)) +#endif /* i860 */ + +/*************************************** + ************** I960 ***************** + ***************************************/ +#if defined (__i960__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 1,0\n" \ + "addc %5,%4,%1\n" \ + "addc %3,%2,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%dI" ((USItype)(ah)), \ + "dI" ((USItype)(bh)), \ + "%dI" ((USItype)(al)), \ + "dI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 0,0\n" \ + "subc %5,%4,%1\n" \ + "subc %3,%2,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "dI" ((USItype)(ah)), \ + "dI" ((USItype)(bh)), \ + "dI" ((USItype)(al)), \ + "dI" ((USItype)(bl))) +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__xx.__ll) \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__w) \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (nh); __nn.__i.__l = (nl); \ + __asm__ ("ediv %d,%n,%0" \ + : "=d" (__rq.__ll) \ + : "dI" (__nn.__ll), \ + "dI" ((USItype)(d))); \ + (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ + } while (0) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("scanbit %1,%0" \ + : "=r" (__cbtmp) \ + : "r" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ +#if defined (__i960mx) /* what is the proper symbol to test??? */ +#define rshift_rhlc(r,h,l,c) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (h); __nn.__i.__l = (l); \ + __asm__ ("shre %2,%1,%0" \ + : "=d" (r) : "dI" (__nn.__ll), "dI" (c)); \ + } +#endif /* i960mx */ +#endif /* i960 */ + + +/*************************************** + ************** 68000 **************** + ***************************************/ +#if (defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%.l %5,%1\n" \ + "addx%.l %3,%0" \ + : "=d" ((USItype)(sh)), \ + "=&d" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "d" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%.l %5,%1\n" \ + "subx%.l %3,%0" \ + : "=d" ((USItype)(sh)), \ + "=&d" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "d" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "dmi" ((USItype)(v))) +#define UMUL_TIME 45 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divu%.l %4,%1:%0" \ + : "=d" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +#define UDIV_TIME 90 +#define sdiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divs%.l %4,%1:%0" \ + : "=d" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" ((USItype)(count)) \ + : "od" ((USItype)(x)), "n" (0)) +#define COUNT_LEADING_ZEROS_0 32 +#else /* not mc68020 */ +#define umul_ppmm(xh, xl, a, b) \ + do { USItype __umul_tmp1, __umul_tmp2; \ + __asm__ ("| Inlined umul_ppmm \n" \ + " move%.l %5,%3 \n" \ + " move%.l %2,%0 \n" \ + " move%.w %3,%1 \n" \ + " swap %3 \n" \ + " swap %0 \n" \ + " mulu %2,%1 \n" \ + " mulu %3,%0 \n" \ + " mulu %2,%3 \n" \ + " swap %2 \n" \ + " mulu %5,%2 \n" \ + " add%.l %3,%2 \n" \ + " jcc 1f \n" \ + " add%.l %#0x10000,%0 \n" \ + "1: move%.l %2,%3 \n" \ + " clr%.w %2 \n" \ + " swap %2 \n" \ + " swap %3 \n" \ + " clr%.w %3 \n" \ + " add%.l %3,%1 \n" \ + " addx%.l %2,%0 \n" \ + " | End inlined umul_ppmm" \ + : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)), \ + "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \ + : "%2" ((USItype)(a)), "d" ((USItype)(b))); \ + } while (0) +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#endif /* not mc68020 */ +#endif /* mc68000 */ + + +/*************************************** + ************** 88000 **************** + ***************************************/ +#if defined (__m88000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addu.co %1,%r4,%r5\n" \ + "addu.ci %0,%r2,%r3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rJ" ((USItype)(ah)), \ + "rJ" ((USItype)(bh)), \ + "%rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subu.co %1,%r4,%r5\n" \ + "subu.ci %0,%r2,%r3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rJ" ((USItype)(ah)), \ + "rJ" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("ff1 %0,%1" \ + : "=r" (__cbtmp) \ + : "r" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__m88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("mulu.d %0,%1,%2" : "=r" (__x.__ll) : "r" (u), "r" (v)); \ + (wh) = __x.__i.__h; \ + (wl) = __x.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x, __q; \ + __x.__i.__h = (n1); __x.__i.__l = (n0); \ + __asm__ ("divu.d %0,%1,%2" \ + : "=r" (__q.__ll) : "r" (__x.__ll), "r" (d)); \ + (r) = (n0) - __q.__l * (d); (q) = __q.__l; }) +#define UMUL_TIME 5 +#define UDIV_TIME 25 +#else +#define UMUL_TIME 17 +#define UDIV_TIME 150 +#endif /* __m88110__ */ +#endif /* __m88000__ */ + +/*************************************** + ************** MIPS ***************** + ***************************************/ +#if defined (__mips__) && W_TYPE_SIZE == 32 +#if defined (__clang__) || (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UDItype _r; \ + _r = (UDItype) u * v; \ + (w1) = _r >> 32; \ + (w0) = (USItype) _r; \ + } while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3" \ + : "=l" ((USItype)(w0)), \ + "=h" ((USItype)(w1)) \ + : "d" ((USItype)(u)), \ + "d" ((USItype)(v))) +#else +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3 \n" \ + "mflo %0 \n" \ + "mfhi %1" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "d" ((USItype)(u)), \ + "d" ((USItype)(v))) +#endif +#define UMUL_TIME 10 +#define UDIV_TIME 100 +#endif /* __mips__ */ + +/*************************************** + ************** MIPS/64 ************** + ***************************************/ +#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64 +#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +typedef unsigned int UTItype __attribute__ ((mode (TI))); +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UTItype _r; \ + _r = (UTItype) u * v; \ + (w1) = _r >> 64; \ + (w0) = (UDItype) _r; \ + } while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3" \ + : "=l" ((UDItype)(w0)), \ + "=h" ((UDItype)(w1)) \ + : "d" ((UDItype)(u)), \ + "d" ((UDItype)(v))) +#else +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3 \n" \ + "mflo %0 \n" \ + "mfhi %1" \ + : "=d" ((UDItype)(w0)), \ + "=d" ((UDItype)(w1)) \ + : "d" ((UDItype)(u)), \ + "d" ((UDItype)(v))) +#endif +#define UMUL_TIME 20 +#define UDIV_TIME 140 +#endif /* __mips__ */ + + +/*************************************** + ************** 32000 **************** + ***************************************/ +#if defined (__ns32000__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("meid %2,%0" \ + : "=g" (__xx.__ll) \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("deid %2,%0" \ + : "=g" (__xx.__ll) \ + : "0" (__xx.__ll), \ + "g" ((USItype)(d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +#define count_trailing_zeros(count,x) \ + do { + __asm__ ("ffsd %2,%0" \ + : "=r" ((USItype) (count)) \ + : "0" ((USItype) 0), \ + "r" ((USItype) (x))); \ + } while (0) +#endif /* __ns32000__ */ + + +/*************************************** + ************** PPC ****************** + ***************************************/ +#if (defined (_ARCH_PPC) || defined (_IBMR2)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "%r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("{cntlz|cntlzw} %0,%1" \ + : "=r" ((count)) \ + : "r" ((USItype)(x))) +#define COUNT_LEADING_ZEROS_0 32 +#if defined (_ARCH_PPC) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" \ + : "=r" (ph) \ + : "%r" (__m0), \ + "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + SItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhw %0,%1,%2" \ + : "=r" ((SItype) ph) \ + : "%r" (__m0), \ + "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 +#define UDIV_TIME 120 +#else +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mul %0,%2,%3" \ + : "=r" ((xh)), \ + "=q" ((xl)) \ + : "r" (__m0), \ + "r" (__m1)); \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 8 +#define smul_ppmm(xh, xl, m0, m1) \ + __asm__ ("mul %0,%2,%3" \ + : "=r" ((SItype)(xh)), \ + "=q" ((SItype)(xl)) \ + : "r" (m0), \ + "r" (m1)) +#define SMUL_TIME 4 +#define sdiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("div %0,%2,%4" \ + : "=r" ((SItype)(q)), "=q" ((SItype)(r)) \ + : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d))) +#define UDIV_TIME 100 +#endif +#endif /* Power architecture variants. */ + +/* Powerpc 64 bit support taken from gmp-4.1.2. */ +/* We should test _IBMR2 here when we add assembly support for the system + vendor compilers. */ +#if 0 /* Not yet enabled because we don't have hardware for a test. */ +#if (defined (_ARCH_PPC) || defined (__powerpc__)) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + DItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 /* ??? */ +#define UDIV_TIME 120 /* ??? */ +#endif /* 64-bit PowerPC. */ +#endif /* if 0 */ + +/*************************************** + ************** PYR ****************** + ***************************************/ +#if defined (__pyr__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addw %5,%1 \n" \ + "addwc %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subw %5,%1 \n" \ + "subwb %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */ +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("movw %1,%R0 \n" \ + "uemul %2,%0" \ + : "=&r" (__xx.__ll) \ + : "g" ((USItype) (u)), \ + "g" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#endif /* __pyr__ */ + + +/*************************************** + ************** RT/ROMP ************** + ***************************************/ +#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("a %1,%5 \n" \ + "ae %0,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "r" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("s %1,%5\n" \ + "se %0,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "r" ((USItype)(bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ( \ + "s r2,r2 \n" \ + "mts r10,%2 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "m r2,%3 \n" \ + "cas %0,r2,r0 \n" \ + "mfs r10,%1" \ + : "=r" ((USItype)(ph)), \ + "=r" ((USItype)(pl)) \ + : "%r" (__m0), \ + "r" (__m1) \ + : "r2"); \ + (ph) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))); \ + (count) += 16; \ + } \ + } while (0) +#endif /* RT/ROMP */ + + +/*************************************** + ************** SH2 ****************** + ***************************************/ +#if (defined (__sh2__) || defined(__sh3__) || defined(__SH4__) ) \ + && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ( \ + "dmulu.l %2,%3\n" \ + "sts macl,%1\n" \ + "sts mach,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "macl", "mach") +#define UMUL_TIME 5 +#endif + +/*************************************** + ************** SPARC **************** + ***************************************/ +#if defined (__sparc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n" \ + "addx %r2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rJ" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%rJ" ((USItype)(al)), \ + "rI" ((USItype)(bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n" \ + "subx %r2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rJ" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rI" ((USItype)(bl)) \ + __CLOBBER_CC) +#if defined (__sparc_v8__) +/* Don't match immediate range because, 1) it is not often useful, + 2) the 'I' flag thinks of the range as a 13 bit signed interval, + while we want to match a 13 bit interval, sign extended to 32 bits, + but INTERPRETED AS UNSIGNED. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))) +#define UMUL_TIME 5 +#ifndef SUPERSPARC /* SuperSPARC's udiv only handles 53 bit dividends */ +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + USItype __q; \ + __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ + : "=r" ((USItype)(__q)) \ + : "r" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))); \ + (r) = (n0) - __q * (d); \ + (q) = __q; \ + } while (0) +#define UDIV_TIME 25 +#endif /* SUPERSPARC */ +#else /* ! __sparc_v8__ */ +#if defined (__sparclite__) +/* This has hardware multiply but not divide. It also has two additional + instructions scan (ffs from high bit) and divscc. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))) +#define UMUL_TIME 5 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("! Inlined udiv_qrnnd \n" \ + " wr %%g0,%2,%%y ! Not a delayed write for sparclite \n" \ + " tst %%g0 \n" \ + " divscc %3,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%%g1 \n" \ + " divscc %%g1,%4,%0 \n" \ + " rd %%y,%1 \n" \ + " bl,a 1f \n" \ + " add %1,%4,%1 \n" \ + "1: ! End of inline udiv_qrnnd" \ + : "=r" ((USItype)(q)), \ + "=r" ((USItype)(r)) \ + : "r" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "rI" ((USItype)(d)) \ + : "%g1" __AND_CLOBBER_CC) +#define UDIV_TIME 37 +#define count_leading_zeros(count, x) \ + __asm__ ("scan %1,0,%0" \ + : "=r" ((USItype)(x)) \ + : "r" ((USItype)(count))) +/* Early sparclites return 63 for an argument of 0, but they warn that future + implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 + undefined. */ +#endif /* __sparclite__ */ +#endif /* __sparc_v8__ */ +/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ +#ifndef umul_ppmm +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm \n" \ + " wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr \n" \ + " sra %3,31,%%g2 ! Don't move this insn \n" \ + " and %2,%%g2,%%g2 ! Don't move this insn \n" \ + " andcc %%g0,0,%%g1 ! Don't move this insn \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,%3,%%g1 \n" \ + " mulscc %%g1,0,%%g1 \n" \ + " add %%g1,%%g2,%0 \n" \ + " rd %%y,%1" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "%rI" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "%g1", "%g2" __AND_CLOBBER_CC) +#define UMUL_TIME 39 /* 39 instructions */ +#endif +#ifndef udiv_qrnnd +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { USItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern USItype __udiv_qrnnd (); +#define UDIV_TIME 140 +#endif /* LONGLONG_STANDALONE */ +#endif /* udiv_qrnnd */ +#endif /* __sparc__ */ + + +/*************************************** + ************** VAX ****************** + ***************************************/ +#if defined (__vax__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl2 %5,%1\n" \ + "adwc %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl2 %5,%1\n" \ + "sbwc %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("emul %1,%2,$0,%0" \ + : "=g" (__xx.__ll) \ + : "g" (__m0), \ + "g" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("ediv %3,%2,%0,%1" \ + : "=g" (q), "=g" (r) \ + : "g" (__xx.__ll), "g" (d)); \ + } while (0) +#endif /* __vax__ */ + + +/*************************************** + ************** Z8000 **************** + ***************************************/ +#if defined (__z8000__) && W_TYPE_SIZE == 16 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "%0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "%1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long int __ll; \ + struct {unsigned int __h, __l;} __i; \ + } __xx; \ + unsigned int __m0 = (m0), __m1 = (m1); \ + __asm__ ("mult %S0,%H3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "rQR" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((signed int) __m0 >> 15) & __m1) \ + + (((signed int) __m1 >> 15) & __m0)); \ + } while (0) +#endif /* __z8000__ */ + +#endif /* __GNUC__ */ +#endif /* !__riscos__ */ + + +/*************************************** + *********** Generic Versions ******** + ***************************************/ +#if !defined (umul_ppmm) && defined (__umulsidi3) +#define umul_ppmm(ph, pl, m0, m1) \ + { \ + UDWtype __ll = __umulsidi3 (m0, m1); \ + ph = (UWtype) (__ll >> W_TYPE_SIZE); \ + pl = (UWtype) __ll; \ + } +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({UWtype __hi, __lo; \ + umul_ppmm (__hi, __lo, u, v); \ + ((UDWtype) __hi << W_TYPE_SIZE) | __lo; }) +#endif + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + UWtype __u = (u), __v = (v); \ + \ + __ul = __ll_lowpart (__u); \ + __uh = __ll_highpart (__u); \ + __vl = __ll_lowpart (__v); \ + __vh = __ll_highpart (__v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define smul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __w1; \ + UWtype __m0 = (u), __m1 = (v); \ + umul_ppmm (__w1, w0, __m0, __m1); \ + (w1) = __w1 - (-(__m0 >> (W_TYPE_SIZE - 1)) & __m1) \ + - (-(__m1 >> (W_TYPE_SIZE - 1)) & __m0); \ + } while (0) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + UWtype __r; \ + (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +extern +#ifdef __STDC__ +const +#endif +unsigned char _gcry_clz_tab[]; +#define MPI_INTERNAL_NEED_CLZ_TAB 1 +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype) 1 << 2*__BITS4) \ + ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4);\ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (_gcry_clz_tab[__xr >> __a] + __a); \ + } while (0) +/* This version gives a well-defined value for zero. */ +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif diff --git a/grub-core/lib/libgcrypt/mpi/m68k/Manifest b/grub-core/lib/libgcrypt/mpi/m68k/Manifest new file mode 100644 index 0000000..8e0538a --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/Manifest @@ -0,0 +1,25 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +syntax.h +mpih-lshift.S +mpih-rshift.S +mpih-add1.S +mpih-sub1.S +$names$ iQCVAwUAP+LmTDEAnp832S/7AQJHUAP/dxfq2U0pDc5ZLoEizoqgjjcnHIyb9EjMG3YjvgK6jQ62yoAOCuo/jFYlJS+Mdve6bgfdTzYMrnKV7BG2SEcwb263pVnIntS7ZhKQPiMCbFgXWR2VjN3+a1v8yjQDZtgqEgm8OlQ+u7jKBY13Oryiuq5nPNxsXZqJpelG6Zkdg9M==PIee diff --git a/grub-core/lib/libgcrypt/mpi/m68k/distfiles b/grub-core/lib/libgcrypt/mpi/m68k/distfiles new file mode 100644 index 0000000..1e2e36f --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/distfiles @@ -0,0 +1,9 @@ +Manifest +syntax.h +mpih-lshift.S +mpih-rshift.S +mpih-add1.S +mpih-sub1.S + + + diff --git a/grub-core/lib/libgcrypt/mpi/m68k/mc68020/Manifest b/grub-core/lib/libgcrypt/mpi/m68k/mc68020/Manifest new file mode 100644 index 0000000..bcb2768 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/mc68020/Manifest @@ -0,0 +1,23 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +$names$ iQCVAwUAP+LmRTEAnp832S/7AQK3rwP/TyGBbii5HCrjDiLCVJHiDNeOdENx6AicRXnu4vuJmMmPZ0y+i7MPusDaeTbIUA0w6RaJx+Ep41nIvthmNDnFePY5Mw0pIUJcpI7AJR4vYqpwNQA6nlEdn/m1jg6sPLKZXUXNUkhroEzcHzoU+12BPS+nvSXlwSksg6rXEGOJ+Ms==XCXP diff --git a/grub-core/lib/libgcrypt/mpi/m68k/mc68020/distfiles b/grub-core/lib/libgcrypt/mpi/m68k/mc68020/distfiles new file mode 100644 index 0000000..6b96433 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/mc68020/distfiles @@ -0,0 +1,4 @@ +Manifest +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S diff --git a/grub-core/lib/libgcrypt/mpi/m68k/mc68020/mpih-mul1.S b/grub-core/lib/libgcrypt/mpi/m68k/mc68020/mpih-mul1.S new file mode 100644 index 0000000..007c94c --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/mc68020/mpih-mul1.S @@ -0,0 +1,104 @@ +/* mc68020 __mpn_mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_mul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(_gcry_mpih_mul_1) + +C_SYMBOL_NAME(_gcry_mpih_mul_1:) +PROLOG(_gcry_mpih_mul_1) + +#define res_ptr a0 +#define s1_ptr a1 +#define s1_size d2 +#define s2_limb d4 + +/* Save used registers on the stack. */ + moveml R(d2)-R(d4),MEM_PREDEC(sp) +#if 0 + movel R(d2),MEM_PREDEC(sp) + movel R(d3),MEM_PREDEC(sp) + movel R(d4),MEM_PREDEC(sp) +#endif + +/* Copy the arguments to registers. Better use movem? */ + movel MEM_DISP(sp,16),R(res_ptr) + movel MEM_DISP(sp,20),R(s1_ptr) + movel MEM_DISP(sp,24),R(s1_size) + movel MEM_DISP(sp,28),R(s2_limb) + + eorw #1,R(s1_size) + clrl R(d1) + lsrl #1,R(s1_size) + bcc L(L1) + subql #1,R(s1_size) + subl R(d0),R(d0) /* (d0,cy) <= (0,0) */ + +L(Loop:) + movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d1):R(d3) + addxl R(d0),R(d3) + movel R(d3),MEM_POSTINC(res_ptr) +L(L1:) movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d0):R(d3) + addxl R(d1),R(d3) + movel R(d3),MEM_POSTINC(res_ptr) + + dbf R(s1_size),L(Loop) + clrl R(d3) + addxl R(d3),R(d0) + subl #0x10000,R(s1_size) + bcc L(Loop) + +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d4) +#if 0 + movel MEM_POSTINC(sp),R(d4) + movel MEM_POSTINC(sp),R(d3) + movel MEM_POSTINC(sp),R(d2) +#endif + rts +EPILOG(_gcry_mpih_mul_1) + + diff --git a/grub-core/lib/libgcrypt/mpi/m68k/mc68020/mpih-mul2.S b/grub-core/lib/libgcrypt/mpi/m68k/mc68020/mpih-mul2.S new file mode 100644 index 0000000..44baa8d --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/mc68020/mpih-mul2.S @@ -0,0 +1,94 @@ +/* mc68020 __mpn_addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(_gcry_mpih_addmul_1) + +C_SYMBOL_NAME(_gcry_mpih_addmul_1:) +PROLOG(_gcry_mpih_addmul_1) + +#define res_ptr a0 +#define s1_ptr a1 +#define s1_size d2 +#define s2_limb d4 + +/* Save used registers on the stack. */ + moveml R(d2)-R(d5),MEM_PREDEC(sp) + +/* Copy the arguments to registers. Better use movem? */ + movel MEM_DISP(sp,20),R(res_ptr) + movel MEM_DISP(sp,24),R(s1_ptr) + movel MEM_DISP(sp,28),R(s1_size) + movel MEM_DISP(sp,32),R(s2_limb) + + eorw #1,R(s1_size) + clrl R(d1) + clrl R(d5) + lsrl #1,R(s1_size) + bcc L(L1) + subql #1,R(s1_size) + subl R(d0),R(d0) /* (d0,cy) <= (0,0) */ + +L(Loop:) + movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d1):R(d3) + addxl R(d0),R(d3) + addxl R(d5),R(d1) + addl R(d3),MEM_POSTINC(res_ptr) +L(L1:) movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d0):R(d3) + addxl R(d1),R(d3) + addxl R(d5),R(d0) + addl R(d3),MEM_POSTINC(res_ptr) + + dbf R(s1_size),L(Loop) + addxl R(d5),R(d0) + subl #0x10000,R(s1_size) + bcc L(Loop) + +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d5) + + rts +EPILOG(_gcry_mpih_addmul_1) + diff --git a/grub-core/lib/libgcrypt/mpi/m68k/mc68020/mpih-mul3.S b/grub-core/lib/libgcrypt/mpi/m68k/mc68020/mpih-mul3.S new file mode 100644 index 0000000..e958ef6 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/mc68020/mpih-mul3.S @@ -0,0 +1,97 @@ +/* mc68020 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract + * the result from a second limb vector. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + + + +#include "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * _gcry_mpih_submul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(_gcry_mpih_submul_1) + +C_SYMBOL_NAME(_gcry_mpih_submul_1:) +PROLOG(_gcry_mpih_submul_1) + +#define res_ptr a0 +#define s1_ptr a1 +#define s1_size d2 +#define s2_limb d4 + +/* Save used registers on the stack. */ + moveml R(d2)-R(d5),MEM_PREDEC(sp) + +/* Copy the arguments to registers. Better use movem? */ + movel MEM_DISP(sp,20),R(res_ptr) + movel MEM_DISP(sp,24),R(s1_ptr) + movel MEM_DISP(sp,28),R(s1_size) + movel MEM_DISP(sp,32),R(s2_limb) + + eorw #1,R(s1_size) + clrl R(d1) + clrl R(d5) + lsrl #1,R(s1_size) + bcc L(L1) + subql #1,R(s1_size) + subl R(d0),R(d0) /* (d0,cy) <= (0,0) */ + +L(Loop:) + movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d1):R(d3) + addxl R(d0),R(d3) + addxl R(d5),R(d1) + subl R(d3),MEM_POSTINC(res_ptr) +L(L1:) movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d0):R(d3) + addxl R(d1),R(d3) + addxl R(d5),R(d0) + subl R(d3),MEM_POSTINC(res_ptr) + + dbf R(s1_size),L(Loop) + addxl R(d5),R(d0) + subl #0x10000,R(s1_size) + bcc L(Loop) + +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d5) + + rts +EPILOG(_gcry_mpih_submul_1) + + diff --git a/grub-core/lib/libgcrypt/mpi/m68k/mpih-add1.S b/grub-core/lib/libgcrypt/mpi/m68k/mpih-add1.S new file mode 100644 index 0000000..8182d21 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/mpih-add1.S @@ -0,0 +1,92 @@ +/* mc68020 __mpn_add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994,1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_add_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 16) + * mpi_size_t size) (sp + 12) + */ + + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(_gcry_mpih_add_n) + +C_SYMBOL_NAME(_gcry_mpih_add_n:) +PROLOG(_gcry_mpih_add_n) + /* Save used registers on the stack. */ + movel R(d2),MEM_PREDEC(sp) + movel R(a2),MEM_PREDEC(sp) + + /* Copy the arguments to registers. Better use movem? */ + movel MEM_DISP(sp,12),R(a2) + movel MEM_DISP(sp,16),R(a0) + movel MEM_DISP(sp,20),R(a1) + movel MEM_DISP(sp,24),R(d2) + + eorw #1,R(d2) + lsrl #1,R(d2) + bcc L(L1) + subql #1,R(d2) /* clears cy as side effect */ + +L(Loop:) + movel MEM_POSTINC(a0),R(d0) + movel MEM_POSTINC(a1),R(d1) + addxl R(d1),R(d0) + movel R(d0),MEM_POSTINC(a2) +L(L1:) movel MEM_POSTINC(a0),R(d0) + movel MEM_POSTINC(a1),R(d1) + addxl R(d1),R(d0) + movel R(d0),MEM_POSTINC(a2) + + dbf R(d2),L(Loop) /* loop until 16 lsb of %4 == -1 */ + subxl R(d0),R(d0) /* d0 <= -cy; save cy as 0 or -1 in d0 */ + subl #0x10000,R(d2) + bcs L(L2) + addl R(d0),R(d0) /* restore cy */ + bra L(Loop) + +L(L2:) + negl R(d0) + + /* Restore used registers from stack frame. */ + movel MEM_POSTINC(sp),R(a2) + movel MEM_POSTINC(sp),R(d2) + + rts +EPILOG(_gcry_mpih_add_n) + + diff --git a/grub-core/lib/libgcrypt/mpi/m68k/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/m68k/mpih-lshift.S new file mode 100644 index 0000000..133d1aa --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/mpih-lshift.S @@ -0,0 +1,164 @@ +/* mc68020 lshift -- Shift left a low-level natural-number integer. + * + * Copyright (C) 1996, 1998, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_lshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +#define res_ptr a1 +#define s_ptr a0 +#define s_size d6 +#define cnt d4 + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(_gcry_mpih_lshift) + +C_SYMBOL_NAME(_gcry_mpih_lshift:) +PROLOG(_gcry_mpih_lshift) + + /* Save used registers on the stack. */ + moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp) + + /* Copy the arguments to registers. */ + movel MEM_DISP(sp,28),R(res_ptr) + movel MEM_DISP(sp,32),R(s_ptr) + movel MEM_DISP(sp,36),R(s_size) + movel MEM_DISP(sp,40),R(cnt) + + moveql #1,R(d5) + cmpl R(d5),R(cnt) + bne L(Lnormal) + cmpl R(s_ptr),R(res_ptr) + bls L(Lspecial) /* jump if s_ptr >= res_ptr */ +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) + lea MEM_INDX1(s_ptr,s_size,l,4),R(a2) +#else /* not mc68020 */ + movel R(s_size),R(d0) + asll #2,R(d0) + lea MEM_INDX(s_ptr,d0,l),R(a2) +#endif + cmpl R(res_ptr),R(a2) + bls L(Lspecial) /* jump if res_ptr >= s_ptr + s_size */ + +L(Lnormal:) + moveql #32,R(d5) + subl R(cnt),R(d5) + +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) + lea MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr) + lea MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr) +#else /* not mc68000 */ + movel R(s_size),R(d0) + asll #2,R(d0) + addl R(s_size),R(s_ptr) + addl R(s_size),R(res_ptr) +#endif + movel MEM_PREDEC(s_ptr),R(d2) + movel R(d2),R(d0) + lsrl R(d5),R(d0) /* compute carry limb */ + + lsll R(cnt),R(d2) + movel R(d2),R(d1) + subql #1,R(s_size) + beq L(Lend) + lsrl #1,R(s_size) + bcs L(L1) + subql #1,R(s_size) + +L(Loop:) + movel MEM_PREDEC(s_ptr),R(d2) + movel R(d2),R(d3) + lsrl R(d5),R(d3) + orl R(d3),R(d1) + movel R(d1),MEM_PREDEC(res_ptr) + lsll R(cnt),R(d2) +L(L1:) + movel MEM_PREDEC(s_ptr),R(d1) + movel R(d1),R(d3) + lsrl R(d5),R(d3) + orl R(d3),R(d2) + movel R(d2),MEM_PREDEC(res_ptr) + lsll R(cnt),R(d1) + + dbf R(s_size),L(Loop) + subl #0x10000,R(s_size) + bcc L(Loop) + +L(Lend:) + movel R(d1),MEM_PREDEC(res_ptr) /* store least significant limb */ + +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) + rts + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. */ + +L(Lspecial:) + clrl R(d0) /* initialize carry */ + eorw #1,R(s_size) + lsrl #1,R(s_size) + bcc L(LL1) + subql #1,R(s_size) + +L(LLoop:) + movel MEM_POSTINC(s_ptr),R(d2) + addxl R(d2),R(d2) + movel R(d2),MEM_POSTINC(res_ptr) +L(LL1:) + movel MEM_POSTINC(s_ptr),R(d2) + addxl R(d2),R(d2) + movel R(d2),MEM_POSTINC(res_ptr) + + dbf R(s_size),L(LLoop) + addxl R(d0),R(d0) /* save cy in lsb */ + subl #0x10000,R(s_size) + bcs L(LLend) + lsrl #1,R(d0) /* restore cy */ + bra L(LLoop) + +L(LLend:) +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) + rts +EPILOG(_gcry_mpih_lshift) + + + + + diff --git a/grub-core/lib/libgcrypt/mpi/m68k/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/m68k/mpih-rshift.S new file mode 100644 index 0000000..be9f435 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/mpih-rshift.S @@ -0,0 +1,162 @@ +/* mc68020 rshift -- Shift right a low-level natural-number integer. + * + * Copyright (C) 1996, 1998, 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_rshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +#define res_ptr a1 +#define s_ptr a0 +#define s_size d6 +#define cnt d4 + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(_gcry_mpih_rshift) + +C_SYMBOL_NAME(_gcry_mpih_rshift:) +PROLOG(_gcry_mpih_rshift) + /* Save used registers on the stack. */ + moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp) + + /* Copy the arguments to registers. */ + movel MEM_DISP(sp,28),R(res_ptr) + movel MEM_DISP(sp,32),R(s_ptr) + movel MEM_DISP(sp,36),R(s_size) + movel MEM_DISP(sp,40),R(cnt) + + moveql #1,R(d5) + cmpl R(d5),R(cnt) + bne L(Rnormal) + cmpl R(res_ptr),R(s_ptr) + bls L(Rspecial) /* jump if res_ptr >= s_ptr */ +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) + lea MEM_INDX1(res_ptr,s_size,l,4),R(a2) +#else /* not mc68020 */ + movel R(s_size),R(d0) + asll #2,R(d0) + lea MEM_INDX(res_ptr,d0,l),R(a2) +#endif + cmpl R(s_ptr),R(a2) + bls L(Rspecial) /* jump if s_ptr >= res_ptr + s_size */ + +L(Rnormal:) + moveql #32,R(d5) + subl R(cnt),R(d5) + movel MEM_POSTINC(s_ptr),R(d2) + movel R(d2),R(d0) + lsll R(d5),R(d0) /* compute carry limb */ + + lsrl R(cnt),R(d2) + movel R(d2),R(d1) + subql #1,R(s_size) + beq L(Rend) + lsrl #1,R(s_size) + bcs L(R1) + subql #1,R(s_size) + +L(Roop:) + movel MEM_POSTINC(s_ptr),R(d2) + movel R(d2),R(d3) + lsll R(d5),R(d3) + orl R(d3),R(d1) + movel R(d1),MEM_POSTINC(res_ptr) + lsrl R(cnt),R(d2) +L(R1:) + movel MEM_POSTINC(s_ptr),R(d1) + movel R(d1),R(d3) + lsll R(d5),R(d3) + orl R(d3),R(d2) + movel R(d2),MEM_POSTINC(res_ptr) + lsrl R(cnt),R(d1) + + dbf R(s_size),L(Roop) + subl #0x10000,R(s_size) + bcc L(Roop) + +L(Rend:) + movel R(d1),MEM(res_ptr) /* store most significant limb */ + +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) + rts + +/* We loop from most significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. */ + +L(Rspecial:) +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) + lea MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr) + lea MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr) +#else /* not mc68000 */ + movel R(s_size),R(d0) + asll #2,R(d0) + addl R(s_size),R(s_ptr) + addl R(s_size),R(res_ptr) +#endif + + clrl R(d0) /* initialize carry */ + eorw #1,R(s_size) + lsrl #1,R(s_size) + bcc L(LR1) + subql #1,R(s_size) + +L(LRoop:) + movel MEM_PREDEC(s_ptr),R(d2) + roxrl #1,R(d2) + movel R(d2),MEM_PREDEC(res_ptr) +L(LR1:) + movel MEM_PREDEC(s_ptr),R(d2) + roxrl #1,R(d2) + movel R(d2),MEM_PREDEC(res_ptr) + + dbf R(s_size),L(LRoop) + roxrl #1,R(d0) /* save cy in msb */ + subl #0x10000,R(s_size) + bcs L(LRend) + addl R(d0),R(d0) /* restore cy */ + bra L(LRoop) + +L(LRend:) +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) + rts +EPILOG(_gcry_mpih_rshift) + + + + diff --git a/grub-core/lib/libgcrypt/mpi/m68k/mpih-sub1.S b/grub-core/lib/libgcrypt/mpi/m68k/mpih-sub1.S new file mode 100644 index 0000000..ee7555f --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/mpih-sub1.S @@ -0,0 +1,91 @@ +/* mc68020 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and + * store difference in a third limb vector. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_sub_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 16) + * mpi_size_t size) (sp + 12) + */ + + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(_gcry_mpih_sub_n) + +C_SYMBOL_NAME(_gcry_mpih_sub_n:) +PROLOG(_gcry_mpih_sub_n) +/* Save used registers on the stack. */ + movel R(d2),MEM_PREDEC(sp) + movel R(a2),MEM_PREDEC(sp) + +/* Copy the arguments to registers. Better use movem? */ + movel MEM_DISP(sp,12),R(a2) + movel MEM_DISP(sp,16),R(a0) + movel MEM_DISP(sp,20),R(a1) + movel MEM_DISP(sp,24),R(d2) + + eorw #1,R(d2) + lsrl #1,R(d2) + bcc L(L1) + subql #1,R(d2) /* clears cy as side effect */ + +L(Loop:) + movel MEM_POSTINC(a0),R(d0) + movel MEM_POSTINC(a1),R(d1) + subxl R(d1),R(d0) + movel R(d0),MEM_POSTINC(a2) +L(L1:) movel MEM_POSTINC(a0),R(d0) + movel MEM_POSTINC(a1),R(d1) + subxl R(d1),R(d0) + movel R(d0),MEM_POSTINC(a2) + + dbf R(d2),L(Loop) /* loop until 16 lsb of %4 == -1 */ + subxl R(d0),R(d0) /* d0 <= -cy; save cy as 0 or -1 in d0 */ + subl #0x10000,R(d2) + bcs L(L2) + addl R(d0),R(d0) /* restore cy */ + bra L(Loop) + +L(L2:) + negl R(d0) + +/* Restore used registers from stack frame. */ + movel MEM_POSTINC(sp),R(a2) + movel MEM_POSTINC(sp),R(d2) + + rts +EPILOG(_gcry_mpih_sub_n) + + diff --git a/grub-core/lib/libgcrypt/mpi/m68k/syntax.h b/grub-core/lib/libgcrypt/mpi/m68k/syntax.h new file mode 100644 index 0000000..e27de98 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/m68k/syntax.h @@ -0,0 +1,185 @@ +/* asm.h -- Definitions for 68k syntax variations. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#undef ALIGN + +#ifdef MIT_SYNTAX +#define PROLOG(name) +#define EPILOG(name) +#define R(r)r +#define MEM(base)base@ +#define MEM_DISP(base,displacement)base@(displacement) +#define MEM_INDX(base,idx,size_suffix)base@(idx:size_suffix) +#define MEM_INDX1(base,idx,size_suffix,scale)base@(idx:size_suffix:scale) +#define MEM_PREDEC(memory_base)memory_base@- +#define MEM_POSTINC(memory_base)memory_base@+ +#define L(label) label +#define TEXT .text +#define ALIGN .even +#define GLOBL .globl +#define moveql moveq +/* Use variable sized opcodes. */ +#define bcc jcc +#define bcs jcs +#define bls jls +#define beq jeq +#define bne jne +#define bra jra +#endif + +#ifdef SONY_SYNTAX +#define PROLOG(name) +#define EPILOG(name) +#define R(r)r +#define MEM(base)(base) +#define MEM_DISP(base,displacement)(displacement,base) +#define MEM_INDX(base,idx,size_suffix)(base,idx.size_suffix) +#define MEM_INDX1(base,idx,size_suffix,scale)(base,idx.size_suffix*scale) +#define MEM_PREDEC(memory_base)-(memory_base) +#define MEM_POSTINC(memory_base)(memory_base)+ +#define L(label) label +#define TEXT .text +#define ALIGN .even +#define GLOBL .globl +#endif + +#ifdef MOTOROLA_SYNTAX +#define PROLOG(name) +#define EPILOG(name) +#define R(r)r +#define MEM(base)(base) +#define MEM_DISP(base,displacement)(displacement,base) +#define MEM_INDX(base,idx,size_suffix)(base,idx.size_suffix) +#define MEM_INDX1(base,idx,size_suffix,scale)(base,idx.size_suffix*scale) +#define MEM_PREDEC(memory_base)-(memory_base) +#define MEM_POSTINC(memory_base)(memory_base)+ +#define L(label) label +#define TEXT +#define ALIGN +#define GLOBL XDEF +#define lea LEA +#define movel MOVE.L +#define moveml MOVEM.L +#define moveql MOVEQ.L +#define cmpl CMP.L +#define orl OR.L +#define clrl CLR.L +#define eorw EOR.W +#define lsrl LSR.L +#define lsll LSL.L +#define roxrl ROXR.L +#define roxll ROXL.L +#define addl ADD.L +#define addxl ADDX.L +#define addql ADDQ.L +#define subl SUB.L +#define subxl SUBX.L +#define subql SUBQ.L +#define negl NEG.L +#define mulul MULU.L +#define bcc BCC +#define bcs BCS +#define bls BLS +#define beq BEQ +#define bne BNE +#define bra BRA +#define dbf DBF +#define rts RTS +#define d0 D0 +#define d1 D1 +#define d2 D2 +#define d3 D3 +#define d4 D4 +#define d5 D5 +#define d6 D6 +#define d7 D7 +#define a0 A0 +#define a1 A1 +#define a2 A2 +#define a3 A3 +#define a4 A4 +#define a5 A5 +#define a6 A6 +#define a7 A7 +#define sp SP +#endif + +#ifdef ELF_SYNTAX +#define PROLOG(name) .type name,@function +#define EPILOG(name) .size name,.-name +#define MEM(base)(R(base)) +#define MEM_DISP(base,displacement)(displacement,R(base)) +#define MEM_PREDEC(memory_base)-(R(memory_base)) +#define MEM_POSTINC(memory_base)(R(memory_base))+ +#ifdef __STDC__ +#define R_(r)%##r +#define R(r)R_(r) +#define MEM_INDX_(base,idx,size_suffix)(R(base),R(idx##.##size_suffix)) +#define MEM_INDX(base,idx,size_suffix)MEM_INDX_(base,idx,size_suffix) +#define MEM_INDX1_(base,idx,size_suffix,scale)(R(base),R(idx##.##size_suffix*scale)) +#define MEM_INDX1(base,idx,size_suffix,scale)MEM_INDX1_(base,idx,size_suffix,scale) +#define L(label) .##label +#else +#define R(r)%/**/r +#define MEM_INDX(base,idx,size_suffix)(R(base),R(idx).size_suffix) +#define MEM_INDX1(base,idx,size_suffix,scale)(R(base),R(idx).size_suffix*scale) +#define L(label) ./**/label +#endif +#define TEXT .text +#define ALIGN .align 2 +#define GLOBL .globl +#define bcc jbcc +#define bcs jbcs +#define bls jbls +#define beq jbeq +#define bne jbne +#define bra jbra +#endif + +#if defined (SONY_SYNTAX) || defined (ELF_SYNTAX) +#define movel move.l +#define moveml movem.l +#define moveql moveq.l +#define cmpl cmp.l +#define orl or.l +#define clrl clr.l +#define eorw eor.w +#define lsrl lsr.l +#define lsll lsl.l +#define roxrl roxr.l +#define roxll roxl.l +#define addl add.l +#define addxl addx.l +#define addql addq.l +#define subl sub.l +#define subxl subx.l +#define subql subq.l +#define negl neg.l +#define mulul mulu.l +#endif diff --git a/grub-core/lib/libgcrypt/mpi/mips3/Manifest b/grub-core/lib/libgcrypt/mpi/mips3/Manifest new file mode 100644 index 0000000..e191184 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mips3/Manifest @@ -0,0 +1,28 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +mpih-add1.S +mpih-sub1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +mpi-asm-defs.h +$names$ iQCVAwUAP+LmUTEAnp832S/7AQLm/gP/RHR2aLMwHPxsq0mGO5H0kneVn8a9l9yDNEZBefkYcOJMb7MZGKxbGspyENiU04Mc2TFnA1wS9gjNHlRWtUYxxn/wyuV6BIRgfstXt2nXGgEQrK07GIz8ETFcYqcxu7JKiICIuXZgnIgdwBJswbBV1zaMUDXeg5B8vkkEeRWj8hQ==IQVO diff --git a/grub-core/lib/libgcrypt/mpi/mips3/README b/grub-core/lib/libgcrypt/mpi/mips3/README new file mode 100644 index 0000000..e94b2c7 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mips3/README @@ -0,0 +1,23 @@ +This directory contains mpn functions optimized for MIPS3. Example of +processors that implement MIPS3 are R4000, R4400, R4600, R4700, and R8000. + +RELEVANT OPTIMIZATION ISSUES + +1. On the R4000 and R4400, branches, both the plain and the "likely" ones, + take 3 cycles to execute. (The fastest possible loop will take 4 cycles, + because of the delay insn.) + + On the R4600, branches takes a single cycle + + On the R8000, branches often take no noticable cycles, as they are + executed in a separate function unit.. + +2. The R4000 and R4400 have a load latency of 4 cycles. + +3. On the R4000 and R4400, multiplies take a data-dependent number of + cycles, contrary to the SGI documentation. There seem to be 3 or 4 + possible latencies. + +STATUS + +Good... diff --git a/grub-core/lib/libgcrypt/mpi/mips3/distfiles b/grub-core/lib/libgcrypt/mpi/mips3/distfiles new file mode 100644 index 0000000..ef9b6fe --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mips3/distfiles @@ -0,0 +1,11 @@ +Manifest +README +mpih-add1.S +mpih-sub1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +mpi-asm-defs.h + diff --git a/grub-core/lib/libgcrypt/mpi/mips3/mpi-asm-defs.h b/grub-core/lib/libgcrypt/mpi/mips3/mpi-asm-defs.h new file mode 100644 index 0000000..2d9a9c1 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mips3/mpi-asm-defs.h @@ -0,0 +1,10 @@ +/* This file defines some basic constants for the MPI machinery. We + * need to define the types on a per-CPU basis, so it is done with + * this file here. */ +#define BYTES_PER_MPI_LIMB 8 + + + + + + diff --git a/grub-core/lib/libgcrypt/mpi/mips3/mpih-add1.S b/grub-core/lib/libgcrypt/mpi/mips3/mpih-add1.S new file mode 100644 index 0000000..f3db029 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mips3/mpih-add1.S @@ -0,0 +1,124 @@ +/* mips3 add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1995, 1998, 2000 + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * _gcry_mpih_add_n( mpi_ptr_t res_ptr, ($4) + * mpi_ptr_t s1_ptr, ($5) + * mpi_ptr_t s2_ptr, ($6) + * mpi_size_t size) ($7) + */ + + .text + .align 2 + .globl _gcry_mpih_add_n + .ent _gcry_mpih_add_n +_gcry_mpih_add_n: + .set noreorder + .set nomacro + + ld $10,0($5) + ld $11,0($6) + + daddiu $7,$7,-1 + and $9,$7,4-1 # number of limbs in first loop + beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop + move $2,$0 + + dsubu $7,$7,$9 + +.Loop0: daddiu $9,$9,-1 + ld $12,8($5) + daddu $11,$11,$2 + ld $13,8($6) + sltu $8,$11,$2 + daddu $11,$10,$11 + sltu $2,$11,$10 + sd $11,0($4) + or $2,$2,$8 + + daddiu $5,$5,8 + daddiu $6,$6,8 + move $10,$12 + move $11,$13 + bne $9,$0,.Loop0 + daddiu $4,$4,8 + +.L0: beq $7,$0,.Lend + nop + +.Loop: daddiu $7,$7,-4 + + ld $12,8($5) + daddu $11,$11,$2 + ld $13,8($6) + sltu $8,$11,$2 + daddu $11,$10,$11 + sltu $2,$11,$10 + sd $11,0($4) + or $2,$2,$8 + + ld $10,16($5) + daddu $13,$13,$2 + ld $11,16($6) + sltu $8,$13,$2 + daddu $13,$12,$13 + sltu $2,$13,$12 + sd $13,8($4) + or $2,$2,$8 + + ld $12,24($5) + daddu $11,$11,$2 + ld $13,24($6) + sltu $8,$11,$2 + daddu $11,$10,$11 + sltu $2,$11,$10 + sd $11,16($4) + or $2,$2,$8 + + ld $10,32($5) + daddu $13,$13,$2 + ld $11,32($6) + sltu $8,$13,$2 + daddu $13,$12,$13 + sltu $2,$13,$12 + sd $13,24($4) + or $2,$2,$8 + + daddiu $5,$5,32 + daddiu $6,$6,32 + + bne $7,$0,.Loop + daddiu $4,$4,32 + +.Lend: daddu $11,$11,$2 + sltu $8,$11,$2 + daddu $11,$10,$11 + sltu $2,$11,$10 + sd $11,0($4) + j $31 + or $2,$2,$8 + + .end _gcry_mpih_add_n + diff --git a/grub-core/lib/libgcrypt/mpi/mips3/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/mips3/mpih-lshift.S new file mode 100644 index 0000000..084c109 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mips3/mpih-lshift.S @@ -0,0 +1,97 @@ +/* mips3 lshift + * + * Copyright (C) 1995, 1998, 2000, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/******************* + * mpi_limb_t + * _gcry_mpih_lshift( mpi_ptr_t wp, ($4) + * mpi_ptr_t up, ($5) + * mpi_size_t usize, ($6) + * unsigned cnt) ($7) + */ + + .text + .align 2 + .globl _gcry_mpih_lshift + .ent _gcry_mpih_lshift +_gcry_mpih_lshift: + .set noreorder + .set nomacro + + dsll $2,$6,3 + daddu $5,$5,$2 # make r5 point at end of src + ld $10,-8($5) # load first limb + dsubu $13,$0,$7 + daddu $4,$4,$2 # make r4 point at end of res + daddiu $6,$6,-1 + and $9,$6,4-1 # number of limbs in first loop + beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop + dsrl $2,$10,$13 # compute function result + + dsubu $6,$6,$9 + +.Loop0: ld $3,-16($5) + daddiu $4,$4,-8 + daddiu $5,$5,-8 + daddiu $9,$9,-1 + dsll $11,$10,$7 + dsrl $12,$3,$13 + move $10,$3 + or $8,$11,$12 + bne $9,$0,.Loop0 + sd $8,0($4) + +.L0: beq $6,$0,.Lend + nop + +.Loop: ld $3,-16($5) + daddiu $4,$4,-32 + daddiu $6,$6,-4 + dsll $11,$10,$7 + dsrl $12,$3,$13 + + ld $10,-24($5) + dsll $14,$3,$7 + or $8,$11,$12 + sd $8,24($4) + dsrl $9,$10,$13 + + ld $3,-32($5) + dsll $11,$10,$7 + or $8,$14,$9 + sd $8,16($4) + dsrl $12,$3,$13 + + ld $10,-40($5) + dsll $14,$3,$7 + or $8,$11,$12 + sd $8,8($4) + dsrl $9,$10,$13 + + daddiu $5,$5,-32 + or $8,$14,$9 + bgtz $6,.Loop + sd $8,0($4) + +.Lend: dsll $8,$10,$7 + j $31 + sd $8,-8($4) + .end _gcry_mpih_lshift diff --git a/grub-core/lib/libgcrypt/mpi/mips3/mpih-mul1.S b/grub-core/lib/libgcrypt/mpi/mips3/mpih-mul1.S new file mode 100644 index 0000000..6c0099d --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mips3/mpih-mul1.S @@ -0,0 +1,89 @@ +/* mips3 mpih-mul1.S -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, 2000 + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * _gcry_mpih_mul_1( mpi_ptr_t res_ptr, (r4) + * mpi_ptr_t s1_ptr, (r5) + * mpi_size_t s1_size, (r6) + * mpi_limb_t s2_limb) (r7) + */ + + .text + .align 4 + .globl _gcry_mpih_mul_1 + .ent _gcry_mpih_mul_1 +_gcry_mpih_mul_1: + .set noreorder + .set nomacro + +/* # warm up phase 0 */ + ld $8,0($5) + +/* # warm up phase 1 */ + daddiu $5,$5,8 + dmultu $8,$7 + + daddiu $6,$6,-1 + beq $6,$0,$LC0 + move $2,$0 # zero cy2 + + daddiu $6,$6,-1 + beq $6,$0,$LC1 + ld $8,0($5) # load new s1 limb as early as possible + +Loop: mflo $10 + mfhi $9 + daddiu $5,$5,8 + daddu $10,$10,$2 # add old carry limb to low product limb + dmultu $8,$7 + ld $8,0($5) # load new s1 limb as early as possible + daddiu $6,$6,-1 # decrement loop counter + sltu $2,$10,$2 # carry from previous addition -> $2 + sd $10,0($4) + daddiu $4,$4,8 + bne $6,$0,Loop + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 1 */ +$LC1: mflo $10 + mfhi $9 + daddu $10,$10,$2 + sltu $2,$10,$2 + dmultu $8,$7 + sd $10,0($4) + daddiu $4,$4,8 + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 0 */ +$LC0: mflo $10 + mfhi $9 + daddu $10,$10,$2 + sltu $2,$10,$2 + sd $10,0($4) + j $31 + daddu $2,$9,$2 # add high product limb and carry from addition + + .end _gcry_mpih_mul_1 + diff --git a/grub-core/lib/libgcrypt/mpi/mips3/mpih-mul2.S b/grub-core/lib/libgcrypt/mpi/mips3/mpih-mul2.S new file mode 100644 index 0000000..ca82763 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mips3/mpih-mul2.S @@ -0,0 +1,101 @@ +/* MIPS3 addmul_1 -- Multiply a limb vector with a single limb and + * add the product to a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, 2000 + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, (r4) + * mpi_ptr_t s1_ptr, (r5) + * mpi_size_t s1_size, (r6) + * mpi_limb_t s2_limb) (r7) + */ + + .text + .align 4 + .globl _gcry_mpih_addmul_1 + .ent _gcry_mpih_addmul_1 +_gcry_mpih_addmul_1: + .set noreorder + .set nomacro + +/* # warm up phase 0 */ + ld $8,0($5) + +/* # warm up phase 1 */ + daddiu $5,$5,8 + dmultu $8,$7 + + daddiu $6,$6,-1 + beq $6,$0,$LC0 + move $2,$0 # zero cy2 + + daddiu $6,$6,-1 + beq $6,$0,$LC1 + ld $8,0($5) # load new s1 limb as early as possible + +Loop: ld $10,0($4) + mflo $3 + mfhi $9 + daddiu $5,$5,8 + daddu $3,$3,$2 # add old carry limb to low product limb + dmultu $8,$7 + ld $8,0($5) # load new s1 limb as early as possible + daddiu $6,$6,-1 # decrement loop counter + sltu $2,$3,$2 # carry from previous addition -> $2 + daddu $3,$10,$3 + sltu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + daddiu $4,$4,8 + bne $6,$0,Loop + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 1 */ +$LC1: ld $10,0($4) + mflo $3 + mfhi $9 + daddu $3,$3,$2 + sltu $2,$3,$2 + dmultu $8,$7 + daddu $3,$10,$3 + sltu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + daddiu $4,$4,8 + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 0 */ +$LC0: ld $10,0($4) + mflo $3 + mfhi $9 + daddu $3,$3,$2 + sltu $2,$3,$2 + daddu $3,$10,$3 + sltu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + j $31 + daddu $2,$9,$2 # add high product limb and carry from addition + + .end _gcry_mpih_addmul_1 + diff --git a/grub-core/lib/libgcrypt/mpi/mips3/mpih-mul3.S b/grub-core/lib/libgcrypt/mpi/mips3/mpih-mul3.S new file mode 100644 index 0000000..be421a6 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mips3/mpih-mul3.S @@ -0,0 +1,101 @@ +/* MIPS3 submul_1 -- Multiply a limb vector with a single limb and + * subtract the product from a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, 2000 + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * _gcry_mpih_submul_1( mpi_ptr_t res_ptr, (r4) + * mpi_ptr_t s1_ptr, (r5) + * mpi_size_t s1_size, (r6) + * mpi_limb_t s2_limb) (r7) + */ + + .text + .align 4 + .globl _gcry_mpih_submul_1 + .ent _gcry_mpih_submul_1 +_gcry_mpih_submul_1: + .set noreorder + .set nomacro + +/* # warm up phase 0 */ + ld $8,0($5) + +/* # warm up phase 1 */ + daddiu $5,$5,8 + dmultu $8,$7 + + daddiu $6,$6,-1 + beq $6,$0,$LC0 + move $2,$0 # zero cy2 + + daddiu $6,$6,-1 + beq $6,$0,$LC1 + ld $8,0($5) # load new s1 limb as early as possible + +Loop: ld $10,0($4) + mflo $3 + mfhi $9 + daddiu $5,$5,8 + daddu $3,$3,$2 # add old carry limb to low product limb + dmultu $8,$7 + ld $8,0($5) # load new s1 limb as early as possible + daddiu $6,$6,-1 # decrement loop counter + sltu $2,$3,$2 # carry from previous addition -> $2 + dsubu $3,$10,$3 + sgtu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + daddiu $4,$4,8 + bne $6,$0,Loop + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 1 */ +$LC1: ld $10,0($4) + mflo $3 + mfhi $9 + daddu $3,$3,$2 + sltu $2,$3,$2 + dmultu $8,$7 + dsubu $3,$10,$3 + sgtu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + daddiu $4,$4,8 + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 0 */ +$LC0: ld $10,0($4) + mflo $3 + mfhi $9 + daddu $3,$3,$2 + sltu $2,$3,$2 + dsubu $3,$10,$3 + sgtu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + j $31 + daddu $2,$9,$2 # add high product limb and carry from addition + + .end _gcry_mpih_submul_1 + diff --git a/grub-core/lib/libgcrypt/mpi/mips3/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/mips3/mpih-rshift.S new file mode 100644 index 0000000..e7e035a --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mips3/mpih-rshift.S @@ -0,0 +1,95 @@ +/* mips3 rshift + * + * Copyright (C) 1995, 1998, 2000 + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/******************* + * mpi_limb_t + * _gcry_mpih_rshift( mpi_ptr_t wp, ($4) + * mpi_ptr_t up, ($5) + * mpi_size_t usize, ($6) + * unsigned cnt) ($7) + */ + + .text + .align 2 + .globl _gcry_mpih_rshift + .ent _gcry_mpih_rshift +_gcry_mpih_rshift: + .set noreorder + .set nomacro + + ld $10,0($5) # load first limb + dsubu $13,$0,$7 + daddiu $6,$6,-1 + and $9,$6,4-1 # number of limbs in first loop + beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop + dsll $2,$10,$13 # compute function result + + dsubu $6,$6,$9 + +.Loop0: ld $3,8($5) + daddiu $4,$4,8 + daddiu $5,$5,8 + daddiu $9,$9,-1 + dsrl $11,$10,$7 + dsll $12,$3,$13 + move $10,$3 + or $8,$11,$12 + bne $9,$0,.Loop0 + sd $8,-8($4) + +.L0: beq $6,$0,.Lend + nop + +.Loop: ld $3,8($5) + daddiu $4,$4,32 + daddiu $6,$6,-4 + dsrl $11,$10,$7 + dsll $12,$3,$13 + + ld $10,16($5) + dsrl $14,$3,$7 + or $8,$11,$12 + sd $8,-32($4) + dsll $9,$10,$13 + + ld $3,24($5) + dsrl $11,$10,$7 + or $8,$14,$9 + sd $8,-24($4) + dsll $12,$3,$13 + + ld $10,32($5) + dsrl $14,$3,$7 + or $8,$11,$12 + sd $8,-16($4) + dsll $9,$10,$13 + + daddiu $5,$5,32 + or $8,$14,$9 + bgtz $6,.Loop + sd $8,-8($4) + +.Lend: dsrl $8,$10,$7 + j $31 + sd $8,0($4) + .end _gcry_mpih_rshift + diff --git a/grub-core/lib/libgcrypt/mpi/mips3/mpih-sub1.S b/grub-core/lib/libgcrypt/mpi/mips3/mpih-sub1.S new file mode 100644 index 0000000..9fac674 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mips3/mpih-sub1.S @@ -0,0 +1,125 @@ +/* mips3 sub_n -- Subtract two limb vectors of the same length > 0 and + * store difference in a third limb vector. + * + * Copyright (C) 1995, 1998, 1999, 2000, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * _gcry_mpih_sub_n( mpi_ptr_t res_ptr, (r4) + * mpi_ptr_t s1_ptr, (r5) + * mpi_ptr_t s2_ptr, (r6) + * mpi_size_t size) (r7) + */ + + + .text + .align 2 + .globl _gcry_mpih_sub_n + .ent _gcry_mpih_sub_n +_gcry_mpih_sub_n: + .set noreorder + .set nomacro + + ld $10,0($5) + ld $11,0($6) + + daddiu $7,$7,-1 + and $9,$7,4-1 # number of limbs in first loop + beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop + move $2,$0 + + dsubu $7,$7,$9 + +.Loop0: daddiu $9,$9,-1 + ld $12,8($5) + daddu $11,$11,$2 + ld $13,8($6) + sltu $8,$11,$2 + dsubu $11,$10,$11 + sltu $2,$10,$11 + sd $11,0($4) + or $2,$2,$8 + + daddiu $5,$5,8 + daddiu $6,$6,8 + move $10,$12 + move $11,$13 + bne $9,$0,.Loop0 + daddiu $4,$4,8 + +.L0: beq $7,$0,.Lend + nop + +.Loop: daddiu $7,$7,-4 + + ld $12,8($5) + daddu $11,$11,$2 + ld $13,8($6) + sltu $8,$11,$2 + dsubu $11,$10,$11 + sltu $2,$10,$11 + sd $11,0($4) + or $2,$2,$8 + + ld $10,16($5) + daddu $13,$13,$2 + ld $11,16($6) + sltu $8,$13,$2 + dsubu $13,$12,$13 + sltu $2,$12,$13 + sd $13,8($4) + or $2,$2,$8 + + ld $12,24($5) + daddu $11,$11,$2 + ld $13,24($6) + sltu $8,$11,$2 + dsubu $11,$10,$11 + sltu $2,$10,$11 + sd $11,16($4) + or $2,$2,$8 + + ld $10,32($5) + daddu $13,$13,$2 + ld $11,32($6) + sltu $8,$13,$2 + dsubu $13,$12,$13 + sltu $2,$12,$13 + sd $13,24($4) + or $2,$2,$8 + + daddiu $5,$5,32 + daddiu $6,$6,32 + + bne $7,$0,.Loop + daddiu $4,$4,32 + +.Lend: daddu $11,$11,$2 + sltu $8,$11,$2 + dsubu $11,$10,$11 + sltu $2,$10,$11 + sd $11,0($4) + j $31 + or $2,$2,$8 + + .end _gcry_mpih_sub_n + diff --git a/grub-core/lib/libgcrypt/mpi/mpi-add.c b/grub-core/lib/libgcrypt/mpi/mpi-add.c new file mode 100644 index 0000000..98abc56 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-add.c @@ -0,0 +1,235 @@ +/* mpi-add.c - MPI functions + * Copyright (C) 1994, 1996, 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "mpi-internal.h" + + +/**************** + * Add the unsigned integer V to the mpi-integer U and store the + * result in W. U and V may be the same. + */ +void +gcry_mpi_add_ui(gcry_mpi_t w, gcry_mpi_t u, unsigned long v ) +{ + mpi_ptr_t wp, up; + mpi_size_t usize, wsize; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + wsign = 0; + + /* If not space for W (and possible carry), increase space. */ + wsize = usize + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->d; + wp = w->d; + + if( !usize ) { /* simple */ + wp[0] = v; + wsize = v? 1:0; + } + else if( !usign ) { /* mpi is not negative */ + mpi_limb_t cy; + cy = _gcry_mpih_add_1(wp, up, usize, v); + wp[usize] = cy; + wsize = usize + cy; + } + else { /* The signs are different. Need exact comparison to determine + * which operand to subtract from which. */ + if( usize == 1 && up[0] < v ) { + wp[0] = v - up[0]; + wsize = 1; + } + else { + _gcry_mpih_sub_1(wp, up, usize, v); + /* Size can decrease with at most one limb. */ + wsize = usize - (wp[usize-1]==0); + wsign = 1; + } + } + + w->nlimbs = wsize; + w->sign = wsign; +} + + +void +gcry_mpi_add(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v) +{ + mpi_ptr_t wp, up, vp; + mpi_size_t usize, vsize, wsize; + int usign, vsign, wsign; + + if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ + usize = v->nlimbs; + usign = v->sign; + vsize = u->nlimbs; + vsign = u->sign; + wsize = usize + 1; + RESIZE_IF_NEEDED(w, wsize); + /* These must be after realloc (u or v may be the same as w). */ + up = v->d; + vp = u->d; + } + else { + usize = u->nlimbs; + usign = u->sign; + vsize = v->nlimbs; + vsign = v->sign; + wsize = usize + 1; + RESIZE_IF_NEEDED(w, wsize); + /* These must be after realloc (u or v may be the same as w). */ + up = u->d; + vp = v->d; + } + wp = w->d; + wsign = 0; + + if( !vsize ) { /* simple */ + MPN_COPY(wp, up, usize ); + wsize = usize; + wsign = usign; + } + else if( usign != vsign ) { /* different sign */ + /* This test is right since USIZE >= VSIZE */ + if( usize != vsize ) { + _gcry_mpih_sub(wp, up, usize, vp, vsize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + wsign = usign; + } + else if( _gcry_mpih_cmp(up, vp, usize) < 0 ) { + _gcry_mpih_sub_n(wp, vp, up, usize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + if( !usign ) + wsign = 1; + } + else { + _gcry_mpih_sub_n(wp, up, vp, usize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + if( usign ) + wsign = 1; + } + } + else { /* U and V have same sign. Add them. */ + mpi_limb_t cy = _gcry_mpih_add(wp, up, usize, vp, vsize); + wp[usize] = cy; + wsize = usize + cy; + if( usign ) + wsign = 1; + } + + w->nlimbs = wsize; + w->sign = wsign; +} + + +/**************** + * Subtract the unsigned integer V from the mpi-integer U and store the + * result in W. + */ +void +gcry_mpi_sub_ui(gcry_mpi_t w, gcry_mpi_t u, unsigned long v ) +{ + mpi_ptr_t wp, up; + mpi_size_t usize, wsize; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + wsign = 0; + + /* If not space for W (and possible carry), increase space. */ + wsize = usize + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->d; + wp = w->d; + + if( !usize ) { /* simple */ + wp[0] = v; + wsize = v? 1:0; + wsign = 1; + } + else if( usign ) { /* mpi and v are negative */ + mpi_limb_t cy; + cy = _gcry_mpih_add_1(wp, up, usize, v); + wp[usize] = cy; + wsize = usize + cy; + } + else { /* The signs are different. Need exact comparison to determine + * which operand to subtract from which. */ + if( usize == 1 && up[0] < v ) { + wp[0] = v - up[0]; + wsize = 1; + wsign = 1; + } + else { + _gcry_mpih_sub_1(wp, up, usize, v); + /* Size can decrease with at most one limb. */ + wsize = usize - (wp[usize-1]==0); + } + } + + w->nlimbs = wsize; + w->sign = wsign; +} + +void +gcry_mpi_sub(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v) +{ + gcry_mpi_t vv = mpi_copy (v); + vv->sign = ! vv->sign; + gcry_mpi_add (w, u, vv); + mpi_free (vv); +} + + +void +gcry_mpi_addm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) +{ + gcry_mpi_add(w, u, v); + _gcry_mpi_fdiv_r( w, w, m ); +} + +void +gcry_mpi_subm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) +{ + gcry_mpi_sub(w, u, v); + _gcry_mpi_fdiv_r( w, w, m ); +} diff --git a/grub-core/lib/libgcrypt/mpi/mpi-bit.c b/grub-core/lib/libgcrypt/mpi/mpi-bit.c new file mode 100644 index 0000000..cdc6b0b --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-bit.c @@ -0,0 +1,364 @@ +/* mpi-bit.c - MPI bit level functions + * Copyright (C) 1998, 1999, 2001, 2002, 2006 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +#ifdef MPI_INTERNAL_NEED_CLZ_TAB +#ifdef __STDC__ +const +#endif +unsigned char +_gcry_clz_tab[] = +{ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +}; +#endif + + +#define A_LIMB_1 ((mpi_limb_t)1) + + +/**************** + * Sometimes we have MSL (most significant limbs) which are 0; + * this is for some reasons not good, so this function removes them. + */ +void +_gcry_mpi_normalize( gcry_mpi_t a ) +{ + if( mpi_is_opaque(a) ) + return; + + for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- ) + ; +} + + + +/**************** + * Return the number of bits in A. + */ +unsigned int +gcry_mpi_get_nbits( gcry_mpi_t a ) +{ + unsigned n; + + if( mpi_is_opaque(a) ) { + return a->sign; /* which holds the number of bits */ + } + + _gcry_mpi_normalize( a ); + if( a->nlimbs ) { + mpi_limb_t alimb = a->d[a->nlimbs-1]; + if( alimb ) + count_leading_zeros( n, alimb ); + else + n = BITS_PER_MPI_LIMB; + n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB; + } + else + n = 0; + return n; +} + + +/**************** + * Test whether bit N is set. + */ +int +gcry_mpi_test_bit( gcry_mpi_t a, unsigned int n ) +{ + unsigned int limbno, bitno; + mpi_limb_t limb; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return 0; /* too far left: this is a 0 */ + limb = a->d[limbno]; + return (limb & (A_LIMB_1 << bitno))? 1: 0; +} + + +/**************** + * Set bit N of A. + */ +void +gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n ) +{ + unsigned int limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if ( limbno >= a->nlimbs ) + { + mpi_resize (a, limbno+1 ); + a->nlimbs = limbno+1; + } + a->d[limbno] |= (A_LIMB_1<<bitno); +} + +/**************** + * Set bit N of A. and clear all bits above + */ +void +gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n ) +{ + unsigned int limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if ( limbno >= a->nlimbs ) + { + mpi_resize (a, limbno+1 ); + a->nlimbs = limbno+1; + } + a->d[limbno] |= (A_LIMB_1<<bitno); + for ( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ ) + a->d[limbno] &= ~(A_LIMB_1 << bitno); + a->nlimbs = limbno+1; +} + +/**************** + * clear bit N of A and all bits above + */ +void +gcry_mpi_clear_highbit( gcry_mpi_t a, unsigned int n ) +{ + unsigned int limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return; /* not allocated, therefore no need to clear bits + :-) */ + + for( ; bitno < BITS_PER_MPI_LIMB; bitno++ ) + a->d[limbno] &= ~(A_LIMB_1 << bitno); + a->nlimbs = limbno+1; +} + +/**************** + * Clear bit N of A. + */ +void +gcry_mpi_clear_bit( gcry_mpi_t a, unsigned int n ) +{ + unsigned int limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return; /* don't need to clear this bit, it's to far to left */ + a->d[limbno] &= ~(A_LIMB_1 << bitno); +} + + +/**************** + * Shift A by COUNT limbs to the right + * This is used only within the MPI library + */ +void +_gcry_mpi_rshift_limbs( gcry_mpi_t a, unsigned int count ) +{ + mpi_ptr_t ap = a->d; + mpi_size_t n = a->nlimbs; + unsigned int i; + + if( count >= n ) { + a->nlimbs = 0; + return; + } + + for( i = 0; i < n - count; i++ ) + ap[i] = ap[i+count]; + ap[i] = 0; + a->nlimbs -= count; +} + + +/* + * Shift A by N bits to the right. + */ +void +gcry_mpi_rshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n ) +{ + mpi_size_t xsize; + unsigned int i; + unsigned int nlimbs = (n/BITS_PER_MPI_LIMB); + unsigned int nbits = (n%BITS_PER_MPI_LIMB); + + if ( x == a ) + { + /* In-place operation. */ + if ( nlimbs >= x->nlimbs ) + { + x->nlimbs = 0; + return; + } + + if (nlimbs) + { + for (i=0; i < x->nlimbs - nlimbs; i++ ) + x->d[i] = x->d[i+nlimbs]; + x->d[i] = 0; + x->nlimbs -= nlimbs; + + } + if ( x->nlimbs && nbits ) + _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits ); + } + else if ( nlimbs ) + { + /* Copy and shift by more or equal bits than in a limb. */ + xsize = a->nlimbs; + x->sign = a->sign; + RESIZE_IF_NEEDED (x, xsize); + x->nlimbs = xsize; + for (i=0; i < a->nlimbs; i++ ) + x->d[i] = a->d[i]; + x->nlimbs = i; + + if ( nlimbs >= x->nlimbs ) + { + x->nlimbs = 0; + return; + } + + if (nlimbs) + { + for (i=0; i < x->nlimbs - nlimbs; i++ ) + x->d[i] = x->d[i+nlimbs]; + x->d[i] = 0; + x->nlimbs -= nlimbs; + } + + if ( x->nlimbs && nbits ) + _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits ); + } + else + { + /* Copy and shift by less than bits in a limb. */ + xsize = a->nlimbs; + x->sign = a->sign; + RESIZE_IF_NEEDED (x, xsize); + x->nlimbs = xsize; + + if ( xsize ) + { + if (nbits ) + _gcry_mpih_rshift (x->d, a->d, x->nlimbs, nbits ); + else + { + /* The rshift helper function is not specified for + NBITS==0, thus we do a plain copy here. */ + for (i=0; i < x->nlimbs; i++ ) + x->d[i] = a->d[i]; + } + } + } + MPN_NORMALIZE (x->d, x->nlimbs); +} + + +/**************** + * Shift A by COUNT limbs to the left + * This is used only within the MPI library + */ +void +_gcry_mpi_lshift_limbs (gcry_mpi_t a, unsigned int count) +{ + mpi_ptr_t ap; + int n = a->nlimbs; + int i; + + if (!count || !n) + return; + + RESIZE_IF_NEEDED (a, n+count); + + ap = a->d; + for (i = n-1; i >= 0; i--) + ap[i+count] = ap[i]; + for (i=0; i < count; i++ ) + ap[i] = 0; + a->nlimbs += count; +} + + +/* + * Shift A by N bits to the left. + */ +void +gcry_mpi_lshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n ) +{ + unsigned int nlimbs = (n/BITS_PER_MPI_LIMB); + unsigned int nbits = (n%BITS_PER_MPI_LIMB); + + if (x == a && !n) + return; /* In-place shift with an amount of zero. */ + + if ( x != a ) + { + /* Copy A to X. */ + unsigned int alimbs = a->nlimbs; + int asign = a->sign; + mpi_ptr_t xp, ap; + + RESIZE_IF_NEEDED (x, alimbs+nlimbs+1); + xp = x->d; + ap = a->d; + MPN_COPY (xp, ap, alimbs); + x->nlimbs = alimbs; + x->flags = a->flags; + x->sign = asign; + } + + if (nlimbs && !nbits) + { + /* Shift a full number of limbs. */ + _gcry_mpi_lshift_limbs (x, nlimbs); + } + else if (n) + { + /* We use a very dump approach: Shift left by the number of + limbs plus one and than fix it up by an rshift. */ + _gcry_mpi_lshift_limbs (x, nlimbs+1); + gcry_mpi_rshift (x, x, BITS_PER_MPI_LIMB - nbits); + } + + MPN_NORMALIZE (x->d, x->nlimbs); +} diff --git a/grub-core/lib/libgcrypt/mpi/mpi-cmp.c b/grub-core/lib/libgcrypt/mpi/mpi-cmp.c new file mode 100644 index 0000000..30e1fce --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-cmp.c @@ -0,0 +1,107 @@ +/* mpi-cmp.c - MPI functions + * Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + +int +gcry_mpi_cmp_ui (gcry_mpi_t u, unsigned long v) +{ + mpi_limb_t limb = v; + + _gcry_mpi_normalize (u); + + /* Handle the case that U contains no limb. */ + if (u->nlimbs == 0) + return -(limb != 0); + + /* Handle the case that U is negative. */ + if (u->sign) + return -1; + + if (u->nlimbs == 1) + { + /* Handle the case that U contains exactly one limb. */ + + if (u->d[0] > limb) + return 1; + if (u->d[0] < limb) + return -1; + return 0; + } + else + /* Handle the case that U contains more than one limb. */ + return 1; +} + + +int +gcry_mpi_cmp (gcry_mpi_t u, gcry_mpi_t v) +{ + mpi_size_t usize; + mpi_size_t vsize; + int cmp; + + if (mpi_is_opaque (u) || mpi_is_opaque (v)) + { + if (mpi_is_opaque (u) && !mpi_is_opaque (v)) + return -1; + if (!mpi_is_opaque (u) && mpi_is_opaque (v)) + return 1; + if (!u->sign && !v->sign) + return 0; /* Empty buffers are identical. */ + if (u->sign < v->sign) + return -1; + if (u->sign > v->sign) + return 1; + return memcmp (u->d, v->d, (u->sign+7)/8); + } + else + { + _gcry_mpi_normalize (u); + _gcry_mpi_normalize (v); + + usize = u->nlimbs; + vsize = v->nlimbs; + + /* Compare sign bits. */ + + if (!u->sign && v->sign) + return 1; + if (u->sign && !v->sign) + return -1; + + /* U and V are either both positive or both negative. */ + + if (usize != vsize && !u->sign && !v->sign) + return usize - vsize; + if (usize != vsize && u->sign && v->sign) + return vsize + usize; + if (!usize ) + return 0; + if (!(cmp = _gcry_mpih_cmp (u->d, v->d, usize))) + return 0; + if ((cmp < 0?1:0) == (u->sign?1:0)) + return 1; + } + return -1; +} diff --git a/grub-core/lib/libgcrypt/mpi/mpi-div.c b/grub-core/lib/libgcrypt/mpi/mpi-div.c new file mode 100644 index 0000000..a6ee300 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-div.c @@ -0,0 +1,355 @@ +/* mpi-div.c - MPI functions + * Copyright (C) 1994, 1996, 1998, 2001, 2002, + * 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" +#include "g10lib.h" + + +void +_gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor ) +{ + int divisor_sign = divisor->sign; + gcry_mpi_t temp_divisor = NULL; + + /* We need the original value of the divisor after the remainder has been + * preliminary calculated. We have to copy it to temporary space if it's + * the same variable as REM. */ + if( rem == divisor ) { + temp_divisor = mpi_copy( divisor ); + divisor = temp_divisor; + } + + _gcry_mpi_tdiv_r( rem, dividend, divisor ); + + if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs ) + gcry_mpi_add( rem, rem, divisor); + + if( temp_divisor ) + mpi_free(temp_divisor); +} + + + +/**************** + * Division rounding the quotient towards -infinity. + * The remainder gets the same sign as the denominator. + * rem is optional + */ + +ulong +_gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor ) +{ + mpi_limb_t rlimb; + + rlimb = _gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor ); + if( rlimb && dividend->sign ) + rlimb = divisor - rlimb; + + if( rem ) { + rem->d[0] = rlimb; + rem->nlimbs = rlimb? 1:0; + } + return rlimb; +} + + +void +_gcry_mpi_fdiv_q( gcry_mpi_t quot, gcry_mpi_t dividend, gcry_mpi_t divisor ) +{ + gcry_mpi_t tmp = mpi_alloc( mpi_get_nlimbs(quot) ); + _gcry_mpi_fdiv_qr( quot, tmp, dividend, divisor); + mpi_free(tmp); +} + +void +_gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor ) +{ + int divisor_sign = divisor->sign; + gcry_mpi_t temp_divisor = NULL; + + if( quot == divisor || rem == divisor ) { + temp_divisor = mpi_copy( divisor ); + divisor = temp_divisor; + } + + _gcry_mpi_tdiv_qr( quot, rem, dividend, divisor ); + + if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) { + gcry_mpi_sub_ui( quot, quot, 1 ); + gcry_mpi_add( rem, rem, divisor); + } + + if( temp_divisor ) + mpi_free(temp_divisor); +} + + +/* If den == quot, den needs temporary storage. + * If den == rem, den needs temporary storage. + * If num == quot, num needs temporary storage. + * If den has temporary storage, it can be normalized while being copied, + * i.e no extra storage should be allocated. + */ + +void +_gcry_mpi_tdiv_r( gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den) +{ + _gcry_mpi_tdiv_qr(NULL, rem, num, den ); +} + +void +_gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den) +{ + mpi_ptr_t np, dp; + mpi_ptr_t qp, rp; + mpi_size_t nsize = num->nlimbs; + mpi_size_t dsize = den->nlimbs; + mpi_size_t qsize, rsize; + mpi_size_t sign_remainder = num->sign; + mpi_size_t sign_quotient = num->sign ^ den->sign; + unsigned normalization_steps; + mpi_limb_t q_limb; + mpi_ptr_t marker[5]; + unsigned int marker_nlimbs[5]; + int markidx=0; + + /* Ensure space is enough for quotient and remainder. + * We need space for an extra limb in the remainder, because it's + * up-shifted (normalized) below. */ + rsize = nsize + 1; + mpi_resize( rem, rsize); + + qsize = rsize - dsize; /* qsize cannot be bigger than this. */ + if( qsize <= 0 ) { + if( num != rem ) { + rem->nlimbs = num->nlimbs; + rem->sign = num->sign; + MPN_COPY(rem->d, num->d, nsize); + } + if( quot ) { + /* This needs to follow the assignment to rem, in case the + * numerator and quotient are the same. */ + quot->nlimbs = 0; + quot->sign = 0; + } + return; + } + + if( quot ) + mpi_resize( quot, qsize); + + /* Read pointers here, when reallocation is finished. */ + np = num->d; + dp = den->d; + rp = rem->d; + + /* Optimize division by a single-limb divisor. */ + if( dsize == 1 ) { + mpi_limb_t rlimb; + if( quot ) { + qp = quot->d; + rlimb = _gcry_mpih_divmod_1( qp, np, nsize, dp[0] ); + qsize -= qp[qsize - 1] == 0; + quot->nlimbs = qsize; + quot->sign = sign_quotient; + } + else + rlimb = _gcry_mpih_mod_1( np, nsize, dp[0] ); + rp[0] = rlimb; + rsize = rlimb != 0?1:0; + rem->nlimbs = rsize; + rem->sign = sign_remainder; + return; + } + + + if( quot ) { + qp = quot->d; + /* Make sure QP and NP point to different objects. Otherwise the + * numerator would be gradually overwritten by the quotient limbs. */ + if(qp == np) { /* Copy NP object to temporary space. */ + marker_nlimbs[markidx] = nsize; + np = marker[markidx++] = mpi_alloc_limb_space(nsize, + mpi_is_secure(quot)); + MPN_COPY(np, qp, nsize); + } + } + else /* Put quotient at top of remainder. */ + qp = rp + dsize; + + count_leading_zeros( normalization_steps, dp[dsize - 1] ); + + /* Normalize the denominator, i.e. make its most significant bit set by + * shifting it NORMALIZATION_STEPS bits to the left. Also shift the + * numerator the same number of steps (to keep the quotient the same!). + */ + if( normalization_steps ) { + mpi_ptr_t tp; + mpi_limb_t nlimb; + + /* Shift up the denominator setting the most significant bit of + * the most significant word. Use temporary storage not to clobber + * the original contents of the denominator. */ + marker_nlimbs[markidx] = dsize; + tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den)); + _gcry_mpih_lshift( tp, dp, dsize, normalization_steps ); + dp = tp; + + /* Shift up the numerator, possibly introducing a new most + * significant word. Move the shifted numerator in the remainder + * meanwhile. */ + nlimb = _gcry_mpih_lshift(rp, np, nsize, normalization_steps); + if( nlimb ) { + rp[nsize] = nlimb; + rsize = nsize + 1; + } + else + rsize = nsize; + } + else { + /* The denominator is already normalized, as required. Copy it to + * temporary space if it overlaps with the quotient or remainder. */ + if( dp == rp || (quot && (dp == qp))) { + mpi_ptr_t tp; + + marker_nlimbs[markidx] = dsize; + tp = marker[markidx++] = mpi_alloc_limb_space(dsize, + mpi_is_secure(den)); + MPN_COPY( tp, dp, dsize ); + dp = tp; + } + + /* Move the numerator to the remainder. */ + if( rp != np ) + MPN_COPY(rp, np, nsize); + + rsize = nsize; + } + + q_limb = _gcry_mpih_divrem( qp, 0, rp, rsize, dp, dsize ); + + if( quot ) { + qsize = rsize - dsize; + if(q_limb) { + qp[qsize] = q_limb; + qsize += 1; + } + + quot->nlimbs = qsize; + quot->sign = sign_quotient; + } + + rsize = dsize; + MPN_NORMALIZE (rp, rsize); + + if( normalization_steps && rsize ) { + _gcry_mpih_rshift(rp, rp, rsize, normalization_steps); + rsize -= rp[rsize - 1] == 0?1:0; + } + + rem->nlimbs = rsize; + rem->sign = sign_remainder; + while( markidx ) + { + markidx--; + _gcry_mpi_free_limb_space (marker[markidx], marker_nlimbs[markidx]); + } +} + +void +_gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned int count ) +{ + mpi_size_t usize, wsize; + mpi_size_t limb_cnt; + + usize = u->nlimbs; + limb_cnt = count / BITS_PER_MPI_LIMB; + wsize = usize - limb_cnt; + if( limb_cnt >= usize ) + w->nlimbs = 0; + else { + mpi_ptr_t wp; + mpi_ptr_t up; + + RESIZE_IF_NEEDED( w, wsize ); + wp = w->d; + up = u->d; + + count %= BITS_PER_MPI_LIMB; + if( count ) { + _gcry_mpih_rshift( wp, up + limb_cnt, wsize, count ); + wsize -= !wp[wsize - 1]; + } + else { + MPN_COPY_INCR( wp, up + limb_cnt, wsize); + } + + w->nlimbs = wsize; + } +} + +/**************** + * Check whether dividend is divisible by divisor + * (note: divisor must fit into a limb) + */ +int +_gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor ) +{ + return !_gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor ); +} + + +void +gcry_mpi_div (gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor, int round) +{ + if (!round) + { + if (!rem) + { + gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs(quot)); + _gcry_mpi_tdiv_qr (quot, tmp, dividend, divisor); + mpi_free (tmp); + } + else + _gcry_mpi_tdiv_qr (quot, rem, dividend, divisor); + } + else if (round < 0) + { + if (!rem) + _gcry_mpi_fdiv_q (quot, dividend, divisor); + else if (!quot) + _gcry_mpi_fdiv_r (rem, dividend, divisor); + else + _gcry_mpi_fdiv_qr (quot, rem, dividend, divisor); + } + else + log_bug ("mpi rounding to ceiling not yet implemented\n"); +} diff --git a/grub-core/lib/libgcrypt/mpi/mpi-gcd.c b/grub-core/lib/libgcrypt/mpi/mpi-gcd.c new file mode 100644 index 0000000..5cbefa1 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-gcd.c @@ -0,0 +1,51 @@ +/* mpi-gcd.c - MPI functions + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + +/**************** + * Find the greatest common divisor G of A and B. + * Return: true if this 1, false in all other cases + */ +int +gcry_mpi_gcd( gcry_mpi_t g, gcry_mpi_t xa, gcry_mpi_t xb ) +{ + gcry_mpi_t a, b; + + a = mpi_copy(xa); + b = mpi_copy(xb); + + /* TAOCP Vol II, 4.5.2, Algorithm A */ + a->sign = 0; + b->sign = 0; + while( gcry_mpi_cmp_ui( b, 0 ) ) { + _gcry_mpi_fdiv_r( g, a, b ); /* g used as temorary variable */ + mpi_set(a,b); + mpi_set(b,g); + } + mpi_set(g, a); + + mpi_free(a); + mpi_free(b); + return !gcry_mpi_cmp_ui( g, 1); +} diff --git a/grub-core/lib/libgcrypt/mpi/mpi-inline.c b/grub-core/lib/libgcrypt/mpi/mpi-inline.c new file mode 100644 index 0000000..39e2222 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-inline.c @@ -0,0 +1,35 @@ +/* mpi-inline.c + * Copyright (C) 1999, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +/* put the inline functions as real functions into the lib */ +#define G10_MPI_INLINE_DECL + +#include "mpi-internal.h" + +/* always include the header because it is only + * included by mpi-internal if __GCC__ is defined but we + * need it here in all cases and the above definition of + * of the macro allows us to do so + */ +#include "mpi-inline.h" diff --git a/grub-core/lib/libgcrypt/mpi/mpi-inline.h b/grub-core/lib/libgcrypt/mpi/mpi-inline.h new file mode 100644 index 0000000..94e2aec --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-inline.h @@ -0,0 +1,161 @@ +/* mpi-inline.h - Internal to the Multi Precision Integers + * Copyright (C) 1994, 1996, 1998, 1999, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#ifndef G10_MPI_INLINE_H +#define G10_MPI_INLINE_H + +/* Starting with gcc 4.3 "extern inline" conforms in c99 mode to the + c99 semantics. To keep the useful old semantics we use an + attribute. */ +#ifndef G10_MPI_INLINE_DECL +# ifdef __GNUC_STDC_INLINE__ +# define G10_MPI_INLINE_DECL extern inline __attribute__ ((__gnu_inline__)) +# else +# define G10_MPI_INLINE_DECL extern __inline__ +# endif +#endif + +G10_MPI_INLINE_DECL mpi_limb_t +_gcry_mpih_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t x; + + x = *s1_ptr++; + s2_limb += x; + *res_ptr++ = s2_limb; + if( s2_limb < x ) { /* sum is less than the left operand: handle carry */ + while( --s1_size ) { + x = *s1_ptr++ + 1; /* add carry */ + *res_ptr++ = x; /* and store */ + if( x ) /* not 0 (no overflow): we can stop */ + goto leave; + } + return 1; /* return carry (size of s1 to small) */ + } + + leave: + if( res_ptr != s1_ptr ) { /* not the same variable */ + mpi_size_t i; /* copy the rest */ + for( i=0; i < s1_size-1; i++ ) + res_ptr[i] = s1_ptr[i]; + } + return 0; /* no carry */ +} + + + +G10_MPI_INLINE_DECL mpi_limb_t +_gcry_mpih_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size) +{ + mpi_limb_t cy = 0; + + if( s2_size ) + cy = _gcry_mpih_add_n( res_ptr, s1_ptr, s2_ptr, s2_size ); + + if( s1_size - s2_size ) + cy = _gcry_mpih_add_1( res_ptr + s2_size, s1_ptr + s2_size, + s1_size - s2_size, cy); + return cy; +} + + +G10_MPI_INLINE_DECL mpi_limb_t +_gcry_mpih_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ) +{ + mpi_limb_t x; + + x = *s1_ptr++; + s2_limb = x - s2_limb; + *res_ptr++ = s2_limb; + if( s2_limb > x ) { + while( --s1_size ) { + x = *s1_ptr++; + *res_ptr++ = x - 1; + if( x ) + goto leave; + } + return 1; + } + + leave: + if( res_ptr != s1_ptr ) { + mpi_size_t i; + for( i=0; i < s1_size-1; i++ ) + res_ptr[i] = s1_ptr[i]; + } + return 0; +} + + + +G10_MPI_INLINE_DECL mpi_limb_t +_gcry_mpih_sub( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size) +{ + mpi_limb_t cy = 0; + + if( s2_size ) + cy = _gcry_mpih_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size); + + if( s1_size - s2_size ) + cy = _gcry_mpih_sub_1(res_ptr + s2_size, s1_ptr + s2_size, + s1_size - s2_size, cy); + return cy; +} + +/**************** + * Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE. + * There are no restrictions on the relative sizes of + * the two arguments. + * Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2. + */ +G10_MPI_INLINE_DECL int +_gcry_mpih_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ) +{ + mpi_size_t i; + mpi_limb_t op1_word, op2_word; + + for( i = size - 1; i >= 0 ; i--) { + op1_word = op1_ptr[i]; + op2_word = op2_ptr[i]; + if( op1_word != op2_word ) + goto diff; + } + return 0; + + diff: + /* This can *not* be simplified to + * op2_word - op2_word + * since that expression might give signed overflow. */ + return (op1_word > op2_word) ? 1 : -1; +} + + +#endif /*G10_MPI_INLINE_H*/ diff --git a/grub-core/lib/libgcrypt/mpi/mpi-internal.h b/grub-core/lib/libgcrypt/mpi/mpi-internal.h new file mode 100644 index 0000000..e75b7c6 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-internal.h @@ -0,0 +1,277 @@ +/* mpi-internal.h - Internal to the Multi Precision Integers + * Copyright (C) 1994, 1996, 1998, 2000, 2002, + * 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#ifndef G10_MPI_INTERNAL_H +#define G10_MPI_INTERNAL_H + +#include "mpi-asm-defs.h" + +#ifndef BITS_PER_MPI_LIMB +#if BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_INT + typedef unsigned int mpi_limb_t; + typedef signed int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG + typedef unsigned long int mpi_limb_t; + typedef signed long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG_LONG + typedef unsigned long long int mpi_limb_t; + typedef signed long long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_SHORT + typedef unsigned short int mpi_limb_t; + typedef signed short int mpi_limb_signed_t; +#else +#error BYTES_PER_MPI_LIMB does not match any C type +#endif +#define BITS_PER_MPI_LIMB (8*BYTES_PER_MPI_LIMB) +#endif /*BITS_PER_MPI_LIMB*/ + +#include "mpi.h" + +/* If KARATSUBA_THRESHOLD is not already defined, define it to a + * value which is good on most machines. */ + +/* tested 4, 16, 32 and 64, where 16 gave the best performance when + * checking a 768 and a 1024 bit ElGamal signature. + * (wk 22.12.97) */ +#ifndef KARATSUBA_THRESHOLD +#define KARATSUBA_THRESHOLD 16 +#endif + +/* The code can't handle KARATSUBA_THRESHOLD smaller than 2. */ +#if KARATSUBA_THRESHOLD < 2 +#undef KARATSUBA_THRESHOLD +#define KARATSUBA_THRESHOLD 2 +#endif + + +typedef mpi_limb_t *mpi_ptr_t; /* pointer to a limb */ +typedef int mpi_size_t; /* (must be a signed type) */ + +#define ABS(x) (x >= 0 ? x : -x) +#define MIN(l,o) ((l) < (o) ? (l) : (o)) +#define MAX(h,i) ((h) > (i) ? (h) : (i)) +#define RESIZE_IF_NEEDED(a,b) \ + do { \ + if( (a)->alloced < (b) ) \ + mpi_resize((a), (b)); \ + } while(0) + +/* Copy N limbs from S to D. */ +#define MPN_COPY( d, s, n) \ + do { \ + mpi_size_t _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = (s)[_i]; \ + } while(0) + +#define MPN_COPY_INCR( d, s, n) \ + do { \ + mpi_size_t _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = (d)[_i]; \ + } while (0) + +#define MPN_COPY_DECR( d, s, n ) \ + do { \ + mpi_size_t _i; \ + for( _i = (n)-1; _i >= 0; _i--) \ + (d)[_i] = (s)[_i]; \ + } while(0) + +/* Zero N limbs at D */ +#define MPN_ZERO(d, n) \ + do { \ + int _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = 0; \ + } while (0) + +#define MPN_NORMALIZE(d, n) \ + do { \ + while( (n) > 0 ) { \ + if( (d)[(n)-1] ) \ + break; \ + (n)--; \ + } \ + } while(0) + +#define MPN_NORMALIZE_NOT_ZERO(d, n) \ + do { \ + for(;;) { \ + if( (d)[(n)-1] ) \ + break; \ + (n)--; \ + } \ + } while(0) + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if( (size) < KARATSUBA_THRESHOLD ) \ + mul_n_basecase (prodp, up, vp, size); \ + else \ + mul_n (prodp, up, vp, size, tspace); \ + } while (0); + + +/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest + * limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB). + * If this would yield overflow, DI should be the largest possible number + * (i.e., only ones). For correct operation, the most significant bit of D + * has to be set. Put the quotient in Q and the remainder in R. + */ +#define UDIV_QRNND_PREINV(q, r, nh, nl, d, di) \ + do { \ + mpi_limb_t _q, _ql, _r; \ + mpi_limb_t _xh, _xl; \ + umul_ppmm (_q, _ql, (nh), (di)); \ + _q += (nh); /* DI is 2**BITS_PER_MPI_LIMB too small */ \ + umul_ppmm (_xh, _xl, _q, (d)); \ + sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl); \ + if( _xh ) { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q++; \ + if( _xh) { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q++; \ + } \ + } \ + if( _r >= (d) ) { \ + _r -= (d); \ + _q++; \ + } \ + (r) = _r; \ + (q) = _q; \ + } while (0) + + +/*-- mpiutil.c --*/ +#define mpi_alloc_limb_space(n,f) _gcry_mpi_alloc_limb_space((n),(f)) +mpi_ptr_t _gcry_mpi_alloc_limb_space( unsigned nlimbs, int sec ); +void _gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs ); +void _gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned nlimbs ); + +/*-- mpi-bit.c --*/ +#define mpi_rshift_limbs(a,n) _gcry_mpi_rshift_limbs ((a), (n)) +#define mpi_lshift_limbs(a,n) _gcry_mpi_lshift_limbs ((a), (n)) + +void _gcry_mpi_rshift_limbs( gcry_mpi_t a, unsigned int count ); +void _gcry_mpi_lshift_limbs( gcry_mpi_t a, unsigned int count ); + + +/*-- mpih-add.c --*/ +mpi_limb_t _gcry_mpih_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ); +mpi_limb_t _gcry_mpih_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size); +mpi_limb_t _gcry_mpih_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size); + +/*-- mpih-sub.c --*/ +mpi_limb_t _gcry_mpih_sub_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ); +mpi_limb_t _gcry_mpih_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size); +mpi_limb_t _gcry_mpih_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size); + +/*-- mpih-cmp.c --*/ +int _gcry_mpih_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ); + +/*-- mpih-mul.c --*/ + +struct karatsuba_ctx { + struct karatsuba_ctx *next; + mpi_ptr_t tspace; + unsigned int tspace_nlimbs; + mpi_size_t tspace_size; + mpi_ptr_t tp; + unsigned int tp_nlimbs; + mpi_size_t tp_size; +}; + +void _gcry_mpih_release_karatsuba_ctx( struct karatsuba_ctx *ctx ); + +mpi_limb_t _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); +mpi_limb_t _gcry_mpih_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); +void _gcry_mpih_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, + mpi_size_t size); +mpi_limb_t _gcry_mpih_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize); +void _gcry_mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ); +void _gcry_mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, + mpi_ptr_t tspace); + +void _gcry_mpih_mul_karatsuba_case( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize, + struct karatsuba_ctx *ctx ); + + +/*-- mpih-mul_1.c (or xxx/cpu/ *.S) --*/ +mpi_limb_t _gcry_mpih_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); + +/*-- mpih-div.c --*/ +mpi_limb_t _gcry_mpih_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb); +mpi_limb_t _gcry_mpih_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, + mpi_ptr_t np, mpi_size_t nsize, + mpi_ptr_t dp, mpi_size_t dsize); +mpi_limb_t _gcry_mpih_divmod_1( mpi_ptr_t quot_ptr, + mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb); + +/*-- mpih-shift.c --*/ +mpi_limb_t _gcry_mpih_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned cnt); +mpi_limb_t _gcry_mpih_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned cnt); + + +/* Define stuff for longlong.h. */ +#define W_TYPE_SIZE BITS_PER_MPI_LIMB + typedef mpi_limb_t UWtype; + typedef unsigned int UHWtype; +#if defined (__GNUC__) + typedef unsigned int UQItype __attribute__ ((mode (QI))); + typedef int SItype __attribute__ ((mode (SI))); + typedef unsigned int USItype __attribute__ ((mode (SI))); + typedef int DItype __attribute__ ((mode (DI))); + typedef unsigned int UDItype __attribute__ ((mode (DI))); +#else + typedef unsigned char UQItype; + typedef long SItype; + typedef unsigned long USItype; +#endif + +#ifdef __GNUC__ +#include "mpi-inline.h" +#endif + +#endif /*G10_MPI_INTERNAL_H*/ diff --git a/grub-core/lib/libgcrypt/mpi/mpi-inv.c b/grub-core/lib/libgcrypt/mpi/mpi-inv.c new file mode 100644 index 0000000..5d26946 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-inv.c @@ -0,0 +1,267 @@ +/* mpi-inv.c - MPI functions + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "g10lib.h" + +/**************** + * Calculate the multiplicative inverse X of A mod N + * That is: Find the solution x for + * 1 = (a*x) mod n + */ +int +gcry_mpi_invm( gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n ) +{ +#if 0 + gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3; + gcry_mpi_t ta, tb, tc; + + u = mpi_copy(a); + v = mpi_copy(n); + u1 = mpi_alloc_set_ui(1); + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_alloc_set_ui(0); + v2 = mpi_alloc_set_ui(1); + v3 = mpi_copy(v); + q = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t1 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t2 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t3 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + while( mpi_cmp_ui( v3, 0 ) ) { + mpi_fdiv_q( q, u3, v3 ); + mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q); + mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3); + mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3); + mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3); + } + /* log_debug("result:\n"); + log_mpidump("q =", q ); + log_mpidump("u1=", u1); + log_mpidump("u2=", u2); + log_mpidump("u3=", u3); + log_mpidump("v1=", v1); + log_mpidump("v2=", v2); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(u2); + mpi_free(u3); + mpi_free(v1); + mpi_free(v2); + mpi_free(v3); + mpi_free(q); + mpi_free(t1); + mpi_free(t2); + mpi_free(t3); + mpi_free(u); + mpi_free(v); +#elif 0 + /* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X) + * modified according to Michael Penk's solution for Exercise 35 */ + + /* FIXME: we can simplify this in most cases (see Knuth) */ + gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3; + unsigned k; + int sign; + + u = mpi_copy(a); + v = mpi_copy(n); + for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { + mpi_rshift(u, u, 1); + mpi_rshift(v, v, 1); + } + + + u1 = mpi_alloc_set_ui(1); + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_copy(v); /* !-- used as const 1 */ + v2 = mpi_alloc( mpi_get_nlimbs(u) ); mpi_sub( v2, u1, u ); + v3 = mpi_copy(v); + if( mpi_test_bit(u, 0) ) { /* u is odd */ + t1 = mpi_alloc_set_ui(0); + t2 = mpi_alloc_set_ui(1); t2->sign = 1; + t3 = mpi_copy(v); t3->sign = !t3->sign; + goto Y4; + } + else { + t1 = mpi_alloc_set_ui(1); + t2 = mpi_alloc_set_ui(0); + t3 = mpi_copy(u); + } + do { + do { + if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + mpi_rshift(t1, t1, 1); + mpi_rshift(t2, t2, 1); + mpi_rshift(t3, t3, 1); + Y4: + ; + } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ + + if( !t3->sign ) { + mpi_set(u1, t1); + mpi_set(u2, t2); + mpi_set(u3, t3); + } + else { + mpi_sub(v1, v, t1); + sign = u->sign; u->sign = !u->sign; + mpi_sub(v2, u, t2); + u->sign = sign; + sign = t3->sign; t3->sign = !t3->sign; + mpi_set(v3, t3); + t3->sign = sign; + } + mpi_sub(t1, u1, v1); + mpi_sub(t2, u2, v2); + mpi_sub(t3, u3, v3); + if( t1->sign ) { + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ + /* mpi_lshift( u3, k ); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(u2); + mpi_free(u3); + mpi_free(v1); + mpi_free(v2); + mpi_free(v3); + mpi_free(t1); + mpi_free(t2); + mpi_free(t3); +#else + /* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X) + * modified according to Michael Penk's solution for Exercise 35 + * with further enhancement */ + gcry_mpi_t u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3; + unsigned k; + int sign; + int odd ; + + u = mpi_copy(a); + v = mpi_copy(n); + + for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { + mpi_rshift(u, u, 1); + mpi_rshift(v, v, 1); + } + odd = mpi_test_bit(v,0); + + u1 = mpi_alloc_set_ui(1); + if( !odd ) + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_copy(v); + if( !odd ) { + v2 = mpi_alloc( mpi_get_nlimbs(u) ); + mpi_sub( v2, u1, u ); /* U is used as const 1 */ + } + v3 = mpi_copy(v); + if( mpi_test_bit(u, 0) ) { /* u is odd */ + t1 = mpi_alloc_set_ui(0); + if( !odd ) { + t2 = mpi_alloc_set_ui(1); t2->sign = 1; + } + t3 = mpi_copy(v); t3->sign = !t3->sign; + goto Y4; + } + else { + t1 = mpi_alloc_set_ui(1); + if( !odd ) + t2 = mpi_alloc_set_ui(0); + t3 = mpi_copy(u); + } + do { + do { + if( !odd ) { + if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + mpi_rshift(t1, t1, 1); + mpi_rshift(t2, t2, 1); + mpi_rshift(t3, t3, 1); + } + else { + if( mpi_test_bit(t1, 0) ) + mpi_add(t1, t1, v); + mpi_rshift(t1, t1, 1); + mpi_rshift(t3, t3, 1); + } + Y4: + ; + } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ + + if( !t3->sign ) { + mpi_set(u1, t1); + if( !odd ) + mpi_set(u2, t2); + mpi_set(u3, t3); + } + else { + mpi_sub(v1, v, t1); + sign = u->sign; u->sign = !u->sign; + if( !odd ) + mpi_sub(v2, u, t2); + u->sign = sign; + sign = t3->sign; t3->sign = !t3->sign; + mpi_set(v3, t3); + t3->sign = sign; + } + mpi_sub(t1, u1, v1); + if( !odd ) + mpi_sub(t2, u2, v2); + mpi_sub(t3, u3, v3); + if( t1->sign ) { + mpi_add(t1, t1, v); + if( !odd ) + mpi_sub(t2, t2, u); + } + } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ + /* mpi_lshift( u3, k ); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(v1); + mpi_free(t1); + if( !odd ) { + mpi_free(u2); + mpi_free(v2); + mpi_free(t2); + } + mpi_free(u3); + mpi_free(v3); + mpi_free(t3); + + mpi_free(u); + mpi_free(v); +#endif + return 1; +} diff --git a/grub-core/lib/libgcrypt/mpi/mpi-mod.c b/grub-core/lib/libgcrypt/mpi/mpi-mod.c new file mode 100644 index 0000000..7ebfe6d --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-mod.c @@ -0,0 +1,184 @@ +/* mpi-mod.c - Modular reduction + Copyright (C) 1998, 1999, 2001, 2002, 2003, + 2007 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "mpi-internal.h" +#include "longlong.h" +#include "g10lib.h" + + +/* Context used with Barrett reduction. */ +struct barrett_ctx_s +{ + gcry_mpi_t m; /* The modulus - may not be modified. */ + int m_copied; /* If true, M needs to be released. */ + int k; + gcry_mpi_t y; + gcry_mpi_t r1; /* Helper MPI. */ + gcry_mpi_t r2; /* Helper MPI. */ + gcry_mpi_t r3; /* Helper MPI allocated on demand. */ +}; + + + +void +_gcry_mpi_mod (gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor) +{ + _gcry_mpi_fdiv_r (rem, dividend, divisor); + rem->sign = 0; +} + + +/* This function returns a new context for Barrett based operations on + the modulus M. This context needs to be released using + _gcry_mpi_barrett_free. If COPY is true M will be transferred to + the context and the user may change M. If COPY is false, M may not + be changed until gcry_mpi_barrett_free has been called. */ +mpi_barrett_t +_gcry_mpi_barrett_init (gcry_mpi_t m, int copy) +{ + mpi_barrett_t ctx; + gcry_mpi_t tmp; + + mpi_normalize (m); + ctx = gcry_xcalloc (1, sizeof *ctx); + + if (copy) + { + ctx->m = mpi_copy (m); + ctx->m_copied = 1; + } + else + ctx->m = m; + + ctx->k = mpi_get_nlimbs (m); + tmp = mpi_alloc (ctx->k + 1); + + /* Barrett precalculation: y = floor(b^(2k) / m). */ + mpi_set_ui (tmp, 1); + mpi_lshift_limbs (tmp, 2 * ctx->k); + mpi_fdiv_q (tmp, tmp, m); + + ctx->y = tmp; + ctx->r1 = mpi_alloc ( 2 * ctx->k + 1 ); + ctx->r2 = mpi_alloc ( 2 * ctx->k + 1 ); + + return ctx; +} + +void +_gcry_mpi_barrett_free (mpi_barrett_t ctx) +{ + if (ctx) + { + mpi_free (ctx->y); + mpi_free (ctx->r1); + mpi_free (ctx->r2); + if (ctx->r3) + mpi_free (ctx->r3); + if (ctx->m_copied) + mpi_free (ctx->m); + gcry_free (ctx); + } +} + + +/* R = X mod M + + Using Barrett reduction. Before using this function + _gcry_mpi_barrett_init must have been called to do the + precalculations. CTX is the context created by this precalculation + and also conveys M. If the Barret reduction could no be done a + starightforward reduction method is used. + + We assume that these conditions are met: + Input: x =(x_2k-1 ...x_0)_b + m =(m_k-1 ....m_0)_b with m_k-1 != 0 + Output: r = x mod m + */ +void +_gcry_mpi_mod_barrett (gcry_mpi_t r, gcry_mpi_t x, mpi_barrett_t ctx) +{ + gcry_mpi_t m = ctx->m; + int k = ctx->k; + gcry_mpi_t y = ctx->y; + gcry_mpi_t r1 = ctx->r1; + gcry_mpi_t r2 = ctx->r2; + + mpi_normalize (x); + if (mpi_get_nlimbs (x) > 2*k ) + { + mpi_mod (r, x, m); + return; + } + + /* 1. q1 = floor( x / b^k-1) + * q2 = q1 * y + * q3 = floor( q2 / b^k+1 ) + * Actually, we don't need qx, we can work direct on r2 + */ + mpi_set ( r2, x ); + mpi_rshift_limbs ( r2, k-1 ); + mpi_mul ( r2, r2, y ); + mpi_rshift_limbs ( r2, k+1 ); + + /* 2. r1 = x mod b^k+1 + * r2 = q3 * m mod b^k+1 + * r = r1 - r2 + * 3. if r < 0 then r = r + b^k+1 + */ + mpi_set ( r1, x ); + if ( r1->nlimbs > k+1 ) /* Quick modulo operation. */ + r1->nlimbs = k+1; + mpi_mul ( r2, r2, m ); + if ( r2->nlimbs > k+1 ) /* Quick modulo operation. */ + r2->nlimbs = k+1; + mpi_sub ( r, r1, r2 ); + + if ( mpi_is_neg( r ) ) + { + if (!ctx->r3) + { + ctx->r3 = mpi_alloc ( k + 2 ); + mpi_set_ui (ctx->r3, 1); + mpi_lshift_limbs (ctx->r3, k + 1 ); + } + mpi_add ( r, r, ctx->r3 ); + } + + /* 4. while r >= m do r = r - m */ + while ( mpi_cmp( r, m ) >= 0 ) + mpi_sub ( r, r, m ); + +} + + +void +_gcry_mpi_mul_barrett (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, + mpi_barrett_t ctx) +{ + gcry_mpi_mul (w, u, v); + mpi_mod_barrett (w, w, ctx); +} diff --git a/grub-core/lib/libgcrypt/mpi/mpi-mpow.c b/grub-core/lib/libgcrypt/mpi/mpi-mpow.c new file mode 100644 index 0000000..ca5b3f1 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-mpow.c @@ -0,0 +1,223 @@ +/* mpi-mpow.c - MPI functions + * Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "mpi-internal.h" +#include "longlong.h" +#include "g10lib.h" + + +/* Barrett is slower than the classical way. It can be tweaked by + * using partial multiplications + */ +/*#define USE_BARRETT*/ + + + +#ifdef USE_BARRETT +static void barrett_mulm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m, gcry_mpi_t y, int k, gcry_mpi_t r1, gcry_mpi_t r2 ); +static gcry_mpi_t init_barrett( gcry_mpi_t m, int *k, gcry_mpi_t *r1, gcry_mpi_t *r2 ); +static int calc_barrett( gcry_mpi_t r, gcry_mpi_t x, gcry_mpi_t m, gcry_mpi_t y, int k, gcry_mpi_t r1, gcry_mpi_t r2 ); +#else +#define barrett_mulm( w, u, v, m, y, k, r1, r2 ) gcry_mpi_mulm( (w), (u), (v), (m) ) +#endif + + +static int +build_index( gcry_mpi_t *exparray, int k, int i, int t ) +{ + int j, bitno; + int idx = 0; + + bitno = t-i; + for(j=k-1; j >= 0; j-- ) { + idx <<= 1; + if( mpi_test_bit( exparray[j], bitno ) ) + idx |= 1; + } + /*log_debug("t=%d i=%d idx=%d\n", t, i, idx );*/ + return idx; +} + +/**************** + * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M + */ +void +_gcry_mpi_mulpowm( gcry_mpi_t res, gcry_mpi_t *basearray, gcry_mpi_t *exparray, gcry_mpi_t m) +{ + int k; /* number of elements */ + int t; /* bit size of largest exponent */ + int i, j, idx; + gcry_mpi_t *G; /* table with precomputed values of size 2^k */ + gcry_mpi_t tmp; +#ifdef USE_BARRETT + gcry_mpi_t barrett_y, barrett_r1, barrett_r2; + int barrett_k; +#endif + + for(k=0; basearray[k]; k++ ) + ; + gcry_assert(k); + for(t=0, i=0; (tmp=exparray[i]); i++ ) { + /*log_mpidump("exp: ", tmp );*/ + j = mpi_get_nbits(tmp); + if( j > t ) + t = j; + } + /*log_mpidump("mod: ", m );*/ + gcry_assert (i==k); + gcry_assert (t); + gcry_assert (k < 10); + + G = gcry_xcalloc( (1<<k) , sizeof *G ); +#ifdef USE_BARRETT + barrett_y = init_barrett( m, &barrett_k, &barrett_r1, &barrett_r2 ); +#endif + /* and calculate */ + tmp = mpi_alloc( mpi_get_nlimbs(m)+1 ); + mpi_set_ui( res, 1 ); + for(i = 1; i <= t; i++ ) { + barrett_mulm(tmp, res, res, m, barrett_y, barrett_k, + barrett_r1, barrett_r2 ); + idx = build_index( exparray, k, i, t ); + gcry_assert (idx >= 0 && idx < (1<<k)); + if( !G[idx] ) { + if( !idx ) + G[0] = mpi_alloc_set_ui( 1 ); + else { + for(j=0; j < k; j++ ) { + if( (idx & (1<<j) ) ) { + if( !G[idx] ) + G[idx] = mpi_copy( basearray[j] ); + else + barrett_mulm( G[idx], G[idx], basearray[j], + m, barrett_y, barrett_k, barrett_r1, barrett_r2 ); + } + } + if( !G[idx] ) + G[idx] = mpi_alloc(0); + } + } + barrett_mulm(res, tmp, G[idx], m, barrett_y, barrett_k, barrett_r1, barrett_r2 ); + } + + /* cleanup */ + mpi_free(tmp); +#ifdef USE_BARRETT + mpi_free(barrett_y); + mpi_free(barrett_r1); + mpi_free(barrett_r2); +#endif + for(i=0; i < (1<<k); i++ ) + mpi_free(G[i]); + gcry_free(G); +} + + + +#ifdef USE_BARRETT +static void +barrett_mulm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m, gcry_mpi_t y, int k, gcry_mpi_t r1, gcry_mpi_t r2 ) +{ + mpi_mul(w, u, v); + if( calc_barrett( w, w, m, y, k, r1, r2 ) ) + mpi_fdiv_r( w, w, m ); +} + +/**************** + * Barrett precalculation: y = floor(b^(2k) / m) + */ +static gcry_mpi_t +init_barrett( gcry_mpi_t m, int *k, gcry_mpi_t *r1, gcry_mpi_t *r2 ) +{ + gcry_mpi_t tmp; + + mpi_normalize( m ); + *k = mpi_get_nlimbs( m ); + tmp = mpi_alloc( *k + 1 ); + mpi_set_ui( tmp, 1 ); + mpi_lshift_limbs( tmp, 2 * *k ); + mpi_fdiv_q( tmp, tmp, m ); + *r1 = mpi_alloc( 2* *k + 1 ); + *r2 = mpi_alloc( 2* *k + 1 ); + return tmp; +} + +/**************** + * Barrett reduction: We assume that these conditions are met: + * Given x =(x_2k-1 ...x_0)_b + * m =(m_k-1 ....m_0)_b with m_k-1 != 0 + * Output r = x mod m + * Before using this function init_barret must be used to calucalte y and k. + * Returns: false = no error + * true = can't perform barret reduction + */ +static int +calc_barrett( gcry_mpi_t r, gcry_mpi_t x, gcry_mpi_t m, gcry_mpi_t y, int k, gcry_mpi_t r1, gcry_mpi_t r2 ) +{ + int xx = k > 3 ? k-3:0; + + mpi_normalize( x ); + if( mpi_get_nlimbs(x) > 2*k ) + return 1; /* can't do it */ + + /* 1. q1 = floor( x / b^k-1) + * q2 = q1 * y + * q3 = floor( q2 / b^k+1 ) + * Actually, we don't need qx, we can work direct on r2 + */ + mpi_set( r2, x ); + mpi_rshift_limbs( r2, k-1 ); + mpi_mul( r2, r2, y ); + mpi_rshift_limbs( r2, k+1 ); + + /* 2. r1 = x mod b^k+1 + * r2 = q3 * m mod b^k+1 + * r = r1 - r2 + * 3. if r < 0 then r = r + b^k+1 + */ + mpi_set( r1, x ); + if( r1->nlimbs > k+1 ) /* quick modulo operation */ + r1->nlimbs = k+1; + mpi_mul( r2, r2, m ); + if( r2->nlimbs > k+1 ) /* quick modulo operation */ + r2->nlimbs = k+1; + mpi_sub( r, r1, r2 ); + + if( mpi_is_neg( r ) ) { + gcry_mpi_t tmp; + + tmp = mpi_alloc( k + 2 ); + mpi_set_ui( tmp, 1 ); + mpi_lshift_limbs( tmp, k+1 ); + mpi_add( r, r, tmp ); + mpi_free(tmp); + } + + /* 4. while r >= m do r = r - m */ + while( mpi_cmp( r, m ) >= 0 ) + mpi_sub( r, r, m ); + + return 0; +} +#endif /* USE_BARRETT */ diff --git a/grub-core/lib/libgcrypt/mpi/mpi-mul.c b/grub-core/lib/libgcrypt/mpi/mpi-mul.c new file mode 100644 index 0000000..9aefd21 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-mul.c @@ -0,0 +1,212 @@ +/* mpi-mul.c - MPI functions + * Copyright (C) 1994, 1996, 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + + +void +gcry_mpi_mul_ui( gcry_mpi_t prod, gcry_mpi_t mult, unsigned long small_mult ) +{ + mpi_size_t size, prod_size; + mpi_ptr_t prod_ptr; + mpi_limb_t cy; + int sign; + + size = mult->nlimbs; + sign = mult->sign; + + if( !size || !small_mult ) { + prod->nlimbs = 0; + prod->sign = 0; + return; + } + + prod_size = size + 1; + if( prod->alloced < prod_size ) + mpi_resize( prod, prod_size ); + prod_ptr = prod->d; + + cy = _gcry_mpih_mul_1( prod_ptr, mult->d, size, (mpi_limb_t)small_mult ); + if( cy ) + prod_ptr[size++] = cy; + prod->nlimbs = size; + prod->sign = sign; +} + + +void +gcry_mpi_mul_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt) +{ + mpi_size_t usize, wsize, limb_cnt; + mpi_ptr_t wp; + mpi_limb_t wlimb; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + + if( !usize ) { + w->nlimbs = 0; + w->sign = 0; + return; + } + + limb_cnt = cnt / BITS_PER_MPI_LIMB; + wsize = usize + limb_cnt + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize ); + wp = w->d; + wsize = usize + limb_cnt; + wsign = usign; + + cnt %= BITS_PER_MPI_LIMB; + if( cnt ) { + wlimb = _gcry_mpih_lshift( wp + limb_cnt, u->d, usize, cnt ); + if( wlimb ) { + wp[wsize] = wlimb; + wsize++; + } + } + else { + MPN_COPY_DECR( wp + limb_cnt, u->d, usize ); + } + + /* Zero all whole limbs at low end. Do it here and not before calling + * mpn_lshift, not to lose for U == W. */ + MPN_ZERO( wp, limb_cnt ); + + w->nlimbs = wsize; + w->sign = wsign; +} + + +void +gcry_mpi_mul( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v) +{ + mpi_size_t usize, vsize, wsize; + mpi_ptr_t up, vp, wp; + mpi_limb_t cy; + int usign, vsign, usecure, vsecure, sign_product; + int assign_wp=0; + mpi_ptr_t tmp_limb=NULL; + unsigned int tmp_limb_nlimbs = 0; + + if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ + usize = v->nlimbs; + usign = v->sign; + usecure = mpi_is_secure(v); + up = v->d; + vsize = u->nlimbs; + vsign = u->sign; + vsecure = mpi_is_secure(u); + vp = u->d; + } + else { + usize = u->nlimbs; + usign = u->sign; + usecure = mpi_is_secure(u); + up = u->d; + vsize = v->nlimbs; + vsign = v->sign; + vsecure = mpi_is_secure(v); + vp = v->d; + } + sign_product = usign ^ vsign; + wp = w->d; + + /* Ensure W has space enough to store the result. */ + wsize = usize + vsize; + if ( !mpi_is_secure (w) && (mpi_is_secure (u) || mpi_is_secure (v)) ) { + /* w is not allocated in secure space but u or v is. To make sure + * that no temporray results are stored in w, we temporary use + * a newly allocated limb space for w */ + wp = mpi_alloc_limb_space( wsize, 1 ); + assign_wp = 2; /* mark it as 2 so that we can later copy it back to + * mormal memory */ + } + else if( w->alloced < wsize ) { + if( wp == up || wp == vp ) { + wp = mpi_alloc_limb_space( wsize, mpi_is_secure(w) ); + assign_wp = 1; + } + else { + mpi_resize(w, wsize ); + wp = w->d; + } + } + else { /* Make U and V not overlap with W. */ + if( wp == up ) { + /* W and U are identical. Allocate temporary space for U. */ + tmp_limb_nlimbs = usize; + up = tmp_limb = mpi_alloc_limb_space( usize, usecure ); + /* Is V identical too? Keep it identical with U. */ + if( wp == vp ) + vp = up; + /* Copy to the temporary space. */ + MPN_COPY( up, wp, usize ); + } + else if( wp == vp ) { + /* W and V are identical. Allocate temporary space for V. */ + tmp_limb_nlimbs = vsize; + vp = tmp_limb = mpi_alloc_limb_space( vsize, vsecure ); + /* Copy to the temporary space. */ + MPN_COPY( vp, wp, vsize ); + } + } + + if( !vsize ) + wsize = 0; + else { + cy = _gcry_mpih_mul( wp, up, usize, vp, vsize ); + wsize -= cy? 0:1; + } + + if( assign_wp ) { + if (assign_wp == 2) { + /* copy the temp wp from secure memory back to normal memory */ + mpi_ptr_t tmp_wp = mpi_alloc_limb_space (wsize, 0); + MPN_COPY (tmp_wp, wp, wsize); + _gcry_mpi_free_limb_space (wp, 0); + wp = tmp_wp; + } + _gcry_mpi_assign_limb_space( w, wp, wsize ); + } + w->nlimbs = wsize; + w->sign = sign_product; + if( tmp_limb ) + _gcry_mpi_free_limb_space (tmp_limb, tmp_limb_nlimbs); +} + + +void +gcry_mpi_mulm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) +{ + gcry_mpi_mul(w, u, v); + _gcry_mpi_fdiv_r( w, w, m ); +} diff --git a/grub-core/lib/libgcrypt/mpi/mpi-pow.c b/grub-core/lib/libgcrypt/mpi/mpi-pow.c new file mode 100644 index 0000000..58643fe --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-pow.c @@ -0,0 +1,338 @@ +/* mpi-pow.c - MPI functions for exponentiation + * Copyright (C) 1994, 1996, 1998, 2000, 2002 + * 2003 Free Software Foundation, Inc. + * 2013 g10 Code GmbH + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "mpi-internal.h" +#include "longlong.h" + + +/**************** + * RES = BASE ^ EXPO mod MOD + */ +void +gcry_mpi_powm (gcry_mpi_t res, + gcry_mpi_t base, gcry_mpi_t expo, gcry_mpi_t mod) +{ + /* Pointer to the limbs of the arguments, their size and signs. */ + mpi_ptr_t rp, ep, mp, bp; + mpi_size_t esize, msize, bsize, rsize; + int msign, bsign, rsign; + /* Flags telling the secure allocation status of the arguments. */ + int esec, msec, bsec; + /* Size of the result including space for temporary values. */ + mpi_size_t size; + /* Helper. */ + int mod_shift_cnt; + int negative_result; + mpi_ptr_t mp_marker = NULL; + mpi_ptr_t bp_marker = NULL; + mpi_ptr_t ep_marker = NULL; + mpi_ptr_t xp_marker = NULL; + unsigned int mp_nlimbs = 0; + unsigned int bp_nlimbs = 0; + unsigned int ep_nlimbs = 0; + unsigned int xp_nlimbs = 0; + mpi_ptr_t tspace = NULL; + mpi_size_t tsize = 0; + + + esize = expo->nlimbs; + msize = mod->nlimbs; + size = 2 * msize; + msign = mod->sign; + + esec = mpi_is_secure(expo); + msec = mpi_is_secure(mod); + bsec = mpi_is_secure(base); + + rp = res->d; + ep = expo->d; + + if (!msize) + grub_fatal ("mpi division by zero"); + + if (!esize) + { + /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 depending + on if MOD equals 1. */ + res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; + if (res->nlimbs) + { + RESIZE_IF_NEEDED (res, 1); + rp = res->d; + rp[0] = 1; + } + res->sign = 0; + goto leave; + } + + /* Normalize MOD (i.e. make its most significant bit set) as + required by mpn_divrem. This will make the intermediate values + in the calculation slightly larger, but the correct result is + obtained after a final reduction using the original MOD value. */ + mp_nlimbs = msec? msize:0; + mp = mp_marker = mpi_alloc_limb_space(msize, msec); + count_leading_zeros (mod_shift_cnt, mod->d[msize-1]); + if (mod_shift_cnt) + _gcry_mpih_lshift (mp, mod->d, msize, mod_shift_cnt); + else + MPN_COPY( mp, mod->d, msize ); + + bsize = base->nlimbs; + bsign = base->sign; + if (bsize > msize) + { + /* The base is larger than the module. Reduce it. + + Allocate (BSIZE + 1) with space for remainder and quotient. + (The quotient is (bsize - msize + 1) limbs.) */ + bp_nlimbs = bsec ? (bsize + 1):0; + bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec ); + MPN_COPY ( bp, base->d, bsize ); + /* We don't care about the quotient, store it above the + * remainder, at BP + MSIZE. */ + _gcry_mpih_divrem( bp + msize, 0, bp, bsize, mp, msize ); + bsize = msize; + /* Canonicalize the base, since we are going to multiply with it + quite a few times. */ + MPN_NORMALIZE( bp, bsize ); + } + else + bp = base->d; + + if (!bsize) + { + res->nlimbs = 0; + res->sign = 0; + goto leave; + } + + + /* Make BASE, EXPO and MOD not overlap with RES. */ + if ( rp == bp ) + { + /* RES and BASE are identical. Allocate temp. space for BASE. */ + gcry_assert (!bp_marker); + bp_nlimbs = bsec? bsize:0; + bp = bp_marker = mpi_alloc_limb_space( bsize, bsec ); + MPN_COPY(bp, rp, bsize); + } + if ( rp == ep ) + { + /* RES and EXPO are identical. Allocate temp. space for EXPO. */ + ep_nlimbs = esec? esize:0; + ep = ep_marker = mpi_alloc_limb_space( esize, esec ); + MPN_COPY(ep, rp, esize); + } + if ( rp == mp ) + { + /* RES and MOD are identical. Allocate temporary space for MOD.*/ + gcry_assert (!mp_marker); + mp_nlimbs = msec?msize:0; + mp = mp_marker = mpi_alloc_limb_space( msize, msec ); + MPN_COPY(mp, rp, msize); + } + + /* Copy base to the result. */ + if (res->alloced < size) + { + mpi_resize (res, size); + rp = res->d; + } + MPN_COPY ( rp, bp, bsize ); + rsize = bsize; + rsign = bsign; + + /* Main processing. */ + { + mpi_size_t i; + mpi_ptr_t xp; + int c; + mpi_limb_t e; + mpi_limb_t carry_limb; + struct karatsuba_ctx karactx; + + xp_nlimbs = msec? (2 * (msize + 1)):0; + xp = xp_marker = mpi_alloc_limb_space( 2 * (msize + 1), msec ); + + memset( &karactx, 0, sizeof karactx ); + negative_result = (ep[0] & 1) && base->sign; + + i = esize - 1; + e = ep[i]; + count_leading_zeros (c, e); + e = (e << c) << 1; /* Shift the expo bits to the left, lose msb. */ + c = BITS_PER_MPI_LIMB - 1 - c; + + /* Main loop. + + Make the result be pointed to alternately by XP and RP. This + helps us avoid block copying, which would otherwise be + necessary with the overlap restrictions of + _gcry_mpih_divmod. With 50% probability the result after this + loop will be in the area originally pointed by RP (==RES->d), + and with 50% probability in the area originally pointed to by XP. */ + for (;;) + { + while (c) + { + mpi_ptr_t tp; + mpi_size_t xsize; + + /*mpih_mul_n(xp, rp, rp, rsize);*/ + if ( rsize < KARATSUBA_THRESHOLD ) + _gcry_mpih_sqr_n_basecase( xp, rp, rsize ); + else + { + if ( !tspace ) + { + tsize = 2 * rsize; + tspace = mpi_alloc_limb_space( tsize, 0 ); + } + else if ( tsize < (2*rsize) ) + { + _gcry_mpi_free_limb_space (tspace, 0); + tsize = 2 * rsize; + tspace = mpi_alloc_limb_space (tsize, 0 ); + } + _gcry_mpih_sqr_n (xp, rp, rsize, tspace); + } + + xsize = 2 * rsize; + if ( xsize > msize ) + { + _gcry_mpih_divrem(xp + msize, 0, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + + /* To mitigate the Yarom/Falkner flush+reload cache + * side-channel attack on the RSA secret exponent, we do + * the multiplication regardless of the value of the + * high-bit of E. But to avoid this performance penalty + * we do it only if the exponent has been stored in secure + * memory and we can thus assume it is a secret exponent. */ + if (esec || (mpi_limb_signed_t)e < 0) + { + /*mpih_mul( xp, rp, rsize, bp, bsize );*/ + if( bsize < KARATSUBA_THRESHOLD ) + _gcry_mpih_mul ( xp, rp, rsize, bp, bsize ); + else + _gcry_mpih_mul_karatsuba_case (xp, rp, rsize, bp, bsize, + &karactx); + + xsize = rsize + bsize; + if ( xsize > msize ) + { + _gcry_mpih_divrem(xp + msize, 0, xp, xsize, mp, msize); + xsize = msize; + } + } + if ( (mpi_limb_signed_t)e < 0 ) + { + tp = rp; rp = xp; xp = tp; + rsize = xsize; + } + e <<= 1; + c--; + } + + i--; + if ( i < 0 ) + break; + e = ep[i]; + c = BITS_PER_MPI_LIMB; + } + + /* We shifted MOD, the modulo reduction argument, left + MOD_SHIFT_CNT steps. Adjust the result by reducing it with the + original MOD. + + Also make sure the result is put in RES->d (where it already + might be, see above). */ + if ( mod_shift_cnt ) + { + carry_limb = _gcry_mpih_lshift( res->d, rp, rsize, mod_shift_cnt); + rp = res->d; + if ( carry_limb ) + { + rp[rsize] = carry_limb; + rsize++; + } + } + else if (res->d != rp) + { + MPN_COPY (res->d, rp, rsize); + rp = res->d; + } + + if ( rsize >= msize ) + { + _gcry_mpih_divrem(rp + msize, 0, rp, rsize, mp, msize); + rsize = msize; + } + + /* Remove any leading zero words from the result. */ + if ( mod_shift_cnt ) + _gcry_mpih_rshift( rp, rp, rsize, mod_shift_cnt); + MPN_NORMALIZE (rp, rsize); + + _gcry_mpih_release_karatsuba_ctx (&karactx ); + } + + /* Fixup for negative results. */ + if ( negative_result && rsize ) + { + if ( mod_shift_cnt ) + _gcry_mpih_rshift( mp, mp, msize, mod_shift_cnt); + _gcry_mpih_sub( rp, mp, msize, rp, rsize); + rsize = msize; + rsign = msign; + MPN_NORMALIZE(rp, rsize); + } + gcry_assert (res->d == rp); + res->nlimbs = rsize; + res->sign = rsign; + + leave: + if (mp_marker) + _gcry_mpi_free_limb_space( mp_marker, mp_nlimbs ); + if (bp_marker) + _gcry_mpi_free_limb_space( bp_marker, bp_nlimbs ); + if (ep_marker) + _gcry_mpi_free_limb_space( ep_marker, ep_nlimbs ); + if (xp_marker) + _gcry_mpi_free_limb_space( xp_marker, xp_nlimbs ); + if (tspace) + _gcry_mpi_free_limb_space( tspace, 0 ); +} diff --git a/grub-core/lib/libgcrypt/mpi/mpi-scan.c b/grub-core/lib/libgcrypt/mpi/mpi-scan.c new file mode 100644 index 0000000..2473cd9 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpi-scan.c @@ -0,0 +1,130 @@ +/* mpi-scan.c - MPI functions + * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +/**************** + * Scan through an mpi and return byte for byte. a -1 is returned to indicate + * the end of the mpi. Scanning is done from the lsb to the msb, returned + * values are in the range of 0 .. 255. + * + * FIXME: This code is VERY ugly! + */ +int +_gcry_mpi_getbyte( gcry_mpi_t a, unsigned idx ) +{ + int i, j; + unsigned n; + mpi_ptr_t ap; + mpi_limb_t limb; + + ap = a->d; + for(n=0,i=0; i < a->nlimbs; i++ ) { + limb = ap[i]; + for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ ) + if( n == idx ) + return (limb >> j*8) & 0xff; + } + return -1; +} + + +/**************** + * Put a value at position IDX into A. idx counts from lsb to msb + */ +void +_gcry_mpi_putbyte( gcry_mpi_t a, unsigned idx, int xc ) +{ + int i, j; + unsigned n; + mpi_ptr_t ap; + mpi_limb_t limb, c; + + c = xc & 0xff; + ap = a->d; + for(n=0,i=0; i < a->alloced; i++ ) { + limb = ap[i]; + for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ ) + if( n == idx ) { + #if BYTES_PER_MPI_LIMB == 4 + if( j == 0 ) + limb = (limb & 0xffffff00) | c; + else if( j == 1 ) + limb = (limb & 0xffff00ff) | (c<<8); + else if( j == 2 ) + limb = (limb & 0xff00ffff) | (c<<16); + else + limb = (limb & 0x00ffffff) | (c<<24); + #elif BYTES_PER_MPI_LIMB == 8 + if( j == 0 ) + limb = (limb & 0xffffffffffffff00) | c; + else if( j == 1 ) + limb = (limb & 0xffffffffffff00ff) | (c<<8); + else if( j == 2 ) + limb = (limb & 0xffffffffff00ffff) | (c<<16); + else if( j == 3 ) + limb = (limb & 0xffffffff00ffffff) | (c<<24); + else if( j == 4 ) + limb = (limb & 0xffffff00ffffffff) | (c<<32); + else if( j == 5 ) + limb = (limb & 0xffff00ffffffffff) | (c<<40); + else if( j == 6 ) + limb = (limb & 0xff00ffffffffffff) | (c<<48); + else + limb = (limb & 0x00ffffffffffffff) | (c<<56); + #else + #error please enhance this function, its ugly - i know. + #endif + if( a->nlimbs <= i ) + a->nlimbs = i+1; + ap[i] = limb; + return; + } + } + abort(); /* index out of range */ +} + + +/**************** + * Count the number of zerobits at the low end of A + */ +unsigned +_gcry_mpi_trailing_zeros( gcry_mpi_t a ) +{ + unsigned n, count = 0; + + for(n=0; n < a->nlimbs; n++ ) { + if( a->d[n] ) { + unsigned nn; + mpi_limb_t alimb = a->d[n]; + + count_trailing_zeros( nn, alimb ); + count += nn; + break; + } + count += BITS_PER_MPI_LIMB; + } + return count; + +} diff --git a/grub-core/lib/libgcrypt/mpi/mpicoder.c b/grub-core/lib/libgcrypt/mpi/mpicoder.c new file mode 100644 index 0000000..6fe3891 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpicoder.c @@ -0,0 +1,753 @@ +/* mpicoder.c - Coder for the external representation of MPIs + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 + * 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "mpi-internal.h" +#include "g10lib.h" + +#define MAX_EXTERN_MPI_BITS 16384 + +/* Helper used to scan PGP style MPIs. Returns NULL on failure. */ +static gcry_mpi_t +mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread, + int secure) +{ + int i, j; + unsigned int nbits, nbytes, nlimbs, nread=0; + mpi_limb_t a; + gcry_mpi_t val = MPI_NULL; + + if ( *ret_nread < 2 ) + goto leave; + nbits = buffer[0] << 8 | buffer[1]; + if ( nbits > MAX_EXTERN_MPI_BITS ) + { +/* log_debug ("mpi too large (%u bits)\n", nbits); */ + goto leave; + } + buffer += 2; + nread = 2; + + nbytes = (nbits+7) / 8; + nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; + val = secure? mpi_alloc_secure (nlimbs) : mpi_alloc (nlimbs); + i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; + i %= BYTES_PER_MPI_LIMB; + j= val->nlimbs = nlimbs; + val->sign = 0; + for ( ; j > 0; j-- ) + { + a = 0; + for (; i < BYTES_PER_MPI_LIMB; i++ ) + { + if ( ++nread > *ret_nread ) + { +/* log_debug ("mpi larger than buffer"); */ + mpi_free (val); + val = NULL; + goto leave; + } + a <<= 8; + a |= *buffer++; + } + i = 0; + val->d[j-1] = a; + } + + leave: + *ret_nread = nread; + return val; +} + + +/**************** + * Fill the mpi VAL from the hex string in STR. + */ +static int +mpi_fromstr (gcry_mpi_t val, const char *str) +{ + int sign = 0; + int prepend_zero = 0; + int i, j, c, c1, c2; + unsigned int nbits, nbytes, nlimbs; + mpi_limb_t a; + + if ( *str == '-' ) + { + sign = 1; + str++; + } + + /* Skip optional hex prefix. */ + if ( *str == '0' && str[1] == 'x' ) + str += 2; + + nbits = 4 * strlen (str); + if ((nbits % 8)) + prepend_zero = 1; + + nbytes = (nbits+7) / 8; + nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; + + if ( val->alloced < nlimbs ) + mpi_resize (val, nlimbs); + + i = BYTES_PER_MPI_LIMB - (nbytes % BYTES_PER_MPI_LIMB); + i %= BYTES_PER_MPI_LIMB; + j = val->nlimbs = nlimbs; + val->sign = sign; + for (; j > 0; j--) + { + a = 0; + for (; i < BYTES_PER_MPI_LIMB; i++) + { + if (prepend_zero) + { + c1 = '0'; + prepend_zero = 0; + } + else + c1 = *str++; + + if (!c1) + { + mpi_clear (val); + return 1; /* Error. */ + } + c2 = *str++; + if (!c2) + { + mpi_clear (val); + return 1; /* Error. */ + } + if ( c1 >= '0' && c1 <= '9' ) + c = c1 - '0'; + else if ( c1 >= 'a' && c1 <= 'f' ) + c = c1 - 'a' + 10; + else if ( c1 >= 'A' && c1 <= 'F' ) + c = c1 - 'A' + 10; + else + { + mpi_clear (val); + return 1; /* Error. */ + } + c <<= 4; + if ( c2 >= '0' && c2 <= '9' ) + c |= c2 - '0'; + else if( c2 >= 'a' && c2 <= 'f' ) + c |= c2 - 'a' + 10; + else if( c2 >= 'A' && c2 <= 'F' ) + c |= c2 - 'A' + 10; + else + { + mpi_clear(val); + return 1; /* Error. */ + } + a <<= 8; + a |= c; + } + i = 0; + val->d[j-1] = a; + } + + return 0; /* Okay. */ +} + + +/* Dump the value of A in a format suitable for debugging to + Libgcrypt's logging stream. Note that one leading space but no + trailing space or linefeed will be printed. It is okay to pass + NULL for A. */ +void +gcry_mpi_dump (const gcry_mpi_t a) +{ + int i; + + log_printf (" "); + if (!a) + log_printf ("[MPI_NULL]"); + else + { + if (a->sign) + log_printf ( "-"); +#if BYTES_PER_MPI_LIMB == 2 +# define X "4" +#elif BYTES_PER_MPI_LIMB == 4 +# define X "8" +#elif BYTES_PER_MPI_LIMB == 8 +# define X "16" +#elif BYTES_PER_MPI_LIMB == 16 +# define X "32" +#else +# error please define the format here +#endif + for (i=a->nlimbs; i > 0 ; i-- ) + { + log_printf (i != a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]); + } +#undef X + if (!a->nlimbs) + log_printf ("0"); + } +} + +/* Convience function used internally. */ +void +_gcry_log_mpidump (const char *text, gcry_mpi_t a) +{ + log_printf ("%s:", text); + gcry_mpi_dump (a); + log_printf ("\n"); +} + + +/* Return an allocated buffer with the MPI (msb first). NBYTES + receives the length of this buffer. Caller must free the return + string. This function returns an allocated buffer with NBYTES set + to zero if the value of A is zero. If sign is not NULL, it will be + set to the sign of the A. On error NULL is returned and ERRNO set + appropriately. */ +static unsigned char * +do_get_buffer (gcry_mpi_t a, unsigned int *nbytes, int *sign, int force_secure) +{ + unsigned char *p, *buffer; + mpi_limb_t alimb; + int i; + size_t n; + + if (sign) + *sign = a->sign; + + *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB; + n = *nbytes? *nbytes:1; /* Allocate at least one byte. */ + p = buffer = (force_secure || mpi_is_secure(a))? gcry_malloc_secure (n) + : gcry_malloc (n); + if (!buffer) + return NULL; + + for (i=a->nlimbs-1; i >= 0; i--) + { + alimb = a->d[i]; +#if BYTES_PER_MPI_LIMB == 4 + *p++ = alimb >> 24; + *p++ = alimb >> 16; + *p++ = alimb >> 8; + *p++ = alimb ; +#elif BYTES_PER_MPI_LIMB == 8 + *p++ = alimb >> 56; + *p++ = alimb >> 48; + *p++ = alimb >> 40; + *p++ = alimb >> 32; + *p++ = alimb >> 24; + *p++ = alimb >> 16; + *p++ = alimb >> 8; + *p++ = alimb ; +#else +# error please implement for this limb size. +#endif + } + + /* This is sub-optimal but we need to do the shift operation because + the caller has to free the returned buffer. */ + for (p=buffer; *nbytes && !*p; p++, --*nbytes) + ; + if (p != buffer) + memmove (buffer,p, *nbytes); + return buffer; +} + + +byte * +_gcry_mpi_get_buffer (gcry_mpi_t a, unsigned int *nbytes, int *sign) +{ + return do_get_buffer (a, nbytes, sign, 0); +} + +byte * +_gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned *nbytes, int *sign) +{ + return do_get_buffer (a, nbytes, sign, 1); +} + + +/* + * Use the NBYTES at BUFFER_ARG to update A. Set the sign of a to + * SIGN. + */ +void +_gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg, + unsigned int nbytes, int sign) +{ + const unsigned char *buffer = (const unsigned char*)buffer_arg; + const unsigned char *p; + mpi_limb_t alimb; + int nlimbs; + int i; + + nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; + RESIZE_IF_NEEDED(a, nlimbs); + a->sign = sign; + + for (i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) + { +#if BYTES_PER_MPI_LIMB == 4 + alimb = *p-- ; + alimb |= *p-- << 8 ; + alimb |= *p-- << 16 ; + alimb |= *p-- << 24 ; +#elif BYTES_PER_MPI_LIMB == 8 + alimb = (mpi_limb_t)*p-- ; + alimb |= (mpi_limb_t)*p-- << 8 ; + alimb |= (mpi_limb_t)*p-- << 16 ; + alimb |= (mpi_limb_t)*p-- << 24 ; + alimb |= (mpi_limb_t)*p-- << 32 ; + alimb |= (mpi_limb_t)*p-- << 40 ; + alimb |= (mpi_limb_t)*p-- << 48 ; + alimb |= (mpi_limb_t)*p-- << 56 ; +#else +# error please implement for this limb size. +#endif + a->d[i++] = alimb; + } + if ( p >= buffer ) + { +#if BYTES_PER_MPI_LIMB == 4 + alimb = *p--; + if (p >= buffer) + alimb |= *p-- << 8; + if (p >= buffer) + alimb |= *p-- << 16; + if (p >= buffer) + alimb |= *p-- << 24; +#elif BYTES_PER_MPI_LIMB == 8 + alimb = (mpi_limb_t)*p--; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 8; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 16; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 24; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 32; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 40; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 48; + if (p >= buffer) + alimb |= (mpi_limb_t)*p-- << 56; +#else +# error please implement for this limb size. +#endif + a->d[i++] = alimb; + } + a->nlimbs = i; + gcry_assert (i == nlimbs); +} + + +/* Convert the external representation of an integer stored in BUFFER + with a length of BUFLEN into a newly create MPI returned in + RET_MPI. If NBYTES is not NULL, it will receive the number of + bytes actually scanned after a successful operation. */ +gcry_error_t +gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format, + const void *buffer_arg, size_t buflen, size_t *nscanned) +{ + const unsigned char *buffer = (const unsigned char*)buffer_arg; + struct gcry_mpi *a = NULL; + unsigned int len; + int secure = (buffer && gcry_is_secure (buffer)); + + if (!buffer) + return gcry_error (GPG_ERR_INV_ARG); + + if (format == GCRYMPI_FMT_SSH) + len = 0; + else + len = buflen; + + if (format == GCRYMPI_FMT_STD) + { + const unsigned char *s = buffer; + + a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1) + /BYTES_PER_MPI_LIMB) + : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); + if (len) + { + a->sign = !!(*s & 0x80); + if (a->sign) + { + /* FIXME: we have to convert from 2compl to magnitude format */ + mpi_free (a); + return gcry_error (GPG_ERR_INTERNAL); + } + else + _gcry_mpi_set_buffer (a, s, len, 0); + } + if (ret_mpi) + { + mpi_normalize ( a ); + *ret_mpi = a; + } + else + mpi_free(a); + return 0; + } + else if (format == GCRYMPI_FMT_USG) + { + a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1) + /BYTES_PER_MPI_LIMB) + : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); + + if (len) + _gcry_mpi_set_buffer (a, buffer, len, 0); + if (ret_mpi) + { + mpi_normalize ( a ); + *ret_mpi = a; + } + else + mpi_free(a); + return 0; + } + else if (format == GCRYMPI_FMT_PGP) + { + a = mpi_read_from_buffer (buffer, &len, secure); + if (nscanned) + *nscanned = len; + if (ret_mpi && a) + { + mpi_normalize (a); + *ret_mpi = a; + } + else if (a) + { + mpi_free(a); + a = NULL; + } + return a? 0 : gcry_error (GPG_ERR_INV_OBJ); + } + else if (format == GCRYMPI_FMT_SSH) + { + const unsigned char *s = buffer; + size_t n; + + /* This test is not strictly necessary and an assert (!len) + would be sufficient. We keep this test in case we later + allow the BUFLEN argument to act as a sanitiy check. Same + below. */ + if (len && len < 4) + return gcry_error (GPG_ERR_TOO_SHORT); + + n = ((size_t)s[0] << 24 | (size_t)s[1] << 16 | (size_t)s[2] << 8 | (size_t)s[3]); + s += 4; + if (len) + len -= 4; + if (len && n > len) + return gcry_error (GPG_ERR_TOO_LARGE); + + a = secure? mpi_alloc_secure ((n+BYTES_PER_MPI_LIMB-1) + /BYTES_PER_MPI_LIMB) + : mpi_alloc ((n+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); + if (n) + { + a->sign = !!(*s & 0x80); + if (a->sign) + { + /* FIXME: we have to convert from 2compl to magnitude format */ + mpi_free(a); + return gcry_error (GPG_ERR_INTERNAL); + } + else + _gcry_mpi_set_buffer( a, s, n, 0 ); + } + if (nscanned) + *nscanned = n+4; + if (ret_mpi) + { + mpi_normalize ( a ); + *ret_mpi = a; + } + else + mpi_free(a); + return 0; + } + else if (format == GCRYMPI_FMT_HEX) + { + /* We can only handle C strings for now. */ + if (buflen) + return gcry_error (GPG_ERR_INV_ARG); + + a = secure? mpi_alloc_secure (0) : mpi_alloc(0); + if (mpi_fromstr (a, (const char *)buffer)) + { + mpi_free (a); + return gcry_error (GPG_ERR_INV_OBJ); + } + if (ret_mpi) + { + mpi_normalize ( a ); + *ret_mpi = a; + } + else + mpi_free(a); + return 0; + } + else + return gcry_error (GPG_ERR_INV_ARG); +} + + +/* Convert the big integer A into the external representation + described by FORMAT and store it in the provided BUFFER which has + been allocated by the user with a size of BUFLEN bytes. NWRITTEN + receives the actual length of the external representation unless it + has been passed as NULL. BUFFER may be NULL to query the required + length. */ +gcry_error_t +gcry_mpi_print (enum gcry_mpi_format format, + unsigned char *buffer, size_t buflen, + size_t *nwritten, struct gcry_mpi *a) +{ + unsigned int nbits = mpi_get_nbits (a); + size_t len; + size_t dummy_nwritten; + + if (!nwritten) + nwritten = &dummy_nwritten; + + len = buflen; + *nwritten = 0; + if (format == GCRYMPI_FMT_STD) + { + unsigned char *tmp; + int extra = 0; + unsigned int n; + + if (a->sign) + return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */ + + tmp = _gcry_mpi_get_buffer (a, &n, NULL); + if (!tmp) + return gpg_error_from_syserror (); + if (n && (*tmp & 0x80)) + { + n++; + extra=1; + } + + if (buffer && n > len) + { + /* The provided buffer is too short. */ + gcry_free (tmp); + return gcry_error (GPG_ERR_TOO_SHORT); + } + if (buffer) + { + unsigned char *s = buffer; + + if (extra) + *s++ = 0; + memcpy (s, tmp, n-extra); + } + gcry_free(tmp); + *nwritten = n; + return 0; + } + else if (format == GCRYMPI_FMT_USG) + { + unsigned int n = (nbits + 7)/8; + + /* Note: We ignore the sign for this format. */ + /* FIXME: for performance reasons we should put this into + mpi_aprint because we can then use the buffer directly. */ + if (buffer && n > len) + return gcry_error (GPG_ERR_TOO_SHORT); + if (buffer) + { + unsigned char *tmp; + + tmp = _gcry_mpi_get_buffer (a, &n, NULL); + if (!tmp) + return gpg_error_from_syserror (); + memcpy (buffer, tmp, n); + gcry_free (tmp); + } + *nwritten = n; + return 0; + } + else if (format == GCRYMPI_FMT_PGP) + { + unsigned int n = (nbits + 7)/8; + + /* The PGP format can only handle unsigned integers. */ + if( a->sign ) + return gcry_error (GPG_ERR_INV_ARG); + + if (buffer && n+2 > len) + return gcry_error (GPG_ERR_TOO_SHORT); + + if (buffer) + { + unsigned char *tmp; + unsigned char *s = buffer; + + s[0] = nbits >> 8; + s[1] = nbits; + + tmp = _gcry_mpi_get_buffer (a, &n, NULL); + if (!tmp) + return gpg_error_from_syserror (); + memcpy (s+2, tmp, n); + gcry_free (tmp); + } + *nwritten = n+2; + return 0; + } + else if (format == GCRYMPI_FMT_SSH) + { + unsigned char *tmp; + int extra = 0; + unsigned int n; + + if (a->sign) + return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */ + + tmp = _gcry_mpi_get_buffer (a, &n, NULL); + if (!tmp) + return gpg_error_from_syserror (); + if (n && (*tmp & 0x80)) + { + n++; + extra=1; + } + + if (buffer && n+4 > len) + { + gcry_free(tmp); + return gcry_error (GPG_ERR_TOO_SHORT); + } + + if (buffer) + { + unsigned char *s = buffer; + + *s++ = n >> 24; + *s++ = n >> 16; + *s++ = n >> 8; + *s++ = n; + if (extra) + *s++ = 0; + + memcpy (s, tmp, n-extra); + } + gcry_free (tmp); + *nwritten = 4+n; + return 0; + } + else if (format == GCRYMPI_FMT_HEX) + { + unsigned char *tmp; + int i; + int extra = 0; + unsigned int n = 0; + + tmp = _gcry_mpi_get_buffer (a, &n, NULL); + if (!tmp) + return gpg_error_from_syserror (); + if (!n || (*tmp & 0x80)) + extra = 2; + + if (buffer && 2*n + extra + !!a->sign + 1 > len) + { + gcry_free(tmp); + return gcry_error (GPG_ERR_TOO_SHORT); + } + if (buffer) + { + unsigned char *s = buffer; + + if (a->sign) + *s++ = '-'; + if (extra) + { + *s++ = '0'; + *s++ = '0'; + } + + for (i=0; i < n; i++) + { + unsigned int c = tmp[i]; + + *s++ = (c >> 4) < 10? '0'+(c>>4) : 'A'+(c>>4)-10 ; + c &= 15; + *s++ = c < 10? '0'+c : 'A'+c-10 ; + } + *s++ = 0; + *nwritten = s - buffer; + } + else + { + *nwritten = 2*n + extra + !!a->sign + 1; + } + gcry_free (tmp); + return 0; + } + else + return gcry_error (GPG_ERR_INV_ARG); +} + + +/* + * Like gcry_mpi_print but this function allocates the buffer itself. + * The caller has to supply the address of a pointer. NWRITTEN may be + * NULL. + */ +gcry_error_t +gcry_mpi_aprint (enum gcry_mpi_format format, + unsigned char **buffer, size_t *nwritten, + struct gcry_mpi *a) +{ + size_t n; + gcry_error_t rc; + + *buffer = NULL; + rc = gcry_mpi_print (format, NULL, 0, &n, a); + if (rc) + return rc; + + *buffer = mpi_is_secure(a) ? gcry_malloc_secure (n) : gcry_malloc (n); + if (!*buffer) + return gpg_error_from_syserror (); + rc = gcry_mpi_print( format, *buffer, n, &n, a ); + if (rc) + { + gcry_free(*buffer); + *buffer = NULL; + } + else if (nwritten) + *nwritten = n; + return rc; +} diff --git a/grub-core/lib/libgcrypt/mpi/mpih-div.c b/grub-core/lib/libgcrypt/mpi/mpih-div.c new file mode 100644 index 0000000..0b458ff --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpih-div.c @@ -0,0 +1,534 @@ +/* mpih-div.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 2000, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +#ifndef UMUL_TIME +#define UMUL_TIME 1 +#endif +#ifndef UDIV_TIME +#define UDIV_TIME UMUL_TIME +#endif + +/* FIXME: We should be using invert_limb (or invert_normalized_limb) + * here (not udiv_qrnnd). + */ + +mpi_limb_t +_gcry_mpih_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb) +{ + mpi_size_t i; + mpi_limb_t n1, n0, r; + int dummy; + + /* Botch: Should this be handled at all? Rely on callers? */ + if( !dividend_size ) + return 0; + + /* If multiplication is much faster than division, and the + * dividend is large, pre-invert the divisor, and use + * only multiplications in the inner loop. + * + * This test should be read: + * Does it ever help to use udiv_qrnnd_preinv? + * && Does what we save compensate for the inversion overhead? + */ + if( UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { + int normalization_steps; + + count_leading_zeros( normalization_steps, divisor_limb ); + if( normalization_steps ) { + mpi_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + * + * Special case for DIVISOR_LIMB == 100...000. + */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV(dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + UDIV_QRNND_PREINV(dummy, r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else { + mpi_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + * + * Special case for DIVISOR_LIMB == 100...000. + */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if( r >= divisor_limb ) + r = 0; + else + i--; + + for( ; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV(dummy, r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else { + if( UDIV_NEEDS_NORMALIZATION ) { + int normalization_steps; + + count_leading_zeros(normalization_steps, divisor_limb); + if( normalization_steps ) { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for(i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (dummy, r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + * it, or because DIVISOR_LIMB is already normalized. */ + i = dividend_size - 1; + r = dividend_ptr[i]; + + if(r >= divisor_limb) + r = 0; + else + i--; + + for(; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, n0, divisor_limb); + } + return r; + } +} + +/* Divide num (NP/NSIZE) by den (DP/DSIZE) and write + * the NSIZE-DSIZE least significant quotient limbs at QP + * and the DSIZE long remainder at NP. If QEXTRA_LIMBS is + * non-zero, generate that many fraction bits and append them after the + * other quotient limbs. + * Return the most significant limb of the quotient, this is always 0 or 1. + * + * Preconditions: + * 0. NSIZE >= DSIZE. + * 1. The most significant bit of the divisor must be set. + * 2. QP must either not overlap with the input operands at all, or + * QP + DSIZE >= NP must hold true. (This means that it's + * possible to put the quotient in the high part of NUM, right after the + * remainder in NUM. + * 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero. + */ + +mpi_limb_t +_gcry_mpih_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, + mpi_ptr_t np, mpi_size_t nsize, + mpi_ptr_t dp, mpi_size_t dsize) +{ + mpi_limb_t most_significant_q_limb = 0; + + switch(dsize) { + case 0: + /* We are asked to divide by zero, so go ahead and do it! (To make + the compiler not remove this statement, return the value.) */ + grub_fatal ("mpi division by zero"); + return 0; + + case 1: + { + mpi_size_t i; + mpi_limb_t n1; + mpi_limb_t d; + + d = dp[0]; + n1 = np[nsize - 1]; + + if( n1 >= d ) { + n1 -= d; + most_significant_q_limb = 1; + } + + qp += qextra_limbs; + for( i = nsize - 2; i >= 0; i--) + udiv_qrnnd( qp[i], n1, n1, np[i], d ); + qp -= qextra_limbs; + + for( i = qextra_limbs - 1; i >= 0; i-- ) + udiv_qrnnd (qp[i], n1, n1, 0, d); + + np[0] = n1; + } + break; + + case 2: + { + mpi_size_t i; + mpi_limb_t n1, n0, n2; + mpi_limb_t d1, d0; + + np += nsize - 2; + d1 = dp[1]; + d0 = dp[0]; + n1 = np[1]; + n0 = np[0]; + + if( n1 >= d1 && (n1 > d1 || n0 >= d0) ) { + sub_ddmmss (n1, n0, n1, n0, d1, d0); + most_significant_q_limb = 1; + } + + for( i = qextra_limbs + nsize - 2 - 1; i >= 0; i-- ) { + mpi_limb_t q; + mpi_limb_t r; + + if( i >= qextra_limbs ) + np--; + else + np[0] = 0; + + if( n1 == d1 ) { + /* Q should be either 111..111 or 111..110. Need special + * treatment of this rare case as normal division would + * give overflow. */ + q = ~(mpi_limb_t)0; + + r = n0 + d1; + if( r < d1 ) { /* Carry in the addition? */ + add_ssaaaa( n1, n0, r - d0, np[0], 0, d0 ); + qp[i] = q; + continue; + } + n1 = d0 - (d0 != 0?1:0); + n0 = -d0; + } + else { + udiv_qrnnd (q, r, n1, n0, d1); + umul_ppmm (n1, n0, d0, q); + } + + n2 = np[0]; + q_test: + if( n1 > r || (n1 == r && n0 > n2) ) { + /* The estimated Q was too large. */ + q--; + sub_ddmmss (n1, n0, n1, n0, 0, d0); + r += d1; + if( r >= d1 ) /* If not carry, test Q again. */ + goto q_test; + } + + qp[i] = q; + sub_ddmmss (n1, n0, r, n2, n1, n0); + } + np[1] = n1; + np[0] = n0; + } + break; + + default: + { + mpi_size_t i; + mpi_limb_t dX, d1, n0; + + np += nsize - dsize; + dX = dp[dsize - 1]; + d1 = dp[dsize - 2]; + n0 = np[dsize - 1]; + + if( n0 >= dX ) { + if(n0 > dX || _gcry_mpih_cmp(np, dp, dsize - 1) >= 0 ) { + _gcry_mpih_sub_n(np, np, dp, dsize); + n0 = np[dsize - 1]; + most_significant_q_limb = 1; + } + } + + for( i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) { + mpi_limb_t q; + mpi_limb_t n1, n2; + mpi_limb_t cy_limb; + + if( i >= qextra_limbs ) { + np--; + n2 = np[dsize]; + } + else { + n2 = np[dsize - 1]; + MPN_COPY_DECR (np + 1, np, dsize - 1); + np[0] = 0; + } + + if( n0 == dX ) { + /* This might over-estimate q, but it's probably not worth + * the extra code here to find out. */ + q = ~(mpi_limb_t)0; + } + else { + mpi_limb_t r; + + udiv_qrnnd(q, r, n0, np[dsize - 1], dX); + umul_ppmm(n1, n0, d1, q); + + while( n1 > r || (n1 == r && n0 > np[dsize - 2])) { + q--; + r += dX; + if( r < dX ) /* I.e. "carry in previous addition?" */ + break; + n1 -= n0 < d1; + n0 -= d1; + } + } + + /* Possible optimization: We already have (q * n0) and (1 * n1) + * after the calculation of q. Taking advantage of that, we + * could make this loop make two iterations less. */ + cy_limb = _gcry_mpih_submul_1(np, dp, dsize, q); + + if( n2 != cy_limb ) { + _gcry_mpih_add_n(np, np, dp, dsize); + q--; + } + + qp[i] = q; + n0 = np[dsize - 1]; + } + } + } + + return most_significant_q_limb; +} + + +/**************** + * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. + * Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. + * Return the single-limb remainder. + * There are no constraints on the value of the divisor. + * + * QUOT_PTR and DIVIDEND_PTR might point to the same limb. + */ + +mpi_limb_t +_gcry_mpih_divmod_1( mpi_ptr_t quot_ptr, + mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb) +{ + mpi_size_t i; + mpi_limb_t n1, n0, r; + int dummy; + + if( !dividend_size ) + return 0; + + /* If multiplication is much faster than division, and the + * dividend is large, pre-invert the divisor, and use + * only multiplications in the inner loop. + * + * This test should be read: + * Does it ever help to use udiv_qrnnd_preinv? + * && Does what we save compensate for the inversion overhead? + */ + if( UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { + int normalization_steps; + + count_leading_zeros( normalization_steps, divisor_limb ); + if( normalization_steps ) { + mpi_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + */ + /* Special case for DIVISOR_LIMB == 100...000. */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV( quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + UDIV_QRNND_PREINV( quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else { + mpi_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + */ + /* Special case for DIVISOR_LIMB == 100...000. */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t) 0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if( r >= divisor_limb ) + r = 0; + else + quot_ptr[i--] = 0; + + for( ; i >= 0; i-- ) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV( quot_ptr[i], r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else { + if(UDIV_NEEDS_NORMALIZATION) { + int normalization_steps; + + count_leading_zeros (normalization_steps, divisor_limb); + if( normalization_steps ) { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + * it, or because DIVISOR_LIMB is already normalized. */ + i = dividend_size - 1; + r = dividend_ptr[i]; + + if(r >= divisor_limb) + r = 0; + else + quot_ptr[i--] = 0; + + for(; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd( quot_ptr[i], r, r, n0, divisor_limb ); + } + return r; + } +} diff --git a/grub-core/lib/libgcrypt/mpi/mpih-mul.c b/grub-core/lib/libgcrypt/mpi/mpih-mul.c new file mode 100644 index 0000000..b8e0561 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpih-mul.c @@ -0,0 +1,528 @@ +/* mpih-mul.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 1999, 2000, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "mpi-internal.h" +#include "longlong.h" +#include "g10lib.h" + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if( (size) < KARATSUBA_THRESHOLD ) \ + mul_n_basecase (prodp, up, vp, size); \ + else \ + mul_n (prodp, up, vp, size, tspace); \ + } while (0); + +#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \ + do { \ + if ((size) < KARATSUBA_THRESHOLD) \ + _gcry_mpih_sqr_n_basecase (prodp, up, size); \ + else \ + _gcry_mpih_sqr_n (prodp, up, size, tspace); \ + } while (0); + + + + +/* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP), + * both with SIZE limbs, and store the result at PRODP. 2 * SIZE limbs are + * always stored. Return the most significant limb. + * + * Argument constraints: + * 1. PRODP != UP and PRODP != VP, i.e. the destination + * must be distinct from the multiplier and the multiplicand. + * + * + * Handle simple cases with traditional multiplication. + * + * This is the most critical code of multiplication. All multiplies rely + * on this, both small and huge. Small ones arrive here immediately. Huge + * ones arrive here as this is the base case for Karatsuba's recursive + * algorithm below. + */ + +static mpi_limb_t +mul_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, + mpi_ptr_t vp, mpi_size_t size) +{ + mpi_size_t i; + mpi_limb_t cy; + mpi_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, size ); + else + MPN_ZERO( prodp, size ); + cy = 0; + } + else + cy = _gcry_mpih_mul_1( prodp, up, size, v_limb ); + + prodp[size] = cy; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i = 1; i < size; i++ ) { + v_limb = vp[i]; + if( v_limb <= 1 ) { + cy = 0; + if( v_limb == 1 ) + cy = _gcry_mpih_add_n(prodp, prodp, up, size); + } + else + cy = _gcry_mpih_addmul_1(prodp, up, size, v_limb); + + prodp[size] = cy; + prodp++; + } + + return cy; +} + + +static void +mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, + mpi_size_t size, mpi_ptr_t tspace ) +{ + if( size & 1 ) { + /* The size is odd, and the code below doesn't handle that. + * Multiply the least significant (size - 1) limbs with a recursive + * call, and handle the most significant limb of S1 and S2 + * separately. + * A slightly faster way to do this would be to make the Karatsuba + * code below behave as if the size were even, and let it check for + * odd size in the end. I.e., in essence move this code to the end. + * Doing so would save us a recursive call, and potentially make the + * stack grow a lot less. + */ + mpi_size_t esize = size - 1; /* even size */ + mpi_limb_t cy_limb; + + MPN_MUL_N_RECURSE( prodp, up, vp, esize, tspace ); + cy_limb = _gcry_mpih_addmul_1( prodp + esize, up, esize, vp[esize] ); + prodp[esize + esize] = cy_limb; + cy_limb = _gcry_mpih_addmul_1( prodp + esize, vp, size, up[esize] ); + prodp[esize + size] = cy_limb; + } + else { + /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm. + * + * Split U in two pieces, U1 and U0, such that + * U = U0 + U1*(B**n), + * and V in V1 and V0, such that + * V = V0 + V1*(B**n). + * + * UV is then computed recursively using the identity + * + * 2n n n n + * UV = (B + B )U V + B (U -U )(V -V ) + (B + 1)U V + * 1 1 1 0 0 1 0 0 + * + * Where B = 2**BITS_PER_MP_LIMB. + */ + mpi_size_t hsize = size >> 1; + mpi_limb_t cy; + int negflg; + + /* Product H. ________________ ________________ + * |_____U1 x V1____||____U0 x V0_____| + * Put result in upper part of PROD and pass low part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(prodp + size, up + hsize, vp + hsize, hsize, tspace); + + /* Product M. ________________ + * |_(U1-U0)(V0-V1)_| + */ + if( _gcry_mpih_cmp(up + hsize, up, hsize) >= 0 ) { + _gcry_mpih_sub_n(prodp, up + hsize, up, hsize); + negflg = 0; + } + else { + _gcry_mpih_sub_n(prodp, up, up + hsize, hsize); + negflg = 1; + } + if( _gcry_mpih_cmp(vp + hsize, vp, hsize) >= 0 ) { + _gcry_mpih_sub_n(prodp + hsize, vp + hsize, vp, hsize); + negflg ^= 1; + } + else { + _gcry_mpih_sub_n(prodp + hsize, vp, vp + hsize, hsize); + /* No change of NEGFLG. */ + } + /* Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(tspace, prodp, prodp + hsize, hsize, tspace + size); + + /* Add/copy product H. */ + MPN_COPY (prodp + hsize, prodp + size, hsize); + cy = _gcry_mpih_add_n( prodp + size, prodp + size, + prodp + size + hsize, hsize); + + /* Add product M (if NEGFLG M is a negative number) */ + if(negflg) + cy -= _gcry_mpih_sub_n(prodp + hsize, prodp + hsize, tspace, size); + else + cy += _gcry_mpih_add_n(prodp + hsize, prodp + hsize, tspace, size); + + /* Product L. ________________ ________________ + * |________________||____U0 x V0_____| + * Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(tspace, up, vp, hsize, tspace + size); + + /* Add/copy Product L (twice) */ + + cy += _gcry_mpih_add_n(prodp + hsize, prodp + hsize, tspace, size); + if( cy ) + _gcry_mpih_add_1(prodp + hsize + size, prodp + hsize + size, hsize, cy); + + MPN_COPY(prodp, tspace, hsize); + cy = _gcry_mpih_add_n(prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if( cy ) + _gcry_mpih_add_1(prodp + size, prodp + size, size, 1); + } +} + + +void +_gcry_mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ) +{ + mpi_size_t i; + mpi_limb_t cy_limb; + mpi_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = up[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, size ); + else + MPN_ZERO(prodp, size); + cy_limb = 0; + } + else + cy_limb = _gcry_mpih_mul_1( prodp, up, size, v_limb ); + + prodp[size] = cy_limb; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i=1; i < size; i++) { + v_limb = up[i]; + if( v_limb <= 1 ) { + cy_limb = 0; + if( v_limb == 1 ) + cy_limb = _gcry_mpih_add_n(prodp, prodp, up, size); + } + else + cy_limb = _gcry_mpih_addmul_1(prodp, up, size, v_limb); + + prodp[size] = cy_limb; + prodp++; + } +} + + +void +_gcry_mpih_sqr_n( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace) +{ + if( size & 1 ) { + /* The size is odd, and the code below doesn't handle that. + * Multiply the least significant (size - 1) limbs with a recursive + * call, and handle the most significant limb of S1 and S2 + * separately. + * A slightly faster way to do this would be to make the Karatsuba + * code below behave as if the size were even, and let it check for + * odd size in the end. I.e., in essence move this code to the end. + * Doing so would save us a recursive call, and potentially make the + * stack grow a lot less. + */ + mpi_size_t esize = size - 1; /* even size */ + mpi_limb_t cy_limb; + + MPN_SQR_N_RECURSE( prodp, up, esize, tspace ); + cy_limb = _gcry_mpih_addmul_1( prodp + esize, up, esize, up[esize] ); + prodp[esize + esize] = cy_limb; + cy_limb = _gcry_mpih_addmul_1( prodp + esize, up, size, up[esize] ); + + prodp[esize + size] = cy_limb; + } + else { + mpi_size_t hsize = size >> 1; + mpi_limb_t cy; + + /* Product H. ________________ ________________ + * |_____U1 x U1____||____U0 x U0_____| + * Put result in upper part of PROD and pass low part of TSPACE + * as new TSPACE. + */ + MPN_SQR_N_RECURSE(prodp + size, up + hsize, hsize, tspace); + + /* Product M. ________________ + * |_(U1-U0)(U0-U1)_| + */ + if( _gcry_mpih_cmp( up + hsize, up, hsize) >= 0 ) + _gcry_mpih_sub_n( prodp, up + hsize, up, hsize); + else + _gcry_mpih_sub_n (prodp, up, up + hsize, hsize); + + /* Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. */ + MPN_SQR_N_RECURSE(tspace, prodp, hsize, tspace + size); + + /* Add/copy product H */ + MPN_COPY(prodp + hsize, prodp + size, hsize); + cy = _gcry_mpih_add_n(prodp + size, prodp + size, + prodp + size + hsize, hsize); + + /* Add product M (if NEGFLG M is a negative number). */ + cy -= _gcry_mpih_sub_n (prodp + hsize, prodp + hsize, tspace, size); + + /* Product L. ________________ ________________ + * |________________||____U0 x U0_____| + * Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. */ + MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size); + + /* Add/copy Product L (twice). */ + cy += _gcry_mpih_add_n (prodp + hsize, prodp + hsize, tspace, size); + if( cy ) + _gcry_mpih_add_1(prodp + hsize + size, prodp + hsize + size, + hsize, cy); + + MPN_COPY(prodp, tspace, hsize); + cy = _gcry_mpih_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if( cy ) + _gcry_mpih_add_1 (prodp + size, prodp + size, size, 1); + } +} + + +/* This should be made into an inline function in gmp.h. */ +void +_gcry_mpih_mul_n( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) +{ + int secure; + + if( up == vp ) { + if( size < KARATSUBA_THRESHOLD ) + _gcry_mpih_sqr_n_basecase( prodp, up, size ); + else { + mpi_ptr_t tspace; + secure = gcry_is_secure( up ); + tspace = mpi_alloc_limb_space( 2 * size, secure ); + _gcry_mpih_sqr_n( prodp, up, size, tspace ); + _gcry_mpi_free_limb_space (tspace, 2 * size ); + } + } + else { + if( size < KARATSUBA_THRESHOLD ) + mul_n_basecase( prodp, up, vp, size ); + else { + mpi_ptr_t tspace; + secure = gcry_is_secure( up ) || gcry_is_secure( vp ); + tspace = mpi_alloc_limb_space( 2 * size, secure ); + mul_n (prodp, up, vp, size, tspace); + _gcry_mpi_free_limb_space (tspace, 2 * size ); + } + } +} + + + +void +_gcry_mpih_mul_karatsuba_case( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize, + struct karatsuba_ctx *ctx ) +{ + mpi_limb_t cy; + + if( !ctx->tspace || ctx->tspace_size < vsize ) { + if( ctx->tspace ) + _gcry_mpi_free_limb_space( ctx->tspace, ctx->tspace_nlimbs ); + ctx->tspace_nlimbs = 2 * vsize; + ctx->tspace = mpi_alloc_limb_space( 2 * vsize, + (gcry_is_secure( up ) + || gcry_is_secure( vp )) ); + ctx->tspace_size = vsize; + } + + MPN_MUL_N_RECURSE( prodp, up, vp, vsize, ctx->tspace ); + + prodp += vsize; + up += vsize; + usize -= vsize; + if( usize >= vsize ) { + if( !ctx->tp || ctx->tp_size < vsize ) { + if( ctx->tp ) + _gcry_mpi_free_limb_space( ctx->tp, ctx->tp_nlimbs ); + ctx->tp_nlimbs = 2 * vsize; + ctx->tp = mpi_alloc_limb_space( 2 * vsize, gcry_is_secure( up ) + || gcry_is_secure( vp ) ); + ctx->tp_size = vsize; + } + + do { + MPN_MUL_N_RECURSE( ctx->tp, up, vp, vsize, ctx->tspace ); + cy = _gcry_mpih_add_n( prodp, prodp, ctx->tp, vsize ); + _gcry_mpih_add_1( prodp + vsize, ctx->tp + vsize, vsize, cy ); + prodp += vsize; + up += vsize; + usize -= vsize; + } while( usize >= vsize ); + } + + if( usize ) { + if( usize < KARATSUBA_THRESHOLD ) { + _gcry_mpih_mul( ctx->tspace, vp, vsize, up, usize ); + } + else { + if( !ctx->next ) { + ctx->next = gcry_xcalloc( 1, sizeof *ctx ); + } + _gcry_mpih_mul_karatsuba_case( ctx->tspace, + vp, vsize, + up, usize, + ctx->next ); + } + + cy = _gcry_mpih_add_n( prodp, prodp, ctx->tspace, vsize); + _gcry_mpih_add_1( prodp + vsize, ctx->tspace + vsize, usize, cy ); + } +} + + +void +_gcry_mpih_release_karatsuba_ctx( struct karatsuba_ctx *ctx ) +{ + struct karatsuba_ctx *ctx2; + + if( ctx->tp ) + _gcry_mpi_free_limb_space( ctx->tp, ctx->tp_nlimbs ); + if( ctx->tspace ) + _gcry_mpi_free_limb_space( ctx->tspace, ctx->tspace_nlimbs ); + for( ctx=ctx->next; ctx; ctx = ctx2 ) { + ctx2 = ctx->next; + if( ctx->tp ) + _gcry_mpi_free_limb_space( ctx->tp, ctx->tp_nlimbs ); + if( ctx->tspace ) + _gcry_mpi_free_limb_space( ctx->tspace, ctx->tspace_nlimbs ); + gcry_free( ctx ); + } +} + +/* Multiply the natural numbers u (pointed to by UP, with USIZE limbs) + * and v (pointed to by VP, with VSIZE limbs), and store the result at + * PRODP. USIZE + VSIZE limbs are always stored, but if the input + * operands are normalized. Return the most significant limb of the + * result. + * + * NOTE: The space pointed to by PRODP is overwritten before finished + * with U and V, so overlap is an error. + * + * Argument constraints: + * 1. USIZE >= VSIZE. + * 2. PRODP != UP and PRODP != VP, i.e. the destination + * must be distinct from the multiplier and the multiplicand. + */ + +mpi_limb_t +_gcry_mpih_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize) +{ + mpi_ptr_t prod_endp = prodp + usize + vsize - 1; + mpi_limb_t cy; + struct karatsuba_ctx ctx; + + if( vsize < KARATSUBA_THRESHOLD ) { + mpi_size_t i; + mpi_limb_t v_limb; + + if( !vsize ) + return 0; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, usize ); + else + MPN_ZERO( prodp, usize ); + cy = 0; + } + else + cy = _gcry_mpih_mul_1( prodp, up, usize, v_limb ); + + prodp[usize] = cy; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i = 1; i < vsize; i++ ) { + v_limb = vp[i]; + if( v_limb <= 1 ) { + cy = 0; + if( v_limb == 1 ) + cy = _gcry_mpih_add_n(prodp, prodp, up, usize); + } + else + cy = _gcry_mpih_addmul_1(prodp, up, usize, v_limb); + + prodp[usize] = cy; + prodp++; + } + + return cy; + } + + memset( &ctx, 0, sizeof ctx ); + _gcry_mpih_mul_karatsuba_case( prodp, up, usize, vp, vsize, &ctx ); + _gcry_mpih_release_karatsuba_ctx( &ctx ); + return *prod_endp; +} diff --git a/grub-core/lib/libgcrypt/mpi/mpiutil.c b/grub-core/lib/libgcrypt/mpi/mpiutil.c new file mode 100644 index 0000000..76630a6 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/mpiutil.c @@ -0,0 +1,460 @@ +/* mpiutil.ac - Utility functions for MPI + * Copyright (C) 1998, 2000, 2001, 2002, 2003, + * 2007 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "g10lib.h" +#include "mpi-internal.h" +#include "mod-source-info.h" + + +const char * +_gcry_mpi_get_hw_config (void) +{ + return mod_source_info + 1; +} + + +/**************** + * Note: It was a bad idea to use the number of limbs to allocate + * because on a alpha the limbs are large but we normally need + * integers of n bits - So we should change this to bits (or bytes). + * + * But mpi_alloc is used in a lot of places :-(. New code + * should use mpi_new. + */ +gcry_mpi_t +_gcry_mpi_alloc( unsigned nlimbs ) +{ + gcry_mpi_t a; + + a = gcry_xmalloc( sizeof *a ); + a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL; + a->alloced = nlimbs; + a->nlimbs = 0; + a->sign = 0; + a->flags = 0; + return a; +} + +void +_gcry_mpi_m_check( gcry_mpi_t a ) +{ + _gcry_check_heap(a); + _gcry_check_heap(a->d); +} + +gcry_mpi_t +_gcry_mpi_alloc_secure( unsigned nlimbs ) +{ + gcry_mpi_t a; + + a = gcry_xmalloc( sizeof *a ); + a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL; + a->alloced = nlimbs; + a->flags = 1; + a->nlimbs = 0; + a->sign = 0; + return a; +} + + + +mpi_ptr_t +_gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure ) +{ + mpi_ptr_t p; + size_t len; + + len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t); + p = secure ? gcry_xmalloc_secure (len) : gcry_xmalloc (len); + if (! nlimbs) + *p = 0; + + return p; +} + +void +_gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs) +{ + if (a) + { + size_t len = nlimbs * sizeof(mpi_limb_t); + + /* If we have information on the number of allocated limbs, we + better wipe that space out. This is a failsafe feature if + secure memory has been disabled or was not properly + implemented in user provided allocation functions. */ + if (len) + wipememory (a, len); + gcry_free(a); + } +} + + +void +_gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned int nlimbs ) +{ + _gcry_mpi_free_limb_space (a->d, a->alloced); + a->d = ap; + a->alloced = nlimbs; +} + + + +/**************** + * Resize the array of A to NLIMBS. The additional space is cleared + * (set to 0). + */ +void +_gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs) +{ + size_t i; + + if (nlimbs <= a->alloced) + { + /* We only need to clear the new space (this is a nop if the + limb space is already of the correct size. */ + for (i=a->nlimbs; i < a->alloced; i++) + a->d[i] = 0; + return; + } + + /* Actually resize the limb space. */ + if (a->d) + { + a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t)); + for (i=a->alloced; i < nlimbs; i++) + a->d[i] = 0; + } + else + { + if (a->flags & 1) + /* Secure memory is wanted. */ + a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t)); + else + /* Standard memory. */ + a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t)); + } + a->alloced = nlimbs; +} + +void +_gcry_mpi_clear( gcry_mpi_t a ) +{ + a->nlimbs = 0; + a->flags = 0; +} + + +void +_gcry_mpi_free( gcry_mpi_t a ) +{ + if (!a ) + return; + if ((a->flags & 4)) + gcry_free( a->d ); + else + { + _gcry_mpi_free_limb_space(a->d, a->alloced); + } + if ((a->flags & ~7)) + log_bug("invalid flag value in mpi\n"); + gcry_free(a); +} + +static void +mpi_set_secure( gcry_mpi_t a ) +{ + mpi_ptr_t ap, bp; + + if ( (a->flags & 1) ) + return; + a->flags |= 1; + ap = a->d; + if (!a->nlimbs) + { + gcry_assert (!ap); + return; + } + bp = mpi_alloc_limb_space (a->nlimbs, 1); + MPN_COPY( bp, ap, a->nlimbs ); + a->d = bp; + _gcry_mpi_free_limb_space (ap, a->alloced); +} + + +gcry_mpi_t +gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits ) +{ + if (!a) + a = mpi_alloc(0); + + if( a->flags & 4 ) + gcry_free( a->d ); + else + _gcry_mpi_free_limb_space (a->d, a->alloced); + + a->d = p; + a->alloced = 0; + a->nlimbs = 0; + a->sign = nbits; + a->flags = 4; + return a; +} + + +void * +gcry_mpi_get_opaque( gcry_mpi_t a, unsigned int *nbits ) +{ + if( !(a->flags & 4) ) + log_bug("mpi_get_opaque on normal mpi\n"); + if( nbits ) + *nbits = a->sign; + return a->d; +} + + +/**************** + * Note: This copy function should not interpret the MPI + * but copy it transparently. + */ +gcry_mpi_t +gcry_mpi_copy( gcry_mpi_t a ) +{ + int i; + gcry_mpi_t b; + + if( a && (a->flags & 4) ) { + void *p = gcry_is_secure(a->d)? gcry_xmalloc_secure( (a->sign+7)/8 ) + : gcry_xmalloc( (a->sign+7)/8 ); + memcpy( p, a->d, (a->sign+7)/8 ); + b = gcry_mpi_set_opaque( NULL, p, a->sign ); + } + else if( a ) { + b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) + : mpi_alloc( a->nlimbs ); + b->nlimbs = a->nlimbs; + b->sign = a->sign; + b->flags = a->flags; + for(i=0; i < b->nlimbs; i++ ) + b->d[i] = a->d[i]; + } + else + b = NULL; + return b; +} + + +/**************** + * This function allocates an MPI which is optimized to hold + * a value as large as the one given in the argument and allocates it + * with the same flags as A. + */ +gcry_mpi_t +_gcry_mpi_alloc_like( gcry_mpi_t a ) +{ + gcry_mpi_t b; + + if( a && (a->flags & 4) ) { + int n = (a->sign+7)/8; + void *p = gcry_is_secure(a->d)? gcry_malloc_secure( n ) + : gcry_malloc( n ); + memcpy( p, a->d, n ); + b = gcry_mpi_set_opaque( NULL, p, a->sign ); + } + else if( a ) { + b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) + : mpi_alloc( a->nlimbs ); + b->nlimbs = 0; + b->sign = 0; + b->flags = a->flags; + } + else + b = NULL; + return b; +} + + +gcry_mpi_t +gcry_mpi_set( gcry_mpi_t w, gcry_mpi_t u) +{ + mpi_ptr_t wp, up; + mpi_size_t usize = u->nlimbs; + int usign = u->sign; + + if (!w) + w = _gcry_mpi_alloc( mpi_get_nlimbs(u) ); + RESIZE_IF_NEEDED(w, usize); + wp = w->d; + up = u->d; + MPN_COPY( wp, up, usize ); + w->nlimbs = usize; + w->flags = u->flags; + w->sign = usign; + return w; +} + + +gcry_mpi_t +gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u) +{ + if (!w) + w = _gcry_mpi_alloc (1); + /* FIXME: If U is 0 we have no need to resize and thus possible + allocating the the limbs. */ + RESIZE_IF_NEEDED(w, 1); + w->d[0] = u; + w->nlimbs = u? 1:0; + w->sign = 0; + w->flags = 0; + return w; +} + +gcry_err_code_t +_gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + unsigned long x = 0; + + if (w->nlimbs > 1) + err = GPG_ERR_TOO_LARGE; + else if (w->nlimbs == 1) + x = w->d[0]; + else + x = 0; + + if (! err) + *u = x; + + return err; +} + +gcry_error_t +gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + + err = _gcry_mpi_get_ui (w, u); + + return gcry_error (err); +} + +gcry_mpi_t +_gcry_mpi_alloc_set_ui( unsigned long u) +{ + gcry_mpi_t w = mpi_alloc(1); + w->d[0] = u; + w->nlimbs = u? 1:0; + w->sign = 0; + return w; +} + +void +gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b) +{ + struct gcry_mpi tmp; + + tmp = *a; *a = *b; *b = tmp; +} + + +gcry_mpi_t +gcry_mpi_new( unsigned int nbits ) +{ + return _gcry_mpi_alloc ( (nbits+BITS_PER_MPI_LIMB-1) + / BITS_PER_MPI_LIMB ); +} + + +gcry_mpi_t +gcry_mpi_snew( unsigned int nbits ) +{ + return _gcry_mpi_alloc_secure ( (nbits+BITS_PER_MPI_LIMB-1) + / BITS_PER_MPI_LIMB ); +} + +void +gcry_mpi_release( gcry_mpi_t a ) +{ + _gcry_mpi_free( a ); +} + +void +gcry_mpi_randomize( gcry_mpi_t w, + unsigned int nbits, enum gcry_random_level level ) +{ + unsigned char *p; + size_t nbytes = (nbits+7)/8; + + if (level == GCRY_WEAK_RANDOM) + { + p = mpi_is_secure(w) ? gcry_xmalloc_secure (nbytes) + : gcry_xmalloc (nbytes); + gcry_create_nonce (p, nbytes); + } + else + { + p = mpi_is_secure(w) ? gcry_random_bytes_secure (nbytes, level) + : gcry_random_bytes (nbytes, level); + } + _gcry_mpi_set_buffer( w, p, nbytes, 0 ); + gcry_free (p); +} + + +void +gcry_mpi_set_flag( gcry_mpi_t a, enum gcry_mpi_flag flag ) +{ + switch( flag ) { + case GCRYMPI_FLAG_SECURE: mpi_set_secure(a); break; + case GCRYMPI_FLAG_OPAQUE: + default: log_bug("invalid flag value\n"); + } +} + +void +gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag ) +{ + (void)a; /* Not yet used. */ + + switch (flag) + { + case GCRYMPI_FLAG_SECURE: + case GCRYMPI_FLAG_OPAQUE: + default: log_bug("invalid flag value\n"); + } +} + +int +gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag flag ) +{ + switch (flag) + { + case GCRYMPI_FLAG_SECURE: return (a->flags & 1); + case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4); + default: log_bug("invalid flag value\n"); + } + /*NOTREACHED*/ + return 0; +} diff --git a/grub-core/lib/libgcrypt/mpi/pa7100/Manifest b/grub-core/lib/libgcrypt/mpi/pa7100/Manifest new file mode 100644 index 0000000..f075ab0 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pa7100/Manifest @@ -0,0 +1,22 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +mpih-lshift.S +mpih-rshift.S +$names$ iQCVAwUAP+LmVjEAnp832S/7AQKlEQQAv2+x/d+Z0t8FwwHlxKpIKOJDr9e+Y2i8y8orcIEa3dnwU5LMOH3EzFoNSD9crc31FMokgm/X5xeLjqRTdcmGHyJJQJDPJVJyuaOm6qHJaFzzfJjrfMW66nJxfNSXIiIm4DgpP20NmumaorLCkiIZ5Z81KGAc8FiRggbRVYx+wxo==Vjh9 diff --git a/grub-core/lib/libgcrypt/mpi/pa7100/distfiles b/grub-core/lib/libgcrypt/mpi/pa7100/distfiles new file mode 100644 index 0000000..e1cde4d --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pa7100/distfiles @@ -0,0 +1,4 @@ +Manifest +mpih-lshift.S +mpih-rshift.S + diff --git a/grub-core/lib/libgcrypt/mpi/pa7100/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/pa7100/mpih-lshift.S new file mode 100644 index 0000000..8ade196 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pa7100/mpih-lshift.S @@ -0,0 +1,96 @@ +/* hppa lshift + * optimized for the PA7100, where it runs at 3.25 cycles/limb + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + +/******************* + * mpi_limb_t + * _gcry_mpih_lshift( mpi_ptr_t wp, (gr26) + * mpi_ptr_t up, (gr25) + * mpi_size_t usize, (gr24) + * unsigned cnt) (gr23) + */ + + .code + .export _gcry_mpih_lshift + .label _gcry_mpih_lshift + .proc + .callinfo frame=64,no_calls + .entry + + sh2add %r24,%r25,%r25 + sh2add %r24,%r26,%r26 + ldws,mb -4(0,%r25),%r22 + subi 32,%r23,%r1 + mtsar %r1 + addib,= -1,%r24,L$0004 + vshd %r0,%r22,%r28 ; compute carry out limb + ldws,mb -4(0,%r25),%r29 + addib,<= -5,%r24,L$rest + vshd %r22,%r29,%r20 + + .label L$loop + ldws,mb -4(0,%r25),%r22 + stws,mb %r20,-4(0,%r26) + vshd %r29,%r22,%r20 + ldws,mb -4(0,%r25),%r29 + stws,mb %r20,-4(0,%r26) + vshd %r22,%r29,%r20 + ldws,mb -4(0,%r25),%r22 + stws,mb %r20,-4(0,%r26) + vshd %r29,%r22,%r20 + ldws,mb -4(0,%r25),%r29 + stws,mb %r20,-4(0,%r26) + addib,> -4,%r24,L$loop + vshd %r22,%r29,%r20 + + .label L$rest + addib,= 4,%r24,L$end1 + nop + .label L$eloop + ldws,mb -4(0,%r25),%r22 + stws,mb %r20,-4(0,%r26) + addib,<= -1,%r24,L$end2 + vshd %r29,%r22,%r20 + ldws,mb -4(0,%r25),%r29 + stws,mb %r20,-4(0,%r26) + addib,> -1,%r24,L$eloop + vshd %r22,%r29,%r20 + + .label L$end1 + stws,mb %r20,-4(0,%r26) + vshd %r29,%r0,%r20 + bv 0(%r2) + stw %r20,-4(0,%r26) + .label L$end2 + stws,mb %r20,-4(0,%r26) + .label L$0004 + vshd %r22,%r0,%r20 + bv 0(%r2) + stw %r20,-4(0,%r26) + + .exit + .procend + + + diff --git a/grub-core/lib/libgcrypt/mpi/pa7100/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/pa7100/mpih-rshift.S new file mode 100644 index 0000000..0624202 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pa7100/mpih-rshift.S @@ -0,0 +1,92 @@ +/* hppa rshift + * optimized for the PA7100, where it runs at 3.25 cycles/limb + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + +/******************* + * mpi_limb_t + * _gcry_mpih_rshift( mpi_ptr_t wp, (gr26) + * mpi_ptr_t up, (gr25) + * mpi_size_t usize, (gr24) + * unsigned cnt) (gr23) + */ + + .code + .export _gcry_mpih_rshift + .label _gcry_mpih_rshift + .proc + .callinfo frame=64,no_calls + .entry + + ldws,ma 4(0,%r25),%r22 + mtsar %r23 + addib,= -1,%r24,L$r004 + vshd %r22,%r0,%r28 ; compute carry out limb + ldws,ma 4(0,%r25),%r29 + addib,<= -5,%r24,L$rrest + vshd %r29,%r22,%r20 + + .label L$roop + ldws,ma 4(0,%r25),%r22 + stws,ma %r20,4(0,%r26) + vshd %r22,%r29,%r20 + ldws,ma 4(0,%r25),%r29 + stws,ma %r20,4(0,%r26) + vshd %r29,%r22,%r20 + ldws,ma 4(0,%r25),%r22 + stws,ma %r20,4(0,%r26) + vshd %r22,%r29,%r20 + ldws,ma 4(0,%r25),%r29 + stws,ma %r20,4(0,%r26) + addib,> -4,%r24,L$roop + vshd %r29,%r22,%r20 + + .label L$rrest + addib,= 4,%r24,L$rend1 + nop + .label L$eroop + ldws,ma 4(0,%r25),%r22 + stws,ma %r20,4(0,%r26) + addib,<= -1,%r24,L$rend2 + vshd %r22,%r29,%r20 + ldws,ma 4(0,%r25),%r29 + stws,ma %r20,4(0,%r26) + addib,> -1,%r24,L$eroop + vshd %r29,%r22,%r20 + + .label L$rend1 + stws,ma %r20,4(0,%r26) + vshd %r0,%r29,%r20 + bv 0(%r2) + stw %r20,0(0,%r26) + .label L$rend2 + stws,ma %r20,4(0,%r26) + .label L$r004 + vshd %r0,%r22,%r20 + bv 0(%r2) + stw %r20,0(0,%r26) + + .exit + .procend + + diff --git a/grub-core/lib/libgcrypt/mpi/pentium4/README b/grub-core/lib/libgcrypt/mpi/pentium4/README new file mode 100644 index 0000000..215fc7f --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pentium4/README @@ -0,0 +1,115 @@ +Copyright 2001 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. + + + + + INTEL PENTIUM-4 MPN SUBROUTINES + + +This directory contains mpn functions optimized for Intel Pentium-4. + +The mmx subdirectory has routines using MMX instructions, the sse2 +subdirectory has routines using SSE2 instructions. All P4s have these, the +separate directories are just so configure can omit that code if the +assembler doesn't support it. + + +STATUS + + cycles/limb + + mpn_add_n/sub_n 4 normal, 6 in-place + + mpn_mul_1 4 normal, 6 in-place + mpn_addmul_1 6 + mpn_submul_1 7 + + mpn_mul_basecase 6 cycles/crossproduct (approx) + + mpn_sqr_basecase 3.5 cycles/crossproduct (approx) + or 7.0 cycles/triangleproduct (approx) + + mpn_l/rshift 1.75 + + + +The shifts ought to be able to go at 1.5 c/l, but not much effort has been +applied to them yet. + +In-place operations, and all addmul, submul, mul_basecase and sqr_basecase +calls, suffer from pipeline anomalies associated with write combining and +movd reads and writes to the same or nearby locations. The movq +instructions do not trigger the same hardware problems. Unfortunately, +using movq and splitting/combining seems to require too many extra +instructions to help. Perhaps future chip steppings will be better. + + + +NOTES + +The Pentium-4 pipeline "Netburst", provides for quite a number of surprises. +Many traditional x86 instructions run very slowly, requiring use of +alterative instructions for acceptable performance. + +adcl and sbbl are quite slow at 8 cycles for reg->reg. paddq of 32-bits +within a 64-bit mmx register seems better, though the combination +paddq/psrlq when propagating a carry is still a 4 cycle latency. + +incl and decl should be avoided, instead use add $1 and sub $1. Apparently +the carry flag is not separately renamed, so incl and decl depend on all +previous flags-setting instructions. + +shll and shrl have a 4 cycle latency, or 8 times the latency of the fastest +integer instructions (addl, subl, orl, andl, and some more). shldl and +shrdl seem to have 13 and 15 cycles latency, respectively. Bizarre. + +movq mmx -> mmx does have 6 cycle latency, as noted in the documentation. +pxor/por or similar combination at 2 cycles latency can be used instead. +The movq however executes in the float unit, thereby saving MMX execution +resources. With the right juggling, data moves shouldn't be on a dependent +chain. + +L1 is write-through, but the write-combining sounds like it does enough to +not require explicit destination prefetching. + +xmm registers so far haven't found a use, but not much effort has been +expended. A configure test for whether the operating system knows +fxsave/fxrestor will be needed if they're used. + + + +REFERENCES + +Intel Pentium-4 processor manuals, + + http://developer.intel.com/design/pentium4/manuals + +"Intel Pentium 4 Processor Optimization Reference Manual", Intel, 2001, +order number 248966. Available on-line: + + http://developer.intel.com/design/pentium4/manuals/248966.htm + + + +---------------- +Local variables: +mode: text +fill-column: 76 +End: diff --git a/grub-core/lib/libgcrypt/mpi/pentium4/distfiles b/grub-core/lib/libgcrypt/mpi/pentium4/distfiles new file mode 100644 index 0000000..b419f85 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pentium4/distfiles @@ -0,0 +1,3 @@ +README + + diff --git a/grub-core/lib/libgcrypt/mpi/pentium4/mmx/distfiles b/grub-core/lib/libgcrypt/mpi/pentium4/mmx/distfiles new file mode 100644 index 0000000..8f0ea42 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pentium4/mmx/distfiles @@ -0,0 +1,2 @@ +mpih-lshift.S +mpih-rshift.S diff --git a/grub-core/lib/libgcrypt/mpi/pentium4/mmx/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/pentium4/mmx/mpih-lshift.S new file mode 100644 index 0000000..e2dd184 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pentium4/mmx/mpih-lshift.S @@ -0,0 +1,457 @@ +/* Intel Pentium-4 mpn_lshift -- left shift. + * + * Copyright 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_lshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + * + * P4 Willamette, Northwood: 1.75 cycles/limb + * P4 Prescott: 2.0 cycles/limb + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(_gcry_mpih_lshift) +C_SYMBOL_NAME(_gcry_mpih_lshift:) + + + pushl %ebx + pushl %edi + + + movl 20(%esp), %eax + movl 12(%esp), %edx + + movl 16(%esp), %ebx + movl 24(%esp), %ecx + + cmp $5, %eax + jae .Lunroll + + movl -4(%ebx,%eax,4), %edi + decl %eax + + jnz .Lsimple + + shldl %cl, %edi, %eax + + shll %cl, %edi + + movl %edi, (%edx) + popl %edi + + popl %ebx + + ret + + + + + +.Lsimple: + + + + + + + + + + movd (%ebx,%eax,4), %mm5 + + movd %ecx, %mm6 + negl %ecx + + psllq %mm6, %mm5 + addl $32, %ecx + + movd %ecx, %mm7 + psrlq $32, %mm5 + + +.Lsimple_top: + + + + + + + + + + + + + movq -4(%ebx,%eax,4), %mm0 + decl %eax + + psrlq %mm7, %mm0 + + + + movd %mm0, 4(%edx,%eax,4) + jnz .Lsimple_top + + + movd (%ebx), %mm0 + + movd %mm5, %eax + psllq %mm6, %mm0 + + popl %edi + popl %ebx + + movd %mm0, (%edx) + + emms + + ret + + + + + + .align 8, 0x90 +.Lunroll: + + + + + + + + + + movd -4(%ebx,%eax,4), %mm5 + leal (%ebx,%eax,4), %edi + + movd %ecx, %mm6 + andl $4, %edi + + psllq %mm6, %mm5 + jz .Lstart_src_aligned + + + + + + + + + + + + + + + + + + + + movq -8(%ebx,%eax,4), %mm0 + + psllq %mm6, %mm0 + decl %eax + + psrlq $32, %mm0 + + + + movd %mm0, (%edx,%eax,4) +.Lstart_src_aligned: + + movq -8(%ebx,%eax,4), %mm1 + leal (%edx,%eax,4), %edi + + andl $4, %edi + psrlq $32, %mm5 + + movq -16(%ebx,%eax,4), %mm3 + jz .Lstart_dst_aligned + + + + + + + + + + + + + + + + + + + + + movq %mm1, %mm0 + addl $32, %ecx + + psllq %mm6, %mm0 + + movd %ecx, %mm6 + psrlq $32, %mm0 + + + + movd %mm0, -4(%edx,%eax,4) + subl $4, %edx +.Lstart_dst_aligned: + + + psllq %mm6, %mm1 + negl %ecx + + addl $64, %ecx + movq %mm3, %mm2 + + movd %ecx, %mm7 + subl $8, %eax + + psrlq %mm7, %mm3 + + por %mm1, %mm3 + jc .Lfinish + + + + + .align 8, 0x90 +.Lunroll_loop: + + + + + + + + + + + + + + + + + movq 8(%ebx,%eax,4), %mm0 + psllq %mm6, %mm2 + + movq %mm0, %mm1 + psrlq %mm7, %mm0 + + movq %mm3, 24(%edx,%eax,4) + por %mm2, %mm0 + + movq (%ebx,%eax,4), %mm3 + psllq %mm6, %mm1 + + movq %mm0, 16(%edx,%eax,4) + movq %mm3, %mm2 + + psrlq %mm7, %mm3 + subl $4, %eax + + por %mm1, %mm3 + jnc .Lunroll_loop + + + +.Lfinish: + + + testb $2, %al + + jz .Lfinish_no_two + + movq 8(%ebx,%eax,4), %mm0 + psllq %mm6, %mm2 + + movq %mm0, %mm1 + psrlq %mm7, %mm0 + + movq %mm3, 24(%edx,%eax,4) + por %mm2, %mm0 + + movq %mm1, %mm2 + movq %mm0, %mm3 + + subl $2, %eax +.Lfinish_no_two: + + + + + + + + testb $1, %al + movd %mm5, %eax + + popl %edi + jz .Lfinish_zero + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + movd (%ebx), %mm0 + psllq %mm6, %mm2 + + movq %mm3, 12(%edx) + psllq $32, %mm0 + + movq %mm0, %mm1 + psrlq %mm7, %mm0 + + por %mm2, %mm0 + psllq %mm6, %mm1 + + movq %mm0, 4(%edx) + psrlq $32, %mm1 + + andl $32, %ecx + popl %ebx + + jz .Lfinish_one_unaligned + + movd %mm1, (%edx) +.Lfinish_one_unaligned: + + emms + + ret + + + + +.Lfinish_zero: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + movq %mm3, 8(%edx) + andl $32, %ecx + + psllq %mm6, %mm2 + jz .Lfinish_zero_unaligned + + movq %mm2, (%edx) +.Lfinish_zero_unaligned: + + psrlq $32, %mm2 + popl %ebx + + movd %mm5, %eax + + movd %mm2, 4(%edx) + + emms + + ret diff --git a/grub-core/lib/libgcrypt/mpi/pentium4/mmx/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/pentium4/mmx/mpih-rshift.S new file mode 100644 index 0000000..e3374e3 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pentium4/mmx/mpih-rshift.S @@ -0,0 +1,453 @@ +/* Intel Pentium-4 mpn_rshift -- right shift. + * + * Copyright 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_rshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + * + * P4 Willamette, Northwood: 1.75 cycles/limb + * P4 Prescott: 2.0 cycles/limb + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(_gcry_mpih_rshift) +C_SYMBOL_NAME(_gcry_mpih_rshift:) + pushl %ebx + pushl %edi + + + movl 20(%esp), %eax + movl 12(%esp), %edx + + movl 16(%esp), %ebx + movl 24(%esp), %ecx + + cmp $5, %eax + jae .Lunroll + + decl %eax + movl (%ebx), %edi + + jnz .Lsimple + + shrdl %cl, %edi, %eax + + shrl %cl, %edi + + movl %edi, (%edx) + popl %edi + + popl %ebx + + ret + + + + + + .align 8, 0x90 +.Lsimple: + + + + + + + + + + movd (%ebx), %mm5 + leal (%ebx,%eax,4), %ebx + + movd %ecx, %mm6 + leal -4(%edx,%eax,4), %edx + + psllq $32, %mm5 + negl %eax + + + + + + + +.Lsimple_top: + + + + + + + + + + movq (%ebx,%eax,4), %mm0 + incl %eax + + psrlq %mm6, %mm0 + + movd %mm0, (%edx,%eax,4) + jnz .Lsimple_top + + + movd (%ebx), %mm0 + psrlq %mm6, %mm5 + + psrlq %mm6, %mm0 + popl %edi + + movd %mm5, %eax + popl %ebx + + movd %mm0, 4(%edx) + + emms + + ret + + + + + + .align 8, 0x90 +.Lunroll: + + + + + + + + + + movd (%ebx), %mm5 + movl $4, %edi + + movd %ecx, %mm6 + testl %edi, %ebx + + psllq $32, %mm5 + jz .Lstart_src_aligned + + + + + + + + + + + + + + + + + movq (%ebx), %mm0 + + psrlq %mm6, %mm0 + addl $4, %ebx + + decl %eax + + movd %mm0, (%edx) + addl $4, %edx +.Lstart_src_aligned: + + + movq (%ebx), %mm1 + testl %edi, %edx + + psrlq %mm6, %mm5 + jz .Lstart_dst_aligned + + + + + + + + + + + + + + + + + + movq %mm1, %mm0 + addl $32, %ecx + + psrlq %mm6, %mm0 + + movd %ecx, %mm6 + + movd %mm0, (%edx) + addl $4, %edx +.Lstart_dst_aligned: + + + movq 8(%ebx), %mm3 + negl %ecx + + movq %mm3, %mm2 + addl $64, %ecx + + movd %ecx, %mm7 + psrlq %mm6, %mm1 + + leal -12(%ebx,%eax,4), %ebx + leal -20(%edx,%eax,4), %edx + + psllq %mm7, %mm3 + subl $7, %eax + + por %mm1, %mm3 + negl %eax + + jns .Lfinish + + + + + + + + + + + + + + + + .align 8, 0x90 +.Lunroll_loop: + + + + + + + + + + + + + + + + + movq (%ebx,%eax,4), %mm0 + psrlq %mm6, %mm2 + + movq %mm0, %mm1 + psllq %mm7, %mm0 + + movq %mm3, -8(%edx,%eax,4) + por %mm2, %mm0 + + movq 8(%ebx,%eax,4), %mm3 + psrlq %mm6, %mm1 + + movq %mm0, (%edx,%eax,4) + movq %mm3, %mm2 + + psllq %mm7, %mm3 + addl $4, %eax + + por %mm1, %mm3 + js .Lunroll_loop + + +.Lfinish: + + + testb $2, %al + + jnz .Lfinish_no_two + + movq (%ebx,%eax,4), %mm0 + psrlq %mm6, %mm2 + + movq %mm0, %mm1 + psllq %mm7, %mm0 + + movq %mm3, -8(%edx,%eax,4) + por %mm2, %mm0 + + movq %mm1, %mm2 + movq %mm0, %mm3 + + addl $2, %eax +.Lfinish_no_two: + + + + + + + + testb $1, %al + popl %edi + + movd %mm5, %eax + jnz .Lfinish_zero + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + movd 8(%ebx), %mm0 + psrlq %mm6, %mm2 + + movq %mm0, %mm1 + psllq %mm7, %mm0 + + movq %mm3, (%edx) + por %mm2, %mm0 + + psrlq %mm6, %mm1 + andl $32, %ecx + + popl %ebx + jz .Lfinish_one_unaligned + + + movd %mm1, 16(%edx) +.Lfinish_one_unaligned: + + movq %mm0, 8(%edx) + + emms + + ret + + + + +.Lfinish_zero: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + movq %mm3, 4(%edx) + psrlq %mm6, %mm2 + + movd %mm2, 12(%edx) + andl $32, %ecx + + popl %ebx + jz .Lfinish_zero_unaligned + + movq %mm2, 12(%edx) +.Lfinish_zero_unaligned: + + emms + + ret diff --git a/grub-core/lib/libgcrypt/mpi/pentium4/sse2/distfiles b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/distfiles new file mode 100644 index 0000000..7252cd7 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/distfiles @@ -0,0 +1,5 @@ +mpih-add1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-sub1.S diff --git a/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-add1.S b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-add1.S new file mode 100644 index 0000000..55ed663 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-add1.S @@ -0,0 +1,91 @@ +/* Intel Pentium-4 mpn_add_n -- mpn addition. + * + * Copyright 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + + /******************* + * mpi_limb_t + * _gcry_mpih_add_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + * + * P4 Willamette, Northwood: 4.0 cycles/limb if dst!=src1 and dst!=src2 + * 6.0 cycles/limb if dst==src1 or dst==src2 + * P4 Prescott: >= 5 cycles/limb + * + * The 4 c/l achieved here isn't particularly good, but is better than 9 c/l + * for a basic adc loop. + */ + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(_gcry_mpih_add_n) +C_SYMBOL_NAME(_gcry_mpih_add_n:) + + pxor %mm0, %mm0 + + movl 8(%esp), %eax /* s1_ptr */ + movl %ebx, 8(%esp) /* re-use parameter space */ + movl 12(%esp), %ebx /* res_ptr */ + movl 4(%esp), %edx /* s2_ptr */ + movl 16(%esp), %ecx /* size */ + + leal (%eax,%ecx,4), %eax /* src1 end */ + leal (%ebx,%ecx,4), %ebx /* src2 end */ + leal (%edx,%ecx,4), %edx /* dst end */ + negl %ecx /* -size */ + +Ltop: +/* + C eax src1 end + C ebx src2 end + C ecx counter, limbs, negative + C edx dst end + C mm0 carry bit +*/ + + movd (%eax,%ecx,4), %mm1 + movd (%ebx,%ecx,4), %mm2 + paddq %mm2, %mm1 + + paddq %mm1, %mm0 + movd %mm0, (%edx,%ecx,4) + + psrlq $32, %mm0 + + addl $1, %ecx + jnz Ltop + + + movd %mm0, %eax + movl 8(%esp), %ebx /* restore saved EBX */ + emms + ret diff --git a/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-mul1.S b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-mul1.S new file mode 100644 index 0000000..a0c98fb --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-mul1.S @@ -0,0 +1,96 @@ +/* Intel Pentium-4 mpn_mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_mul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + * + * src != dst src == dst + * P6 model 9 (Banias) ?.? + * P6 model 13 (Dothan) 4.75 4.75 + * P4 model 0 (Willamette) 4.0 6.0 + * P4 model 1 (?) 4.0 6.0 + * P4 model 2 (Northwood) 4.0 6.0 + * P4 model 3 (Prescott) ?.? ?.? + * P4 model 4 (Nocona) ?.? ?.? + * Unfortunately when src==dst the write-combining described in + * pentium4/README takes us up to 6 c/l. + * + */ + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(_gcry_mpih_mul_1) +C_SYMBOL_NAME(_gcry_mpih_mul_1:); + + pxor %mm0, %mm0 + +.Lstart_1c: + movl 8(%esp), %eax + movd 16(%esp), %mm7 + movl 4(%esp), %edx + movl 12(%esp), %ecx + +.Ltop: + +/* + C eax src, incrementing + C ebx + C ecx counter, size iterations + C edx dst, incrementing + C + C mm0 carry limb + C mm7 multiplier +*/ + + movd (%eax), %mm1 + addl $4, %eax + pmuludq %mm7, %mm1 + + paddq %mm1, %mm0 + movd %mm0, (%edx) + addl $4, %edx + + psrlq $32, %mm0 + + subl $1, %ecx + jnz .Ltop + + + movd %mm0, %eax + emms + ret + diff --git a/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-mul2.S b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-mul2.S new file mode 100644 index 0000000..f975adf --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-mul2.S @@ -0,0 +1,136 @@ +/* Intel Pentium-4 mpn_addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + * + * P3 model 9 (Banias) ?.? + * P3 model 13 (Dothan) 5.8 + * P4 model 0 (Willamette) 5.5 + * P4 model 1 (?) 5.5 + * P4 model 2 (Northwood) 5.5 + * P4 model 3 (Prescott) 6.0 + * P4 model 4 (Nocona) + * + * Only the carry limb propagation is on the dependent chain, but some other + * Pentium4 pipeline magic brings down performance to 6 cycles/l from the + * ideal 4 cycles/l. + */ + + + TEXT + ALIGN (4) + GLOBL C_SYMBOL_NAME(_gcry_mpih_addmul_1) +C_SYMBOL_NAME(_gcry_mpih_addmul_1:) + + pxor %mm4, %mm4 +.Lstart_1c: + movl 8(%esp), %eax + movl 12(%esp), %ecx + movl 4(%esp), %edx + movd 16(%esp), %mm7 + +/* + C eax src, incrementing ; 5B + C ecx loop counter, decrementing + C edx dst, incrementing + C + C mm4 carry, low 32-bits + C mm7 multiplier +*/ + + movd (%eax), %mm2 + pmuludq %mm7, %mm2 + + shrl $1, %ecx + jnc .Leven + + leal 4(%eax), %eax + movd (%edx), %mm1 + paddq %mm2, %mm1 + paddq %mm1, %mm4 + movd %mm4, (%edx) + psrlq $32, %mm4 + + testl %ecx, %ecx + jz .Lrtn + leal 4(%edx), %edx + + movd (%eax), %mm2 + pmuludq %mm7, %mm2 +.Leven: + movd 4(%eax), %mm0 + movd (%edx), %mm1 + pmuludq %mm7, %mm0 + + subl $1, %ecx + jz .Lend +.Lloop: + paddq %mm2, %mm1 + movd 8(%eax), %mm2 + paddq %mm1, %mm4 + movd 4(%edx), %mm3 + pmuludq %mm7, %mm2 + movd %mm4, (%edx) + psrlq $32, %mm4 + + paddq %mm0, %mm3 + movd 12(%eax), %mm0 + paddq %mm3, %mm4 + movd 8(%edx), %mm1 + pmuludq %mm7, %mm0 + movd %mm4, 4(%edx) + psrlq $32, %mm4 + + leal 8(%eax), %eax + leal 8(%edx), %edx + subl $1, %ecx + jnz .Lloop +.Lend: + paddq %mm2, %mm1 + paddq %mm1, %mm4 + movd 4(%edx), %mm3 + movd %mm4, (%edx) + psrlq $32, %mm4 + paddq %mm0, %mm3 + paddq %mm3, %mm4 + movd %mm4, 4(%edx) + psrlq $32, %mm4 +.Lrtn: + movd %mm4, %eax + emms + ret diff --git a/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-mul3.S b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-mul3.S new file mode 100644 index 0000000..ebcd2a6 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-mul3.S @@ -0,0 +1,127 @@ +/* Intel Pentium-4 mpn_submul_1 -- Multiply a limb vector with a limb and + * subtract the result from a second limb vector. + * + * Copyright 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_submul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + * + * P4: 7 cycles/limb, unstable timing, at least on early Pentium4 silicon + * (stepping 10). + * + * This code is not particularly good at 7 c/l. The dependent chain is only + * 4 c/l and there's only 4 MMX unit instructions, so it's not clear why that + * speed isn't achieved. + * + * The arrangements made here to get a two instruction dependent chain are + * slightly subtle. In the loop the carry (or borrow rather) is a negative + * so that a paddq can be used to give a low limb ready to store, and a high + * limb ready to become the new carry after a psrlq. + * + * If the carry was a simple twos complement negative then the psrlq shift + * would need to bring in 0 bits or 1 bits according to whether the high was + * zero or non-zero, since a non-zero value would represent a negative + * needing sign extension. That wouldn't be particularly easy to arrange and + * certainly would add an instruction to the dependent chain, so instead an + * offset is applied so that the high limb will be 0xFFFFFFFF+c. With c in + * the range -0xFFFFFFFF to 0, the value 0xFFFFFFFF+c is in the range 0 to + * 0xFFFFFFFF and is therefore always positive and can always have 0 bits + * shifted in, which is what psrlq does. + * + * The extra 0xFFFFFFFF must be subtracted before c is used, but that can be + * done off the dependent chain. The total adjustment then is to add + * 0xFFFFFFFF00000000 to offset the new carry, and subtract + * 0x00000000FFFFFFFF to remove the offset from the current carry, for a net + * add of 0xFFFFFFFE00000001. In the code this is applied to the destination + * limb when fetched. + * + * It's also possible to view the 0xFFFFFFFF adjustment as a ones-complement + * negative, which is how it's undone for the return value, but that doesn't + * seem as clear. +*/ + + TEXT + ALIGN (4) + GLOBL C_SYMBOL_NAME(_gcry_mpih_submul_1) +C_SYMBOL_NAME(_gcry_mpih_submul_1:) + + pxor %mm1, %mm1 + +.Lstart_1c: + movl 8(%esp), %eax + pcmpeqd %mm0, %mm0 + + movd 16(%esp), %mm7 + pcmpeqd %mm6, %mm6 + + movl 4(%esp), %edx + psrlq $32, %mm0 + + movl 12(%esp), %ecx + psllq $32, %mm6 + + psubq %mm0, %mm6 + + psubq %mm1, %mm0 + +/* + C eax src, incrementing + C ebx + C ecx loop counter, decrementing + C edx dst, incrementing + C + C mm0 0xFFFFFFFF - borrow + C mm6 0xFFFFFFFE00000001 + C mm7 multiplier +*/ + +.Lloop: + movd (%eax), %mm1 + leal 4(%eax), %eax + movd (%edx), %mm2 + paddq %mm6, %mm2 + pmuludq %mm7, %mm1 + psubq %mm1, %mm2 + paddq %mm2, %mm0 + subl $1, %ecx + movd %mm0, (%edx) + psrlq $32, %mm0 + leal 4(%edx), %edx + jnz .Lloop + + movd %mm0, %eax + notl %eax + emms + ret diff --git a/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-sub1.S b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-sub1.S new file mode 100644 index 0000000..33900c7 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/pentium4/sse2/mpih-sub1.S @@ -0,0 +1,112 @@ +/* Intel Pentium-4 mpn_sub_n -- mpn subtraction. + * + * Copyright 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * _gcry_mpih_sub_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + * + * P4 Willamette, Northwood: 4.0 cycles/limb if dst!=src1 and dst!=src2 + * 6.0 cycles/limb if dst==src1 or dst==src2 + * P4 Prescott: >= 5 cycles/limb + * + * The main loop code is 2x unrolled so that the carry bit can alternate + * between mm0 and mm1. + */ + + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(_gcry_mpih_sub_n) +C_SYMBOL_NAME(_gcry_mpih_sub_n:) + + pxor %mm0, %mm0 +.Lstart_nc: + movl 8(%esp), %eax + movl %ebx, 8(%esp) + movl 12(%esp), %ebx + movl 4(%esp), %edx + movl 16(%esp), %ecx + + leal (%eax,%ecx,4), %eax + leal (%ebx,%ecx,4), %ebx + leal (%edx,%ecx,4), %edx + negl %ecx + +.Ltop: +/* + C eax src1 end + C ebx src2 end + C ecx counter, limbs, negative + C edx dst end + C mm0 carry bit +*/ + + movd (%eax,%ecx,4), %mm1 + movd (%ebx,%ecx,4), %mm2 + psubq %mm2, %mm1 + + psubq %mm0, %mm1 + movd %mm1, (%edx,%ecx,4) + + psrlq $63, %mm1 + + addl $1, %ecx + jz .Ldone_mm1 + + movd (%eax,%ecx,4), %mm0 + movd (%ebx,%ecx,4), %mm2 + psubq %mm2, %mm0 + + psubq %mm1, %mm0 + movd %mm0, (%edx,%ecx,4) + + psrlq $63, %mm0 + + addl $1, %ecx + jnz .Ltop + + + movd %mm0, %eax + movl 8(%esp), %ebx + emms + ret + + + +.Ldone_mm1: + movd %mm1, %eax + movl 8(%esp), %ebx + emms + ret diff --git a/grub-core/lib/libgcrypt/mpi/power/Manifest b/grub-core/lib/libgcrypt/mpi/power/Manifest new file mode 100644 index 0000000..c60fc23 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/power/Manifest @@ -0,0 +1,27 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +mpih-add1.S +mpih-lshift.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-rshift.S +mpih-sub1.S +$names$ iQCVAwUAP+LmXTEAnp832S/7AQJ+ngP/XYr5Fvl/8WGVHcIKaehxvnKcSD2ILTWZNGubgnWp8ebIxVijjQCxYneTTy+zO0sNaB002neyscyiwaJj/JQIwZXfr06uGweIqlSpwpj9ndkoJc8E4/FZu+5NTO+E3RaBDAD+Tpo+MTfbC1s18p5i+an93VrSTgNck5PPYQrUcPA==sl3t diff --git a/grub-core/lib/libgcrypt/mpi/power/distfiles b/grub-core/lib/libgcrypt/mpi/power/distfiles new file mode 100644 index 0000000..e1bc008 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/power/distfiles @@ -0,0 +1,8 @@ +Manifest +mpih-add1.S +mpih-lshift.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-rshift.S +mpih-sub1.S diff --git a/grub-core/lib/libgcrypt/mpi/power/mpih-add1.S b/grub-core/lib/libgcrypt/mpi/power/mpih-add1.S new file mode 100644 index 0000000..876b56c --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/power/mpih-add1.S @@ -0,0 +1,87 @@ +/* IBM POWER add_n -- Add two limb vectors of equal, non-zero length. + * + * Copyright (C) 1992, 1994, 1996, 1999, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s1_ptr r4 +# s2_ptr r5 +# size r6 + */ + + .toc + .extern _gcry_mpih_add_n[DS] + .extern ._gcry_mpih_add_n +.csect [PR] + .align 2 + .globl _gcry_mpih_add_n + .globl ._gcry_mpih_add_n + .csect _gcry_mpih_add_n[DS] +_gcry_mpih_add_n: + .long ._gcry_mpih_add_n, TOC[tc0], 0 + .csect [PR] +._gcry_mpih_add_n: + andil. 10,6,1 # odd or even number of limbs? + l 8,0(4) # load least significant s1 limb + l 0,0(5) # load least significant s2 limb + cal 3,-4(3) # offset res_ptr, it's updated before it's used + sri 10,6,1 # count for unrolled loop + a 7,0,8 # add least significant limbs, set cy + mtctr 10 # copy count into CTR + beq 0,Leven # branch if even # of limbs (# of limbs >= 2) + +# We have an odd # of limbs. Add the first limbs separately. + cmpi 1,10,0 # is count for unrolled loop zero? + bne 1,L1 # branch if not + st 7,4(3) + aze 3,10 # use the fact that r10 is zero... + br # return + +# We added least significant limbs. Now reload the next limbs to enter loop. +L1: lu 8,4(4) # load s1 limb and update s1_ptr + lu 0,4(5) # load s2 limb and update s2_ptr + stu 7,4(3) + ae 7,0,8 # add limbs, set cy +Leven: lu 9,4(4) # load s1 limb and update s1_ptr + lu 10,4(5) # load s2 limb and update s2_ptr + bdz Lend # If done, skip loop + +Loop: lu 8,4(4) # load s1 limb and update s1_ptr + lu 0,4(5) # load s2 limb and update s2_ptr + ae 11,9,10 # add previous limbs with cy, set cy + stu 7,4(3) # + lu 9,4(4) # load s1 limb and update s1_ptr + lu 10,4(5) # load s2 limb and update s2_ptr + ae 7,0,8 # add previous limbs with cy, set cy + stu 11,4(3) # + bdn Loop # decrement CTR and loop back + +Lend: ae 11,9,10 # add limbs with cy, set cy + st 7,4(3) # + st 11,8(3) # + lil 3,0 # load cy into ... + aze 3,3 # ... return value register + br + diff --git a/grub-core/lib/libgcrypt/mpi/power/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/power/mpih-lshift.S new file mode 100644 index 0000000..d9e42da --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/power/mpih-lshift.S @@ -0,0 +1,64 @@ +/* IBM POWER lshift + * + * Copyright (C) 1992, 1994, 1999, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s_ptr r4 +# size r5 +# cnt r6 + */ + + .toc + .extern _gcry_mpih_lshift[DS] + .extern ._gcry_mpih_lshift +.csect [PR] + .align 2 + .globl _gcry_mpih_lshift + .globl ._gcry_mpih_lshift + .csect _gcry_mpih_lshift[DS] +_gcry_mpih_lshift: + .long ._gcry_mpih_lshift, TOC[tc0], 0 + .csect [PR] +._gcry_mpih_lshift: + sli 0,5,2 + cax 9,3,0 + cax 4,4,0 + sfi 8,6,32 + mtctr 5 # put limb count in CTR loop register + lu 0,-4(4) # read most significant limb + sre 3,0,8 # compute carry out limb, and init MQ register + bdz Lend2 # if just one limb, skip loop + lu 0,-4(4) # read 2:nd most significant limb + sreq 7,0,8 # compute most significant limb of result + bdz Lend # if just two limb, skip loop +Loop: lu 0,-4(4) # load next lower limb + stu 7,-4(9) # store previous result during read latency + sreq 7,0,8 # compute result limb + bdn Loop # loop back until CTR is zero +Lend: stu 7,-4(9) # store 2:nd least significant limb +Lend2: sle 7,0,6 # compute least significant limb + st 7,-4(9) # store it + br + diff --git a/grub-core/lib/libgcrypt/mpi/power/mpih-mul1.S b/grub-core/lib/libgcrypt/mpi/power/mpih-mul1.S new file mode 100644 index 0000000..35034fa --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/power/mpih-mul1.S @@ -0,0 +1,115 @@ +/* IBM POWER mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1999, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s1_ptr r4 +# size r5 +# s2_limb r6 + +# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To +# obtain that operation, we have to use the 32x32->64 signed multiplication +# instruction, and add the appropriate compensation to the high limb of the +# result. We add the multiplicand if the multiplier has its most significant +# bit set, and we add the multiplier if the multiplicand has its most +# significant bit set. We need to preserve the carry flag between each +# iteration, so we have to compute the compensation carefully (the natural, +# srai+and doesn't work). Since the POWER architecture has a branch unit +# we can branch in zero cycles, so that's how we perform the additions. + */ + + .toc + .csect ._gcry_mpih_mul_1[PR] + .align 2 + .globl _gcry_mpih_mul_1 + .globl ._gcry_mpih_mul_1 + .csect _gcry_mpih_mul_1[DS] +_gcry_mpih_mul_1: + .long ._gcry_mpih_mul_1[PR], TOC[tc0], 0 + .csect ._gcry_mpih_mul_1[PR] +._gcry_mpih_mul_1: + + cal 3,-4(3) + l 0,0(4) + cmpi 0,6,0 + mtctr 5 + mul 9,0,6 + srai 7,0,31 + and 7,7,6 + mfmq 8 + ai 0,0,0 # reset carry + cax 9,9,7 + blt Lneg +Lpos: bdz Lend +Lploop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + mfmq 0 + ae 8,0,9 + bge Lp0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Lp0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + mfmq 0 + ae 8,0,10 + bge Lp1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Lp1: bdn Lploop + b Lend + +Lneg: cax 9,9,0 + bdz Lend +Lnloop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + cax 10,10,0 # adjust high limb for negative s2_limb + mfmq 0 + ae 8,0,9 + bge Ln0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Ln0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + cax 9,9,0 # adjust high limb for negative s2_limb + mfmq 0 + ae 8,0,10 + bge Ln1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Ln1: bdn Lnloop + b Lend + +Lend0: cal 9,0(10) +Lend: st 8,4(3) + aze 3,9 + br + diff --git a/grub-core/lib/libgcrypt/mpi/power/mpih-mul2.S b/grub-core/lib/libgcrypt/mpi/power/mpih-mul2.S new file mode 100644 index 0000000..d056e8f --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/power/mpih-mul2.S @@ -0,0 +1,130 @@ +/* IBM POWER addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1999, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s1_ptr r4 +# size r5 +# s2_limb r6 + +# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To +# obtain that operation, we have to use the 32x32->64 signed multiplication +# instruction, and add the appropriate compensation to the high limb of the +# result. We add the multiplicand if the multiplier has its most significant +# bit set, and we add the multiplier if the multiplicand has its most +# significant bit set. We need to preserve the carry flag between each +# iteration, so we have to compute the compensation carefully (the natural, +# srai+and doesn't work). Since the POWER architecture has a branch unit +# we can branch in zero cycles, so that's how we perform the additions. + */ + + .toc + .csect ._gcry_mpih_addmul_1[PR] + .align 2 + .globl _gcry_mpih_addmul_1 + .globl ._gcry_mpih_addmul_1 + .csect _gcry_mpih_addmul_1[DS] +_gcry_mpih_addmul_1: + .long ._gcry_mpih_addmul_1[PR], TOC[tc0], 0 + .csect ._gcry_mpih_addmul_1[PR] +._gcry_mpih_addmul_1: + + cal 3,-4(3) + l 0,0(4) + cmpi 0,6,0 + mtctr 5 + mul 9,0,6 + srai 7,0,31 + and 7,7,6 + mfmq 8 + cax 9,9,7 + l 7,4(3) + a 8,8,7 # add res_limb + blt Lneg +Lpos: bdz Lend + +Lploop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + mfmq 0 + ae 8,0,9 # low limb + old_cy_limb + old cy + l 7,4(3) + aze 10,10 # propagate cy to new cy_limb + a 8,8,7 # add res_limb + bge Lp0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Lp0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + mfmq 0 + ae 8,0,10 + l 7,4(3) + aze 9,9 + a 8,8,7 + bge Lp1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Lp1: bdn Lploop + + b Lend + +Lneg: cax 9,9,0 + bdz Lend +Lnloop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + mfmq 7 + ae 8,7,9 + l 7,4(3) + ae 10,10,0 # propagate cy to new cy_limb + a 8,8,7 # add res_limb + bge Ln0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Ln0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + mfmq 7 + ae 8,7,10 + l 7,4(3) + ae 9,9,0 # propagate cy to new cy_limb + a 8,8,7 # add res_limb + bge Ln1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Ln1: bdn Lnloop + b Lend + +Lend0: cal 9,0(10) +Lend: st 8,4(3) + aze 3,9 + br + diff --git a/grub-core/lib/libgcrypt/mpi/power/mpih-mul3.S b/grub-core/lib/libgcrypt/mpi/power/mpih-mul3.S new file mode 100644 index 0000000..8bc317b --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/power/mpih-mul3.S @@ -0,0 +1,135 @@ +/* IBM POWER submul_1 -- Multiply a limb vector with a limb and subtract + * the result from a second limb vector. + * + * Copyright (C) 1992, 1994, 1999, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +/* + +# INPUT PARAMETERS +# res_ptr r3 +# s1_ptr r4 +# size r5 +# s2_limb r6 + +# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To +# obtain that operation, we have to use the 32x32->64 signed multiplication +# instruction, and add the appropriate compensation to the high limb of the +# result. We add the multiplicand if the multiplier has its most significant +# bit set, and we add the multiplier if the multiplicand has its most +# significant bit set. We need to preserve the carry flag between each +# iteration, so we have to compute the compensation carefully (the natural, +# srai+and doesn't work). Since the POWER architecture has a branch unit +# we can branch in zero cycles, so that's how we perform the additions. + */ + + .toc + .csect ._gcry_mpih_submul_1[PR] + .align 2 + .globl _gcry_mpih_submul_1 + .globl ._gcry_mpih_submul_1 + .csect _gcry_mpih_submul_1[DS] +_gcry_mpih_submul_1: + .long ._gcry_mpih_submul_1[PR], TOC[tc0], 0 + .csect ._gcry_mpih_submul_1[PR] +._gcry_mpih_submul_1: + + cal 3,-4(3) + l 0,0(4) + cmpi 0,6,0 + mtctr 5 + mul 9,0,6 + srai 7,0,31 + and 7,7,6 + mfmq 11 + cax 9,9,7 + l 7,4(3) + sf 8,11,7 # add res_limb + a 11,8,11 # invert cy (r11 is junk) + blt Lneg +Lpos: bdz Lend + +Lploop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + mfmq 0 + ae 11,0,9 # low limb + old_cy_limb + old cy + l 7,4(3) + aze 10,10 # propagate cy to new cy_limb + sf 8,11,7 # add res_limb + a 11,8,11 # invert cy (r11 is junk) + bge Lp0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Lp0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + mfmq 0 + ae 11,0,10 + l 7,4(3) + aze 9,9 + sf 8,11,7 + a 11,8,11 # invert cy (r11 is junk) + bge Lp1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Lp1: bdn Lploop + + b Lend + +Lneg: cax 9,9,0 + bdz Lend +Lnloop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + mfmq 7 + ae 11,7,9 + l 7,4(3) + ae 10,10,0 # propagate cy to new cy_limb + sf 8,11,7 # add res_limb + a 11,8,11 # invert cy (r11 is junk) + bge Ln0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Ln0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + mfmq 7 + ae 11,7,10 + l 7,4(3) + ae 9,9,0 # propagate cy to new cy_limb + sf 8,11,7 # add res_limb + a 11,8,11 # invert cy (r11 is junk) + bge Ln1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Ln1: bdn Lnloop + b Lend + +Lend0: cal 9,0(10) +Lend: st 8,4(3) + aze 3,9 + br + diff --git a/grub-core/lib/libgcrypt/mpi/power/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/power/mpih-rshift.S new file mode 100644 index 0000000..f131a86 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/power/mpih-rshift.S @@ -0,0 +1,64 @@ +/* IBM POWER rshift + * + * Copyright (C) 1992, 1994, 1999, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s_ptr r4 +# size r5 +# cnt r6 +*/ + + .toc + .extern _gcry_mpih_rshift[DS] + .extern ._gcry_mpih_rshift +.csect [PR] + .align 2 + .globl _gcry_mpih_rshift + .globl ._gcry_mpih_rshift + .csect _gcry_mpih_rshift[DS] +_gcry_mpih_rshift: + .long ._gcry_mpih_rshift, TOC[tc0], 0 + .csect [PR] +._gcry_mpih_rshift: + sfi 8,6,32 + mtctr 5 # put limb count in CTR loop register + l 0,0(4) # read least significant limb + ai 9,3,-4 # adjust res_ptr since it's offset in the stu:s + sle 3,0,8 # compute carry limb, and init MQ register + bdz Lend2 # if just one limb, skip loop + lu 0,4(4) # read 2:nd least significant limb + sleq 7,0,8 # compute least significant limb of result + bdz Lend # if just two limb, skip loop +Loop: lu 0,4(4) # load next higher limb + stu 7,4(9) # store previous result during read latency + sleq 7,0,8 # compute result limb + bdn Loop # loop back until CTR is zero +Lend: stu 7,4(9) # store 2:nd most significant limb +Lend2: sre 7,0,6 # compute most significant limb + st 7,4(9) # store it + br + + diff --git a/grub-core/lib/libgcrypt/mpi/power/mpih-sub1.S b/grub-core/lib/libgcrypt/mpi/power/mpih-sub1.S new file mode 100644 index 0000000..02748fc --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/power/mpih-sub1.S @@ -0,0 +1,88 @@ +/* IBM POWER sub_n -- Subtract two limb vectors of equal, non-zero length. + * + * Copyright (C) 1992, 1994, 1995, 1996, 1999, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s1_ptr r4 +# s2_ptr r5 +# size r6 + */ + + .toc + .extern _gcry_mpih_sub_n[DS] + .extern ._gcry_mpih_sub_n +.csect [PR] + .align 2 + .globl _gcry_mpih_sub_n + .globl ._gcry_mpih_sub_n + .csect _gcry_mpih_sub_n[DS] +_gcry_mpih_sub_n: + .long ._gcry_mpih_sub_n, TOC[tc0], 0 + .csect [PR] +._gcry_mpih_sub_n: + andil. 10,6,1 # odd or even number of limbs? + l 8,0(4) # load least significant s1 limb + l 0,0(5) # load least significant s2 limb + cal 3,-4(3) # offset res_ptr, it's updated before it's used + sri 10,6,1 # count for unrolled loop + sf 7,0,8 # subtract least significant limbs, set cy + mtctr 10 # copy count into CTR + beq 0,Leven # branch if even # of limbs (# of limbs >= 2) + +# We have an odd # of limbs. Add the first limbs separately. + cmpi 1,10,0 # is count for unrolled loop zero? + bne 1,L1 # branch if not + st 7,4(3) + sfe 3,0,0 # load !cy into ... + sfi 3,3,0 # ... return value register + br # return + +# We added least significant limbs. Now reload the next limbs to enter loop. +L1: lu 8,4(4) # load s1 limb and update s1_ptr + lu 0,4(5) # load s2 limb and update s2_ptr + stu 7,4(3) + sfe 7,0,8 # subtract limbs, set cy +Leven: lu 9,4(4) # load s1 limb and update s1_ptr + lu 10,4(5) # load s2 limb and update s2_ptr + bdz Lend # If done, skip loop + +Loop: lu 8,4(4) # load s1 limb and update s1_ptr + lu 0,4(5) # load s2 limb and update s2_ptr + sfe 11,10,9 # subtract previous limbs with cy, set cy + stu 7,4(3) # + lu 9,4(4) # load s1 limb and update s1_ptr + lu 10,4(5) # load s2 limb and update s2_ptr + sfe 7,0,8 # subtract previous limbs with cy, set cy + stu 11,4(3) # + bdn Loop # decrement CTR and loop back + +Lend: sfe 11,10,9 # subtract limbs with cy, set cy + st 7,4(3) # + st 11,8(3) # + sfe 3,0,0 # load !cy into ... + sfi 3,3,0 # ... return value register + br + diff --git a/grub-core/lib/libgcrypt/mpi/powerpc32/Manifest b/grub-core/lib/libgcrypt/mpi/powerpc32/Manifest new file mode 100644 index 0000000..26ab6ea --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/powerpc32/Manifest @@ -0,0 +1,28 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +mpih-add1.S +mpih-sub1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +syntax.h +$names$ iQCVAwUAP+LmYzEAnp832S/7AQI/cQP+Mcg9rF/c/bJTY48PE1/ARt7vCMtpIlv9alZSSSrU3WHzCtv9nVczFmwHU3DdKFawigY2DljQcK92dZ5ZlOfpFNMz4PKlVMWaKDk+jKlqm2dxvlHuqEvXPpjFAE2gHrhq5qLXS5ZHeMLJIEK84GYC6fjfLUMdZU3altXTUBvoXhA==Yax+ diff --git a/grub-core/lib/libgcrypt/mpi/powerpc32/distfiles b/grub-core/lib/libgcrypt/mpi/powerpc32/distfiles new file mode 100644 index 0000000..a086614 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/powerpc32/distfiles @@ -0,0 +1,10 @@ +Manifest +mpih-add1.S +mpih-sub1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +syntax.h + diff --git a/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-add1.S b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-add1.S new file mode 100644 index 0000000..1661f5e --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-add1.S @@ -0,0 +1,136 @@ +/* PowerPC-32 add_n -- Add two limb vectors of equal, non-zero length. + * + * Copyright (C) 1992, 1994, 1995, 1998, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * _gcry_mpih_add_n( mpi_ptr_t res_ptr, (r3) + * mpi_ptr_t s1_ptr, (r4) + * mpi_ptr_t s2_ptr, (r5) + * mpi_size_t size) (r6) + */ + + .toc + .extern _gcry_mpih_add_n[DS] + .extern ._gcry_mpih_add_n +.csect [PR] + .align 2 + .globl _gcry_mpih_add_n + .globl ._gcry_mpih_add_n + .csect _gcry_mpih_add_n[DS] +_gcry_mpih_add_n: + .long ._gcry_mpih_add_n, TOC[tc0], 0 + .csect [PR] +._gcry_mpih_add_n: + mtctr 6 # copy size into CTR + lwz 8,0(4) # load least significant s1 limb + lwz 0,0(5) # load least significant s2 limb + addi 3,3,-4 # offset res_ptr, it is updated before used + addc 7,0,8 # add least significant limbs, set cy + bdz Lend # If done, skip loop +Loop: lwzu 8,4(4) # load s1 limb and update s1_ptr + lwzu 0,4(5) # load s2 limb and update s2_ptr + stwu 7,4(3) # store previous limb in load latency slot + adde 7,0,8 # add new limbs with cy, set cy + bdnz Loop # decrement CTR and loop back +Lend: stw 7,4(3) # store ultimate result limb + li 3,0 # load cy into ... + addze 3,3 # ... return value register + blr + +#else +/* Add two limb vectors of equal, non-zero length for PowerPC. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +/* mp_limb_t mpn_add_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, + mp_size_t size) + Calculate s1+s2 and put result in res_ptr; return carry, 0 or 1. */ + +/* Note on optimisation: This code is optimal for the 601. Almost every other + possible 2-unrolled inner loop will not be. Also, watch out for the + alignment... */ + +EALIGN(_gcry_mpih_add_n,3,0) +/* Set up for loop below. */ + mtcrf 0x01,%r6 + srwi. %r7,%r6,1 + li %r10,0 + mtctr %r7 + bt 31,2f + +/* Clear the carry. */ + addic %r0,%r0,0 +/* Adjust pointers for loop. */ + addi %r3,%r3,-4 + addi %r4,%r4,-4 + addi %r5,%r5,-4 + b 0f + +2: lwz %r7,0(%r5) + lwz %r6,0(%r4) + addc %r6,%r6,%r7 + stw %r6,0(%r3) + beq 1f + +/* The loop. */ + +/* Align start of loop to an odd word boundary to guarantee that the + last two words can be fetched in one access (for 601). */ +0: lwz %r9,4(%r4) + lwz %r8,4(%r5) + lwzu %r6,8(%r4) + lwzu %r7,8(%r5) + adde %r8,%r9,%r8 + stw %r8,4(%r3) + adde %r6,%r6,%r7 + stwu %r6,8(%r3) + bdnz 0b +/* Return the carry. */ +1: addze %r3,%r10 + blr +END(_gcry_mpih_add_n) +#endif + diff --git a/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-lshift.S new file mode 100644 index 0000000..6231095 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-lshift.S @@ -0,0 +1,198 @@ +/* PowerPC-32 lshift + * + * Copyright (C) 1995, 1998, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * _gcry_mpih_lshift( mpi_ptr_t wp, (r3) + * mpi_ptr_t up, (r4) + * mpi_size_t usize, (r5) + * unsigned cnt) (r6) + */ + + .toc +.csect .text[PR] + .align 2 + .globl _gcry_mpih_lshift + .globl ._gcry_mpih_lshift + .csect _gcry_mpih_lshift[DS] +_gcry_mpih_lshift: + .long ._gcry_mpih_lshift, TOC[tc0], 0 + .csect .text[PR] +._gcry_mpih_lshift: + mtctr 5 # copy size into CTR + slwi 0,5,2 + add 7,3,0 # make r7 point at end of res + add 4,4,0 # make r4 point at end of s1 + subfic 8,6,32 + lwzu 11,-4(4) # load first s1 limb + srw 3,11,8 # compute function return value + bdz Lend1 + +Loop: lwzu 10,-4(4) + slw 9,11,6 + srw 12,10,8 + or 9,9,12 + stwu 9,-4(7) + bdz Lend2 + lwzu 11,-4(4) + slw 9,10,6 + srw 12,11,8 + or 9,9,12 + stwu 9,-4(7) + bdnz Loop + +Lend1: slw 0,11,6 + stw 0,-4(7) + blr + +Lend2: slw 0,10,6 + stw 0,-4(7) + blr + +#else +/* Shift a limb left, low level routine. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* mp_limb_t mpn_lshift (mp_ptr wp, mp_srcptr up, mp_size_t usize, + unsigned int cnt) */ + +EALIGN(_gcry_mpih_lshift,3,0) + mtctr %r5 # copy size into CTR + cmplwi %cr0,%r5,16 # is size < 16 + slwi %r0,%r5,2 + add %r7,%r3,%r0 # make r7 point at end of res + add %r4,%r4,%r0 # make r4 point at end of s1 + lwzu %r11,-4(%r4) # load first s1 limb + subfic %r8,%r6,32 + srw %r3,%r11,%r8 # compute function return value + bge %cr0,L(big) # branch if size >= 16 + + bdz L(end1) + +0: lwzu %r10,-4(%r4) + slw %r9,%r11,%r6 + srw %r12,%r10,%r8 + or %r9,%r9,%r12 + stwu %r9,-4(%r7) + bdz L(end2) + lwzu %r11,-4(%r4) + slw %r9,%r10,%r6 + srw %r12,%r11,%r8 + or %r9,%r9,%r12 + stwu %r9,-4(%r7) + bdnz 0b + +L(end1):slw %r0,%r11,%r6 + stw %r0,-4(%r7) + blr + + +/* Guaranteed not to succeed. */ +L(boom): tweq %r0,%r0 + +/* We imitate a case statement, by using (yuk!) fixed-length code chunks, + of size 4*12 bytes. We have to do this (or something) to make this PIC. */ +L(big): mflr %r9 + bltl- %cr0,L(boom) # Never taken, only used to set LR. + slwi %r10,%r6,4 + mflr %r12 + add %r10,%r12,%r10 + slwi %r8,%r6,5 + add %r10,%r8,%r10 + mtctr %r10 + addi %r5,%r5,-1 + mtlr %r9 + bctr + +L(end2):slw %r0,%r10,%r6 + stw %r0,-4(%r7) + blr + +#define DO_LSHIFT(n) \ + mtctr %r5; \ +0: lwzu %r10,-4(%r4); \ + slwi %r9,%r11,n; \ + inslwi %r9,%r10,n,32-n; \ + stwu %r9,-4(%r7); \ + bdz- L(end2); \ + lwzu %r11,-4(%r4); \ + slwi %r9,%r10,n; \ + inslwi %r9,%r11,n,32-n; \ + stwu %r9,-4(%r7); \ + bdnz 0b; \ + b L(end1) + + DO_LSHIFT(1) + DO_LSHIFT(2) + DO_LSHIFT(3) + DO_LSHIFT(4) + DO_LSHIFT(5) + DO_LSHIFT(6) + DO_LSHIFT(7) + DO_LSHIFT(8) + DO_LSHIFT(9) + DO_LSHIFT(10) + DO_LSHIFT(11) + DO_LSHIFT(12) + DO_LSHIFT(13) + DO_LSHIFT(14) + DO_LSHIFT(15) + DO_LSHIFT(16) + DO_LSHIFT(17) + DO_LSHIFT(18) + DO_LSHIFT(19) + DO_LSHIFT(20) + DO_LSHIFT(21) + DO_LSHIFT(22) + DO_LSHIFT(23) + DO_LSHIFT(24) + DO_LSHIFT(25) + DO_LSHIFT(26) + DO_LSHIFT(27) + DO_LSHIFT(28) + DO_LSHIFT(29) + DO_LSHIFT(30) + DO_LSHIFT(31) + +END(_gcry_mpih_lshift) +#endif diff --git a/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-mul1.S b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-mul1.S new file mode 100644 index 0000000..bd418f7 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-mul1.S @@ -0,0 +1,120 @@ +/* PowerPC-32 mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1993, 1994, 1995, + * 1998, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * _gcry_mpih_mul_1( mpi_ptr_t res_ptr, (r3) + * mpi_ptr_t s1_ptr, (r4) + * mpi_size_t s1_size, (r5) + * mpi_limb_t s2_limb) (r6) + * + * This is a fairly straightforward implementation. The timing of the PC601 + * is hard to understand, so I will wait to optimize this until I have some + * hardware to play with. + * + * The code trivially generalizes to 64 bit limbs for the PC620. + */ + + .toc + .csect ._gcry_mpih_mul_1[PR] + .align 2 + .globl _gcry_mpih_mul_1 + .globl ._gcry_mpih_mul_1 + .csect _gcry_mpih_mul_1[DS] +_gcry_mpih_mul_1: + .long ._gcry_mpih_mul_1[PR], TOC[tc0], 0 + .csect ._gcry_mpih_mul_1[PR] +._gcry_mpih_mul_1: + mtctr 5 + + lwz 0,0(4) + mullw 7,0,6 + mulhwu 10,0,6 + addi 3,3,-4 # adjust res_ptr + addic 5,5,0 # clear cy with dummy insn + bdz Lend + +Loop: lwzu 0,4(4) + stwu 7,4(3) + mullw 8,0,6 + adde 7,8,10 + mulhwu 10,0,6 + bdnz Loop + +Lend: stw 7,4(3) + addze 3,10 + blr + +#else +/* Multiply a limb vector by a limb, for PowerPC. + Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +/* mp_limb_t mpn_mul_1 (mp_ptr res_ptr, mp_srcptr s1_ptr, + mp_size_t s1_size, mp_limb_t s2_limb) + Calculate s1*s2 and put result in res_ptr; return carry. */ + +ENTRY(_gcry_mpih_mul_1) + mtctr %r5 + + lwz %r0,0(%r4) + mullw %r7,%r0,%r6 + mulhwu %r10,%r0,%r6 + addi %r3,%r3,-4 # adjust res_ptr + addic %r5,%r5,0 # clear cy with dummy insn + bdz 1f + +0: lwzu %r0,4(%r4) + stwu %r7,4(%r3) + mullw %r8,%r0,%r6 + adde %r7,%r8,%r10 + mulhwu %r10,%r0,%r6 + bdnz 0b + +1: stw %r7,4(%r3) + addze %r3,%r10 + blr +END(_gcry_mpih_mul_1) +#endif diff --git a/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-mul2.S b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-mul2.S new file mode 100644 index 0000000..1d97b81 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-mul2.S @@ -0,0 +1,127 @@ +/* PowerPC-32 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1995, 1998, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, (r3) + * mpi_ptr_t s1_ptr, (r4) + * mpi_size_t s1_size, (r5) + * mpi_limb_t s2_limb) (r6) + * + * This is a fairly straightforward implementation. The timing of the PC601 + * is hard to understand, so I will wait to optimize this until I have some + * hardware to play with. + * + * The code trivially generalizes to 64 bit limbs for the PC620. + */ + + + .toc + .csect ._gcry_mpih_addmul_1[PR] + .align 2 + .globl _gcry_mpih_addmul_1 + .globl ._gcry_mpih_addmul_1 + .csect _gcry_mpih_addmul_1[DS] +_gcry_mpih_addmul_1: + .long ._gcry_mpih_addmul_1[PR], TOC[tc0], 0 + .csect ._gcry_mpih_addmul_1[PR] +._gcry_mpih_addmul_1: + mtctr 5 + + lwz 0,0(4) + mullw 7,0,6 + mulhwu 10,0,6 + lwz 9,0(3) + addc 8,7,9 + addi 3,3,-4 + bdz Lend + +Loop: lwzu 0,4(4) + stwu 8,4(3) + mullw 8,0,6 + adde 7,8,10 + mulhwu 10,0,6 + lwz 9,4(3) + addze 10,10 + addc 8,7,9 + bdnz Loop + +Lend: stw 8,4(3) + addze 3,10 + blr + +#else +/* Multiply a limb vector by a single limb, for PowerPC. + Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +/* mp_limb_t mpn_addmul_1 (mp_ptr res_ptr, mp_srcptr s1_ptr, + mp_size_t s1_size, mp_limb_t s2_limb) + Calculate res+s1*s2 and put result back in res; return carry. */ +ENTRY(_gcry_mpih_addmul_1) + mtctr %r5 + + lwz %r0,0(%r4) + mullw %r7,%r0,%r6 + mulhwu %r10,%r0,%r6 + lwz %r9,0(%r3) + addc %r8,%r7,%r9 + addi %r3,%r3,-4 /* adjust res_ptr */ + bdz 1f + +0: lwzu %r0,4(%r4) + stwu %r8,4(%r3) + mullw %r8,%r0,%r6 + adde %r7,%r8,%r10 + mulhwu %r10,%r0,%r6 + lwz %r9,4(%r3) + addze %r10,%r10 + addc %r8,%r7,%r9 + bdnz 0b + +1: stw %r8,4(%r3) + addze %r3,%r10 + blr +END(_gcry_mpih_addmul_1) +#endif diff --git a/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-mul3.S b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-mul3.S new file mode 100644 index 0000000..c410dbb --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-mul3.S @@ -0,0 +1,130 @@ +/* PowerPC-32 submul_1 -- Multiply a limb vector with a limb and subtract + * the result from a second limb vector. + * + * Copyright (C) 1995, 1998, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * _gcry_mpih_submul_1( mpi_ptr_t res_ptr, (r3) + * mpi_ptr_t s1_ptr, (r4) + * mpi_size_t s1_size, (r5) + * mpi_limb_t s2_limb) (r6) + * + * This is a fairly straightforward implementation. The timing of the PC601 + * is hard to understand, so I will wait to optimize this until I have some + * hardware to play with. + * + * The code trivially generalizes to 64 bit limbs for the PC620. + */ + + .toc + .csect ._gcry_mpih_submul_1[PR] + .align 2 + .globl _gcry_mpih_submul_1 + .globl ._gcry_mpih_submul_1 + .csect _gcry_mpih_submul_1[DS] +_gcry_mpih_submul_1: + .long ._gcry_mpih_submul_1[PR], TOC[tc0], 0 + .csect ._gcry_mpih_submul_1[PR] +._gcry_mpih_submul_1: + mtctr 5 + + lwz 0,0(4) + mullw 7,0,6 + mulhwu 10,0,6 + lwz 9,0(3) + subfc 8,7,9 + addc 7,7,8 # invert cy (r7 is junk) + addi 3,3,-4 + bdz Lend + +Loop: lwzu 0,4(4) + stwu 8,4(3) + mullw 8,0,6 + adde 7,8,10 + mulhwu 10,0,6 + lwz 9,4(3) + addze 10,10 + subfc 8,7,9 + addc 7,7,8 # invert cy (r7 is junk) + bdnz Loop + +Lend: stw 8,4(3) + addze 3,10 + blr + +#else +/* Multiply a limb vector by a single limb, for PowerPC. + Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* mp_limb_t mpn_submul_1 (mp_ptr res_ptr, mp_srcptr s1_ptr, + mp_size_t s1_size, mp_limb_t s2_limb) + Calculate res-s1*s2 and put result back in res; return carry. */ + +ENTRY(_gcry_mpih_submul_1) + mtctr %r5 + + lwz %r0,0(%r4) + mullw %r7,%r0,%r6 + mulhwu %r10,%r0,%r6 + lwz %r9,0(%r3) + subf %r8,%r7,%r9 + addc %r7,%r7,%r8 # invert cy (r7 is junk) + addi %r3,%r3,-4 # adjust res_ptr + bdz 1f + +0: lwzu %r0,4(%r4) + stwu %r8,4(%r3) + mullw %r8,%r0,%r6 + adde %r7,%r8,%r10 + mulhwu %r10,%r0,%r6 + lwz %r9,4(%r3) + addze %r10,%r10 + subf %r8,%r7,%r9 + addc %r7,%r7,%r8 # invert cy (r7 is junk) + bdnz 0b + +1: stw %r8,4(%r3) + addze %r3,%r10 + blr +END(_gcry_mpih_submul_1) +#endif diff --git a/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-rshift.S new file mode 100644 index 0000000..98349ed --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-rshift.S @@ -0,0 +1,131 @@ +/* PowerPC-32 rshift + * + * Copyright (C) 1995, 1998, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * _gcry_mpih_rshift( mpi_ptr_t wp, (r3) + * mpi_ptr_t up, (r4) + * mpi_size_t usize, (r5) + * unsigned cnt) (r6) + */ + + .toc +.csect .text[PR] + .align 2 + .globl _gcry_mpih_rshift + .globl ._gcry_mpih_rshift + .csect _gcry_mpih_rshift[DS] +_gcry_mpih_rshift: + .long ._gcry_mpih_rshift, TOC[tc0], 0 + .csect .text[PR] +._gcry_mpih_rshift: + mtctr 5 # copy size into CTR + addi 7,3,-4 # move adjusted res_ptr to free return reg + subfic 8,6,32 + lwz 11,0(4) # load first s1 limb + slw 3,11,8 # compute function return value + bdz Lend1 + +Loop: lwzu 10,4(4) + srw 9,11,6 + slw 12,10,8 + or 9,9,12 + stwu 9,4(7) + bdz Lend2 + lwzu 11,4(4) + srw 9,10,6 + slw 12,11,8 + or 9,9,12 + stwu 9,4(7) + bdnz Loop + +Lend1: srw 0,11,6 + stw 0,4(7) + blr + +Lend2: srw 0,10,6 + stw 0,4(7) + blr + +#else +/* Shift a limb right, low level routine. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +/* INPUT PARAMETERS + res_ptr r3 + s1_ptr r4 + size r5 + cnt r6 */ + +ENTRY(_gcry_mpih_rshift) + mtctr 5 # copy size into CTR + addi 7,3,-4 # move adjusted res_ptr to free return reg + subfic 8,6,32 + lwz 11,0(4) # load first s1 limb + slw 3,11,8 # compute function return value + bdz 1f + +0: lwzu 10,4(4) + srw 9,11,6 + slw 12,10,8 + or 9,9,12 + stwu 9,4(7) + bdz 2f + lwzu 11,4(4) + srw 9,10,6 + slw 12,11,8 + or 9,9,12 + stwu 9,4(7) + bdnz 0b + +1: srw 0,11,6 + stw 0,4(7) + blr + +2: srw 0,10,6 + stw 0,4(7) + blr +END(_gcry_mpih_rshift) +#endif diff --git a/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-sub1.S b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-sub1.S new file mode 100644 index 0000000..d612ea8 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/powerpc32/mpih-sub1.S @@ -0,0 +1,133 @@ +/* PowerPC-32 sub_n -- Subtract two limb vectors of the same length > 0 + * and store difference in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * _gcry_mpih_sub_n( mpi_ptr_t res_ptr, (r3) + * mpi_ptr_t s1_ptr, (r4) + * mpi_ptr_t s2_ptr, (r5) + * mpi_size_t size) (r6) + */ + + .toc + .extern _gcry_mpih_sub_n[DS] + .extern ._gcry_mpih_sub_n +.csect [PR] + .align 2 + .globl _gcry_mpih_sub_n + .globl ._gcry_mpih_sub_n + .csect _gcry_mpih_sub_n[DS] +_gcry_mpih_sub_n: + .long ._gcry_mpih_sub_n, TOC[tc0], 0 + .csect [PR] +._gcry_mpih_sub_n: + mtctr 6 # copy size into CTR + lwz 8,0(4) # load least significant s1 limb + lwz 0,0(5) # load least significant s2 limb + addi 3,3,-4 # offset res_ptr, it is updated before used + subfc 7,0,8 # add least significant limbs, set cy + bdz Lend # If done, skip loop +Loop: lwzu 8,4(4) # load s1 limb and update s1_ptr + lwzu 0,4(5) # load s2 limb and update s2_ptr + stwu 7,4(3) # store previous limb in load latency slot + subfe 7,0,8 # add new limbs with cy, set cy + bdnz Loop # decrement CTR and loop back +Lend: stw 7,4(3) # store ultimate result limb + subfe 3,0,0 # load !cy into ... + subfic 3,3,0 # ... return value register + blr + +#else +/* Subtract two limb vectors of equal, non-zero length for PowerPC. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* mp_limb_t mpn_sub_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, + mp_size_t size) + Calculate s1-s2 and put result in res_ptr; return borrow, 0 or 1. */ + +/* Note on optimisation: This code is optimal for the 601. Almost every other + possible 2-unrolled inner loop will not be. Also, watch out for the + alignment... */ + +EALIGN(_gcry_mpih_sub_n,3,1) +/* Set up for loop below. */ + mtcrf 0x01,%r6 + srwi. %r7,%r6,1 + mtctr %r7 + bt 31,2f + +/* Set the carry (clear the borrow). */ + subfc %r0,%r0,%r0 +/* Adjust pointers for loop. */ + addi %r3,%r3,-4 + addi %r4,%r4,-4 + addi %r5,%r5,-4 + b 0f + +2: lwz %r7,0(%r5) + lwz %r6,0(%r4) + subfc %r6,%r7,%r6 + stw %r6,0(%r3) + beq 1f + +/* Align start of loop to an odd word boundary to guarantee that the + last two words can be fetched in one access (for 601). This turns + out to be important. */ +0: + lwz %r9,4(%r4) + lwz %r8,4(%r5) + lwzu %r6,8(%r4) + lwzu %r7,8(%r5) + subfe %r8,%r8,%r9 + stw %r8,4(%r3) + subfe %r6,%r7,%r6 + stwu %r6,8(%r3) + bdnz 0b +/* Return the borrow. */ +1: subfe %r3,%r3,%r3 + neg %r3,%r3 + blr +END(_gcry_mpih_sub_n) +#endif diff --git a/grub-core/lib/libgcrypt/mpi/powerpc32/syntax.h b/grub-core/lib/libgcrypt/mpi/powerpc32/syntax.h new file mode 100644 index 0000000..5d4af9f --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/powerpc32/syntax.h @@ -0,0 +1,75 @@ +/* gmp2-2.0.2-ppc/mpn/powerpc-linux/syntax.h Tue Oct 6 19:27:01 1998 */ +/* From glibc's sysdeps/unix/sysv/linux/powerpc/sysdep.h */ + +/* Copyright (C) 1992, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +#define USE_PPC_PATCHES 1 + +/* This seems to always be the case on PPC. */ +#define ALIGNARG(log2) log2 +/* For ELF we need the `.type' directive to make shared libs work right. */ +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name +#define ASM_GLOBAL_DIRECTIVE .globl + +#ifdef __STDC__ +#define C_LABEL(name) C_SYMBOL_NAME(name)##: +#else +#define C_LABEL(name) C_SYMBOL_NAME(name)/**/: +#endif + +#ifdef __STDC__ +#define L(body) .L##body +#else +#define L(body) .L/**/body +#endif + +/* No profiling of gmp's assembly for now... */ +#define CALL_MCOUNT /* no profiling */ + +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(2); \ + C_LABEL(name) \ + CALL_MCOUNT + +#define EALIGN_W_0 /* No words to insert. */ +#define EALIGN_W_1 nop +#define EALIGN_W_2 nop;nop +#define EALIGN_W_3 nop;nop;nop +#define EALIGN_W_4 EALIGN_W_3;nop +#define EALIGN_W_5 EALIGN_W_4;nop +#define EALIGN_W_6 EALIGN_W_5;nop +#define EALIGN_W_7 EALIGN_W_6;nop + +/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes + past a 2^align boundary. */ +#define EALIGN(name, alignt, words) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(alignt); \ + EALIGN_W_##words; \ + C_LABEL(name) + +#undef END +#define END(name) \ + ASM_SIZE_DIRECTIVE(name) + diff --git a/grub-core/lib/libgcrypt/mpi/powerpc64/distfiles b/grub-core/lib/libgcrypt/mpi/powerpc64/distfiles new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/powerpc64/distfiles diff --git a/grub-core/lib/libgcrypt/mpi/sparc32/Manifest b/grub-core/lib/libgcrypt/mpi/sparc32/Manifest new file mode 100644 index 0000000..d279229 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/sparc32/Manifest @@ -0,0 +1,24 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +mpih-lshift.S +mpih-rshift.S +mpih-add1.S +udiv.S +$names$ iQCVAwUAP+LmaDEAnp832S/7AQISHgP/Z5orU+CPKBeRFCogSQDm4p7J2VpDovU6mtfMTdjhqWuZG0U6y8WqH0aj3USfziOhtc8YjQHQ+97g3+EnIWZgLjKacWC6pScY/QbATEpF1D0Wrcea5rk3qR1t7isdBVVOrxedZ5vuj5Op2zx/0OlPI+wt6fTtW88BdG/a6w/ZU/8==Py6h diff --git a/grub-core/lib/libgcrypt/mpi/sparc32/distfiles b/grub-core/lib/libgcrypt/mpi/sparc32/distfiles new file mode 100644 index 0000000..a20f18e --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/sparc32/distfiles @@ -0,0 +1,6 @@ +Manifest +mpih-lshift.S +mpih-rshift.S +mpih-add1.S +udiv.S + diff --git a/grub-core/lib/libgcrypt/mpi/sparc32/mpih-add1.S b/grub-core/lib/libgcrypt/mpi/sparc32/mpih-add1.S new file mode 100644 index 0000000..61a80ca --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/sparc32/mpih-add1.S @@ -0,0 +1,239 @@ +/* SPARC _add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1995, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + +/******************* + * mpi_limb_t + * _gcry_mpih_add_n( mpi_ptr_t res_ptr, + * mpi_ptr_t s1_ptr, + * mpi_ptr_t s2_ptr, + * mpi_size_t size) + */ + +! INPUT PARAMETERS +#define res_ptr %o0 +#define s1_ptr %o1 +#define s2_ptr %o2 +#define size %o3 + +#include "sysdep.h" + + .text + .align 4 + .global C_SYMBOL_NAME(_gcry_mpih_add_n) +C_SYMBOL_NAME(_gcry_mpih_add_n): + xor s2_ptr,res_ptr,%g1 + andcc %g1,4,%g0 + bne L1 ! branch if alignment differs + nop +! ** V1a ** +L0: andcc res_ptr,4,%g0 ! res_ptr unaligned? Side effect: cy=0 + be L_v1 ! if no, branch + nop +/* Add least significant limb separately to align res_ptr and s2_ptr */ + ld [s1_ptr],%g4 + add s1_ptr,4,s1_ptr + ld [s2_ptr],%g2 + add s2_ptr,4,s2_ptr + add size,-1,size + addcc %g4,%g2,%o4 + st %o4,[res_ptr] + add res_ptr,4,res_ptr +L_v1: addx %g0,%g0,%o4 ! save cy in register + cmp size,2 ! if size < 2 ... + bl Lend2 ! ... branch to tail code + subcc %g0,%o4,%g0 ! restore cy + + ld [s1_ptr+0],%g4 + addcc size,-10,size + ld [s1_ptr+4],%g1 + ldd [s2_ptr+0],%g2 + blt Lfin1 + subcc %g0,%o4,%g0 ! restore cy +/* Add blocks of 8 limbs until less than 8 limbs remain */ +Loop1: addxcc %g4,%g2,%o4 + ld [s1_ptr+8],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+12],%g1 + ldd [s2_ptr+8],%g2 + std %o4,[res_ptr+0] + addxcc %g4,%g2,%o4 + ld [s1_ptr+16],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+20],%g1 + ldd [s2_ptr+16],%g2 + std %o4,[res_ptr+8] + addxcc %g4,%g2,%o4 + ld [s1_ptr+24],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+28],%g1 + ldd [s2_ptr+24],%g2 + std %o4,[res_ptr+16] + addxcc %g4,%g2,%o4 + ld [s1_ptr+32],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+36],%g1 + ldd [s2_ptr+32],%g2 + std %o4,[res_ptr+24] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-8,size + add s1_ptr,32,s1_ptr + add s2_ptr,32,s2_ptr + add res_ptr,32,res_ptr + bge Loop1 + subcc %g0,%o4,%g0 ! restore cy + +Lfin1: addcc size,8-2,size + blt Lend1 + subcc %g0,%o4,%g0 ! restore cy +/* Add blocks of 2 limbs until less than 2 limbs remain */ +Loope1: addxcc %g4,%g2,%o4 + ld [s1_ptr+8],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+12],%g1 + ldd [s2_ptr+8],%g2 + std %o4,[res_ptr+0] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-2,size + add s1_ptr,8,s1_ptr + add s2_ptr,8,s2_ptr + add res_ptr,8,res_ptr + bge Loope1 + subcc %g0,%o4,%g0 ! restore cy +Lend1: addxcc %g4,%g2,%o4 + addxcc %g1,%g3,%o5 + std %o4,[res_ptr+0] + addx %g0,%g0,%o4 ! save cy in register + + andcc size,1,%g0 + be Lret1 + subcc %g0,%o4,%g0 ! restore cy +/* Add last limb */ + ld [s1_ptr+8],%g4 + ld [s2_ptr+8],%g2 + addxcc %g4,%g2,%o4 + st %o4,[res_ptr+8] + +Lret1: retl + addx %g0,%g0,%o0 ! return carry-out from most sign. limb + +L1: xor s1_ptr,res_ptr,%g1 + andcc %g1,4,%g0 + bne L2 + nop +! ** V1b ** + mov s2_ptr,%g1 + mov s1_ptr,s2_ptr + b L0 + mov %g1,s1_ptr + +! ** V2 ** +/* If we come here, the alignment of s1_ptr and res_ptr as well as the + alignment of s2_ptr and res_ptr differ. Since there are only two ways + things can be aligned (that we care about) we now know that the alignment + of s1_ptr and s2_ptr are the same. */ + +L2: cmp size,1 + be Ljone + nop + andcc s1_ptr,4,%g0 ! s1_ptr unaligned? Side effect: cy=0 + be L_v2 ! if no, branch + nop +/* Add least significant limb separately to align s1_ptr and s2_ptr */ + ld [s1_ptr],%g4 + add s1_ptr,4,s1_ptr + ld [s2_ptr],%g2 + add s2_ptr,4,s2_ptr + add size,-1,size + addcc %g4,%g2,%o4 + st %o4,[res_ptr] + add res_ptr,4,res_ptr + +L_v2: addx %g0,%g0,%o4 ! save cy in register + addcc size,-8,size + blt Lfin2 + subcc %g0,%o4,%g0 ! restore cy +/* Add blocks of 8 limbs until less than 8 limbs remain */ +Loop2: ldd [s1_ptr+0],%g2 + ldd [s2_ptr+0],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+0] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+4] + ldd [s1_ptr+8],%g2 + ldd [s2_ptr+8],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+8] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+12] + ldd [s1_ptr+16],%g2 + ldd [s2_ptr+16],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+16] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+20] + ldd [s1_ptr+24],%g2 + ldd [s2_ptr+24],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+24] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+28] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-8,size + add s1_ptr,32,s1_ptr + add s2_ptr,32,s2_ptr + add res_ptr,32,res_ptr + bge Loop2 + subcc %g0,%o4,%g0 ! restore cy + +Lfin2: addcc size,8-2,size + blt Lend2 + subcc %g0,%o4,%g0 ! restore cy +Loope2: ldd [s1_ptr+0],%g2 + ldd [s2_ptr+0],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+0] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+4] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-2,size + add s1_ptr,8,s1_ptr + add s2_ptr,8,s2_ptr + add res_ptr,8,res_ptr + bge Loope2 + subcc %g0,%o4,%g0 ! restore cy +Lend2: andcc size,1,%g0 + be Lret2 + subcc %g0,%o4,%g0 ! restore cy +/* Add last limb */ +Ljone: ld [s1_ptr],%g4 + ld [s2_ptr],%g2 + addxcc %g4,%g2,%o4 + st %o4,[res_ptr] + +Lret2: retl + addx %g0,%g0,%o0 ! return carry-out from most sign. limb + + + diff --git a/grub-core/lib/libgcrypt/mpi/sparc32/mpih-lshift.S b/grub-core/lib/libgcrypt/mpi/sparc32/mpih-lshift.S new file mode 100644 index 0000000..3422ab0 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/sparc32/mpih-lshift.S @@ -0,0 +1,97 @@ +/* sparc lshift + * + * Copyright (C) 1995, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +! INPUT PARAMETERS +! res_ptr %o0 +! src_ptr %o1 +! size %o2 +! cnt %o3 + +#include "sysdep.h" + + .text + .align 4 + .global C_SYMBOL_NAME(_gcry_mpih_lshift) +C_SYMBOL_NAME(_gcry_mpih_lshift): + sll %o2,2,%g1 + add %o1,%g1,%o1 ! make %o1 point at end of src + ld [%o1-4],%g2 ! load first limb + sub %g0,%o3,%o5 ! negate shift count + add %o0,%g1,%o0 ! make %o0 point at end of res + add %o2,-1,%o2 + andcc %o2,4-1,%g4 ! number of limbs in first loop + srl %g2,%o5,%g1 ! compute function result + be L0 ! if multiple of 4 limbs, skip first loop + st %g1,[%sp+80] + + sub %o2,%g4,%o2 ! adjust count for main loop + +Loop0: ld [%o1-8],%g3 + add %o0,-4,%o0 + add %o1,-4,%o1 + addcc %g4,-1,%g4 + sll %g2,%o3,%o4 + srl %g3,%o5,%g1 + mov %g3,%g2 + or %o4,%g1,%o4 + bne Loop0 + st %o4,[%o0+0] + +L0: tst %o2 + be Lend + nop + +Loop: ld [%o1-8],%g3 + add %o0,-16,%o0 + addcc %o2,-4,%o2 + sll %g2,%o3,%o4 + srl %g3,%o5,%g1 + + ld [%o1-12],%g2 + sll %g3,%o3,%g4 + or %o4,%g1,%o4 + st %o4,[%o0+12] + srl %g2,%o5,%g1 + + ld [%o1-16],%g3 + sll %g2,%o3,%o4 + or %g4,%g1,%g4 + st %g4,[%o0+8] + srl %g3,%o5,%g1 + + ld [%o1-20],%g2 + sll %g3,%o3,%g4 + or %o4,%g1,%o4 + st %o4,[%o0+4] + srl %g2,%o5,%g1 + + add %o1,-16,%o1 + or %g4,%g1,%g4 + bne Loop + st %g4,[%o0+0] + +Lend: sll %g2,%o3,%g2 + st %g2,[%o0-4] + retl + ld [%sp+80],%o0 + diff --git a/grub-core/lib/libgcrypt/mpi/sparc32/mpih-rshift.S b/grub-core/lib/libgcrypt/mpi/sparc32/mpih-rshift.S new file mode 100644 index 0000000..cd3db41 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/sparc32/mpih-rshift.S @@ -0,0 +1,93 @@ +/* sparc rshift + * + * Copyright (C) 1995, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +! INPUT PARAMETERS +! res_ptr %o0 +! src_ptr %o1 +! size %o2 +! cnt %o3 + +#include "sysdep.h" + + .text + .align 4 + .global C_SYMBOL_NAME(_gcry_mpih_rshift) +C_SYMBOL_NAME(_gcry_mpih_rshift): + ld [%o1],%g2 ! load first limb + sub %g0,%o3,%o5 ! negate shift count + add %o2,-1,%o2 + andcc %o2,4-1,%g4 ! number of limbs in first loop + sll %g2,%o5,%g1 ! compute function result + be L0 ! if multiple of 4 limbs, skip first loop + st %g1,[%sp+80] + + sub %o2,%g4,%o2 ! adjust count for main loop + +Loop0: ld [%o1+4],%g3 + add %o0,4,%o0 + add %o1,4,%o1 + addcc %g4,-1,%g4 + srl %g2,%o3,%o4 + sll %g3,%o5,%g1 + mov %g3,%g2 + or %o4,%g1,%o4 + bne Loop0 + st %o4,[%o0-4] + +L0: tst %o2 + be Lend + nop + +Loop: ld [%o1+4],%g3 + add %o0,16,%o0 + addcc %o2,-4,%o2 + srl %g2,%o3,%o4 + sll %g3,%o5,%g1 + + ld [%o1+8],%g2 + srl %g3,%o3,%g4 + or %o4,%g1,%o4 + st %o4,[%o0-16] + sll %g2,%o5,%g1 + + ld [%o1+12],%g3 + srl %g2,%o3,%o4 + or %g4,%g1,%g4 + st %g4,[%o0-12] + sll %g3,%o5,%g1 + + ld [%o1+16],%g2 + srl %g3,%o3,%g4 + or %o4,%g1,%o4 + st %o4,[%o0-8] + sll %g2,%o5,%g1 + + add %o1,16,%o1 + or %g4,%g1,%g4 + bne Loop + st %g4,[%o0-4] + +Lend: srl %g2,%o3,%g2 + st %g2,[%o0-0] + retl + ld [%sp+80],%o0 + diff --git a/grub-core/lib/libgcrypt/mpi/sparc32/udiv.S b/grub-core/lib/libgcrypt/mpi/sparc32/udiv.S new file mode 100644 index 0000000..006b5c1 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/sparc32/udiv.S @@ -0,0 +1,195 @@ +/* SPARC v7 __udiv_qrnnd division support, used from longlong.h. + * This is for v7 CPUs without a floating-point unit. + * + * Copyright (C) 1993, 1994, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +! INPUT PARAMETERS +! rem_ptr o0 +! n1 o1 +! n0 o2 +! d o3 + +#include "sysdep.h" + + .text + .align 4 + .global C_SYMBOL_NAME(__udiv_qrnnd) +C_SYMBOL_NAME(__udiv_qrnnd): + tst %o3 + bneg Largedivisor + mov 8,%g1 + + b Lp1 + addxcc %o2,%o2,%o2 + +Lplop: bcc Ln1 + addxcc %o2,%o2,%o2 +Lp1: addx %o1,%o1,%o1 + subcc %o1,%o3,%o4 + bcc Ln2 + addxcc %o2,%o2,%o2 +Lp2: addx %o1,%o1,%o1 + subcc %o1,%o3,%o4 + bcc Ln3 + addxcc %o2,%o2,%o2 +Lp3: addx %o1,%o1,%o1 + subcc %o1,%o3,%o4 + bcc Ln4 + addxcc %o2,%o2,%o2 +Lp4: addx %o1,%o1,%o1 + addcc %g1,-1,%g1 + bne Lplop + subcc %o1,%o3,%o4 + bcc Ln5 + addxcc %o2,%o2,%o2 +Lp5: st %o1,[%o0] + retl + xnor %g0,%o2,%o0 + +Lnlop: bcc Lp1 + addxcc %o2,%o2,%o2 +Ln1: addx %o4,%o4,%o4 + subcc %o4,%o3,%o1 + bcc Lp2 + addxcc %o2,%o2,%o2 +Ln2: addx %o4,%o4,%o4 + subcc %o4,%o3,%o1 + bcc Lp3 + addxcc %o2,%o2,%o2 +Ln3: addx %o4,%o4,%o4 + subcc %o4,%o3,%o1 + bcc Lp4 + addxcc %o2,%o2,%o2 +Ln4: addx %o4,%o4,%o4 + addcc %g1,-1,%g1 + bne Lnlop + subcc %o4,%o3,%o1 + bcc Lp5 + addxcc %o2,%o2,%o2 +Ln5: st %o4,[%o0] + retl + xnor %g0,%o2,%o0 + +Largedivisor: + and %o2,1,%o5 ! %o5 = n0 & 1 + + srl %o2,1,%o2 + sll %o1,31,%g2 + or %g2,%o2,%o2 ! %o2 = lo(n1n0 >> 1) + srl %o1,1,%o1 ! %o1 = hi(n1n0 >> 1) + + and %o3,1,%g2 + srl %o3,1,%g3 ! %g3 = floor(d / 2) + add %g3,%g2,%g3 ! %g3 = ceil(d / 2) + + b LLp1 + addxcc %o2,%o2,%o2 + +LLplop: bcc LLn1 + addxcc %o2,%o2,%o2 +LLp1: addx %o1,%o1,%o1 + subcc %o1,%g3,%o4 + bcc LLn2 + addxcc %o2,%o2,%o2 +LLp2: addx %o1,%o1,%o1 + subcc %o1,%g3,%o4 + bcc LLn3 + addxcc %o2,%o2,%o2 +LLp3: addx %o1,%o1,%o1 + subcc %o1,%g3,%o4 + bcc LLn4 + addxcc %o2,%o2,%o2 +LLp4: addx %o1,%o1,%o1 + addcc %g1,-1,%g1 + bne LLplop + subcc %o1,%g3,%o4 + bcc LLn5 + addxcc %o2,%o2,%o2 +LLp5: add %o1,%o1,%o1 ! << 1 + tst %g2 + bne Oddp + add %o5,%o1,%o1 + st %o1,[%o0] + retl + xnor %g0,%o2,%o0 + +LLnlop: bcc LLp1 + addxcc %o2,%o2,%o2 +LLn1: addx %o4,%o4,%o4 + subcc %o4,%g3,%o1 + bcc LLp2 + addxcc %o2,%o2,%o2 +LLn2: addx %o4,%o4,%o4 + subcc %o4,%g3,%o1 + bcc LLp3 + addxcc %o2,%o2,%o2 +LLn3: addx %o4,%o4,%o4 + subcc %o4,%g3,%o1 + bcc LLp4 + addxcc %o2,%o2,%o2 +LLn4: addx %o4,%o4,%o4 + addcc %g1,-1,%g1 + bne LLnlop + subcc %o4,%g3,%o1 + bcc LLp5 + addxcc %o2,%o2,%o2 +LLn5: add %o4,%o4,%o4 ! << 1 + tst %g2 + bne Oddn + add %o5,%o4,%o4 + st %o4,[%o0] + retl + xnor %g0,%o2,%o0 + +Oddp: xnor %g0,%o2,%o2 + ! q' in %o2. r' in %o1 + addcc %o1,%o2,%o1 + bcc LLp6 + addx %o2,0,%o2 + sub %o1,%o3,%o1 +LLp6: subcc %o1,%o3,%g0 + bcs LLp7 + subx %o2,-1,%o2 + sub %o1,%o3,%o1 +LLp7: st %o1,[%o0] + retl + mov %o2,%o0 + +Oddn: xnor %g0,%o2,%o2 + ! q' in %o2. r' in %o4 + addcc %o4,%o2,%o4 + bcc LLn6 + addx %o2,0,%o2 + sub %o4,%o3,%o4 +LLn6: subcc %o4,%o3,%g0 + bcs LLn7 + subx %o2,-1,%o2 + sub %o4,%o3,%o4 +LLn7: st %o4,[%o0] + retl + mov %o2,%o0 diff --git a/grub-core/lib/libgcrypt/mpi/sparc32v8/Manifest b/grub-core/lib/libgcrypt/mpi/sparc32v8/Manifest new file mode 100644 index 0000000..dc1ce6a --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/sparc32v8/Manifest @@ -0,0 +1,23 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +$names$ iQCVAwUAP+LmbjEAnp832S/7AQKQ2gQAotpCpY9rOJUCdZHbDLXXB9i1UUMraRKbVWimtKq493Y2d2wcqXCK2WaGs1AePK3K6Qk6msxZ0PL5Ho7KgHMkzsZ+wG0EUziiuX0yZRTWNm0r3TYerP6SdWH5GOVdSXn7ckkppk2sVOokfQTy+Tmrnah3+dlYJoujan+fmXWN6Us==DolM diff --git a/grub-core/lib/libgcrypt/mpi/sparc32v8/distfiles b/grub-core/lib/libgcrypt/mpi/sparc32v8/distfiles new file mode 100644 index 0000000..6e9a530 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/sparc32v8/distfiles @@ -0,0 +1,5 @@ +Manifest +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S + diff --git a/grub-core/lib/libgcrypt/mpi/sparc32v8/mpih-mul1.S b/grub-core/lib/libgcrypt/mpi/sparc32v8/mpih-mul1.S new file mode 100644 index 0000000..03fcdda --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/sparc32v8/mpih-mul1.S @@ -0,0 +1,109 @@ +/* SPARC v8 __mpn_mul_1 -- Multiply a limb vector with a single limb and + * store the product in a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + + +! INPUT PARAMETERS +! res_ptr o0 +! s1_ptr o1 +! size o2 +! s2_limb o3 + +#include "sysdep.h" + +.text + .align 8 + .global C_SYMBOL_NAME(_gcry_mpih_mul_1) +C_SYMBOL_NAME(_gcry_mpih_mul_1): + sll %o2,4,%g1 + and %g1,(4-1)<<4,%g1 +#if PIC + mov %o7,%g4 ! Save return address register + call 1f + add %o7,LL-1f,%g3 +1: mov %g4,%o7 ! Restore return address register +#else + sethi %hi(LL),%g3 + or %g3,%lo(LL),%g3 +#endif + jmp %g3+%g1 + ld [%o1+0],%o4 ! 1 +LL: +LL00: add %o0,-4,%o0 + add %o1,-4,%o1 + b Loop00 /* 4, 8, 12, ... */ + orcc %g0,%g0,%g2 +LL01: b Loop01 /* 1, 5, 9, ... */ + orcc %g0,%g0,%g2 + nop + nop +LL10: add %o0,-12,%o0 /* 2, 6, 10, ... */ + add %o1,4,%o1 + b Loop10 + orcc %g0,%g0,%g2 + nop +LL11: add %o0,-8,%o0 /* 3, 7, 11, ... */ + add %o1,-8,%o1 + b Loop11 + orcc %g0,%g0,%g2 + +Loop: addcc %g3,%g2,%g3 ! 1 + ld [%o1+4],%o4 ! 2 + st %g3,[%o0+0] ! 1 + rd %y,%g2 ! 1 +Loop00: umul %o4,%o3,%g3 ! 2 + addxcc %g3,%g2,%g3 ! 2 + ld [%o1+8],%o4 ! 3 + st %g3,[%o0+4] ! 2 + rd %y,%g2 ! 2 +Loop11: umul %o4,%o3,%g3 ! 3 + addxcc %g3,%g2,%g3 ! 3 + ld [%o1+12],%o4 ! 4 + add %o1,16,%o1 + st %g3,[%o0+8] ! 3 + rd %y,%g2 ! 3 +Loop10: umul %o4,%o3,%g3 ! 4 + addxcc %g3,%g2,%g3 ! 4 + ld [%o1+0],%o4 ! 1 + st %g3,[%o0+12] ! 4 + add %o0,16,%o0 + rd %y,%g2 ! 4 + addx %g0,%g2,%g2 +Loop01: addcc %o2,-4,%o2 + bg Loop + umul %o4,%o3,%g3 ! 1 + + addcc %g3,%g2,%g3 ! 4 + st %g3,[%o0+0] ! 4 + rd %y,%g2 ! 4 + + retl + addx %g0,%g2,%o0 + + diff --git a/grub-core/lib/libgcrypt/mpi/sparc32v8/mpih-mul2.S b/grub-core/lib/libgcrypt/mpi/sparc32v8/mpih-mul2.S new file mode 100644 index 0000000..6f5cc43 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/sparc32v8/mpih-mul2.S @@ -0,0 +1,132 @@ +/* SPARC v8 __mpn_addmul_1 -- Multiply a limb vector with a limb and + * add the result to a second limb vector. + * + * Copyright (C) 1992, 1993, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + + +! INPUT PARAMETERS +! res_ptr o0 +! s1_ptr o1 +! size o2 +! s2_limb o3 + +#include "sysdep.h" + +.text + .align 4 + .global C_SYMBOL_NAME(_gcry_mpih_addmul_1) +C_SYMBOL_NAME(_gcry_mpih_addmul_1): + orcc %g0,%g0,%g2 + ld [%o1+0],%o4 ! 1 + + sll %o2,4,%g1 + and %g1,(4-1)<<4,%g1 +#if PIC + mov %o7,%g4 ! Save return address register + call 1f + add %o7,LL-1f,%g3 +1: mov %g4,%o7 ! Restore return address register +#else + sethi %hi(LL),%g3 + or %g3,%lo(LL),%g3 +#endif + jmp %g3+%g1 + nop +LL: +LL00: add %o0,-4,%o0 + b Loop00 /* 4, 8, 12, ... */ + add %o1,-4,%o1 + nop +LL01: b Loop01 /* 1, 5, 9, ... */ + nop + nop + nop +LL10: add %o0,-12,%o0 /* 2, 6, 10, ... */ + b Loop10 + add %o1,4,%o1 + nop +LL11: add %o0,-8,%o0 /* 3, 7, 11, ... */ + b Loop11 + add %o1,-8,%o1 + nop + +1: addcc %g3,%g2,%g3 ! 1 + ld [%o1+4],%o4 ! 2 + rd %y,%g2 ! 1 + addx %g0,%g2,%g2 + ld [%o0+0],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+0] ! 1 +Loop00: umul %o4,%o3,%g3 ! 2 + ld [%o0+4],%g1 ! 2 + addxcc %g3,%g2,%g3 ! 2 + ld [%o1+8],%o4 ! 3 + rd %y,%g2 ! 2 + addx %g0,%g2,%g2 + nop + addcc %g1,%g3,%g3 + st %g3,[%o0+4] ! 2 +Loop11: umul %o4,%o3,%g3 ! 3 + addxcc %g3,%g2,%g3 ! 3 + ld [%o1+12],%o4 ! 4 + rd %y,%g2 ! 3 + add %o1,16,%o1 + addx %g0,%g2,%g2 + ld [%o0+8],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+8] ! 3 +Loop10: umul %o4,%o3,%g3 ! 4 + addxcc %g3,%g2,%g3 ! 4 + ld [%o1+0],%o4 ! 1 + rd %y,%g2 ! 4 + addx %g0,%g2,%g2 + ld [%o0+12],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+12] ! 4 + add %o0,16,%o0 + addx %g0,%g2,%g2 +Loop01: addcc %o2,-4,%o2 + bg 1b + umul %o4,%o3,%g3 ! 1 + + addcc %g3,%g2,%g3 ! 4 + rd %y,%g2 ! 4 + addx %g0,%g2,%g2 + ld [%o0+0],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+0] ! 4 + addx %g0,%g2,%o0 + + retl + nop + + +! umul, ld, addxcc, rd, st + +! umul, ld, addxcc, rd, ld, addcc, st, addx + diff --git a/grub-core/lib/libgcrypt/mpi/sparc32v8/mpih-mul3.S b/grub-core/lib/libgcrypt/mpi/sparc32v8/mpih-mul3.S new file mode 100644 index 0000000..93bb194 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/sparc32v8/mpih-mul3.S @@ -0,0 +1,67 @@ +/* SPARC v8 __mpn_submul_1 -- Multiply a limb vector with a limb and + * subtract the result from a second limb vector. + * + * Copyright (C) 1992, 1993, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + +! INPUT PARAMETERS +! res_ptr o0 +! s1_ptr o1 +! size o2 +! s2_limb o3 + +#include "sysdep.h" + +.text + .align 4 + .global C_SYMBOL_NAME(_gcry_mpih_submul_1) +C_SYMBOL_NAME(_gcry_mpih_submul_1): + sub %g0,%o2,%o2 ! negate ... + sll %o2,2,%o2 ! ... and scale size + sub %o1,%o2,%o1 ! o1 is offset s1_ptr + sub %o0,%o2,%g1 ! g1 is offset res_ptr + + mov 0,%o0 ! clear cy_limb + +Loop: ld [%o1+%o2],%o4 + ld [%g1+%o2],%g2 + umul %o4,%o3,%o5 + rd %y,%g3 + addcc %o5,%o0,%o5 + addx %g3,0,%o0 + subcc %g2,%o5,%g2 + addx %o0,0,%o0 + st %g2,[%g1+%o2] + + addcc %o2,4,%o2 + bne Loop + nop + + retl + nop + + diff --git a/grub-core/lib/libgcrypt/mpi/supersparc/Manifest b/grub-core/lib/libgcrypt/mpi/supersparc/Manifest new file mode 100644 index 0000000..869b97b --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/supersparc/Manifest @@ -0,0 +1,21 @@ +# Manifest - checksums +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +udiv.S +$names$ iQCVAwUAP+LmdjEAnp832S/7AQIrUgQA3YmurZhK7r20DqRvg0gwNe9jMDcFfUY4ZPhW5HkGzMbmrxXtj5Dx50RIPteum72bXE+IhcngljQb/cskiN5Hi9oc2a2CPhyTqVFEeGyF+kJ170GI1pVfFOfzbVG0F4nEwm5lGHgv/nvFsvrjmmAXVW1v/yk5N35wbiLviOFrLOQ==byFc diff --git a/grub-core/lib/libgcrypt/mpi/supersparc/distfiles b/grub-core/lib/libgcrypt/mpi/supersparc/distfiles new file mode 100644 index 0000000..ef7c0a5 --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/supersparc/distfiles @@ -0,0 +1,3 @@ +Manifest +udiv.S + diff --git a/grub-core/lib/libgcrypt/mpi/supersparc/udiv.S b/grub-core/lib/libgcrypt/mpi/supersparc/udiv.S new file mode 100644 index 0000000..79e506a --- /dev/null +++ b/grub-core/lib/libgcrypt/mpi/supersparc/udiv.S @@ -0,0 +1,118 @@ +/* SuperSPARC __udiv_qrnnd division support, used from longlong.h. + * This is for SuperSPARC only, to compensate for its + * semi-functional udiv instruction. + * + * Copyright (C) 1993, 1994, 1996, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + + + +! INPUT PARAMETERS +! rem_ptr i0 +! n1 i1 +! n0 i2 +! d i3 + +#include "sysdep.h" +#undef ret /* Kludge for glibc */ + + .text + .align 8 +LC0: .double 0r4294967296 +LC1: .double 0r2147483648 + + .align 4 + .global C_SYMBOL_NAME(__udiv_qrnnd) +C_SYMBOL_NAME(__udiv_qrnnd): + !#PROLOGUE# 0 + save %sp,-104,%sp + !#PROLOGUE# 1 + st %i1,[%fp-8] + ld [%fp-8],%f10 + sethi %hi(LC0),%o7 + fitod %f10,%f4 + ldd [%o7+%lo(LC0)],%f8 + cmp %i1,0 + bge L248 + mov %i0,%i5 + faddd %f4,%f8,%f4 +L248: + st %i2,[%fp-8] + ld [%fp-8],%f10 + fmuld %f4,%f8,%f6 + cmp %i2,0 + bge L249 + fitod %f10,%f2 + faddd %f2,%f8,%f2 +L249: + st %i3,[%fp-8] + faddd %f6,%f2,%f2 + ld [%fp-8],%f10 + cmp %i3,0 + bge L250 + fitod %f10,%f4 + faddd %f4,%f8,%f4 +L250: + fdivd %f2,%f4,%f2 + sethi %hi(LC1),%o7 + ldd [%o7+%lo(LC1)],%f4 + fcmped %f2,%f4 + nop + fbge,a L251 + fsubd %f2,%f4,%f2 + fdtoi %f2,%f2 + st %f2,[%fp-8] + b L252 + ld [%fp-8],%i4 +L251: + fdtoi %f2,%f2 + st %f2,[%fp-8] + ld [%fp-8],%i4 + sethi %hi(-2147483648),%g2 + xor %i4,%g2,%i4 +L252: + umul %i3,%i4,%g3 + rd %y,%i0 + subcc %i2,%g3,%o7 + subxcc %i1,%i0,%g0 + be L253 + cmp %o7,%i3 + + add %i4,-1,%i0 + add %o7,%i3,%o7 + st %o7,[%i5] + ret + restore +L253: + blu L246 + mov %i4,%i0 + add %i4,1,%i0 + sub %o7,%i3,%o7 +L246: + st %o7,[%i5] + ret + restore + diff --git a/grub-core/lib/libgcrypt/src/ChangeLog-2011 b/grub-core/lib/libgcrypt/src/ChangeLog-2011 new file mode 100644 index 0000000..796fea4 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/ChangeLog-2011 @@ -0,0 +1,2335 @@ +2011-12-01 Werner Koch <wk@g10code.com> + + NB: ChangeLog files are no longer manually maintained. Starting + on December 1st, 2011 we put change information only in the GIT + commit log, and generate a top-level ChangeLog file from logs at + "make dist". See doc/HACKING for details. + +2011-09-08 Werner Koch <wk@g10code.com> + + * gcrypt.h.in [GCRYPT_NO_DEPRECATED]: Exclude gcry_ac structures. + +2011-06-10 Werner Koch <wk@g10code.com> + + * sexp.c (vsexp_sscan): Add new format specifiers 'M' and 'u'. + +2011-05-24 Daiki Ueno <ueno@unixuser.org> + + * cipher.h (pk_operation): New. + (pk_encoding_ctx): Add new fields: op, nbits, flags, verify_cmp, + and verify_arg. + +2011-05-19 Daiki Ueno <ueno@unixuser.org> + + * Makefile.am (gcryptrnd_LDADD): Supply $(GPG_ERROR_LIBS) for + gpg_strerror. + +2011-05-18 Daiki Ueno <ueno@unixuser.org> + + * cipher.h: Remove PUBKEY_FLAG_UNPAD. + +2011-05-11 Daiki Ueno <ueno@unixuser.org> + + * cipher.h (PUBKEY_FLAG_UNPAD): New. + (enum pk_encoding): New. + (struct pk_encoding_ctx): New. + +2011-04-19 Werner Koch <wk@g10code.com> + + * stdmem.c (_gcry_private_malloc_secure, _gcry_private_malloc): + Set ERRNO on failure. + * secmem.c (mb_get_new): Set ERRNO on failure. + (_gcry_secmem_malloc_internal): Ditto. + +2011-04-01 Werner Koch <wk@g10code.com> + + * global.c (gcry_realloc): Divert to gcry_malloc or gcry_free. + +2011-03-09 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (gcry_kdf_algos): New. + (gcry_kdf_derive): New. + * visibility.c (gcry_kdf_derive): New. + * visibility.h, libgcrypt.vers, libgcrypt.def: Add gcry_kdf_derive. + +2011-02-23 Werner Koch <wk@g10code.com> + + * libgcrypt-config.in: Add option --host. + * libgcrypt.m4: Use AC_PROG_TOOL to find the config script. Print + a warning is the config scripts does not match the configure host. + +2011-02-21 Werner Koch <wk@g10code.com> + + * global.c (gcry_check_version): Do not take the patchlevel in + account; it is not well defined. + +2011-02-17 Werner Koch <wk@g10code.com> + + * gcrypt-module.h (gcry_cipher_register, gcry_cipher_unregister) + (gcry_pk_register, gcry_pk_unregister, gcry_md_register) + (gcry_md_unregister): Mark as deprecated by the API; in a future + version the module register feature will be removed. + + * gcrypt.h.in: Attribute all _ac_ functions and types as + deprecated by the API. + + * hwfeatures.c (detect_ia32_gnuc): Fix AES-NI detection. Use AND + instead of SUB for bit testing. + +2011-02-16 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (GCRYCTL_DISABLE_HWF): New. + * global.c (_gcry_vcontrol): Support new control code. + (print_config): Factor list of hwfeatures out to ... + (hwflist): new. + (disabled_hw_features): New. + (global_init): Pass new variable to _gcry_detect_hw_features. + * hwfeatures.c (_gcry_detect_hw_features): Add arg + DISABLED_FEATURES and disable detected features. + +2011-02-11 Werner Koch <wk@g10code.com> + + * g10lib.h (HWF_INTEL_AES): Rename to HWF_INTEL_AESNI. + * hwfeatures.c (detect_ia32_gnuc): Fix setting of this flag. + +2011-02-01 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (gcry_pk_get_curve, gcry_pk_get_param): New. + * libgcrypt.vers (gcry_pk_get_curve, gcry_pk_get_param): Add. + * libgcrypt.def (gcry_pk_get_curve, gcry_pk_get_param): Add. + * visibility.c (gcry_pk_get_curve, gcry_pk_get_param): New. + * cipher-proto.h (pk_extra_spec): Add fields GET_CURVE and + GET_CURVE_PARM. + +2011-01-31 Werner Koch <wk@g10code.com> + + * sexp.c (vsexp_sscan): Allow opaque MPIs in "%m". + +2010-08-27 Werner Koch <wk@g10code.com> + + * g10lib.h (HWF_INTEL_AES): New. + * global.c (print_config): Print new flag. + * hwfeatures.c (detect_ia32_gnuc): Detect this flag. + +2010-08-16 Werner Koch <wk@g10code.com> + + * gcrypt.h.in [!WIN32]: Add INSERT_SYS_SELECT_H autoconf substitute. + +2010-07-09 Werner Koch <wk@g10code.com> + + * gcrypt.h.in [!__GNUC__ && W32]: Typedef ssize_t and pid_t to + help building with MSVC. + +2010-06-24 Werner Koch <wk@g10code.com> + + * gcrypt.h.in [W32]: Include time.h and not sys/time.h. + +2010-04-19 Marcus Brinkmann <marcus@g10code.de> + + * misc.c (write2stderr): Dummy variable to silence gcc warning. + +2010-04-16 Marcus Brinkmann <marcus@g10code.de> + + * sexp.c: (sexp_sscan): Make it variable length, and rename the + old version to ... + (vsexp_sscan): ... this new function. Also swap last two arguments. + (gcry_sexp_create): Remove dummy va_list. + (gcry_sexp_build): Use vsexp_sscan instead of sexp_sscan. + (_gcry_sexp_vbuild): Likewise. + (gcry_sexp_build_array): Remove dummy va_list. + (gcry_sexp_sscan): Likewise. + +2010-04-12 Brad Hards <bradh@frogmouth.net> (wk) + + Spelling fixes. + +2010-03-15 Werner Koch <wk@g10code.com> + + * gcrypt.h.in: Add autoconf template to set generated file to + read-only in an Emacs buffer. + +2010-01-21 Werner Koch <wk@g10code.com> + + * Makefile.am (arch_gpg_error_cflags, arch_gpg_error_libs): New. + (dumpsexp_CFLAGS): New. + (dumpsexp_LDADD): Add arch_gpg_error_libs. + (hmac256_CFLAGS, hmac256_LDADD): Add the arch variables. + (libgcrypt_la_DEPENDENCIES): Add libcompat. + * secmem.c (lock_pool): Mark unused args. + * global.c (do_malloc, gcry_realloc, gcry_free, gcry_calloc) + (gcry_calloc_secure, gcry_xcalloc, gcry_xcalloc_secure): Use + gpg_err_set_errno. + (_gcry_vcontrol): Call _gcry_compat_identification. + * hmac256.c [__MINGW32CE__]: Include gpg-error.h. + (_gcry_hmac256_file): Use gpg_err_set_errno. + (gpg_err_set_errno) [!GPG_ERR_INLINE]: Add macro. + * g10lib.h: Include libcompat.h. + +2010-01-05 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (GCRY_PK_ECDH): New. + +2009-12-08 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (GCRY_CIPHER_MODE_AESWRAP): New. + +2009-12-08 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (LTRCCOMPILE): Refactor with ... + (RCCOMPILE): ... this new macro. Add $(libgcrypt_la_CPPFLAGS). + (SUFFIXES): Add .lo. + (.rc.o): Change to ... + (.rc.lo): ... this implicit rule. + (gcrypt_res_ldflag): Removed. + (gcrypt_res): Use libtool object file name here. + (libgcrypt_la_LDFLAGS): Remove gcrypt_res_ldflag usage. + (libgcrypt_la_LIBADD): Add gcrypt_res. + +2009-11-29 Werner Koch <wk@g10code.com> + + * hwfeatures.c (detect_ia32_gnuc): Repalce "=r" by "+r" so that + HAS-CPUDID is always initialized. Thanks to Ben Hutchings for + pointing out this problem. + +2009-08-05 Werner Koch <wk@g10code.com> + + * ath.h: Include sys/msg.h. + +2009-07-02 Werner Koch <wk@g10code.com> + + * fips.c (_gcry_initialize_fips_mode): Do not use FIPS mode if + /proc/.../fips_enabled has insufficient permissions. + + * dumpsexp.c (main): Fix handling multiple files. + (parse_and_print): Implement hex and octal escaping. + + * sexp.c (unquote_string): Remove superfluous clearing of ESC. + * dumpsexp.c (parse_and_print): Add missing break. + (main): Fix return value. + Reported by Fabian Keil. + +2009-02-16 Werner Koch <wk@g10code.com> + + * ath.h [HAVE_SYS_SELECT_H]: Include <sys/select.h> for fd_set. + [!HAVE_SYS_SELECT_H]: Include <sys/time.h>. Move inclusion of + config.h to the top. The actual configure check was already + there. + + * sexp.c: Remove memory.h. + * mpi.h: Remove memory.h. Add string.h. + +2009-02-02 Werner Koch <wk@g10code.com> + + * ath.h: Include sys/time.h. Fixes bug#993. + +2009-01-22 Werner Koch <wk@g10code.com> + + * fips.c (_gcry_initialize_fips_mode): Remove superfluous const + from static string. Reported by Albert Chin. + * hmac256.c (selftest): Ditto and change to unsigned char. + +2008-12-10 Werner Koch <wk@g10code.com> + + * hmac256.c (finalize): Fix for big endian hosts. + +2008-12-05 Werner Koch <wk@g10code.com> + + * global.c (gcry_free): Save and restore ERRNO if set. + +2008-11-24 Werner Koch <wk@g10code.com> + + * sexp.c (get_internal_buffer): New. + (sexp_sscan): Add format character S. + * cipher-proto.h (pk_ext_generate_t): Add field EXTRAINFO changed + all implementors. + + * cipher-proto.h (pk_ext_generate_t): Simplify. + (pk_get_param): New. + (pk_extra_spec_t): Add field GET_PARAM. + * cipher.h (PUBKEY_FLAG_TRANSIENT_KEY): Remove. + (_gcry_pubkey_extraspec_elg): New. + +2008-11-05 Werner Koch <wk@g10code.com> + + * cipher.h (CIPHER_INFO_NO_WEAK_KEY): New. + + * cipher-proto.h (cipher_set_extra_info_t): New. + (cipher_extra_spec): Add field SET_EXTRA_INFO. + +2008-10-30 Werner Koch <wk@g10code.com> + + * g10lib.h (GCC_ATTR_FORMAT_ARG): New. + (_gcry_gettext): Use it. + +2008-10-24 Werner Koch <wk@g10code.com> + + * global.c (inactive_fips_mode): Move to fips.c. + (gcry_set_allocation_handler): Factor code out to ... + * fips.c (_gcry_inactivate_fips_mode): New. + (_gcry_is_fips_mode_inactive): New. + +2008-09-29 Werner Koch <wk@g10code.com> + + * gcrypt-module.h (GCRY_MODULE_ID_USER, GCRY_MODULE_ID_USER_LAST): + New. + * module.c (MODULE_ID_USER, MODULE_ID_USER_LAST): Define using new + macros. + +2008-09-20 Werner Koch <wk@g10code.com> + + * hmac256.c (finalize) [WORDS_BIGENDIAN]: Fix sigbus problem. + +2008-09-18 Werner Koch <wk@g10code.com> + + * cipher-proto.h (pk_ext_generate_t): Add args QBITS, NAME, DOMAIN. + + * fips.c (fips_new_state): Allow Error => Error transition. + +2008-09-18 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (gcry_fips_mode_active): New. + + * secmem.c (_gcry_secmem_init): Factor most code out to .. + (secmem_init): .. new. + (DEFAULT_POOL_SIZE): Rename to MINIMUM_POOL_SIZE. + (STANDARD_POOL_SIZE): New. + (_gcry_secmem_malloc_internal): Don't abort if the pool is not + initialized but try to out intialize it first and only then print + an error message and return NULL. If the pool is not locked while + in FIPS mode, return NULL. + + * fips.c (FIPS_FORCE_FILE): New constant. Change the file name to + "/etc/gcrypt/fips_enabled". + (enforced_fips_mode): New. + (_gcry_initialize_fips_mode): Set that flag. + (_gcry_enforced_fips_mode): New. + * global.c (inactive_fips_mode): New. + (_gcry_vcontrol): Take that flag in account for GCRYCTL_FIPS_MODE_P. + (gcry_set_allocation_handler): Take care of the enforced fips mdoe + flag. + (get_no_secure_memory): New. + (do_malloc, gcry_is_secure): Use it. + +2008-09-16 Werner Koch <wk@g10code.com> + + * global.c (print_config): Use y/n for fips mode. + + * fips.c (fips_new_state): Allow transition to Error and + Fatal-error from Init. + +2008-09-15 Werner Koch <wk@g10code.com> + + * fips.c [HAVE_SYSLOG]: Include syslog.h. + (_gcry_initialize_fips_mode, lock_fsm, unlock_fsm) + (_gcry_fips_signal_error, fips_new_state) + (_gcry_fips_noreturn) [HAVE_SYSLOG]: Also log via syslog. + (check_binary_integrity) [HAVE_SYSLOG]: Log failure. + * global.h [HAVE_SYSLOG]: Include syslog.h. + (_gcry_global_is_operational) [HAVE_SYSLOG]: Print warning. + + * global.c (_gcry_vcontrol): Use GCRYCTL_INITIALIZATION_FINISHED + to run power-up tests. Add unpublished control commands 58-60. + + * global.c (_gcry_global_is_operational): New. + * g10lib.h (fips_is_operational): Change to call this function. + +2008-09-12 Werner Koch <wk@g10code.com> + + * fips.c (_gcry_fips_run_selftests): Add arg EXTENDED. + (run_cipher_selftests, run_digest_selftests, run_hmac_selftests) + (run_pubkey_selftests): Ditto. + * cipher-proto.h (selftest_func_t): Add arg EXTENDED + +2008-09-11 Werner Koch <wk@g10code.com> + + * fips.c: Include string.h. + (loxtoi_1, loxtoi_2, loxdigit_p): New. + (check_binary_integrity): Change the format of the expected file. + + * fips.c (_gcry_fips_run_selftests): Run random tests before the + pubkey tests. + +2008-09-05 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (GCYRCTL_SELFTEST): New. + * global.c (_gcry_vcontrol): Implement. + * fips.c (_gcry_fips_run_selftests): Do state transitions only if + in fips mode. Return an error code. + +2008-09-01 Werner Koch <wk@g10code.com> + + * stdmem.c: Re-indented. + +2008-08-29 Werner Koch <wk@g10code.com> + + * fips.c (_gcry_initialize_fips_mode): Changed /proc file to test + for FIPS mode. + + * cipher-proto.h (pk_compute_keygrip_t): New. + (pk_extra_spec): Add field comp_keygrip. + +2008-08-28 Werner Koch <wk@g10code.com> + + * hwfeatures.c (_gcry_detect_hw_features): Disable hardware + detection in FIPS mode. + +2008-08-27 Werner Koch <wk@g10code.com> + + * global.c (_gcry_vcontrol): Allow running selftests from error + state. + (gcry_set_outofcore_handler): Only print a warning if used in FIPS + mode. + (gcry_xmalloc, gcry_xrealloc, gcry_xmalloc_secure, gcry_xstrdup): + Ignore an outofcore handler in FIPS mode. + + * fips.c (_gcry_fips_test_error_or_operational): New. + (fips_new_state): Allow transition from error into selftest. + Disallow error to init. + +2008-08-26 Werner Koch <wk@g10code.com> + + * fips.c (fips_new_state): Print state transitions only at + verbosity level of 2. + (reporter): Likewise. + + * cipher-proto.h (pk_ext_generate_t): New. + (pk_extra_spec): Add member ext_generate. + * cipher.h (PUBKEY_FLAG_TRANSIENT_KEY): New. + +2008-08-22 Werner Koch <wk@g10code.com> + + * hmac256.c (_gcry_hmac256_file): New. + (main): New option --binary. + * fips.c (check_binary_integrity): New. + (_gcry_fips_run_selftests): Run it. + + * global.c (_gcry_vcontrol) <GCRYCTL_UPDATE_RANDOM_SEED_FILE>: + Check for fips operational state. + (_gcry_vcontrol) <GCRYCTL_FAST_POLL>: Ditt. + +2008-08-21 Werner Koch <wk@g10code.com> + + * misc.c (_gcry_log_printhex): New. + +2008-08-20 Werner Koch <wk@g10code.com> + + * g10lib.h (gcry_assert): New. use this at almost all places + where we used a plain assert. + * misc.c (_gcry_assert_failed): New. + (_gcry_bug): Also use func variant for ISO-C99. + +2008-08-19 Werner Koch <wk@g10code.com> + + * visibility.c, visibility.h (gcry_mpi_lshift): New. + * libgcrypt.vers, libgcrypt.def, gcrypt.h.in: Ditto. + +2008-08-15 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (gcry_cipher_setkey): Replace macro by function. + (gcry_cipher_setiv): Ditto. + (gcry_cipher_setctr): Ditto. + * visibility.c (gcry_cipher_setkey, gcry_cipher_setiv) + (gcry_cipher_setctr): New. + * visibility.h (gcry_cipher_setkey, gcry_cipher_setiv) + (gcry_cipher_setctr): New. + * libgcrypt.vers (gcry_cipher_setkey, gcry_cipher_setiv) + (gcry_cipher_setctr): New. + * libgcrypt.def (gcry_cipher_setkey, gcry_cipher_setiv) + (gcry_cipher_setctr): New. + + * hmac256.h, hmac256.c: New. + * Makefile.am (hmac256_SOURCES): New. + * Makefile.am (bin_PROGRAMS): Add hmac256. + + * gcrypt.h.in (struct gcry_thread_cbs): Change type of OPTION to + unsigned int. Although this is a type change it does not make a + difference. + * ath.c (ath_install): Take the version of the option field in + account. + + * visibility.c (gcry_pk_encrypt, gcry_pk_decrypt, gcry_pk_sign) + (gcry_pk_verify, gcry_pk_testkey, gcry_pk_genkey) + (gcry_pk_get_nbits, gcry_pk_get_keygrip) + (gcry_md_open, gcry_md_copy, gcry_md_enable) + (gcry_md_write, md_final, gcry_md_ctl, gcry_md_setkey) + (gcry_md_hash_buffer, gcry_md_get_algo, gcry_md_info) + (gcry_md_is_enabled) + (gcry_cipher_open, gcry_cipher_encrypt) + (gcry_cipher_decrypt, gcry_cipher_ctl) + (gcry_cipher_algo_info): Check whether the library is operational. + + * cipher-proto.h: New. + * cipher.h: Include cipher-proto.h. + * visibility.h: Remove duplicate macro definitions. Remove + gcry_cipher_register, gcry_md_register, gcry_pk_register macros. + * visibility.c: Include cipher-proto.h. + (gcry_cipher_register): Pass dummy extra args to the internal + register function. + (gcry_md_register, gcry_pk_register): Ditto. + * g10lib.h (struct gcry_module): Add field EXTRASPEC. + * module.c (_gcry_module_add): Add arg EXTRASPEC. Changed all + callers to pass NULL. + + * fips.c: New. + * gcrypt.h.in (GCRYCTL_FIPS_MODE_P): New. + * global.c (global_init): Call fips initialization. + (_gcry_vcontrol): Add GCRYCTL_FIPS_MODE_P code. + (print_config): Add config item fips-mode. + (gcry_set_allocation_handler): Do not allow the use of custom + allocation handlers. + (gcry_set_outofcore_handler): Ditto. + (_gcry_get_debug_flag): Do not return any debug flags in fips mode. + * misc.c (_gcry_logv): Signal fips error on BUG or FATAL. + (_gcry_fatal_error): Ditto. + +2008-07-05 Werner Koch <wk@g10code.com> + + * Makefile.am: Include librandom.la. + +2008-04-18 Werner Koch <wk@g10code.com> + + * missing-string.c (vasprintf): Remove. It is not used. Reported + by Simon Josefsson. + +2008-03-11 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (gcry_ac_em_t, gcry_ac_scheme_t): Remove trailing + comma for full C-89 compatibility. + +2008-01-21 Marcus Brinkmann <marcus@g10code.de> + + * hwfeatures.c (detect_ia32_gnuc): Fix inline asm. + +2007-12-11 Werner Koch <wk@g10code.com> + + * visibility.c (gcry_md_hash_buffer): Don't use return vor a void + function. Hey, why does gcc not complain about this? + (gcry_ac_io_init_va): Ditto. + +2007-12-05 Werner Koch <wk@g10code.com> + + * hwfeatures.c (detect_ia32_gnuc): Depend on ENABLE_PADLOCK_SUPPORT. + +2007-12-03 Werner Koch <wk@g10code.com> + + * misc.c (_gcry_logv): Use abort for error levels fatal and bug as + this is more approriate for a library. Terminate the secmem + before doing so. + (_gcry_fatal_error): Terminate secmem before abort. + * secmem.c (_gcry_secmem_malloc_internal): Use log_bug instead of + exit. + +2007-11-29 Werner Koch <wk@g10code.com> + + * hwfeatures.c (detect_ia32_gnuc): Detect Padlock engine. + +2007-11-13 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (_GCRY_GCC_ATTR_MALLOC): Fixed gcc version check. + Reported by Gabriele Monti. + +2007-10-31 Werner Koch <wk@g10code.com> + + * global.c (gcry_control): Factor most code out to .. + (_gcry_vcontrol): .. new. + * sexp.c (_gcry_sexp_vbuild): New. + * mpi.h (_gcry_mpi_set, _gcry_mpi_set_ui, _gcry_mpi_invm): Remove + prototypes as they are already in gcrypt.h. + +2007-10-30 Werner Koch <wk@g10code.com> + + * sexp.c (gcry_sexp_nth_string): Replace by _gcry_sexp_nth_string. + + * visibility.h, visibility.c: New. + * g10lib.h: Include visibility.h instead of gcrypt.h. + * globals.c (_gcry_malloc): Rename to .. + (do_malloc): .. this. + + * hwfeatures.c: New. + * global.c (global_init): Detect features. + (print_config): Print them. + +2007-08-22 Werner Koch <wk@g10code.com> + + * dumpsexp.c: New. + * Makefile.am (bin_PROGRAMS): Install it. + + * getrandom.c (print_version): Use new standard license line. + * gcryptrnd.c (print_version): Ditto. + +2007-06-06 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (GCRY_THREAD_OPTION_PTH_IMPL): Factror network + related code out so that the prototypes can be adjusted for W32. + (_GCRY_THREAD_OPTION_PTH_IMPL_NET): New. + +2007-05-09 Werner Koch <wk@g10code.com> + + * libgcrypt.m4: Print found version on success. + +2007-05-09 Marcus Brinkmann <marcus@g10code.de> + + * gcrypt.h.in (gcry_ac_io_t): Add name for anonymous union, and mark + all members as internal (actually: deprecated). + +2007-05-04 Werner Koch <wk@g10code.com> + + * Makefile.am (.rc.lo): New to replace gmake specific suffix rule. + +2007-05-03 Werner Koch <wk@g10code.com> + + * libgcrypt.def (gcry_sexp_nth_string): New. + * Makefile.am (EXTRA_DIST): Add libgcrypt.def. + +2007-05-02 Werner Koch <wk@g10code.com> + + * global.c (print_config): Print ciphers, digests and pubkeys. + +2007-05-02 David Shaw <dshaw@jabberwocky.com> + + * cipher.h, gcrypt.h.in: Add Camellia. + +2007-04-30 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (GCRYCTL_PRINT_CONFIG): New. + (GCRYCTL_SET_RNDEGD_SOCKET): New. + * global.c (gcry_control): Add GCRYCTL_PRINT_CONFIG and + GCRYCTL_SET_RNDEGD_SOCKET. + (print_config): New. + * misc.c (_gcry_log_info_with_dummy_fp): New. + +2007-04-18 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (gcry_sexp_nth_string): New. + + * sexp.c (gcry_sexp_nth_data): Factored code out to ... + (sexp_nth_data): ... new. + (gcry_sexp_nth_string): New. + (gcry_sexp_nth_mpi): Reimplemented in terms of sexp_ntd_data. + +2007-04-16 Werner Koch <wk@g10code.com> + + * secmem.c (init_pool): Use sysconf() if available to determine + page size. + +2007-03-22 Werner Koch <wk@g10code.com> + + * mpi.h (mpi_mod): New. + (mpi_new, mpi_snew): New. + + * gcrypt.h.in: Add GCRY_PK_ECDSA. + +2007-03-16 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (GCRY_THREAD_OPTION_PTHREAD_IMPL): Fixed typo + introduced by me on 2006-10-23. + +2007-02-22 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (gcry_ac_id_to_name, gcry_ac_name_to_id): Mark as + deprecated. + + * libgcrypt.def (gcry_fast_random_poll): Removed - it is a macro. + (gcry_cipher_register, gcry_cipher_unregister): New. + (gcry_md_register, gcry_md_unregister): New. + (gcry_pk_register, gcry_pk_unregister): New. + (gcry_ac_data_from_sexp, gcry_ac_data_to_sexp): New. + (gcry_ac_io_init, gcry_ac_io_init_va): New. + (gcry_ac_data_encrypt_scheme, gcry_ac_data_decrypt_scheme): New. + (gcry_ac_data_sign_scheme, gcry_ac_data_verify_scheme): New. + + * missing-string.c: Include stdio.h for the vsprintf prototype. + + * ath.h (struct ath_ops) [_WIN32]: Use int instead of socklen_t. + +2007-02-21 Werner Koch <wk@g10code.com> + + * libgcrypt.def (gcry_create_nonce, gcry_fast_random_poll) + (gcry_md_debug): New. + + * libgcrypt-config.in: Remove duplicates from --cflags and --libs. + Print a error for option --thread. + + * gcrypt.h.in (gcry_sexp_sprint): Change BUFFER from char* to void*. + (gcry_md_ctl): Change BUFFER from unsigned char* to void*. + (gcry_md_debug): New. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Change buffer args to + void*. + (gcry_randomize): Change BUFFER to void. + (gcry_create_nonce): Ditto. + + * libgcrypt.vers (gcry_md_debug): New. + + * sexp.c (gcry_sexp_sprint): Ditto. + (normalize): Make P unsigned. + (gcry_sexp_nth_data): Cast return value to char*. + (sexp_sscan): Fix sign/unsigned conflicts. + (whitespacep): Change P to char*. + (unquote_string): Change STRING to char*. + (convert_to_hex): Change DEST to char*. + (convert_to_string): Change DEST and P to char*. + (convert_to_token): Chnage DEST to char*. + (gcry_sexp_canon_len): Change DISPHINT to unsigned char*. + + * gcrypt-module.h (gcry_pk_spec): Made ALIASES a const. + (gcry_md_write_t): Changed BUF to a const void*. + +2007-02-12 Werner Koch <wk@g10code.com> + + * gcrypt.h.in: Include stdlib.h for the sake fo the trheading + macros. Suggested by Andreas Metzler. + + * secmem.c (ptr_into_pool_p): New. + (_gcry_private_is_secure): Implement in terms of new function. + (BLOCK_VALID): Removed. Replaced all users by new function. + +2007-01-31 Werner Koch <wk@g10code.com> + + * secmem.c (_gcry_private_is_secure): Fixed severe implementation + flaw. Might be the reason for some of the more obscure bugs. + (MB_WIPE_OUT): Use wipememory2. + +2006-10-23 Werner Koch <wk@g10code.com> + + * gcrypt.h.in (GCRY_THREAD_OPTION_PTHREAD_IMPL): Add some cast for + use by C-doubleplus. In general I don't like this but due to + public demand I give up ;-) + +2006-10-19 Werner Koch <wk@g10code.com> + + * global.c (gcry_control) <GCRYCTL_INIT_SECMEM>: Return an error + if the memory could not be locked. + * secmem.c (not_locked): New. + (_gcry_secmem_get_flags): Return that flag. + * secmem.h (GCRY_SECMEM_FLAG_NOT_LOCKED): New. + +2006-10-05 Werner Koch <wk@g10code.com> + + * module.c (_gcry_module_id_new): Don't assign modules in the range + the range of 1024..4096. + * gcrypt.h (GCRY_MD_USER, GCRY_MD_USER_LAST): New + (GCRY_PK_USER, GCRY_PK_USER_LAST): New. + (GCRY_CIPHER_USER, GCRY_CIPHER_USER_LAST): New. + +2006-10-12 Marcus Brinkmann <marcus@g10code.de> + + * gcrypt.h.in: Replace socklen_t with gcry_socklen_t. + +2006-10-11 Marcus Brinkmann <marcus@g10code.de> + + * gcrypt.h.in: Replace version by @VERSION@. + +2006-10-10 Marcus Brinkmann <marcus@g10code.de> + + * gcrypt.h: Add fallback type for socklen_t. Move to ... + * gcrypt.h.in: ... this file. + * Makefile.am (EXTRA_DIST): Add gcrypt.h.in. + +2006-09-04 Werner Koch <wk@g10code.com> + + * gcrypt.h: Removed some trailing comma in enums. + +2006-08-29 Werner Koch <wk@g10code.com> + + * global.c (gcry_xrealloc): Pass secure flag to outofcore handler. + + * gcrypt.h (GCRY_CIPHER_SEED): New. + +2006-08-21 Werner Koch <wk@g10code.com> + + * gcrypt.h (GCRYCTL_FAKED_RANDOM_P): New. + +2006-07-29 Marcus Brinkmann <marcus@g10code.de> + + * secmem.c (init_pool): Close FD after establishing the mapping. + +2006-07-12 Marcus Brinkmann <marcus@g10code.de> + + * ath.c (ath_mutex_destroy): Microoptimize destruction of unused + statitically initialized mutexes. Suggested by Victor Stinner + <victor.stinner@inl.fr>. + + * gcrypt.h (GCRY_THREAD_OPTION_PTHREAD_IMPL, + (GCRY_THREAD_OPTION_PTH_IMPL): Add missing initializers to + suppress gcc warning. + Submitted by Victor Stinner <victor.stinner@inl.fr>. + +2006-07-04 Marcus Brinkmann <marcus@g10code.de> + + * ath.c: Avoid warning about double defined type byte and other + hacks to let it build for W32 (backported from LIBGCRYPT-1-2-BRANCH). + * ath.h, gcrypt.h, tests/benchmark.c, src/types.h: Likewise. + + * gcrypt.h: Revert last change, and instead: + [_WIN32 || __WIN32__]: Do not include <sys/socket.h>, but + <winsock2.h> and <ws2tcpip.h>. + Suggested by Simon Josefsson <jas@extundo.com>. + + * Makefile.am (install-data-local, uninstall-local, %.lo, + (install-def-file, uninstall-def-file): New targets. + (LTRCCOMPILE, gcrypt_res, gcrypt_res_ldflag, no_undefined, + (export_symbols, gcrypt_deps): New variables. + * versioninfo.rc.in: New file. + * libgcrypt.def: New file from ../w32-dll/libgcrypt.def. + + * gcrypt.h [!HAVE_SYS_SOCKET_H]: Do not include sys/socket.h, but + the appropriate windows socket header. + +2006-06-21 Werner Koch <wk@g10code.com> + + * global.c (gcry_xcalloc, gcry_xcalloc_secure): Made safe against + integer overflow. + + * sexp.c (make_space): Return an error on out of core. + (sexp_sscan): Remove all xmalloc style calls and return proper + error codes on allocation failures. + (gcry_sexp_find_token): Ditto. + (gcry_sexp_nth): + + * sexp.c (gcry_sexp_find_token): Re-indented and removed a cruft + "while(level);" which fortunately had no effect. + +2006-04-28 Werner Koch <wk@g10code.com> + + * gcrypt.h (GCRY_MD_SHA224): Change value from 306 to 11 to match + the use in OpenPGP. There has been no release yet, so we can + safely do it. + +2006-04-22 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h (gcry_ctl_cmds): New commands: + GCRYCTL_SET_RANDOM_DAEMON_SOCKET, GCRYCTL_USE_RANDOM_DAEMON. + * global.c (gcry_control): Handle new commands, calling + _gcry_set_random_daemon_socket() and _gcry_use_random_daemon(). + +2006-04-18 Werner Koch <wk@g10code.com> + + * gcrypt.h (GCRY_PK_USAGE_CERT, GCRY_PK_USAGE_AUTH) + (GCRY_PK_USAGE_UNKN): New. + +2006-04-01 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h (gcry_ac_eme_pkcs_v1_5): Removed members: key, handle; + added member: key_size. + + * secmem.c (MB_FLAG_ACTIVE): Write braces around MB_FLAG_ACTIVE + definition. + +2006-03-15 Werner Koch <wk@g10code.com> + + * getrandom.c: New. + +2006-03-14 Werner Koch <wk@g10code.com> + + * gcryptrnd.c: New. + +2006-03-10 Werner Koch <wk@g10code.com> + + * gcrypt.h: Add GCRY_MD_SHA224. + +2005-11-02 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h: Update comments for functions: gcry_cipher_algo_name, + gcry_pk_algo_name. + +2005-10-31 Moritz Schulte <moritz@g10code.com> + + * global.c: Added documentation. + +2005-10-16 Moritz Schulte <moritz@g10code.com> + + * global.c (global_init): Use gcry_error_t instead of + gcry_err_code_t; use goto instead of if constructs. + + * stdmem.c: Inserted description of the layered memory management + in Libgcrypt. + + * g10lib.h: Removed G10_I18N_H related check; it seems to be a + GnuPG relict (Libgcrypt does not define this symbol anywhere). + (FLAG_MODULE_DISABLED): Don't forget parantheses around shifted + value. + + Removed GCC_ATTR_PURE macro definitions, since gcrypt.h does + already contain such a macro named _GCRY_GCC_ATTR_PURE, which we + can use here as well. + + Likewise for GCC_ATTR_MALLOC and _GCRY_GCC_ATTR_MALLOC. + + * stdmem.h: Use _GCRY_GCC_ATTR_MALLOC instead of GCC_ATTR_MALLOC. + * secmem.h: Likewise. + +2005-10-09 Moritz Schulte <moritz@g10code.com> + + * global.c (gcry_control): Call global_init() after passing thread + cbs to ath. global_init() MUST to be called AFTER passing the cbs + to ath and BEFORE calling library functions, which make use of + ath. This change combines cbs installing with ath initialization + and thus removes the need to call other library initialization + functions inbetween like e.g. gcry_check_version(). + +2005-10-01 Moritz Schulte <moritz@g10code.com> + + * ath.c: Assign copyright to FSF. + * ath.h: Likewise. + +2005-06-25 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (pkgconfigdir, pkgconfig_DATA): Removed variables. + * libgcrypt.pc.in: Removed file - we do not want to support a + second, foreign configuration system. + +2005-06-17 Moritz Schulte <moritz@g10code.com> + + * global.c (gcry_xstrdup): Removed superfluous strcpy call. + +2005-04-22 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (pkgconfigdir, pkgconfig_DATA): New; support for + pkgconfig provided by Albert Chin. + * libgcrypt.pc.in (Cflags): New file. + +2005-04-16 Moritz Schulte <moritz@g10code.com> + + * g10lib.h (_gcry_ac_init): Declare. + * global.c (global_init): Call _gcry_ac_init; don't forget to set + err. + +2005-04-14 Werner Koch <wk@g10code.com> + + * sexp.c (whitespacep): New. + (sexp_sscan): Replaced isdigit and isspace by whitespacep and + digitp. + +2005-04-11 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h (gcry_md_algos): Added: GCRY_MD_WHIRLPOOL. + * cipher.h (_gcry_digest_spec_whirlpool): Declare. + +2005-03-30 Moritz Schulte <moritz@g10code.com> + + * libgcrypt.vers: Added: gcry_ac_io_init, gry_ac_io_init_va. + + * gcrypt.h (gcry_ac_data_read_cb_t, gcry_ac_data_write_cb_t, + gcry_ac_io_mode_t, gcry_ac_io_type_t, gcry_ac_io_t): New types. + (gcry_ac_io_init_va): Declare function. + (gcry_ac_data_encode, gcry_ac_data_decode, + gcry_ac_data_encrypt_scheme, gcry_ac_data_decrypt_scheme, + gcry_ac_data_sign_scheme, gcry_ac_data_verify_scheme): Use + gcry_ac_io_type_t objects instead of memory strings directly. + +2005-03-03 Moritz Schulte <moritz@g10code.com> + + * libgcrypt.vers: Added: gcry_ac_data_to_sexp() and + gcry_ac_data_from_sexp(). + +2005-02-22 Werner Koch <wk@g10code.com> + + * global.c (_gcry_malloc): Make sure ERRNO is set if we return + NULL. Remove unneeded initialization of M to allow the compiler + to catch errors. + (gcry_realloc): Make sure ERRNO is set if we return NULL> + +2005-02-13 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h: Declare new functions: gcry_ac_data_encrypt_scheme, + gcry_ac_data_decrypt_scheme, gcry_ac_data_sign_scheme, + gcry_ac_data_verify_scheme, gcry_ac_data_encode, + gcry_ac_data_decode, gcry_ac_data_to_sexp, gcry_ac_data_from_sexp. + New types: gcry_ac_emsa_pkcs_v1_5_t, gcry_ac_ssa_pkcs_v1_5_t, + gcry_md_algo_t. + New enumeration lists: gcry_ac_scheme_t, gcry_ac_em_t. + * libgcrypt.vers: Added new ac functions. + * g10lib.h: Declare function: _gcry_pk_get_elements. + * mpi.h (mpi_get_ui): New macro. + Declare function: _gcry_mpi_get_ui. + +2004-11-09 Werner Koch <wk@g10code.com> + + * gcrypt.h: Removed 3 trailing commas from enums. Noted by Heiko + Stamer. + +2004-09-21 Werner Koch <wk@g10code.de> + + * sexp.c (sexp_sscan): Removed C++ style comments. Noted by Yoann + Vandoorselaere. + +2004-08-23 Moritz Schulte <moritz@g10code.com> + + * global.c: Do not include <assert.h>. + * sexp.c: Likewise. + * module.c: Likewise. + * misc.c: Likewise. + +2004-08-18 Moritz Schulte <moritz@g10code.com> + + * secmem.c (_gcry_secmem_init): Try to lock pool into core not + only when running with root privileges. + +2004-08-16 Werner Koch <wk@g10code.de> + + * secmem.h (_gcry_secmem_set_flags,_gcry_secmem_get_flags): + Removed __pure__. + (GCRY_SECMEM_FLAG_NO_WARNING): Put macro value into parens. + + * secmem.c (_gcry_secmem_init): Defer printing of the warning. + +2004-08-10 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h: Include <sys/time.h>, thanks to Simon Josefsson. + +2004-05-07 Werner Koch <wk@gnupg.org> + + * gcrypt.h: Added GCRYCTL_FAST_POLL. + (gcry_fast_random_poll): New. + * global.c (gcry_control) <INITIALIZATION_FINISHED>: Do only basic + random subsystem init. + (gcry_control) <FAST_POLL>: New. + +2004-04-22 Marcus Brinkmann <marcus@g10code.de> + + * libgcrypt.m4: Quote first argument to AC_DEFUN. + +2004-04-15 Werner Koch <wk@gnupg.org> + + * secmem.c (_gcry_secmem_malloc_internal): Removed old extra info + error output. + (_gcry_secmem_term): Use wipememory2 here. + + * misc.c (_gcry_burn_stack): Use wipememory to avoid optimizations. + + * string.c: Removed. Was never used. + * global.c (gcry_strdup): Replaced by the version from string.c + (gcry_xstrdup): Rewritten. + * gcrypt.h: Removed duplicate prototype for gcry_strdup. + +2004-03-29 Werner Koch <wk@gnupg.org> + + * secmem.c (_gcry_secmem_realloc): Fixed double unlock; bug + manifested itself due to the more rigorous checking in the changed + ath.h + + * libgcrypt-config.in (Options): Ignore the obsolete --threads + option for now. + +2004-03-17 Marcus Brinkmann <marcus@g10code.de> + + * libgcrypt-config.in (includedir, libdir): Quote'em. Use + $gpg_error_cflags and $gpg_error_libs. Fix construction of + $includes. + +2004-03-14 Marcus Brinkmann <marcus@g10code.de> + + * libgcrypt-config.in (includedir, libdir): New variables. For + --cflags, don't test $cflags. Also check against /include for the + GNU/Hurd. Don't overwrite but extend $cflags_final. Likewise for + --libs. + +2004-03-10 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (ltlib_libgcrypt_pthread, ltlib_libgcrypt_pth): Removed. + (lib_LTLIBRARIES): Remove those variables from here. + (libgcrypt_pthread_la_SOURCES, libgcrypt_pthread_la_LDFLAGS, + (libgcrypt_pthread_la_DEPENDENCIES, libgcrypt_pthread_la_LIBADD, + (libgcrypt_pth_la_SOURCES, libgcrypt_pth_la_LDFLAGS, + (libgcrypt_pth_la_DEPENDENCIES, libgcrypt_pth_la_LIBADD, + (noinst_LTLIBRARIES): Removed. + (libgcrypt_real_la_SOURCES): Merge with ... + (libgcrypt_la_SOURCES): ... likewise. + (libgcrypt_real_la_DEPENDENCIES): Merge with ... + (libgcrypt_la_DEPENDENCIES): ... this. + (libgcrypt_real_la_LIBADD): Merge with ... + (libgcrypt_la_LIBADD): ... this. + * libgcrypt-config.in (libs_pthread, libs_pth, cflags_pth) + (cflags_pthread, thread_module, thread_modules): Removed. + (Options): Remove --thread option from help output. If the option + is specified, output an error and exit. + For --cflags and --libs option, remove pth and pthread from output. + * gcrypt.h: Include <sys/types.h> and <sys/socket.h>. + (enum gcry_ctl_cmds): Add GCRYCTL_SET_THREAD_CBS. + (gcry_thread_cbs): New struct. + * global.c (gcry_control): Implement GCRYCTL_SET_THREAD_CBS. + (global_init): Don't call ath_init here. + * ath.h: Rewritten. + * ath.c: Rewritten. + +2004-03-06 Werner Koch <wk@gnupg.org> + + * libgcrypt-config.in: s/--soname-number/--api-version/ + * libgcrypt.m4: Changed test for API version. + +2004-03-05 Werner Koch <wk@gnupg.org> + + * libgcrypt.m4: Optionally check the SONAME number. + + * libgcrypt-config.in: Add option --soname-number + +2004-03-01 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (libgcrypt_la_SOURCES): Add ath.c. + * ath.c (ath_init): Add missing function. + + * Makefile.am (ath_pth_src): Removed. + (ath_pthread_src): Removed. + (libgcrypt_la_SOURCES): Remove ath-compat, $(ath_pth_src) and + $(ath_pthread_src). + * ath-compat.c, ath-pth-compat.c, ath-pthread-compat.c: Files + removed. + +2004-02-20 Werner Koch <wk@gnupg.org> + + * gcrypt.h (GCRY_PRIME_CHECK_AT_GOT_PRIME) + (GCRY_PRIME_CHECK_AT_FINISH), + (GCRY_PRIME_CHECK_AT_MAYBE_PRIME): New. + +2004-02-18 Werner Koch <wk@gnupg.org> + + * libgcrypt-config.in: Ignore setting of --prefix. + +2004-02-13 Werner Koch <wk@gnupg.org> + + * gcrypt.h: Added GCRY_CIPHER_RFC2268_128, alsthough not yet + supported. + +2004-02-06 Werner Koch <wk@gnupg.org> + + * gcrypt.h: Added GCRY_CIPHER_RFC2268_40. + +2004-02-03 Werner Koch <wk@gnupg.org> + + * secmem.c (_gcry_secmem_init): Do not print the "not locked into + core warning" if the NO_WARNING flag has been set. + + * sexp.c (sexp_sscan): Allocate result in secure memory if BUFFER + is in secure memory. Switch to secure memory for the a secure %b + format item. Extra paranoid wipe on error. + (gcry_sexp_release): Added paranoid wiping for securely allocated + S-expressions. + +2004-01-25 Moritz Schulte <mo@g10code.com> + + * ath.h: Include <config.h>. + +2004-01-12 Moritz Schulte <mo@g10code.com> + + * gcrypt.h: Adjusted declarations of: gcry_ac_data_set, + gcry_ac_data_get_name, gcry_ac_data_get_index, + gcry_ac_key_pair_generate, gcry_ac_key_test, + gcry_ac_key_get_nbits, gcry_ac_key_get_grip. + + * gcrypt.h (GCRY_AC_FLAG_DATA_NO_BLINDING): Removed symbol. + (GCRY_AC_FLAG_DEALLOC, GCRY_AC_FLAG_COPY) + (GCRY_AC_FLAG_NO_BLINDING): New symbols. + + * global.c (gcry_strdup): Removed function. + * string.c: New file. + * Makefile.am (libgcrypt_real_la_SOURCES): Added: string.c. + * string.c (gcry_strdup): New function. + * gcrypt.h (gcry_strdup): Declare. + +2003-12-19 Werner Koch <wk@gnupg.org> + + * g10lib.h (wipememory, wipememory2): New; taken from gnupg. + +2003-11-14 Werner Koch <wk@gnupg.org> + + * global.c (gcry_strdup): Don't copy the string after a malloc + error. + +2003-11-11 Werner Koch <wk@gnupg.org> + + * sexp.c (sexp_sscan): Implemented "%b" format specifier. + +2003-11-11 Moritz Schulte <mo@g10code.com> + + * libgcrypt.m4: Do not set prefix when calling libgcrypt-config. + Thanks to Nikos Mavroyanopoulos. + +2003-11-08 Moritz Schulte <mo@g10code.com> + + * cipher.h (small_prime_numbers): Removed declaration. + (PUBKEY_FLAG_NO_BLINDING): Put braces around shift. + +2003-11-04 Werner Koch <wk@gnupg.org> + + * cipher.h (_gcry_sha1_has_buffer): New. + + * gcrypt.h (gcry_create_nonce): New. + +2003-10-31 Werner Koch <wk@gnupg.org> + + * libgcrypt.vers (_gcry_generate_elg_prime): Removed this symbol; + gnutls does not need it anymore. + + * secmem.c (mb_get_new): s/pool/block/ due to global pool. + + * misc.c (gcry_set_log_handler): s/logf/f/ to avoid shadowing + warning against a builtin. + + * ath-pth-compat.c: cast pth_connect to get rid of the const + prototype. + +2003-10-27 Werner Koch <wk@gnupg.org> + + * ath.h (ATH_MUTEX_INITIALIZER): Removed spurious semicolon. + +2003-10-27 Moritz Schulte <mo@g10code.com> + + * libgcrypt-config.in: Include libs/cflags of libgpg-error. + + * sexp.c (sexp_sscan): Cleaned up, deallocate scanned sexp on + error. + + * module.c (MODULE_ID_MIN): New symbol, use it. + +2003-10-27 Werner Koch <wk@gnupg.org> + + * gcrypt.h (gcry_pk_testkey): Doc fix. + +2003-09-29 Moritz Schulte <mo@g10code.com> + + * libgcrypt-config.in: Fix --algorithms option. + +2003-10-23 Werner Koch <wk@gnupg.org> + + * gcrypt.h (gcry_err_code): Use GPG_ERR_INLINE instead of + __inline__. + + * secmem.c (lock_pool): Don't print the warning for certain + systems, handle ENOMEM. + +2003-10-21 Werner Koch <wk@gnupg.org> + + * secmem.c (_gcry_secmem_dump_stats): Fixed format sepcifier for a + size_t. Reported by Stephane Corthesy. + +2003-10-10 Werner Koch <wk@gnupg.org> + + * global.c (_gcry_malloc): Handle the no_secure_memory option. + + * gcrypt.h (gcry_prime_group_generator): New. + (gcry_prime_release_factors): New. + +2003-10-07 Werner Koch <wk@gnupg.org> + + * sexp.c (sexp_sscan): Check that parenthesis are matching. + +2003-09-28 Moritz Schulte <mo@g10code.com> + + * g10lib.h: Declare: _gcry_malloc. + (GCRY_ALLOC_FLAG_SECURE): New symbol. + + * global.c (_gcry_malloc): New function... + (gcry_malloc): ... use it. + (gcry_malloc_secure): Likewise. + + * ath.c: Change License to LGPL. + * ath-pthread-compat.c: Likewise. + * ath-pthread.c: Likewise. + * ath-pth-compat.c: Likewise. + * ath-pth.c: Likewise. + * ath.h: Likewise. + * ath-compat.c: Likewise. + + * secmem.c (_gcry_secmem_realloc): Do not forget to release secmem + lock. Thanks to low halo for triggering this bug. + +2003-09-04 Werner Koch <wk@gnupg.org> + + * gcrypt.h (_GCRY_ERR_SOURCE_DEFAULT): Removed cruft. + (gcry_prime_check_func_t): Renamed arg for clarity. + +2003-09-02 Moritz Schulte <mo@g10code.com> + + * gcrypt.h (GCRY_PRIME_FLAG_SPECIAL_FACTOR): New symbol. + +2003-09-01 Moritz Schulte <mo@g10code.com> + + * gcrypt.h (gcry_random_level_t): New type. + (gcry_prime_check_func_t): Likewise. + (GCRY_PRIME_FLAG_SECRET): New symbol. + (gcry_prime_generate, gcry_prime_check): Declare functions. + +2003-08-28 Werner Koch <wk@gnupg.org> + + * Makefile.am (libgcrypt_pth_la_LDFLAGS): Removed PTH_CFLAGS cruft. + +2003-08-27 Moritz Schulte <mo@g10code.com> + + * global.c (gcry_control): Remove call to ath_deinit. + + * Makefile.am (libgcrypt_real_la_DEPENDENCIES): Fixed. + (libgcrypt_real_la_LIBADD): Fixed. + Removed unecessary variables. + + * libgcrypt-config.in: Adjusted script for new thread handling. + + * Makefile.am: New version, based on GPGMEs Makefile.am. + + * ath.c, ath-compat.c, ath.h, ath-pth.c, ath-pth-compat.c, + ath-pthread.c, ath-pthread-compat.c: New files, merged from GPGME. + * ath.c, ath.h, ath-pthread.c, ath-pth.c: Removed files. + +2003-08-08 Moritz Schulte <moritz@g10code.com> + + * global.c (gcry_realloc): Remove FIXME about `clearing out + realloced memory', since _gcry_secmem_realloc takes care of + overwriting old memory. + +2003-08-07 Werner Koch <wk@gnupg.org> + + * module.c (_gcry_module_release): Don't act if module is NULL. + +2003-07-30 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h (enum gcry_ac_id): Added: GCRY_AC_ELG_E. + Reverted change: use gcry_md_flags enumeration list instead of + defines. + +2003-07-29 Werner Koch <wk@gnupg.org> + + * global.c (gcry_control): Add GCRYCTL_SET_RANDOM_SEED_FILE and + GCRYCTL_UPDATE_RANDOM_SEED_FILE. + * gcrypt.h: Ditto. Renamed index to idx, so avoid warning + related to the old index function. + +2003-07-28 Moritz Schulte <moritz@g10code.com> + + * global.c (gcry_err_code_from_errno, gcry_err_code_to_errno) + (gcry_err_make_from_errno, gcry_error_from_errno): New functions. + + * gcrypt.h: Declared: gcry_err_code_from_errno, + gcry_err_code_to_errno, gcry_err_make_from_errno, + gcry_error_from_errno. + + * Makefile.am (include_HEADERS): Added: gcrypt-module.h. + + * gcrypt.h: Include <gcrypt-module.h>. + + * gcrypt-module.h: New file. + +2003-07-27 Werner Koch <wk@gnupg.org> + + * gcrypt.h (gcry_mpi_scan, gcry_mpi_print): API change. + (gcry_mpi_dump): New. + +2003-07-21 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h: Declared: gcry_ac_key_data_get. + (gcry_pk_spec): Renamed member `sexp_names' into `aliases'. + +2003-07-20 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h (gcry_md_oid_spec_t): New type. + (gcry_md_spec): New member: oids. + +2003-07-19 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h (gcry_cipher_oid_spec_t): New type. + (gcry_cipher_spec): New member: oids; + +2003-07-18 Werner Koch <wk@gnupg.org> + + * gcrypt.h (gcry_mpi_set_opaque): Add a warning comment. + +2003-07-15 Moritz Schulte <moritz@g10code.com> + + * secmem.c (compress_pool): Remove function, since unused blocks + are automatically concatenad. + + * gcrypt.h: Bumped version number up to 1.1.42-cvs. + +2003-07-14 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h (gcry_cipher_spec): New member: aliases. + + * Makefile.am (noinst_PROGRAMS, testapi_SOURCES, testapai_LDADD, + benchmark_SOURCES, benchmark_LDADD): Removed. + + * benchmark.c, testapi.c: Removed files. + + * mpi.h: Removed disabled typedef. + * g10lib.h: Likewise. + + * benchmark.c, g10lib.h, gcrypt.h, global.c, module.c, sexp.c: + Used gcry_err* wrappers for libgpg-error symbols. + +2003-07-12 Moritz Schulte <moritz@g10code.com> + + * global.c: Likewise. + + * gcrypt.h: New type: gcry_error_t, gcry_err_code_t and + gcry_err_source_t. + (gcry_err_make, gcry_error, gcry_err_code, gcry_err_source): New + functions. + + * global.c (gcry_strerror): New function. + (gcry_strsource): New function. + + * gcrypt.h: New symbol: GCRY_CIPHER_TWOFISH128. + +2003-07-09 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h (enum gcry_md_flags): Removed, used define instead, + since that is more common than an enumeration list when it comes + to flags that can be bitwise ORed. + +2003-07-08 Moritz Schulte <moritz@g10code.com> + + * global.c: Use new types for handlers. + + * gcrypt.h: Declare: gcry_ac_data_copy. + +2003-07-07 Moritz Schulte <moritz@g10code.com> + + * sexp.c (gcry_sexp_build_array): Use dummy argument pointer. + Thanks to Simon Josefsson <jas@extunde.com>. + + * gcrypt.h: Declare: gcry_cipher_list, gcry_pk_list, gcry_md_list. + +2003-07-05 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h: Declare: gcry_cipher_register, gcry_cipher_unregister, + gcry_md_register, gcry_md_unregister, gcry_pk_register, + gcry_pk_unregister. + (gcry_cipher_spec): Removed member: algorithm. + (gcry_pk_spec): Likewise. + (gcry_md_spec): Likewise. + Adjusted declarations: gcry_cipher_register, gcry_pk_register, + gcry_md_register. + + * module.c: Replaced all occurences of `id' with `mod_id', since + `id' is a keyword in obj-c. + + * gcrypt.h (gcry_cipher_spec): Renamed member `id' to `algorithm'. + (gcry_pk_spec): Likewise. + (gcry_md_spec): Likewise. + + * cipher.h: Removed types: gcry_pubkey_generate_t, + gcry_pubkey_check_secret_key_t, gcry_pubkey_encrypt_t, + gcry_pubkey_decrypt_t, gcry_pubkey_sign_t, gcry_pubkey_verify_t, + gcry_pubkey_get_nbits_t, gcry_pk_spec_t, gcry_digest_init_t, + gcry_digest_write_t, gcry_digest_final_t, gcry_digest_read_t, + gcry_digest_spec_t, gcry_cipher_setkey_t, gcry_cipher_encrypt_t, + gcry_cipher_decrypt_t, gcry_cipher_stencrypt_t, + gcry_cipher_stdecrypt_t, gcry_cipher_spec_t. + + * gcrypt.h: New types: gcry_pk_generate_t, + gcry_pk_check_secret_key_t, gcry_pk_encrypt_t, gcry_pk_decrypt_t, + gcry_pk_sign_t, gcry_pk_verify_t, gcry_pk_get_nbits_t, + gcry_pk_spec_t, gcry_md_init_t, gcry_md_write_t, gcry_md_final_t, + gcry_md_read_t, gcry_md_spec_t, gcry_cipher_setkey_t, + gcry_cipher_encrypt_t, gcry_cipher_decrypt_t, + gcry_cipher_stencrypt_t, gcry_cipher_stdecrypt_t, + gcry_cipher_spec_t, gcry_module_t. + +2003-07-04 Moritz Schulte <moritz@g10code.com> + + * module.c (_gcry_module_list): New function. + +2003-07-02 Moritz Schulte <moritz@g10code.com> + + * module.c (_gcry_module_lookup): Fixed typo. + + * gcrypt.h: Added all definitions and declarations necessary for + the new ac interface. + +2003-06-30 Moritz Schulte <moritz@g10code.com> + + * g10lib.h: Added declarations: _gcry_pk_module_lookup, + _gcry_pk_module_release. + +2003-06-18 Werner Koch <wk@gnupg.org> + + * benchmark.c (cipher_bench): Adjusted for new API of get_blklen + and get_keylen. + + * gcrypt.h (gcry_cipher_get_algo_blklen) + (gcry_cipher_get_algo_keylen): Replaced macro by funcion. + +2003-06-18 Moritz Schulte <moritz@g10code.com> + + * cipher.h: Renamed types GcryDigestSpec, GcryCipherSpec and + GcryPubkeySpec into: gcry_digest_spec_t, gcry_cipher_spec_t and + gcry_pubkey_spec_t. + (gcry_pubkey_spec): Defined member `id' as unsigned. + (gcry_digest_spec): Likewise. + (gcry_cipher_spec): Likewise. + + * module.c (_gcry_module_id_new): New function. + (_gcry_module_add): Generate a new ID via _gcry_module_id_new in + case `id' is zero. + + * g10lib.h, module.c: Replace old type GcryModule with newer one: + gcry_module_t. + + * module.c (_gcry_module_add): Added argument `id', use it. + + * g10lib.h: Added declaration: _gcry_module_lookup_id. + (_gcry_module_add): Added argument `id'. + + * module.c (_gcry_module_lookup_id): New function. + + * g10lib.h (struct gcry_module): New member: id. + + * gcrypt.h: New type: gcry_handler_progress_t, + gcry_handler_alloc_t, gcry_haandler_secure_check_t, + gcry_handler_realloc_t, gcry_handler_free_t, + gcry_handler_no_mem_t, gcry_handler_error_t, gcry_handler_log_t. + Use new types. + + * cipher.h: Include <gcrypt.h>. + New types: gcry_pk_generate_t, gcry_pk_check_secret_key_t, + gcry_pk_encrypt_t, gcry_pk_decrypt_t, gcry_pk_sign_t, + gcry_pk_verify_t, gcry_pk_get_nbits_t, gcry_md_init_t, + gcry_md_write_t, gcry_md_final_t, gcry_md_read_t, + gcry_cipher_setkey_t, gcry_cipher_encrypt_t, + gcry_cipher_decrypt_t, gcry_cipher_stencrypt_t, + gcry_cipher_stdecrypt_t. + Use new types. + +2003-06-17 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (AM_CFLAGS): Added: @GPG_ERROR_CFLAGS@. + +2003-06-16 Moritz Schulte <moritz@g10code.com> + + * g10lib.h: Replace last occurences of old type names with newer + names (i.e. replace MPI with gcry_mpi_t). + * mpi.h: Likewise. + * sexp.c: Likewise. + +2003-06-15 Moritz Schulte <moritz@g10code.com> + + * testapi.c (test_genkey): Use gpg_strerror instead of + gcry_strerror. + + * global.c (gcry_control): Fixed typo. + + * misc.c (_gcry_fatal_error): Use gpg_strerror instead of + gcry_strerror. + + * types.h (STRLIST): Removed type since it is not used. + +2003-06-11 Moritz Schulte <moritz@g10code.com> + + * global.c (global_init): Call: _gcry_cipher_init, _gcry_md_init, + _gcry_pk_init. + + * g10lib.h: Declare: _gcry_cipher_init, _gcry_md_init, + _gcry_pk_init. + + * global.c (gcry_strerror): Remove compatibility code. + + * Makefile.am: Remove support libgpg-error special handling. + (AM_CPPFLAGS): Add @GPG_ERROR_CFLAGS@ + + * gcrypt.h: Likewise. + +2003-06-13 Werner Koch <wk@gnupg.org> + + * gcrypt.h (gcry_md_get_algo): Reverted to old API. This is a + convenience function anyway and error checking is not approriate. + (gcry_md_is_enabled): New. + (gcry_md_is_secure): Replaced macro by function and reverted to old + API. + +2003-06-11 Werner Koch <wk@gnupg.org> + + * gcrypt.h (GCRYERR): Define _GCRY_ERR_SOURCE_DEFAULT instead of + GPG_ERR_SOURCE_DEFAULT, so that libgpg-error still works despite + the use of the old gcrypt error codes. + (gcry_md_copy): Swapped arguments. + +2003-06-09 Moritz Schulte <moritz@g10code.com> + + * Makefile.am: Support for libgpg-error. + +2003-06-08 Moritz Schulte <moritz@g10code.com> + + * sexp.c (gcry_sexp_create): Expect sane error values from + gcry_sexp_canon_len instead of the `historical' values. + +2003-06-07 Moritz Schulte <moritz@g10code.com> + + * ath.c, ath.c, ath-pth.c, ath-pthread.c, benchmark.c, cipher.h, + g10lib.h, gcrypt.h, global.c, misc.c, missing-string.c, module.c, + mpi.h, secmem.c, secmem.h, sexp.c, stdmem.c, stdmem.h, testapi.c, + types.h: Edited all preprocessor instructions to remove whitespace + before the '#'. This is not required by C89, but there are some + compilers out there that don't like it. Replaced any occurence of + the now deprecated type names with the new ones. + + * gcrypt.h: Re-organized checking for gcc features; New macro: + _GCRY_GCC_ATTR_DEPRECATED. + Include copy of libgpg-error's gpg-error.h in order to make it + easy to build libgcrypt without needing libgpg-error.h. + + (GCRY_MPI, GcryMPI, GCRY_SEXP, GcrySexp, GCRY_CIPHER_HD, + GcryCipherHd, GCRY_MD_HD, GcryMDHd): Declared deprecated. + (gcry_mpi_t, gcry_sexp_t, gcry_cipher_hd_t, gcry_md_hd_t): New + types. + +2003-06-04 Moritz Schulte <moritz@g10code.com> + + * sexp.c (sexp_sscan): New argument: arg_list, adjusted all + callers. + (ARG_NEXT): New macro. + (sexp_sscan): Use ARG_NEXT for receiving format string arguments. + (gcry_sexp_build_array): New function. + +2003-06-02 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h: Added some comments describing the gcry_sexp_* + functions. + Include <gpg-error.h> instead of <gpg/error.h>. + +2003-06-01 Moritz Schulte <moritz@g10code.com> + + * sexp.c (OLDPARSECODE): Removed macro... + (gcry_sexp_canon_len): ... and do not use it. + + * gcrypt.h (gcry_errno): Removed declaration. + + * g10lib.h (string_to_pubkey_algo, pubkey_algo_to_string, + pubkey_nbits): Removed declarations for non-existing functions. + +2003-05-31 Moritz Schulte <moritz@g10code.com> + + * cipher.h (is_RSA, is_ELGAMAL): Removed macros. + + * g10lib.h (set_lasterr): Removed macro. + (_gcry_set_lasterr): Removed declaration. + + * gcrypt.h: Changed declarations for: gcry_pk_algo_info, + gcry_md_open, gcry_md_copy, gcry_md_algo_info, gcry_md_info, + gcry_md_get_algo, gcry_random_add_bytes. + + (gcry_md_is_secure): Adjust macro for new API. + +2003-05-29 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h: Changed declarations for: gcry_cipher_open, + gcry_cipher_info, gcry_cipher_algo_info. + (gcry_cipher_get_algo_keylen): Adjuster for new + gcry_cipher_algo_info interface. + (gcry_cipher_get_algo_blklen): Likewise. + + * global.c (gcry_errno): Removed function. + (gcry_strerror): Do not use gcry_errno. + (_gcry_set_lasterr): Removed function. + (last_ec): Removed variable. + +2003-05-27 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h (enum gcry_cipher_algos): Make Serpent IDs do not + conflict with OpenPGP. Reported by Timo Schulz. + + * global.c (gcry_control): Fixed name of enum list. + +2003-05-25 Moritz Schulte <moritz@g10code.com> + + * cipher.h (gcry_cipher_spec): Adjust return type of `setkey' for + libgpg-error. + (gcry_pubkey_spec): Adjust return type of `generate', + `check_secret_key', `encrypt', `decrypt', `sign' and `verify' for + libgpg-error. + + * sexp.c (gcry_sexp_canon_len): Adjusted for libgpg-error. + (gcry_sexp_create): Likewise. + (gcry_sexp_new): Likewise. + (sexp_sscan): Likewise. + (gcry_sexp_build): Likewise. + (gcry_sexp_sscan): Likewise. + + * module.c (_gcry_module_add): Likewise. + + * global.c (last_ec): Change type to gpg_error_t. + (gcry_control): Adjust for libgpg-error. + (gcry_errno): Likewise. + (gcry_strerror): Likewise. + (_gcry_set_lasterr): Likewise. + (gcry_xmalloc): Likewise. + (gcry_xrealloc): Likewise. + +2003-05-22 Moritz Schulte <moritz@g10code.com> + + * types.h: Merged code from GnuPG regarding U64_C. + + * missing-string.c (strsep): Removed function. + + * g10lib.h: Removed declarations: strsep, strlwr. + + * secmem.c (secmem_lock): New variable. + (SECMEM_LOCK, SECMEM_UNLOCK): New macros. + (_gcry_secmem_set_flags): Use SECMEM_LOCK and SECMEM_UNLOCK. + (_gcry_secmem_get_flags): Likewise. + (_gcry_secmem_init): Likewie. + (_gcry_secmem_malloc): Likewise. + (_gcry_secmem_free): Likewise. + (_gcry_secmem_malloc): Renamed to ... + (_gcry_secmem_malloc_internal): ... this. + (_gcry_secmem_malloc): New function, use SECMEM_LOCK, + SECMEM_UNLOCK, call _gcry_secmem_malloc_internal. + (_gcry_secmem_free): Renamed to ... + (_gcry_secmem_free_internal): ... this. + (_gcry_secmem_free): New function, use SECMEM_LOCK, SECMEM_UNLOCK, + call _gcry_secmem_free_internal. + (_gcry_secmem_realloc): Use SECMEM_LOCK, SECMEM_UNLOCK, call + _gcry_secmem_malloc_internal and _gcry_secmem_free_internal. + (_gcry_private_is_secure): Use SECMEM_LOCK, SECMEM_UNLOCK. + (_gcry_secmem_dump_stats): Likewise. + (_gcry_secmem_malloc_internal): Removed unused variable: + compressed. + Include "ath.h". + +2003-05-21 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h (GCRY_CIPHER_SERPENT128, GCRY_CIPHER_SERPENT192, + GCRY_CIPHER_SERPENT256): New symbols. + +2003-05-19 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h: Reversed changes from 2003-03-03 since they would have + been an unnecessary ABI break. + +2003-05-13 Moritz Schulte <moritz@g10code.com> + + * secmem.c (stats_update): New function. + (BLOCK_HEAD_SIZE): New symbol. + (MB_FLAG_ACTIVE): New symbol. + (ADDR_TO_BLOCK, BLOCK_VALID): New macros. + (mb_get_next): New function. + (mb_get_prev): New function. + (mb_merge): New function. + (mb_get_new): New function. + (unused_blocks): Removed variable. + (init_pool): Initialize new memory pool. + (_gcry_secmem_malloc): Use new heap management code. + (_gcry_secmem_free): Likewise. + (_gcry_secmem_realloc): Likewise. + Renamed type MEMBLOCK to memblock_t. + +2003-04-27 Moritz Schulte <moritz@g10code.com> + + * cipher.h (gcry_pubkey_spec): New member: sexp_names. + +2003-04-23 Moritz Schulte <moritz@g10code.com> + + * cipher.h (gcry_pubkey_spec): Removed members: npkey, nskey, + nenc, nsig. + (gcry_pubkey_spec): Added members: elements_pkey, elements_skey, + elements_enc, elements_sig, elements_grip. + +2003-04-17 Moritz Schulte <moritz@g10code.com> + + * g10lib.h (GcryModule): New typedef. + + * gcrypt.h (gcry_cipher_register, gcry_cipher_unregister, + gcry_digest_register, gcry_digest_unregister, + gcry_pubkey_register, gcry_pubkey_unregister): Function + declarations removed - for now. + + * gcrypt.h (GcryModule): Declaration removed. + * gcrypt.h (GcryPubkeySpec, GcryDigestSpec, GcryCipherSpec): + Types Moved... + * cipher.h: ... here. + +2003-04-17 Moritz Schulte <moritz@g10code.com> + + * cipher.h: Declare digest_spec_sha512 and digest_spec_384. + +2003-04-16 Moritz Schulte <moritz@g10code.com> + + * module.c (_gcry_module_use): New function. + * g10lib.h (_gcry_module_use): Declare function. + + * libgcrypt-config.in: Support for --algorithms switch, which + prints the algorithms included in the built libgcrypt. + + * global.c (gcry_set_progress_handler): Register progress + functions depending on the enabled algorithms. + +2003-04-07 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (libgcrypt_la_SOURCES): Added module.c + + * module.c: New file. + (_gcry_module_add): New function. + (_gcry_module_drop): New function. + (_gcry_module_lookup): New function. + (_gcry_module_release): New function. + + * g10lib.h (GcryModule): New types. + (FLAG_MODULE_DISABLED): New symbol. + Added declarations for _gcry_module_add, _gcry_module_release and + _gcry_module_lookup. + + * gcrypt.h: New types: GcryPubkeySpec, GcryDigestSpec, + GcryCipherSpec. + Added declarations for: gcry_cipher_register, + gcry_cipher_unregister, gcry_digest_register, + gcry_digest_unregister, gcry_pubkey_register and + gcry_pubkey_unregister. + + * cipher.h: Removed symbols: CIPHER_ALGO_NONE, CIPHER_ALGO_IDEA, + CIPHER_ALGO_3DES, CIPHER_ALGO_CAST5, CIPHER_ALGO_BLOWFISH, + CIPHER_ALGO_SAFER_SK128, CIPHER_ALGO_DES_SK, CIPHER_ALGO_TWOFISH, + CIPHER_ALGO_TWOFISH_OLD, CIPHER_ALGO_DUMMY, PUBKEY_USAGE_SIG, + PUBKEY_USAGE_ENC, DIGEST_ALGO_MD5, DIGEST_ALGO_SHA1, + DIGEST_ALGO_RMD160, DIGEST_ALGO_TIGER, PUBKEY_ALGO_RSA, + PUBKEY_ALGO_RSA_E, PUBKEY_ALGO_RSA_S, PUBKEY_ALGO_DSA, + PUBKEY_ALGO_ELGAMAL, PUBKEY_ALGO_ELGAMAL_E. + +2003-04-02 Moritz Schulte <moritz@g10code.com> + + * benchmark.c (md_bench): Fix error message. + +2003-03-31 Moritz Schulte <moritz@g10code.com> + + * benchmark.c (cipher_bench): Added CTR mode. + +2003-03-30 Simon Josefsson <jas@extundo.com> + + * gcrypt.h (enum gcry_control_cmds): Add GCRY_SET_CTR. + (enum gcry_cipher_modes): Add GCRY_CIPHER_MODE_CTR. + (gcry_cipher_setctr): New macro to set counter. + +2003-03-19 Moritz Schulte <moritz@g10code.com> + + * cipher.h (PUBKEY_FLAG_NO_BLINDING): New symbol. + +2003-03-22 Simon Josefsson <jas@extundo.com> + + * gcrypt.h: Add GCRYCTL_SET_CBC_MAC and GCRY_CIPHER_CBC_MAC. + +2003-03-19 Werner Koch <wk@gnupg.org> + + * g10lib.h: Adjusted primegen.c prototypes. + +2003-03-12 Werner Koch <wk@gnupg.org> + + * sexp.c (sexp_sscan): Initialize NM. Thanks to Ian Peters for + valgrinding this. + +2003-03-06 Moritz Schulte <mo@g10code.com> + + * secmem.h (GCRY_SECMEM_FLAG_NO_WARNING, + GCRY_SECMEM_FLAG_SUSPEND_WARNING): New symbols. + + * global.c (gcry_control): Use + GCRY_SECMEM_FLAG_{NO,SUSPEND}_WARNING, instead of hard-coded + values. + * secmem.c (_gcry_secmem_set_flags): Likewise. + * secmem.c (_gcry_secmem_get_flags): Likewise. + +2003-03-03 Moritz Schulte <moritz@g10code.com> + + * misc.c: Removed old FIXME, since there is already a function to + set the value of `verbosity_level'. + + * gcrypt.h: Removed enumeration list: gcry_ctl_cmds. + New enumeration lists: gcry_global_control_cmds, + gcry_control_cmds, gcry_info_cmds, gcry_algo_info_cmds. + +2003-03-02 Moritz Schulte <moritz@g10code.com> + + * gcrypt.h (gcry_cipher_reset): New macro for resetting a handle. + +2003-02-28 Moritz Schulte <moritz@g10code.com> + + * secmem.c (DEFAULT_PAGESIZE): New symbol. + (init_pool): Use DEFAULT_PAGESIZE. + +2003-02-23 Moritz Schulte <moritz@g10code.com> + + * secmem.h: Fix typo in declaration of _gcry_secmem_term. + + * sexp.c: Move macro definitions of `digitp', `octdigit', `alphap' + and `hexdigit' ... + * g10lib.h: ... here. + + * misc.c (_gcry_burn_stack): New function (former name: + burn_stack). + + * g10lib.h (burn_stack): Declare _gcry_burn_stack(). + +2003-01-24 Werner Koch <wk@gnupg.org> + + * global.c (gcry_set_progress_handler): Register a random progress + handler. + +2003-01-23 Werner Koch <wk@gnupg.org> + + * gcrypt.h (GCRY_ENABLE_QUICK_RANDOM): New. + * global.c (gcry_control): Make use of it. + +2003-01-21 Werner Koch <wk@gnupg.org> + + * gcrypt.h (gcry_random_add_bytes): Add QUALITY argument. + +2003-01-21 Timo Schulz <twoaday@freakmail.de> + + * gcrypt.h (gcry_random_add_bytes): New. + +2003-01-20 Simon Josefsson <jas@extundo.com> + + * gcrypt.h (gcry_md_algos): Add GCRY_MD_CRC32, + GCRY_MD_CRC32_RFC1510, GCRY_MD_CRC24_RFC2440. + +2003-01-16 Werner Koch <wk@gnupg.org> + + * gcrypt.h (gcry_md_write): Changed type of 2nd argument to void*. + (gcry_md_hash_buffer): Changed type of both buffers to void*. + (gcry_md_setkey): Changed type of 2nd argument to void*. + (gcry_md_get_asnoid): New. + +2003-01-15 Werner Koch <wk@gnupg.org> + + * sexp.c (gcry_sexp_length): Fixed. This was seriously broken. + +2003-01-14 Werner Koch <wk@gnupg.org> + + * gcrypt.h (GCRYERR_INV_FLAG), global.c (gcry_strerror): New. + +2003-01-02 Werner Koch <wk@gnupg.org> + + * libgcrypt.vers: Temporary export _gcry_generate_elg_prime for + use by GNUTLS. + +2002-12-21 Werner Koch <wk@gnupg.org> + + * gcrypt.h: Make use of gcc's pure and malloc attributes + (gcry_md_putc): Use a helper variable to avoid multiple + evaluation of H. + * g10lib.h, stdmem.h, secmem.h: Use gcc attributes pure and malloc. + + * stdmem.c (use_m_guard): Don't default to yes. + +2002-12-19 Werner Koch <wk@gnupg.org> + + * global.c (global_init): The meat was never run due to a faulty + check. Thanks to Nikos for pointing this out. + + * global.c (gcry_control): Return 1 and not -1 for the + initialization tests. + + * libgcrypt.vers: New. + * Makefile.am: Use this instead of the build symbol file. + + * global.c (gcry_control) <initialization>: Call the random module + initializer to make sure that the pool lock flag has been + initialized. + +2002-12-09 Werner Koch <wk@gnupg.org> + + * global.c (gcry_calloc,gcry_calloc_secure): Check for overflow. + Noted by Florian Weimer. + +2002-11-10 Simon Josefsson <jas@extundo.com> + + * gcrypt.h (gcry_ctl_cmds): New GCRYCTL_SET_CBC_CTS control flag. + (gcry_cipher_flags): New GCRY_CIPHER_CBC_CTS gcry_cipher_open() flag. + (gcry_cipher_cts): New macro for toggling CTS. + +2002-11-10 Werner Koch <wk@gnupg.org> + + * gcrypt.h (GCRY_MD_MD4): New. We use a non OpenPGP value here. + +2002-09-20 Werner Koch <wk@gnupg.org> + + * ath.c: Include sys.time.h if sys/select.h does not exist. + (ath_select, ath_waitpid): Shortcut for Windows. + * ath.h: Include some Windows headers. By Timo. + +2002-09-18 Werner Koch <wk@gnupg.org> + + * ath.h: Prefix ath_deinit. + +2002-09-17 Werner Koch <wk@gnupg.org> + + * benchmark.c: New. + (mpi_bench, do_powm): Add a a simple test for RSA. + + * global.c (global_init): New. Use it instead of the setting + any_init_done. Initialize the ATH system. + (gcry_check_version): Hook global_init in. This is the suggested + way to initialize the library. + (_gcry_no_internal_locking): Removed. We simply call a ath_deinit + and leave it to ATH to disbale the locking. + + * ath.c, ath.h, ath-pth.c, ath-pthread.c: New. Taken from GPGME. + * mutex.h: Removed. + * Makefile.am (ath_components): New. + +2002-09-16 Werner Koch <wk@gnupg.org> + + * secmem.c (_gcry_secmem_dump_stats): Replaced fprintf by log_*. + +2002-08-23 Werner Koch <wk@gnupg.org> + + * missing-string.c: Removed unneeded strlwr. + + * libgcrypt.m4: Made much more simple. + * libgcrypt-config.in: Made --prefix work for --libs. + +2002-08-14 Werner Koch <wk@gnupg.org> + + * gcrypt.h: Add GCRY_CIPGER_DES. Included string.h for size_t. + Suggested by Simon Josefsson. + +2002-07-25 Werner Koch <wk@gnupg.org> + + * cipher.h: Added prototypes for progress functions. + * global.c: Include cipher.h for those prototypes. + + * stdmem.c (_gcry_private_realloc): Replaced void* by char * for + pointer arithmetic reasons. Noted by Stephan Austermuehle. + +2002-06-24 Werner Koch <wk@gnupg.org> + + * missing-string.c: Include ctype.h. + + * gcrypt.h (gcry_mpi_invm, gcry_mpi_div, gcry_mpi_mod) + (gcry_mpi_swap): New. + +2002-06-18 Werner Koch <wk@gnupg.org> + + * gcrypt.h: Added a bunch of brief function descriptions. + +2002-05-21 Werner Koch <wk@gnupg.org> + + * misc.c (_gcry_log_printf): Don't initialize a va_list. Noted by + Jeff Johnson. + + * global.c (gcry_set_progress_handler): New. + + * gcrypt.h: Replaced the typedef for byte. + +2002-05-16 Werner Koch <wk@gnupg.org> + + * missing-string.c: New. + + * gcrypt.h: Add new error codes GCRYERR_SEXP_ and typedefs + GcryMPI, GcrySexp, GcryCipherHd, GcryMDHd as aliases for the old + ones using an underscore. + + * global.c (gcry_strerror): Add strings fro the new error codes. + * sexp.c (gcry_sexp_canon_len): Use a macro to convert from new to + old error codes. + (gcry_sexp_create,gcry_sexp_new): New. + +2002-05-15 Werner Koch <wk@gnupg.org> + + * mutex.h (DEFINE_LOCAL_MUTEX): Macro to define a mutex and + initialize it so that we can detect an unitialized mutex and don't + read from stdin. + +2002-05-14 Werner Koch <wk@gnupg.org> + + Changed license of all files to the LGPL. + +2002-05-07 Werner Koch <wk@gnupg.org> + + * global.c (gcry_control): Add commands + GCRYCTL_ANY_INITIALIZATION_P and GCRYCTL_INITIALIZATION_FINISHED_P + so that other libraries are able to check for required + initializations. + +2002-05-02 Werner Koch <wk@gnupg.org> + + * gcrypt.h (GCRYCTL_DISABLE_INTERNAL_LOCKING): New. + * global.c (gcry_control): Implement it. + (_gcry_no_internal_locking): New. + * mutex.h: Prefixed all fucntions with _gcry_. Bypass all + functions when desired. + + * gcrypt.h (GCRYCTL_DISABLE_SECMEM): New. + * global.c (gcry_control,gcry_malloc_secure,gcry_is_secure): + Implement it here. + * secmem.c (_gcry_private_is_secure): Return false if the pool is + not initialized. + + * gcrypt.h (GCRYCTL_INITIALIZATION_FINISHED): New. + + * gcrypt.h (gcry_cipher_algos): Replaced RINDAEL by AES and change + the macros to expand from rijdael to aes. + + * stdmem.c (_gcry_private_malloc): Return NULL for 0 byte allocation. + (_gcry_private_malloc_secure): Ditto. + + * g10lib.h: Copied the JNLIB_GCC macros from ../jnlib/mischelp.h + and removed the inclusion of that file. + +2002-04-15 Werner Koch <wk@gnupg.org> + + * global.c (gcry_strdup): New. + +2002-03-18 Werner Koch <wk@gnupg.org> + + * mutex.h: New file with a portable thread mutex implementation + written by Marcus Brinkmann. Taken from GPGME. + +2002-02-18 Werner Koch <wk@gnupg.org> + + * sexp.c (gcry_sexp_sscan): Don't initialize the dummy + variable. Suggested by Jordi Mallach. + +2002-01-31 Werner Koch <wk@gnupg.org> + + * sexp.c (suitable_encoding,convert_to_hex,convert_to_string) + (convert_to_token): New. + (gcry_sexp_sprint): Better formatting of advanced encoding, does + now insert LFs and escapes all unprintable characters. + (unquote_string): New. + (sexp_sscan): Implemented the missing conversion of quoted strings. + +2002-01-26 Werner Koch <wk@gnupg.org> + + * libgcrypt-config.in: Add copyright notice. + +2002-01-11 Werner Koch <wk@gnupg.org> + + * sexp.c (gcry_sexp_canon_len): Fixed last change. + +2002-01-01 Timo Schulz <ts@winpt.org> + + * stdmem.c (_gcry_private_realloc): If pointer is NULL now realloc + behaves like malloc. + +2001-12-20 Werner Koch <wk@gnupg.org> + + * sexp.c (gcry_sexp_canon_len): Describe the error codes and + return an error if this is not a S-Exp; i.e. it does not start + with an open parenthesis. + +2001-12-18 Werner Koch <wk@gnupg.org> + + * sexp.c (gcry_sexp_canon_len): Fixed the test on NULL buffer. + + * Makefile.am (DISTCLEANFILES): Include libgcrypt.sym + + * sexp.c: Removed the commented test code because we now have a + test in ../tests/ + +2001-12-17 Werner Koch <wk@gnupg.org> + + * sexp.c (gcry_sexp_canon_len): New. + +2001-12-11 Werner Koch <wk@gnupg.org> + + * gcrypt.h: Fixed AES128 macro, add enum for OFB mode. + +2001-12-05 Werner Koch <wk@gnupg.org> + + * misc.c (_gcry_log_printf): New. + * sexp.c (dump_string,gcry_sexp_dump): Use logging functions + instead of stderr. + +2001-11-16 Werner Koch <wk@gnupg.org> + + * gcrypt.h: New constant GCRYCTL_IS_ALGO_ENABLED. + +2001-10-02 Werner Koch <wk@gnupg.org> + + * gcrypt.h: Removed a couple of trailing commas. + +2001-08-28 Werner Koch <wk@gnupg.org> + + * sexp.c (sexp_sscan): Add an argument to enable the + arg_ptr. Changed all callers. Suggested by Tom Holroyd. + +2001-08-03 Werner Koch <wk@gnupg.org> + + * global.c (gcry_strerror): Updated list of error codes. + +2001-07-23 Werner Koch <wk@gnupg.org> + + * gcrypt.h: Replaced the last ulong. Noted by Rami Lehti. + +2001-05-31 Werner Koch <wk@gnupg.org> + + * gcrypt.h, mpi.h: Made some mpi functions public. + + * wrapper.c: Removed. + * global.c: Renamed all g10_ prefixed functions which had wrappers + to gcry_xxx. So we now use the exported memory functions inernally. + + Renamed all g10_ prefixed functions to _gcry_ prefixed ones. + + * g10lib.h (_GCRYPT_IN_LIBGCRYPT): Replace defintion by a test on it. + +2001-05-28 Werner Koch <wk@gnupg.org> + + * libgcrypt.m4: Check GCRYPT_VERSION macro and not LIBGCRYPT_VERSION. + + * mpi.h: Removed mpi_fromstr prototype. + +2001-01-11 Werner Koch <wk@gnupg.org> + + * Makefile.am (libgcrypt_la_SOURCES): Add mpi.h + +2000-12-19 Werner Koch <wk@gnupg.org> + + * types.h: Moved from ../include to here. + + Major change: + Removed all GnuPG stuff and renamed this piece of software + to gcrypt. + +2000-11-14 Werner Koch <wk@gnupg.org> + + * mpi.h: Moved to ../mpi. + + * Makefile.am (OMIT_DEPENDENCIES): Hack to work around dependency + problems. + +2000-10-11 Werner Koch <wk@gnupg.org> + + * mpi.h: Changed the way mpi_limb_t is defined. + +2000-10-10 Werner Koch <wk@gnupg.org> + + * Makefile.am: Take version-info from configure. + +2000-10-09 Werner Koch <wk@gnupg.org> + + * gcrypt.h: New cipher mode, new algo Arcfour and new error code + GCRYERR_INV_CIPHER_MODE. + * global.c (gcry_strerror): New errorcode. + +Wed Oct 4 13:16:18 CEST 2000 Werner Koch <wk@openit.de> + + * gcrypt.h (gcry_md_setkey): Replaced macro by function prototype. + +Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de> + + * gcrypt.h (GCRYCTL_GET_ALGO_USAGE): New. + + * secmem.c (secmem_realloc): check for failed secmem_malloc. By + Matt Kraai. + +Mon Jul 31 10:04:47 CEST 2000 Werner Koch <wk@openit.de> + + * sexp.c: Removed the datalen fields from list tags. + (gcry_sexp_car_data,gcry_sexp_cdr_data,gcry_sexp_car_mpi, + gcry_sexp_cdr_mpi): Removed. + (gcry_sexp_nth,gcry_sexp_nth_data,gcry_sexp_nth_mpi): New. + +Fri Jul 28 18:19:11 CEST 2000 Werner Koch <wk@openit.de> + + * sexp.c (sexp_sscan): Fixed reallocation to secure memory. + (new_empty_list): Removed + (gcry_sexp_length): New. + (gcry_sexp_enum): Removed. + (normalize): New. Reworked the whole thing to use NULL for an empty list. + (make_space): New instead of the macro. + +Tue Jul 25 17:44:15 CEST 2000 Werner Koch <wk@openit.de> + + * sexp.c: Major rewrite. + (gcry_sexp_sscan): Reordered arguments. Moved functionality to .. + (sexp_sscan): .. this. + (gcry_sexp_build): New. + (gcry_sexp_new_name_mpi, gcry_sexp_new_name_data, gcry_sexp_new_data, + gcry_sexp_new_mpi): Removed. + +Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@> + + * gcrypt.h (gcry_md_start_debug, gcry_md_stop_debug): New. + (gcry_ctl_cmds): New control values + + * sexp.c (gcry_sexp_sscan): Add hex format parsing. + + * secmem.c (lock_pool): Check for ENOSYS return my mlock() on old SCOs. + (pool_is_mmapped): Made volatile. + (lock_pool): No more warning for QNX. By Sam Roberts. + (lock_pool,secmem_init): Additional check for dropped privs. + +2000-03-21 09:18:48 Werner Koch (wk@habibti.gnupg.de) + + * gcrypt.h (gcry_md_setkey): New. + (GCRY_MD_FLAG_HMAC): New. + +Mon Jan 31 16:37:34 CET 2000 Werner Koch <wk@gnupg.de> + + * Makefile.am: Add g10lib.h + +Thu Jan 27 18:00:44 CET 2000 Werner Koch <wk@gnupg.de> + + * sexp.c (gcry_sexp_sscan): Allow NULL for erroff. + +Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de> + + * sexp.c (gcry_sexp_alist): New. + +Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de> + + * secmem.c: Moved from ../util to here. + * secmem.h: New. + * stdmem.c: New. Based on the old ../util/memory.c. + * stdmem.h: New. + +Wed Dec 8 21:58:32 CET 1999 Werner Koch <wk@gnupg.de> + + * gcrypt.m4: New. + * gcrypt-config: New. + + * mpi.h (mpi_get_nbit_info): Removed + (mpi_set_nbit_info): Removed. + (struct gcry_mpi): Removed the nbits field. + + * misc.c (g10_log_verbosity): New. + + * global.c (g10_xstrdup): New. + + * mpiapi.c: Removed. + + * mpi.h: Moved from ../include to here. Removed some obsolete + prototypes and the iobuf.h header. + * cipher.h: Moved from ../include to here. Removed the mpi.h header. + * g10lib.h: Moved from ../include to here. + +Fri Nov 19 17:15:20 CET 1999 Werner Koch <wk@gnupg.de> + + * sexp.c (dump_string): New. Taken from gnupg/util/miscutil.c. + (do_dump_list): s/print_string/dump_string/. + + * testapi.c: New. + + * mpiapi.c (gcry_mpi_randomize): Use new random API. + +Sat Nov 13 17:44:23 CET 1999 Werner Koch <wk@gnupg.de> + + * gloabl.c (gcry_control): Add cases for dumping random + and secmem stats. + +Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de> + + * pkapi.c: Removed. + + * symapi.c: Removed. + + * g10lib.h: Moved to ../include. + + * mdapi.c: Removed. + +Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * sexp.c: New. + +Tue Dec 8 13:15:16 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * gcrypt.h: New + * mpiapi.c: New + + + Copyright (C) 1998,1999,2000,2001,2002,2003 + 2004,2005,2008,2009,2011 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/grub-core/lib/libgcrypt/src/Makefile.am b/grub-core/lib/libgcrypt/src/Makefile.am new file mode 100644 index 0000000..9168022 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/Makefile.am @@ -0,0 +1,143 @@ +# Makefile.am - for gcrypt/src +# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, +# 2006, 2007 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + + +## Process this file with automake to produce Makefile.in + +EXTRA_DIST = Manifest libgcrypt-config.in libgcrypt.m4 libgcrypt.vers \ + gcrypt.h.in libgcrypt.def + +bin_SCRIPTS = libgcrypt-config +m4datadir = $(datadir)/aclocal +m4data_DATA = libgcrypt.m4 +include_HEADERS = gcrypt.h gcrypt-module.h + +lib_LTLIBRARIES = libgcrypt.la +bin_PROGRAMS = dumpsexp hmac256 +if USE_RANDOM_DAEMON +sbin_PROGRAMS = gcryptrnd +bin_PROGRAMS += getrandom +endif USE_RANDOM_DAEMON + +# Depending on the architecture some targets require libgpg-error. +if HAVE_W32CE_SYSTEM +arch_gpg_error_cflags = $(GPG_ERROR_CFLAGS) +arch_gpg_error_libs = $(GPG_ERROR_LIBS) +else +arch_gpg_error_cflags = +arch_gpg_error_libs = +endif + + +if HAVE_LD_VERSION_SCRIPT + libgcrypt_version_script_cmd = -Wl,--version-script=$(srcdir)/libgcrypt.vers +else + libgcrypt_version_script_cmd = +endif + +libgcrypt_la_CFLAGS = $(GPG_ERROR_CFLAGS) +libgcrypt_la_SOURCES = g10lib.h visibility.c visibility.h types.h \ + cipher.h cipher-proto.h \ + misc.c global.c sexp.c hwfeatures.c \ + stdmem.c stdmem.h secmem.c secmem.h \ + mpi.h missing-string.c module.c fips.c \ + hmac256.c hmac256.h \ + ath.h ath.c + +if HAVE_W32_SYSTEM + +RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(libgcrypt_la_CPPFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) +LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE) + +SUFFIXES = .rc .lo + +.rc.lo: + $(LTRCCOMPILE) -i "$<" -o "$@" + +gcrypt_res = versioninfo.lo +no_undefined = -no-undefined +export_symbols = -export-symbols $(srcdir)/libgcrypt.def + +install-def-file: + $(INSTALL) $(srcdir)/libgcrypt.def $(DESTDIR)$(libdir)/libgcrypt.def + +uninstall-def-file: + -rm $(DESTDIR)$(libdir)/libgcrypt.def + +gcrypt_deps = $(gcrypt_res) libgcrypt.def + +else !HAVE_W32_SYSTEM + +gcrypt_res = +gcrypt_res_ldflag = +no_undefined = +export_symbols = +install-def-file: +uninstall-def-file: + +gcrypt_deps = + +endif !HAVE_W32_SYSTEM + + +libgcrypt_la_LDFLAGS = $(no_undefined) $(export_symbols) \ + $(libgcrypt_version_script_cmd) -version-info \ + @LIBGCRYPT_LT_CURRENT@:@LIBGCRYPT_LT_REVISION@:@LIBGCRYPT_LT_AGE@ +libgcrypt_la_DEPENDENCIES = \ + ../cipher/libcipher.la \ + ../random/librandom.la \ + ../mpi/libmpi.la \ + ../compat/libcompat.la \ + $(srcdir)/libgcrypt.vers $(gcrypt_deps) +libgcrypt_la_LIBADD = $(gcrypt_res) \ + ../cipher/libcipher.la \ + ../random/librandom.la \ + ../mpi/libmpi.la \ + ../compat/libcompat.la $(GPG_ERROR_LIBS) + + +dumpsexp_SOURCES = dumpsexp.c +dumpsexp_CFLAGS = $(arch_gpg_error_cflags) +dumpsexp_LDADD = $(arch_gpg_error_libs) + +hmac256_SOURCES = hmac256.c +hmac256_CFLAGS = -DSTANDALONE $(arch_gpg_error_cflags) +hmac256_LDADD = $(arch_gpg_error_libs) + +if USE_RANDOM_DAEMON +gcryptrnd_SOURCES = gcryptrnd.c +gcryptrnd_CFLAGS = $(GPG_ERROR_CFLAGS) $(PTH_CFLAGS) +gcryptrnd_LDADD = libgcrypt.la $(GPG_ERROR_LIBS) $(PTH_LIBS) + +getrandom_SOURCES = getrandom.c +endif USE_RANDOM_DAEMON + + +install-data-local: install-def-file + +uninstall-local: uninstall-def-file + +# FIXME: We need to figure out how to get the actual name (parsing +# libgcrypt.la?) and how to create the hmac file already at link time +# so that it can be used without installing libgcrypt first. +#install-exec-hook: +# ./hmac256 "What am I, a doctor or a moonshuttle conductor?" \ +# < $(DESTDIR)$(libdir)/libgcrypt.so.11.5.0 \ +# > $(DESTDIR)$(libdir)/.libgcrypt.so.11.5.0.hmac diff --git a/grub-core/lib/libgcrypt/src/Manifest b/grub-core/lib/libgcrypt/src/Manifest new file mode 100644 index 0000000..2d003d8 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/Manifest @@ -0,0 +1,58 @@ +# Manifest - checksums of the src directory +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +# Checksums for all source files in this directory. Format is +# filename, blanks, base-64 part of an OpenPGP detached signature +# without the header lines. Blank lines and lines beginning with a +# hash mark are ignored. A tool to process this file is available by +# cvs -d :pserver:anoncvs@cvs.gnupg.org:/cvs/wk co misc-scripts/manifest-tool +# +# The special entry "$names$" holds a signature over all sorted +# filenames excluding itself. + +gcrypt.h iQCVAwUAQH5RsTEAnp832S/7AQK7xgP+Kc3NY9lipZkaAMrnHDkQVLdHYwTbZWuGOYdTLp8Xy7Auh9wtWV9hrWVUqs+kxDzT/2iF6XkO3WT3rf/PmQ/Q0TIGfOyjE3c/qvB/jVippaxoGda3tnGpODytdI3XPhfPS0Ss8nDzfCStPBGAEq0OVU7imnExrFzhRXt+Gljr0o0==Yagz +gcrypt-module.h iQCVAwUAQH5UXzEAnp832S/7AQJMQgQAzumz9aaZelhw+FxTCeVadphBxt1bbNQvMrnddYYblyJv+AcxZ9ZxGz2oPeusN58Qg54DQcaW3lYhTgnWfXultsi+Ruxlz7400OUrzSXOl3At7KssdODAoscFzZIgh94G9lzQxEBr9lTXI9R3LsPFJP6muNG4frcNBAA42yckK7w==BBp5 + +ath.c iQCVAwUAQH5E+DEAnp832S/7AQKFpgP+KSZHtVcnh9FFggIyHKbALUljW2FXauasZvFyN8Sk/mIMgKxyXFOG1THBAUzWLaKWIEWU+WkYU7uThqBtpnEImM5AenWzbQuJjftPC3gVHO8yjjmBWD4zmJj28htoKDoa/xDsoqumrHxae3FYcaCWtYGVjM/Pbl+OMRMOFAhp0ho==lQZ3 +ath.h iQCVAwUAQH5FODEAnp832S/7AQKiuQQAg4K+KOAn1LWBZN32MAhms4FeZKoce0fAuZW7BpyY4cCxIVgxqrtUC90CDykw8XegFfOyyYrgd0NmaMVdY7HZDncNOvIPxpgFQPCZrycsMOoAtoVwjK704RDeNo3zmeyxTKeDH+3M1J7JmLiafaEdSbOC8flX/W0icaV0Ol4dmBc==Ll6w + +cipher.h iQCVAwUAQH5FUzEAnp832S/7AQJKLgP9GSSk9f7EINIRqSQH1XKX+dYzt3phDHdqFTUGIfYNh7YzGdy0drvgFhG4k15nqDouKRuFVM/hKY3ZVY7JccmKXKGAH6+ZYShoG6LMFfIGgDX8zne0dNxc72PLfns3fVxNn/RlHmHBkrQ+ppjR9HnSthFmOqzbQaW1BKmc3Z2x5GU==lIeW +g10lib.h iQCVAwUAQH5FejEAnp832S/7AQJ75wP/ZjOybwRix5eoXdfVeXPjoPygejzpYJJdMUGN3Y5UtkfBu9mPREsKfvZ6tH+Evjx+3xfeAb4bU/k2mRMp0tiWnk2koToS08vI9uxnioKQr9oulZH6r28S+NLSgMQuEGN1JNUky6RQ9TTNRndeTjKKSrEjZ7V6bv+rb8A1bYCKChs==P5mk +mpi.h iQCVAwUAQH5FwzEAnp832S/7AQJJ4wP9E3jVkcO9M0YtSBHIbjG3hDWKWXzi86AlUh51qiE8/2XP0FfjA4TosyvmicZs7j48HitAByr9tHOSxnbeo7NBf17ICwAo6Eqty+wKDg+eyLeEGUy7VpVK3RJRQAA4H+kl3S2l3YMTKf3WJlbc7qkWSXZspdy5c9sAxeodCKrAubU==oALf + +global.c iQCVAwUAQH5HFzEAnp832S/7AQJc+QQAvi53ZkMCzLnVULHvhI6W+EX537zi9n8cplYguvIJqUhAZrP68yGAIyqyCONbZVDyB7wqeXdUMLzMk7W8fg+xuk5JSDpppAQf2m/bdQyze6XVqJso682eYBM8+b9z/IVEvLaFwhZcOKO1bcXudBlBCcJgVDpupfTtAWgPnewil9Q==Xwy1 +misc.c iQCVAwUAQH5IIjEAnp832S/7AQKNJAQAkEpyY3fCG7tvADJFAW9xA7DEQwLCa8YmiUhHvrEsWOI4YgvS7LUbWWc7VqK+ryORvXLKRAVieznbnHAuy0TKtqdnmA/kUmiurS0ah5SWqR/iuAeJtt0RGsmZaZ6oa2m4PZ2Y2GCHSTZqcclvwsetS9eq5AipxHxYFUltu5wGZNI==twM2 +missing-string.c iQCVAwUAQH5JfjEAnp832S/7AQI3ZQQAg55eEJbGQQHyBEJGxvt/FXpQiXcoDit3ZHzvdaQn/NUgdLjCHiWVzhyCXACGivLWMNModDaSaZk073NXxVkWfPcX9vkF//Wugwzidd5P3Bfu5k35o+Xxz82fsk5KuFGGq1mBUZ07xUYQ8KkKkhADUkr0QiQAuypp079Yq0uUC7Q==zvKn +module.c iQCVAwUAQH5JvjEAnp832S/7AQKlMgQAjZYTXMpWb5kHxCMXzRi069Ku/4/xnWsD+S0dje1LiKzCnRpwTTxARzc/y10Y8OcygkMuR4unEaWedO+9syjjty3fBCcue/j7YlLitq5EC9UE4o23poWvWCuX9Tadm2DK5qf4p7smMJ22O22cLTYTVCyAoYTQ2xC8ajzBsBRkX80==yRRD +secmem.c iQCVAwUAQH5LLDEAnp832S/7AQKtFwQAwY2wBr6WJC1cwqp/1DQoKzHx9C3plONxbZMazwR7VMI83NUbBAbv1mcxpeZWXmb2dRrnsR1VBbNPDSbJLN5T6czLQ2nIb6mnq9u8Ip4SAa+GCWfDV4AUtAJ4hN/yvWo8iEKu+KD5iJ6xJh31NdXjt5yk6vnk46SA6R4FkHdIEXc==UKVr +secmem.h iQCVAwUAQH5LTDEAnp832S/7AQIsJwQAkZUu4hvmh9NXCLNm98+tGZFzWYvZO/NffC2wdPE8Q/OTa/m3g+oBbEhaV1ze3oY4t1F/p7ZHFx5CsIp4zVjyPkxlni8AAVMUOQr/LopyxouHn2OjKO+dVqecWQf01+nPWjklbL2FZ3mQ99k2qeWZlVSkz0nm8u39F3v7z3OTCss==AJqE +sexp.c iQCVAwUAQH5LojEAnp832S/7AQKCTQQArlrj1KGwR2x93fcyN3M0iXuGkBq5R9KNu+1Bq04G4SLlpZ1RRY0OjV3L9To1BHTd01lXlO8MNz7NpRxWlG1Sw5FohbBlhWZQRcW8GdAawJPcfIY2Y8Ek6Yx8quZKbk9uD3bcBmStmg0P+TIA0nr20bmtfB3uX2KQVHQqWZQT5qU==P8FE +stdmem.c iQCVAwUAQH5LzjEAnp832S/7AQLOUAP9FU16itXBBrkfRDGmhUjAOeEEKdd+brQ3XdT8xoLvP/IH/6U1Kq3ampP2/xcL4kwVdz2rw6NRzP7jlL/yM3tW722lSS/JPJkH+2+qUkcb0fYNoql/WYPMYp1/Mzu6ttXnjag1cQGlKIyYAD+G6h3FtpLwQy0hEJopnF9+Ovd8U7A==CkiZ +stdmem.h iQCVAwUAQH5L8jEAnp832S/7AQIH0wP+Lyqh0tj++s2L79Tmf/gqgCK+HLMxTddcewF3XbsYf9T5FmLez1gz6Ggti4Ss9VjozOA3ti3trCiA/YNRmV9AYw4zLUPm+MsjJuveL/AgB9HdoD2v+RfJm0WwgSKiysp+8iyjg3Plopmhba4cGuOP5MJ3CWTqYwPmJVscUKC6g38==02MN + +types.h iQCVAwUAQH5MKTEAnp832S/7AQLqTAP6A3mUMD5MMkBkebq4bRY6Bq0KsgdKfZ8TLhc2o87gFay8YD0Uom3YJNG2LF/rAIct2ih4jYJaIb5dRfJ0KJoPi2ETd462J8OFCL4fjq9TaSjB2pXcB+kWoxzPasGNg2Ukk0dQ6lvF1tSYrtt32PVI7q/UaPsjTylgRmzLfX/VxrU==OMu3 + + +# Configuration +Makefile.am iQCVAwUAQH5WVjEAnp832S/7AQLmsQP/bbI8/UWAC5yITVhGcCOCbN/FaMqXVKjxESzo6GTs02jxK1y3RuuaoNU1ssQZGAxpFiMJW8u933V3yTHFMxWpwHemDnEyv/a8YACxJBQ0tQgpgHS716BjMbHOfcuOis2WlCOOm0ErjhAYNa4NQ1q3jwkOvTDLFpdnqaWI2wWn08U==Yjun +libgcrypt.m4 iQCVAwUAQH5MbTEAnp832S/7AQJ1uAQA1C6xI7qXiKVtUeXawhPytAldosrzcXmqz34xi7JklQqw83d68WtWHFMBEUa7MKfi4WCbuQb7FjGUvMRw5z/T9ez7CoDekHc63+cIIZLQ23weUK8GaA1uQLoD0scmT41J5RkBlJbH7ck1zRd3d04o75rWNEUNit6KBvrQ4Pd8oQ8==uMgB +libgcrypt-config.in iQCVAwUAQH5UbzEAnp832S/7AQJISgP+Nbd2AQnDM/k8sQLbvz8YZjwX3LigZM+AkF1VAwyAm6YOU3nrXnz5t+cXkQD2dkz4L2F0AAsIkFiJsrgmZgCp2h1L6LeFnH+hoId9RhbYw4NkDaHb+MC9JcalpcfFvvxq6vM/W37bSFimM78P+5RLKypXCytVQNAAaIRgZjVfXY8==IGDS +libgcrypt.vers iQCVAwUAQH5MjTEAnp832S/7AQKCdQQAotG6Z3zdcePI0V33YY2sh91uYkLBNhQw+PzyE3BRRAVhMGLOBD1nSWJHJvE3eyCVOqFY0ZmvpVex51Fa0D/TwsJOO4RVxf1L9bbAncu9OuEXaGXKytLZp54TliDTAWGDq0lvtx1TvDDgtM8TbbaXvMbjfQ4wXBxdLvaenFCTlR4==kgHq + +$names$ iQCVAwUAQH5UhDEAnp832S/7AQK/jwP9H7A3mI99M1NGuhD+16C+2gJIITB8GJeYeUd3vm8kWQ5n76WyMCdeA62qn0JUddIBjAbagtfvTL5aesnD9MlhEGaNlHauU7SINTIJ8njKf87EAAfDZrhS/tGDziC2nakMPweRxXQCLDWHkBPjYfrspSLLohjdegqBvTNyVM76+KE==3p9Z diff --git a/grub-core/lib/libgcrypt/src/ath.c b/grub-core/lib/libgcrypt/src/ath.c new file mode 100644 index 0000000..656ed89 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/ath.c @@ -0,0 +1,344 @@ +/* ath.c - Thread-safeness library. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with Libgcrypt; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <assert.h> /* Right: We need to use assert and not gcry_assert. */ +#include <unistd.h> +#ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +#else +# include <sys/time.h> +#endif +#include <sys/types.h> +#ifndef _WIN32 +#include <sys/wait.h> +#endif +#include <errno.h> + +#include "ath.h" + + + +/* The interface table. */ +static struct ath_ops ops; + +/* True if we should use the external callbacks. */ +static int ops_set; + + +/* For the dummy interface. */ +#define MUTEX_UNLOCKED ((ath_mutex_t) 0) +#define MUTEX_LOCKED ((ath_mutex_t) 1) +#define MUTEX_DESTROYED ((ath_mutex_t) 2) + + +/* Return the thread type from the option field. */ +#define GET_OPTION(a) ((a) & 0xff) +/* Return the version number from the option field. */ +#define GET_VERSION(a) (((a) >> 8)& 0xff) + + + +/* The lock we take while checking for lazy lock initialization. */ +static ath_mutex_t check_init_lock = ATH_MUTEX_INITIALIZER; + +int +ath_init (void) +{ + int err = 0; + + if (ops_set) + { + if (ops.init) + err = (*ops.init) (); + if (err) + return err; + err = (*ops.mutex_init) (&check_init_lock); + } + return err; +} + + +/* Initialize the locking library. Returns 0 if the operation was + successful, EINVAL if the operation table was invalid and EBUSY if + we already were initialized. */ +gpg_err_code_t +ath_install (struct ath_ops *ath_ops, int check_only) +{ + if (check_only) + { + unsigned int option = 0; + + /* Check if the requested thread option is compatible to the + thread option we are already committed to. */ + if (ath_ops) + option = ath_ops->option; + + if (!ops_set && GET_OPTION (option)) + return GPG_ERR_NOT_SUPPORTED; + + if (GET_OPTION (ops.option) == ATH_THREAD_OPTION_USER + || GET_OPTION (option) == ATH_THREAD_OPTION_USER + || GET_OPTION (ops.option) != GET_OPTION (option) + || GET_VERSION (ops.option) != GET_VERSION (option)) + return GPG_ERR_NOT_SUPPORTED; + + return 0; + } + + if (ath_ops) + { + /* It is convenient to not require DESTROY. */ + if (!ath_ops->mutex_init || !ath_ops->mutex_lock + || !ath_ops->mutex_unlock) + return GPG_ERR_INV_ARG; + + ops = *ath_ops; + ops_set = 1; + } + else + ops_set = 0; + + return 0; +} + + +static int +mutex_init (ath_mutex_t *lock, int just_check) +{ + int err = 0; + + if (just_check) + (*ops.mutex_lock) (&check_init_lock); + if (*lock == ATH_MUTEX_INITIALIZER || !just_check) + err = (*ops.mutex_init) (lock); + if (just_check) + (*ops.mutex_unlock) (&check_init_lock); + return err; +} + + +int +ath_mutex_init (ath_mutex_t *lock) +{ + if (ops_set) + return mutex_init (lock, 0); + +#ifndef NDEBUG + *lock = MUTEX_UNLOCKED; +#endif + return 0; +} + + +int +ath_mutex_destroy (ath_mutex_t *lock) +{ + if (ops_set) + { + if (!ops.mutex_destroy) + return 0; + + (*ops.mutex_lock) (&check_init_lock); + if (*lock == ATH_MUTEX_INITIALIZER) + { + (*ops.mutex_unlock) (&check_init_lock); + return 0; + } + (*ops.mutex_unlock) (&check_init_lock); + return (*ops.mutex_destroy) (lock); + } + +#ifndef NDEBUG + assert (*lock == MUTEX_UNLOCKED); + + *lock = MUTEX_DESTROYED; +#endif + return 0; +} + + +int +ath_mutex_lock (ath_mutex_t *lock) +{ + if (ops_set) + { + int ret = mutex_init (lock, 1); + if (ret) + return ret; + return (*ops.mutex_lock) (lock); + } + +#ifndef NDEBUG + assert (*lock == MUTEX_UNLOCKED); + + *lock = MUTEX_LOCKED; +#endif + return 0; +} + + +int +ath_mutex_unlock (ath_mutex_t *lock) +{ + if (ops_set) + { + int ret = mutex_init (lock, 1); + if (ret) + return ret; + return (*ops.mutex_unlock) (lock); + } + +#ifndef NDEBUG + assert (*lock == MUTEX_LOCKED); + + *lock = MUTEX_UNLOCKED; +#endif + return 0; +} + + +ssize_t +ath_read (int fd, void *buf, size_t nbytes) +{ + if (ops_set && ops.read) + return (*ops.read) (fd, buf, nbytes); + else + return read (fd, buf, nbytes); +} + + +ssize_t +ath_write (int fd, const void *buf, size_t nbytes) +{ + if (ops_set && ops.write) + return (*ops.write) (fd, buf, nbytes); + else + return write (fd, buf, nbytes); +} + + +ssize_t +#ifdef _WIN32 +ath_select (int nfd, void *rset, void *wset, void *eset, + struct timeval *timeout) +#else +ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout) +#endif +{ + if (ops_set && ops.select) + return (*ops.select) (nfd, rset, wset, eset, timeout); + else +#ifdef _WIN32 + return -1; +#else + return select (nfd, rset, wset, eset, timeout); +#endif +} + + +ssize_t +ath_waitpid (pid_t pid, int *status, int options) +{ + if (ops_set && ops.waitpid) + return (*ops.waitpid) (pid, status, options); + else +#ifdef _WIN32 + return -1; +#else + return waitpid (pid, status, options); +#endif +} + + +int +#ifdef _WIN32 +ath_accept (int s, void *addr, int *length_ptr) +#else +ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr) +#endif +{ + if (ops_set && ops.accept) + return (*ops.accept) (s, addr, length_ptr); + else +#ifdef _WIN32 + return -1; +#else + return accept (s, addr, length_ptr); +#endif +} + + +int +#ifdef _WIN32 +ath_connect (int s, void *addr, int length) +#else +ath_connect (int s, struct sockaddr *addr, socklen_t length) +#endif +{ + if (ops_set && ops.connect) + return (*ops.connect) (s, addr, length); + else +#ifdef _WIN32 + return -1; +#else + return connect (s, addr, length); +#endif +} + + +int +#ifdef _WIN32 +ath_sendmsg (int s, const void *msg, int flags) +#else +ath_sendmsg (int s, const struct msghdr *msg, int flags) +#endif +{ + if (ops_set && ops.sendmsg) + return (*ops.sendmsg) (s, msg, flags); + else +#ifdef _WIN32 + return -1; +#else + return sendmsg (s, msg, flags); +#endif +} + + +int +#ifdef _WIN32 +ath_recvmsg (int s, void *msg, int flags) +#else +ath_recvmsg (int s, struct msghdr *msg, int flags) +#endif +{ + if (ops_set && ops.recvmsg) + return (*ops.recvmsg) (s, msg, flags); + else +#ifdef _WIN32 + return -1; +#else + return recvmsg (s, msg, flags); +#endif +} diff --git a/grub-core/lib/libgcrypt/src/ath.h b/grub-core/lib/libgcrypt/src/ath.h new file mode 100644 index 0000000..8769551 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/ath.h @@ -0,0 +1,147 @@ +/* ath.h - Thread-safeness library. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with Libgcrypt; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef ATH_H +#define ATH_H + +#include <config.h> + +#ifdef _WIN32 +# include <windows.h> +#else /* !_WIN32 */ +# ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +# else +# include <sys/time.h> +# endif +# include <sys/types.h> +# ifdef HAVE_SYS_MSG_H +# include <sys/msg.h> /* (e.g. for zOS) */ +# endif +# include <sys/socket.h> +#endif /* !_WIN32 */ +#include <gpg-error.h> + + + +/* Define _ATH_EXT_SYM_PREFIX if you want to give all external symbols + a prefix. */ +#define _ATH_EXT_SYM_PREFIX _gcry_ + +#ifdef _ATH_EXT_SYM_PREFIX +#define _ATH_PREFIX1(x,y) x ## y +#define _ATH_PREFIX2(x,y) _ATH_PREFIX1(x,y) +#define _ATH_PREFIX(x) _ATH_PREFIX2(_ATH_EXT_SYM_PREFIX,x) +#define ath_install _ATH_PREFIX(ath_install) +#define ath_init _ATH_PREFIX(ath_init) +#define ath_mutex_init _ATH_PREFIX(ath_mutex_init) +#define ath_mutex_destroy _ATH_PREFIX(ath_mutex_destroy) +#define ath_mutex_lock _ATH_PREFIX(ath_mutex_lock) +#define ath_mutex_unlock _ATH_PREFIX(ath_mutex_unlock) +#define ath_read _ATH_PREFIX(ath_read) +#define ath_write _ATH_PREFIX(ath_write) +#define ath_select _ATH_PREFIX(ath_select) +#define ath_waitpid _ATH_PREFIX(ath_waitpid) +#define ath_connect _ATH_PREFIX(ath_connect) +#define ath_accept _ATH_PREFIX(ath_accept) +#define ath_sendmsg _ATH_PREFIX(ath_sendmsg) +#define ath_recvmsg _ATH_PREFIX(ath_recvmsg) +#endif + + +enum ath_thread_option + { + ATH_THREAD_OPTION_DEFAULT = 0, + ATH_THREAD_OPTION_USER = 1, + ATH_THREAD_OPTION_PTH = 2, + ATH_THREAD_OPTION_PTHREAD = 3 + }; + +struct ath_ops +{ + /* The OPTION field encodes the thread model and the version number + of this structure. + Bits 7 - 0 are used for the thread model + Bits 15 - 8 are used for the version number. + */ + unsigned int option; + + int (*init) (void); + int (*mutex_init) (void **priv); + int (*mutex_destroy) (void *priv); + int (*mutex_lock) (void *priv); + int (*mutex_unlock) (void *priv); + ssize_t (*read) (int fd, void *buf, size_t nbytes); + ssize_t (*write) (int fd, const void *buf, size_t nbytes); +#ifdef _WIN32 + ssize_t (*select) (int nfd, void *rset, void *wset, void *eset, + struct timeval *timeout); + ssize_t (*waitpid) (pid_t pid, int *status, int options); + int (*accept) (int s, void *addr, int *length_ptr); + int (*connect) (int s, void *addr, int length); + int (*sendmsg) (int s, const void *msg, int flags); + int (*recvmsg) (int s, void *msg, int flags); +#else + ssize_t (*select) (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout); + ssize_t (*waitpid) (pid_t pid, int *status, int options); + int (*accept) (int s, struct sockaddr *addr, socklen_t *length_ptr); + int (*connect) (int s, struct sockaddr *addr, socklen_t length); + int (*sendmsg) (int s, const struct msghdr *msg, int flags); + int (*recvmsg) (int s, struct msghdr *msg, int flags); +#endif +}; + +gpg_err_code_t ath_install (struct ath_ops *ath_ops, int check_only); +int ath_init (void); + + +/* Functions for mutual exclusion. */ +typedef void *ath_mutex_t; +#define ATH_MUTEX_INITIALIZER 0 + +int ath_mutex_init (ath_mutex_t *mutex); +int ath_mutex_destroy (ath_mutex_t *mutex); +int ath_mutex_lock (ath_mutex_t *mutex); +int ath_mutex_unlock (ath_mutex_t *mutex); + +/* Replacement for the POSIX functions, which can be used to allow + other (user-level) threads to run. */ +ssize_t ath_read (int fd, void *buf, size_t nbytes); +ssize_t ath_write (int fd, const void *buf, size_t nbytes); +#ifdef _WIN32 +ssize_t ath_select (int nfd, void *rset, void *wset, void *eset, + struct timeval *timeout); +ssize_t ath_waitpid (pid_t pid, int *status, int options); +int ath_accept (int s, void *addr, int *length_ptr); +int ath_connect (int s, void *addr, int length); +int ath_sendmsg (int s, const void *msg, int flags); +int ath_recvmsg (int s, void *msg, int flags); +#else +ssize_t ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, + struct timeval *timeout); +ssize_t ath_waitpid (pid_t pid, int *status, int options); +int ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr); +int ath_connect (int s, struct sockaddr *addr, socklen_t length); +int ath_sendmsg (int s, const struct msghdr *msg, int flags); +int ath_recvmsg (int s, struct msghdr *msg, int flags); +#endif + +#endif /* ATH_H */ diff --git a/grub-core/lib/libgcrypt/src/cipher-proto.h b/grub-core/lib/libgcrypt/src/cipher-proto.h new file mode 100644 index 0000000..347681f --- /dev/null +++ b/grub-core/lib/libgcrypt/src/cipher-proto.h @@ -0,0 +1,124 @@ +/* cipher-proto.h - Internal declarations + * Copyright (C) 2008, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* This file has been factored out from cipher.h so that it can be + used standalone in visibility.c . */ + +#ifndef G10_CIPHER_PROTO_H +#define G10_CIPHER_PROTO_H + +/* Definition of a function used to report selftest failures. + DOMAIN is a string describing the function block: + "cipher", "digest", "pubkey or "random", + ALGO is the algorithm under test, + WHAT is a string describing what has been tested, + DESC is a string describing the error. */ +typedef void (*selftest_report_func_t)(const char *domain, + int algo, + const char *what, + const char *errdesc); + +/* Definition of the selftest functions. */ +typedef gpg_err_code_t (*selftest_func_t) + (int algo, int extended, selftest_report_func_t report); + + +/* An extended type of the generate function. */ +typedef gcry_err_code_t (*pk_ext_generate_t) + (int algo, + unsigned int nbits, + unsigned long evalue, + gcry_sexp_t genparms, + gcry_mpi_t *skey, + gcry_mpi_t **retfactors, + gcry_sexp_t *extrainfo); + +/* The type used to compute the keygrip. */ +typedef gpg_err_code_t (*pk_comp_keygrip_t) + (gcry_md_hd_t md, gcry_sexp_t keyparm); + +/* The type used to query ECC curve parameters. */ +typedef gcry_err_code_t (*pk_get_param_t) + (const char *name, gcry_mpi_t *pkey); + +/* The type used to query an ECC curve name. */ +typedef const char *(*pk_get_curve_t)(gcry_mpi_t *pkey, int iterator, + unsigned int *r_nbits); + +/* The type used to query ECC curve parameters by name. */ +typedef gcry_sexp_t (*pk_get_curve_param_t)(const char *name); + +/* The type used to convey additional information to a cipher. */ +typedef gpg_err_code_t (*cipher_set_extra_info_t) + (void *c, int what, const void *buffer, size_t buflen); + + +/* Extra module specification structures. These are used for internal + modules which provide more functions than available through the + public algorithm register APIs. */ +typedef struct cipher_extra_spec +{ + selftest_func_t selftest; + cipher_set_extra_info_t set_extra_info; +} cipher_extra_spec_t; + +typedef struct md_extra_spec +{ + selftest_func_t selftest; +} md_extra_spec_t; + +typedef struct pk_extra_spec +{ + selftest_func_t selftest; + pk_ext_generate_t ext_generate; + pk_comp_keygrip_t comp_keygrip; + pk_get_param_t get_param; + pk_get_curve_t get_curve; + pk_get_curve_param_t get_curve_param; +} pk_extra_spec_t; + + + +/* The private register functions. */ +gcry_error_t _gcry_cipher_register (gcry_cipher_spec_t *cipher, + cipher_extra_spec_t *extraspec, + int *algorithm_id, + gcry_module_t *module); +gcry_error_t _gcry_md_register (gcry_md_spec_t *cipher, + md_extra_spec_t *extraspec, + unsigned int *algorithm_id, + gcry_module_t *module); +gcry_error_t _gcry_pk_register (gcry_pk_spec_t *cipher, + pk_extra_spec_t *extraspec, + unsigned int *algorithm_id, + gcry_module_t *module); + +/* The selftest functions. */ +gcry_error_t _gcry_cipher_selftest (int algo, int extended, + selftest_report_func_t report); +gcry_error_t _gcry_md_selftest (int algo, int extended, + selftest_report_func_t report); +gcry_error_t _gcry_pk_selftest (int algo, int extended, + selftest_report_func_t report); +gcry_error_t _gcry_hmac_selftest (int algo, int extended, + selftest_report_func_t report); + +gcry_error_t _gcry_random_selftest (selftest_report_func_t report); + +#endif /*G10_CIPHER_PROTO_H*/ diff --git a/grub-core/lib/libgcrypt/src/cipher.h b/grub-core/lib/libgcrypt/src/cipher.h new file mode 100644 index 0000000..48eeeda --- /dev/null +++ b/grub-core/lib/libgcrypt/src/cipher.h @@ -0,0 +1,182 @@ +/* cipher.h + * Copyright (C) 1998, 2002, 2003, 2009 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef G10_CIPHER_H +#define G10_CIPHER_H + +#include <gcrypt.h> + +#define DBG_CIPHER _gcry_get_debug_flag( 1 ) + +#include "../random/random.h" + +#define PUBKEY_FLAG_NO_BLINDING (1 << 0) + +enum pk_operation + { + PUBKEY_OP_ENCRYPT, + PUBKEY_OP_DECRYPT, + PUBKEY_OP_SIGN, + PUBKEY_OP_VERIFY + }; + +enum pk_encoding + { + PUBKEY_ENC_RAW, + PUBKEY_ENC_PKCS1, + PUBKEY_ENC_OAEP, + PUBKEY_ENC_PSS, + PUBKEY_ENC_UNKNOWN + }; + +struct pk_encoding_ctx +{ + enum pk_operation op; + unsigned int nbits; + + enum pk_encoding encoding; + int flags; + + int hash_algo; + + /* for OAEP */ + unsigned char *label; + size_t labellen; + + /* for PSS */ + size_t saltlen; + + int (* verify_cmp) (void *opaque, gcry_mpi_t tmp); + void *verify_arg; +}; + +#define CIPHER_INFO_NO_WEAK_KEY 1 + +#include "cipher-proto.h" + + +/*-- rmd160.c --*/ +void _gcry_rmd160_hash_buffer (void *outbuf, + const void *buffer, size_t length); +/*-- sha1.c --*/ +void _gcry_sha1_hash_buffer (void *outbuf, + const void *buffer, size_t length); + +/*-- rijndael.c --*/ +void _gcry_aes_cfb_enc (void *context, unsigned char *iv, + void *outbuf, const void *inbuf, + unsigned int nblocks); +void _gcry_aes_cfb_dec (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); +void _gcry_aes_cbc_enc (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks, int cbc_mac); +void _gcry_aes_cbc_dec (void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); +void _gcry_aes_ctr_enc (void *context, unsigned char *ctr, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); + + +/*-- dsa.c --*/ +void _gcry_register_pk_dsa_progress (gcry_handler_progress_t cbc, void *cb_data); + +/*-- elgamal.c --*/ +void _gcry_register_pk_elg_progress (gcry_handler_progress_t cb, + void *cb_data); + + +/*-- ecc.c --*/ +void _gcry_register_pk_ecc_progress (gcry_handler_progress_t cbc, + void *cb_data); + + +/*-- primegen.c --*/ +void _gcry_register_primegen_progress (gcry_handler_progress_t cb, + void *cb_data); + +/*-- pubkey.c --*/ +const char * _gcry_pk_aliased_algo_name (int algorithm); + +/* Declarations for the cipher specifications. */ +extern gcry_cipher_spec_t _gcry_cipher_spec_blowfish; +extern gcry_cipher_spec_t _gcry_cipher_spec_des; +extern gcry_cipher_spec_t _gcry_cipher_spec_tripledes; +extern gcry_cipher_spec_t _gcry_cipher_spec_arcfour; +extern gcry_cipher_spec_t _gcry_cipher_spec_cast5; +extern gcry_cipher_spec_t _gcry_cipher_spec_aes; +extern gcry_cipher_spec_t _gcry_cipher_spec_aes192; +extern gcry_cipher_spec_t _gcry_cipher_spec_aes256; +extern gcry_cipher_spec_t _gcry_cipher_spec_twofish; +extern gcry_cipher_spec_t _gcry_cipher_spec_twofish128; +extern gcry_cipher_spec_t _gcry_cipher_spec_serpent128; +extern gcry_cipher_spec_t _gcry_cipher_spec_serpent192; +extern gcry_cipher_spec_t _gcry_cipher_spec_serpent256; +extern gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_40; +extern gcry_cipher_spec_t _gcry_cipher_spec_seed; +extern gcry_cipher_spec_t _gcry_cipher_spec_camellia128; +extern gcry_cipher_spec_t _gcry_cipher_spec_camellia192; +extern gcry_cipher_spec_t _gcry_cipher_spec_camellia256; +extern gcry_cipher_spec_t _gcry_cipher_spec_idea; + +extern cipher_extra_spec_t _gcry_cipher_extraspec_tripledes; +extern cipher_extra_spec_t _gcry_cipher_extraspec_aes; +extern cipher_extra_spec_t _gcry_cipher_extraspec_aes192; +extern cipher_extra_spec_t _gcry_cipher_extraspec_aes256; + + +/* Declarations for the digest specifications. */ +extern gcry_md_spec_t _gcry_digest_spec_crc32; +extern gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510; +extern gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440; +extern gcry_md_spec_t _gcry_digest_spec_md4; +extern gcry_md_spec_t _gcry_digest_spec_md5; +extern gcry_md_spec_t _gcry_digest_spec_rmd160; +extern gcry_md_spec_t _gcry_digest_spec_sha1; +extern gcry_md_spec_t _gcry_digest_spec_sha224; +extern gcry_md_spec_t _gcry_digest_spec_sha256; +extern gcry_md_spec_t _gcry_digest_spec_sha512; +extern gcry_md_spec_t _gcry_digest_spec_sha384; +extern gcry_md_spec_t _gcry_digest_spec_tiger; +extern gcry_md_spec_t _gcry_digest_spec_tiger1; +extern gcry_md_spec_t _gcry_digest_spec_tiger2; +extern gcry_md_spec_t _gcry_digest_spec_whirlpool; + +extern md_extra_spec_t _gcry_digest_extraspec_sha1; +extern md_extra_spec_t _gcry_digest_extraspec_sha224; +extern md_extra_spec_t _gcry_digest_extraspec_sha256; +extern md_extra_spec_t _gcry_digest_extraspec_sha384; +extern md_extra_spec_t _gcry_digest_extraspec_sha512; + +/* Declarations for the pubkey cipher specifications. */ +extern gcry_pk_spec_t _gcry_pubkey_spec_rsa; +extern gcry_pk_spec_t _gcry_pubkey_spec_elg; +extern gcry_pk_spec_t _gcry_pubkey_spec_dsa; +extern gcry_pk_spec_t _gcry_pubkey_spec_ecdsa; +extern gcry_pk_spec_t _gcry_pubkey_spec_ecdh; + +extern pk_extra_spec_t _gcry_pubkey_extraspec_rsa; +extern pk_extra_spec_t _gcry_pubkey_extraspec_dsa; +extern pk_extra_spec_t _gcry_pubkey_extraspec_elg; +extern pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa; + + +#endif /*G10_CIPHER_H*/ diff --git a/grub-core/lib/libgcrypt/src/dumpsexp.c b/grub-core/lib/libgcrypt/src/dumpsexp.c new file mode 100644 index 0000000..f6384d7 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/dumpsexp.c @@ -0,0 +1,766 @@ +/* dumpsexp.c - Dump S-expressions. + * Copyright (C) 2007, 2010 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 3 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> +#include <stdarg.h> +#include <errno.h> +/* For a native WindowsCE binary we need to include gpg-error.h to + provide a replacement for strerror. */ +#ifdef __MINGW32CE__ +# include <gpg-error.h> +#endif + +#define PGM "dumpsexp" +#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION +#define BUGREPORT_LINE "\nReport bugs to <bug-libgcrypt@gnupg.org>.\n" + + +static int verbose; /* Verbose mode. */ +static int decimal; /* Print addresses in decimal. */ +static int assume_hex; /* Assume input is hexencoded. */ +static int advanced; /* Advanced format output. */ + +static void +print_version (int with_help) +{ + fputs (MYVERSION_LINE "\n" + "Copyright (C) 2010 Free Software Foundation, Inc.\n" + "License GPLv3+: GNU GPL version 3 or later " + "<http://gnu.org/licenses/gpl.html>\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", + stdout); + + if (with_help) + fputs ("\n" + "Usage: " PGM " [OPTIONS] [file]\n" + "Debug tool for S-expressions\n" + "\n" + " --decimal Print offsets using decimal notation\n" + " --assume-hex Assume input is a hex dump\n" + " --advanced Print file in advanced format\n" + " --verbose Show what we are doing\n" + " --version Print version of the program and exit\n" + " --help Display this help and exit\n" + BUGREPORT_LINE, stdout ); + + exit (0); +} + +static int +print_usage (void) +{ + fputs ("usage: " PGM " [OPTIONS] NBYTES\n", stderr); + fputs (" (use --help to display options)\n", stderr); + exit (1); +} + + +#define space_p(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t') +#define digit_p(a) ((a) >= '0' && (a) <= '9') +#define octdigit_p(a) ((a) >= '0' && (a) <= '7') +#define alpha_p(a) ( ((a) >= 'A' && (a) <= 'Z') \ + || ((a) >= 'a' && (a) <= 'z')) +#define hexdigit_p(a) (digit_p (a) \ + || ((a) >= 'A' && (a) <= 'F') \ + || ((a) >= 'a' && (a) <= 'f')) +#define xtoi_1(a) ((a) <= '9'? ((a)- '0'): \ + (a) <= 'F'? ((a)-'A'+10):((a)-'a'+10)) + + +/* Return true if P points to a byte containing a whitespace according + to the S-expressions definition. */ +static inline int +whitespace_p (int c) +{ + switch (c) + { + case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1; + default: return 0; + } +} + +static void +logit (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format) ; + fputs (PGM ": ", stderr); + vfprintf (stderr, format, arg_ptr); + putc ('\n', stderr); + va_end (arg_ptr); +} + +/* The raw data buffer and its current length */ +static unsigned char databuffer[16]; +static int databufferlen; +/* The number of bytes in databuffer which should be skipped at a flush. */ +static int skipdatabufferlen; +/* The number of raw bytes printed on the last line. */ +static int nbytesprinted; +/* The file offset of the current data buffer . */ +static unsigned long databufferoffset; + + + +static int +my_getc (FILE *fp) +{ + int c1, c2; + + if (!assume_hex) + return getc (fp); + + while ( (c1=getc (fp)) != EOF && space_p (c1) ) + ; + if (c1 == EOF) + return EOF; + + if (!hexdigit_p (c1)) + { + logit ("non hex-digit encountered\n"); + return EOF; + } + + while ( (c2=getc (fp)) != EOF && space_p (c2) ) + ; + if (c2 == EOF) + { + logit ("error reading second hex nibble\n"); + return EOF; + } + if (!hexdigit_p (c2)) + { + logit ("second hex nibble is not a hex-digit\n"); + return EOF; + } + return xtoi_1 (c1) * 16 + xtoi_1 (c2); +} + + + + + +/* Flush the raw data buffer. */ +static void +flushdatabuffer (void) +{ + int i; + + if (!databufferlen) + return; + nbytesprinted = 0; + if (decimal) + printf ("%08lu ", databufferoffset); + else + printf ("%08lx ", databufferoffset); + for (i=0; i < databufferlen; i++) + { + if (i == 8) + putchar (' '); + if (i < skipdatabufferlen) + fputs (" ", stdout); + else + { + printf (" %02x", databuffer[i]); + databufferoffset++; + } + nbytesprinted++; + } + for (; i < sizeof (databuffer); i++) + { + if (i == 8) + putchar (' '); + fputs (" ", stdout); + } + fputs (" |", stdout); + for (i=0; i < databufferlen; i++) + { + if (i < skipdatabufferlen) + putchar (' '); + else if (databuffer[i] >= ' ' && databuffer[i] <= '~' + && databuffer[i] != '|') + putchar (databuffer[i]); + else + putchar ('.'); + } + putchar ('|'); + putchar ('\n'); + databufferlen = 0; + skipdatabufferlen = 0; +} + + +/* Add C to the raw data buffer and flush as needed. */ +static void +addrawdata (int c) +{ + if ( databufferlen >= sizeof databuffer ) + flushdatabuffer (); + databuffer[databufferlen++] = c; +} + + +static void +printcursor (int both) +{ + int i; + + flushdatabuffer (); + printf ("%8s ", ""); + for (i=0; i < sizeof (databuffer); i++) + { + if (i == 8) + putchar (' '); + if (i+1 == nbytesprinted) + { + fputs (" ^ ", stdout); + if (!both) + break; + } + else + fputs (" ", stdout); + } + if (both) + { + fputs (" ", stdout); + for (i=0; i < nbytesprinted-1; i++) + putchar (' '); + putchar ('^'); + } + databufferlen = skipdatabufferlen = nbytesprinted; +} + +static void +printerr (const char *text) +{ + printcursor (1); + printf ("\n Error: %s\n", text); +} + +static void +printctl (const char *text) +{ + if (verbose && !advanced) + { + printcursor (0); + printf ("%s\n", text); + } +} + +static void +printchr (int c) +{ + putchar (c); +} + +/* static void */ +/* printhex (int c) */ +/* { */ +/* printf ("\\x%02x", c); */ +/* } */ + + +#if 0 +/**************** + * Print SEXP to buffer using the MODE. Returns the length of the + * SEXP in buffer or 0 if the buffer is too short (We have at least an + * empty list consisting of 2 bytes). If a buffer of NULL is provided, + * the required length is returned. + */ +size_t +gcry_sexp_sprint (const gcry_sexp_t list, + void *buffer, size_t maxlength ) +{ + static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP }; + const unsigned char *s; + char *d; + DATALEN n; + char numbuf[20]; + int i, indent = 0; + + s = list? list->d : empty; + d = buffer; + while ( *s != ST_STOP ) + { + switch ( *s ) + { + case ST_OPEN: + s++; + if (indent) + putchar ('\n'); + for (i=0; i < indent; i++) + putchar (' '); + putchar ('('); + indent++; + break; + case ST_CLOSE: + s++; + putchar (')'); + indent--; + if (*s != ST_OPEN && *s != ST_STOP) + { + putchar ('\n'); + for (i=0; i < indent; i++) + putchar (' '); + } + break; + case ST_DATA: + s++; + memcpy (&n, s, sizeof n); + s += sizeof n; + { + int type; + size_t nn; + + switch ( (type=suitable_encoding (s, n))) + { + case 1: nn = convert_to_string (s, n, NULL); break; + case 2: nn = convert_to_token (s, n, NULL); break; + default: nn = convert_to_hex (s, n, NULL); break; + } + switch (type) + { + case 1: convert_to_string (s, n, d); break; + case 2: convert_to_token (s, n, d); break; + default: convert_to_hex (s, n, d); break; + } + d += nn; + if (s[n] != ST_CLOSE) + putchar (' '); + } + else + { + snprintf (numbuf, sizeof numbuf, "%u:", (unsigned int)n ); + d = stpcpy (d, numbuf); + memcpy (d, s, n); + d += n; + } + s += n; + break; + default: + BUG (); + } + } + putchar ('\n'); + return len; +} +#endif + + +/* Prepare for saving a chunk of data. */ +static void +init_data (void) +{ + +} + +/* Push C on the current data chunk. */ +static void +push_data (int c) +{ + (void)c; +} + +/* Flush and thus print the current data chunk. */ +static void +flush_data (void) +{ + +} + + +/* Returns 0 on success. */ +static int +parse_and_print (FILE *fp) +{ + static const char tokenchars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789-./_:*+="; + int c; + int level = 0; + int tokenc = 0; + int hexcount = 0; + int disphint = 0; + unsigned long datalen = 0; + char quote_buf[10]; + int quote_idx = 0; + enum + { + INIT_STATE = 0, IN_NUMBER, PRE_DATA, IN_DATA, IN_STRING, + IN_ESCAPE, IN_OCT_ESC, IN_HEX_ESC, + CR_ESC, LF_ESC, IN_HEXFMT, IN_BASE64 + } + state = INIT_STATE; + + + while ((c = my_getc (fp)) != EOF ) + { + addrawdata (c); + switch (state) + { + case INIT_STATE: + if (tokenc) + { + if (strchr (tokenchars, c)) + { + printchr (c); + continue; + } + tokenc = 0; + } + parse_init_state: + if (c == '(') + { + if (disphint) + { + printerr ("unmatched display hint"); + disphint = 0; + } + printctl ("open"); + level++; + } + else if (c == ')') + { + if (disphint) + { + printerr ("unmatched display hint"); + disphint = 0; + } + printctl ("close"); + level--; + } + else if (c == '\"') + { + state = IN_STRING; + printctl ("beginstring"); + init_data (); + } + else if (c == '#') + { + state = IN_HEXFMT; + hexcount = 0; + printctl ("beginhex"); + init_data (); + } + else if (c == '|') + { + state = IN_BASE64; + printctl ("beginbase64"); + init_data (); + } + else if (c == '[') + { + if (disphint) + printerr ("nested display hint"); + disphint = c; + } + else if (c == ']') + { + if (!disphint) + printerr ("no open display hint"); + disphint = 0; + } + else if (c >= '0' && c <= '9') + { + if (c == '0') + printerr ("zero prefixed length"); + state = IN_NUMBER; + datalen = (c - '0'); + } + else if (strchr (tokenchars, c)) + { + printchr (c); + tokenc = c; + } + else if (whitespace_p (c)) + ; + else if (c == '{') + { + printerr ("rescanning is not supported"); + } + else if (c == '&' || c == '\\') + { + printerr ("reserved punctuation detected"); + } + else + { + printerr ("bad character detected"); + } + break; + + case IN_NUMBER: + if (digit_p (c)) + { + unsigned long tmp = datalen * 10 + (c - '0'); + if (tmp < datalen) + { + printerr ("overflow in data length"); + state = INIT_STATE; + datalen = 0; + } + else + datalen = tmp; + } + else if (c == ':') + { + if (!datalen) + { + printerr ("no data length"); + state = INIT_STATE; + } + else + state = PRE_DATA; + } + else if (c == '\"' || c == '#' || c == '|' ) + { + /* We ignore the optional length and divert to the init + state parser code. */ + goto parse_init_state; + } + else + printerr ("invalid length specification"); + break; + + case PRE_DATA: + state = IN_DATA; + printctl ("begindata"); + init_data (); + case IN_DATA: + if (datalen) + { + push_data (c); + datalen--; + } + if (!datalen) + { + state = INIT_STATE; + printctl ("enddata"); + flush_data (); + } + break; + + case IN_STRING: + if (c == '\"') + { + printctl ("endstring"); + flush_data (); + state = INIT_STATE; + } + else if (c == '\\') + state = IN_ESCAPE; + else + push_data (c); + break; + + case IN_ESCAPE: + switch (c) + { + case 'b': push_data ('\b'); state = IN_STRING; break; + case 't': push_data ('\t'); state = IN_STRING; break; + case 'v': push_data ('\v'); state = IN_STRING; break; + case 'n': push_data ('\n'); state = IN_STRING; break; + case 'f': push_data ('\f'); state = IN_STRING; break; + case 'r': push_data ('\r'); state = IN_STRING; break; + case '"': push_data ('"'); state = IN_STRING; break; + case '\'': push_data ('\''); state = IN_STRING; break; + case '\\': push_data ('\\'); state = IN_STRING; break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + state = IN_OCT_ESC; + quote_idx = 0; + quote_buf[quote_idx++] = c; + break; + + case 'x': + state = IN_HEX_ESC; + quote_idx = 0; + break; + + case '\r': + state = CR_ESC; + break; + + case '\n': + state = LF_ESC; + break; + + default: + printerr ("invalid escape sequence"); + state = IN_STRING; + break; + } + break; + + case IN_OCT_ESC: + if (quote_idx < 3 && strchr ("01234567", c)) + { + quote_buf[quote_idx++] = c; + if (quote_idx == 3) + { + push_data ((unsigned int)quote_buf[0] * 8 * 8 + + (unsigned int)quote_buf[1] * 8 + + (unsigned int)quote_buf[2]); + state = IN_STRING; + } + } + else + state = IN_STRING; + break; + case IN_HEX_ESC: + if (quote_idx < 2 && strchr ("0123456789abcdefABCDEF", c)) + { + quote_buf[quote_idx++] = c; + if (quote_idx == 2) + { + push_data (xtoi_1 (quote_buf[0]) * 16 + + xtoi_1 (quote_buf[1])); + state = IN_STRING; + } + } + else + state = IN_STRING; + break; + case CR_ESC: + state = IN_STRING; + break; + case LF_ESC: + state = IN_STRING; + break; + + case IN_HEXFMT: + if (hexdigit_p (c)) + { + push_data (c); + hexcount++; + } + else if (c == '#') + { + if ((hexcount & 1)) + printerr ("odd number of hex digits"); + printctl ("endhex"); + flush_data (); + state = INIT_STATE; + } + else if (!whitespace_p (c)) + printerr ("bad hex character"); + break; + + case IN_BASE64: + if (c == '|') + { + printctl ("endbase64"); + flush_data (); + state = INIT_STATE; + } + else + push_data (c); + break; + + default: + logit ("invalid state %d detected", state); + exit (1); + } + } + flushdatabuffer (); + if (ferror (fp)) + { + logit ("error reading input: %s\n", strerror (errno)); + return -1; + } + return 0; +} + + + +int +main (int argc, char **argv) +{ + int rc; + + if (argc) + { + argc--; argv++; + } + while (argc && **argv == '-' && (*argv)[1] == '-') + { + if (!(*argv)[2]) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--version")) + print_version (0); + else if (!strcmp (*argv, "--help")) + print_version (1); + else if (!strcmp (*argv, "--verbose")) + { + argc--; argv++; + verbose = 1; + } + else if (!strcmp (*argv, "--decimal")) + { + argc--; argv++; + decimal = 1; + } + else if (!strcmp (*argv, "--assume-hex")) + { + argc--; argv++; + assume_hex = 1; + } + else if (!strcmp (*argv, "--advanced")) + { + argc--; argv++; + advanced = 1; + } + else + print_usage (); + } + + if (!argc) + { + rc = parse_and_print (stdin); + } + else + { + rc = 0; + for (; argc; argv++, argc--) + { + FILE *fp = fopen (*argv, "rb"); + if (!fp) + { + logit ("can't open `%s': %s\n", *argv, strerror (errno)); + rc = 1; + } + else + { + if (parse_and_print (fp)) + rc = 1; + fclose (fp); + } + } + } + + return !!rc; +} diff --git a/grub-core/lib/libgcrypt/src/fips.c b/grub-core/lib/libgcrypt/src/fips.c new file mode 100644 index 0000000..c5737a7 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/fips.c @@ -0,0 +1,860 @@ +/* fips.c - FIPS mode management + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#ifdef ENABLE_HMAC_BINARY_CHECK +# include <dlfcn.h> +#endif +#ifdef HAVE_SYSLOG +# include <syslog.h> +#endif /*HAVE_SYSLOG*/ + +#include "g10lib.h" +#include "ath.h" +#include "cipher-proto.h" +#include "hmac256.h" + + +/* The name of the file used to foce libgcrypt into fips mode. */ +#define FIPS_FORCE_FILE "/etc/gcrypt/fips_enabled" + + +/* The states of the finite state machine used in fips mode. */ +enum module_states + { + /* POWEROFF cannot be represented. */ + STATE_POWERON = 0, + STATE_INIT, + STATE_SELFTEST, + STATE_OPERATIONAL, + STATE_ERROR, + STATE_FATALERROR, + STATE_SHUTDOWN + }; + + +/* Flag telling whether we are in fips mode. It uses inverse logic so + that fips mode is the default unless changed by the initialization + code. To check whether fips mode is enabled, use the function + fips_mode()! */ +static int no_fips_mode_required; + +/* Flag to indicate that we are in the enforced FIPS mode. */ +static int enforced_fips_mode; + +/* If this flag is set, the application may no longer assume that the + process is running in FIPS mode. This flag is protected by the + FSM_LOCK. */ +static int inactive_fips_mode; + +/* This is the lock we use to protect the FSM. */ +static ath_mutex_t fsm_lock = ATH_MUTEX_INITIALIZER; + +/* The current state of the FSM. The whole state machinery is only + used while in fips mode. Change this only while holding fsm_lock. */ +static enum module_states current_state; + + + + + +static void fips_new_state (enum module_states new_state); + + + +/* Convert lowercase hex digits; assumes valid hex digits. */ +#define loxtoi_1(p) (*(p) <= '9'? (*(p)- '0'): (*(p)-'a'+10)) +#define loxtoi_2(p) ((loxtoi_1(p) * 16) + loxtoi_1((p)+1)) + +/* Returns true if P points to a lowercase hex digit. */ +#define loxdigit_p(p) !!strchr ("01234567890abcdef", *(p)) + + + +/* Check whether the OS is in FIPS mode and record that in a module + local variable. If FORCE is passed as true, fips mode will be + enabled anyway. Note: This function is not thread-safe and should + be called before any threads are created. This function may only + be called once. */ +void +_gcry_initialize_fips_mode (int force) +{ + static int done; + gpg_error_t err; + + /* Make sure we are not accidently called twice. */ + if (done) + { + if ( fips_mode () ) + { + fips_new_state (STATE_FATALERROR); + fips_noreturn (); + } + /* If not in fips mode an assert is sufficient. */ + gcry_assert (!done); + } + done = 1; + + /* If the calling application explicitly requested fipsmode, do so. */ + if (force) + { + gcry_assert (!no_fips_mode_required); + goto leave; + } + + /* For testing the system it is useful to override the system + provided detection of the FIPS mode and force FIPS mode using a + file. The filename is hardwired so that there won't be any + confusion on whether /etc/gcrypt/ or /usr/local/etc/gcrypt/ is + actually used. The file itself may be empty. */ + if ( !access (FIPS_FORCE_FILE, F_OK) ) + { + gcry_assert (!no_fips_mode_required); + goto leave; + } + + /* Checking based on /proc file properties. */ + { + static const char procfname[] = "/proc/sys/crypto/fips_enabled"; + FILE *fp; + int saved_errno; + + fp = fopen (procfname, "r"); + if (fp) + { + char line[256]; + + if (fgets (line, sizeof line, fp) && atoi (line)) + { + /* System is in fips mode. */ + fclose (fp); + gcry_assert (!no_fips_mode_required); + goto leave; + } + fclose (fp); + } + else if ((saved_errno = errno) != ENOENT + && saved_errno != EACCES + && !access ("/proc/version", F_OK) ) + { + /* Problem reading the fips file despite that we have the proc + file system. We better stop right away. */ + log_info ("FATAL: error reading `%s' in libgcrypt: %s\n", + procfname, strerror (saved_errno)); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " + "reading `%s' failed: %s - abort", + procfname, strerror (saved_errno)); +#endif /*HAVE_SYSLOG*/ + abort (); + } + } + + /* Fips not not requested, set flag. */ + no_fips_mode_required = 1; + + leave: + if (!no_fips_mode_required) + { + /* Yes, we are in FIPS mode. */ + FILE *fp; + + /* Intitialize the lock to protect the FSM. */ + err = ath_mutex_init (&fsm_lock); + if (err) + { + /* If that fails we can't do anything but abort the + process. We need to use log_info so that the FSM won't + get involved. */ + log_info ("FATAL: failed to create the FSM lock in libgcrypt: %s\n", + strerror (err)); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " + "creating FSM lock failed: %s - abort", + strerror (err)); +#endif /*HAVE_SYSLOG*/ + abort (); + } + + + /* If the FIPS force files exists, is readable and has a number + != 0 on its first line, we enable the enforced fips mode. */ + fp = fopen (FIPS_FORCE_FILE, "r"); + if (fp) + { + char line[256]; + + if (fgets (line, sizeof line, fp) && atoi (line)) + enforced_fips_mode = 1; + fclose (fp); + } + + /* Now get us into the INIT state. */ + fips_new_state (STATE_INIT); + + } + return; +} + +static void +lock_fsm (void) +{ + gpg_error_t err; + + err = ath_mutex_lock (&fsm_lock); + if (err) + { + log_info ("FATAL: failed to acquire the FSM lock in libgrypt: %s\n", + strerror (err)); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " + "acquiring FSM lock failed: %s - abort", + strerror (err)); +#endif /*HAVE_SYSLOG*/ + abort (); + } +} + +static void +unlock_fsm (void) +{ + gpg_error_t err; + + err = ath_mutex_unlock (&fsm_lock); + if (err) + { + log_info ("FATAL: failed to release the FSM lock in libgrypt: %s\n", + strerror (err)); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " + "releasing FSM lock failed: %s - abort", + strerror (err)); +#endif /*HAVE_SYSLOG*/ + abort (); + } +} + + +/* This function returns true if fips mode is enabled. This is + independent of the fips required finite state machine and only used + to enable fips specific code. Please use the fips_mode macro + instead of calling this function directly. */ +int +_gcry_fips_mode (void) +{ + /* No locking is required because we have the requirement that this + variable is only initialized once with no other threads + existing. */ + return !no_fips_mode_required; +} + + +/* Return a flag telling whether we are in the enforced fips mode. */ +int +_gcry_enforced_fips_mode (void) +{ + if (!_gcry_fips_mode ()) + return 0; + return enforced_fips_mode; +} + +/* Set a flag telling whether we are in the enforced fips mode. */ +void +_gcry_set_enforced_fips_mode (void) +{ + enforced_fips_mode = 1; +} + +/* If we do not want to enforce the fips mode, we can set a flag so + that the application may check whether it is still in fips mode. + TEXT will be printed as part of a syslog message. This function + may only be be called if in fips mode. */ +void +_gcry_inactivate_fips_mode (const char *text) +{ + gcry_assert (_gcry_fips_mode ()); + + if (_gcry_enforced_fips_mode () ) + { + /* Get us into the error state. */ + fips_signal_error (text); + return; + } + + lock_fsm (); + if (!inactive_fips_mode) + { + inactive_fips_mode = 1; + unlock_fsm (); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " + "%s - FIPS mode inactivated", text); +#endif /*HAVE_SYSLOG*/ + } + else + unlock_fsm (); +} + + +/* Return the FIPS mode inactive flag. If it is true the FIPS mode is + not anymore active. */ +int +_gcry_is_fips_mode_inactive (void) +{ + int flag; + + if (!_gcry_fips_mode ()) + return 0; + lock_fsm (); + flag = inactive_fips_mode; + unlock_fsm (); + return flag; +} + + + +static const char * +state2str (enum module_states state) +{ + const char *s; + + switch (state) + { + case STATE_POWERON: s = "Power-On"; break; + case STATE_INIT: s = "Init"; break; + case STATE_SELFTEST: s = "Self-Test"; break; + case STATE_OPERATIONAL: s = "Operational"; break; + case STATE_ERROR: s = "Error"; break; + case STATE_FATALERROR: s = "Fatal-Error"; break; + case STATE_SHUTDOWN: s = "Shutdown"; break; + default: s = "?"; break; + } + return s; +} + + +/* Return true if the library is in the operational state. */ +int +_gcry_fips_is_operational (void) +{ + int result; + + if (!fips_mode ()) + result = 1; + else + { + lock_fsm (); + if (current_state == STATE_INIT) + { + /* If we are still in the INIT state, we need to run the + selftests so that the FSM can eventually get into + operational state. Given that we would need a 2-phase + initialization of libgcrypt, but that has traditionally + not been enforced, we use this on demand self-test + checking. Note that Proper applications would do the + application specific libgcrypt initialization between a + gcry_check_version() and gcry_control + (GCRYCTL_INITIALIZATION_FINISHED) where the latter will + run the selftests. The drawback of these on-demand + self-tests are a small chance that self-tests are + performed by severeal threads; that is no problem because + our FSM make sure that we won't oversee any error. */ + unlock_fsm (); + _gcry_fips_run_selftests (0); + lock_fsm (); + } + + result = (current_state == STATE_OPERATIONAL); + unlock_fsm (); + } + return result; +} + + +/* This is test on whether the library is in the operational state. In + contrast to _gcry_fips_is_operational this function won't do a + state transition on the fly. */ +int +_gcry_fips_test_operational (void) +{ + int result; + + if (!fips_mode ()) + result = 1; + else + { + lock_fsm (); + result = (current_state == STATE_OPERATIONAL); + unlock_fsm (); + } + return result; +} + + +/* This is a test on whether the library is in the error or + operational state. */ +int +_gcry_fips_test_error_or_operational (void) +{ + int result; + + if (!fips_mode ()) + result = 1; + else + { + lock_fsm (); + result = (current_state == STATE_OPERATIONAL + || current_state == STATE_ERROR); + unlock_fsm (); + } + return result; +} + + +static void +reporter (const char *domain, int algo, const char *what, const char *errtxt) +{ + if (!errtxt && !_gcry_log_verbosity (2)) + return; + + log_info ("libgcrypt selftest: %s %s%s (%d): %s%s%s%s\n", + !strcmp (domain, "hmac")? "digest":domain, + !strcmp (domain, "hmac")? "HMAC-":"", + !strcmp (domain, "cipher")? _gcry_cipher_algo_name (algo) : + !strcmp (domain, "digest")? _gcry_md_algo_name (algo) : + !strcmp (domain, "hmac")? _gcry_md_algo_name (algo) : + !strcmp (domain, "pubkey")? _gcry_pk_algo_name (algo) : "", + algo, errtxt? errtxt:"Okay", + what?" (":"", what? what:"", what?")":""); +} + +/* Run self-tests for all required cipher algorithms. Return 0 on + success. */ +static int +run_cipher_selftests (int extended) +{ + static int algos[] = + { + GCRY_CIPHER_3DES, + GCRY_CIPHER_AES128, + GCRY_CIPHER_AES192, + GCRY_CIPHER_AES256, + 0 + }; + int idx; + gpg_error_t err; + int anyerr = 0; + + for (idx=0; algos[idx]; idx++) + { + err = _gcry_cipher_selftest (algos[idx], extended, reporter); + reporter ("cipher", algos[idx], NULL, + err? gpg_strerror (err):NULL); + if (err) + anyerr = 1; + } + return anyerr; +} + + +/* Run self-tests for all required hash algorithms. Return 0 on + success. */ +static int +run_digest_selftests (int extended) +{ + static int algos[] = + { + GCRY_MD_SHA1, + GCRY_MD_SHA224, + GCRY_MD_SHA256, + GCRY_MD_SHA384, + GCRY_MD_SHA512, + 0 + }; + int idx; + gpg_error_t err; + int anyerr = 0; + + for (idx=0; algos[idx]; idx++) + { + err = _gcry_md_selftest (algos[idx], extended, reporter); + reporter ("digest", algos[idx], NULL, + err? gpg_strerror (err):NULL); + if (err) + anyerr = 1; + } + return anyerr; +} + + +/* Run self-tests for all HMAC algorithms. Return 0 on success. */ +static int +run_hmac_selftests (int extended) +{ + static int algos[] = + { + GCRY_MD_SHA1, + GCRY_MD_SHA224, + GCRY_MD_SHA256, + GCRY_MD_SHA384, + GCRY_MD_SHA512, + 0 + }; + int idx; + gpg_error_t err; + int anyerr = 0; + + for (idx=0; algos[idx]; idx++) + { + err = _gcry_hmac_selftest (algos[idx], extended, reporter); + reporter ("hmac", algos[idx], NULL, + err? gpg_strerror (err):NULL); + if (err) + anyerr = 1; + } + return anyerr; +} + + +/* Run self-tests for all required public key algorithms. Return 0 on + success. */ +static int +run_pubkey_selftests (int extended) +{ + static int algos[] = + { + GCRY_PK_RSA, + GCRY_PK_DSA, + /* GCRY_PK_ECDSA is not enabled in fips mode. */ + 0 + }; + int idx; + gpg_error_t err; + int anyerr = 0; + + for (idx=0; algos[idx]; idx++) + { + err = _gcry_pk_selftest (algos[idx], extended, reporter); + reporter ("pubkey", algos[idx], NULL, + err? gpg_strerror (err):NULL); + if (err) + anyerr = 1; + } + return anyerr; +} + + +/* Run self-tests for the random number generator. Returns 0 on + success. */ +static int +run_random_selftests (void) +{ + gpg_error_t err; + + err = _gcry_random_selftest (reporter); + reporter ("random", 0, NULL, err? gpg_strerror (err):NULL); + + return !!err; +} + +/* Run an integrity check on the binary. Returns 0 on success. */ +static int +check_binary_integrity (void) +{ +#ifdef ENABLE_HMAC_BINARY_CHECK + gpg_error_t err; + Dl_info info; + unsigned char digest[32]; + int dlen; + char *fname = NULL; + const char key[] = "What am I, a doctor or a moonshuttle conductor?"; + + if (!dladdr ("gcry_check_version", &info)) + err = gpg_error_from_syserror (); + else + { + dlen = _gcry_hmac256_file (digest, sizeof digest, info.dli_fname, + key, strlen (key)); + if (dlen < 0) + err = gpg_error_from_syserror (); + else if (dlen != 32) + err = gpg_error (GPG_ERR_INTERNAL); + else + { + fname = gcry_malloc (strlen (info.dli_fname) + 1 + 5 + 1 ); + if (!fname) + err = gpg_error_from_syserror (); + else + { + FILE *fp; + char *p; + + /* Prefix the basename with a dot. */ + strcpy (fname, info.dli_fname); + p = strrchr (fname, '/'); + if (p) + p++; + else + p = fname; + memmove (p+1, p, strlen (p)+1); + *p = '.'; + strcat (fname, ".hmac"); + + /* Open the file. */ + fp = fopen (fname, "r"); + if (!fp) + err = gpg_error_from_syserror (); + else + { + /* A buffer of 64 bytes plus one for a LF and one to + detect garbage. */ + unsigned char buffer[64+1+1]; + const unsigned char *s; + int n; + + /* The HMAC files consists of lowercase hex digits + only with an optional trailing linefeed. Fail if + there is any garbage. */ + err = gpg_error (GPG_ERR_SELFTEST_FAILED); + n = fread (buffer, 1, sizeof buffer, fp); + if (n == 64 || (n == 65 && buffer[64] == '\n')) + { + buffer[64] = 0; + for (n=0, s= buffer; + n < 32 && loxdigit_p (s) && loxdigit_p (s+1); + n++, s += 2) + buffer[n] = loxtoi_2 (s); + if ( n == 32 && !memcmp (digest, buffer, 32) ) + err = 0; + } + fclose (fp); + } + } + } + } + reporter ("binary", 0, fname, err? gpg_strerror (err):NULL); +#ifdef HAVE_SYSLOG + if (err) + syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " + "integrity check using `%s' failed: %s", + fname? fname:"[?]", gpg_strerror (err)); +#endif /*HAVE_SYSLOG*/ + gcry_free (fname); + return !!err; +#else + return 0; +#endif +} + + +/* Run the self-tests. If EXTENDED is true, extended versions of the + selftest are run, that is more tests than required by FIPS. */ +gpg_err_code_t +_gcry_fips_run_selftests (int extended) +{ + enum module_states result = STATE_ERROR; + gcry_err_code_t ec = GPG_ERR_SELFTEST_FAILED; + + if (fips_mode ()) + fips_new_state (STATE_SELFTEST); + + if (run_cipher_selftests (extended)) + goto leave; + + if (run_digest_selftests (extended)) + goto leave; + + if (run_hmac_selftests (extended)) + goto leave; + + /* Run random tests before the pubkey tests because the latter + require random. */ + if (run_random_selftests ()) + goto leave; + + if (run_pubkey_selftests (extended)) + goto leave; + + /* Now check the integrity of the binary. We do this this after + having checked the HMAC code. */ + if (check_binary_integrity ()) + goto leave; + + /* All selftests passed. */ + result = STATE_OPERATIONAL; + ec = 0; + + leave: + if (fips_mode ()) + fips_new_state (result); + + return ec; +} + + +/* This function is used to tell the FSM about errors in the library. + The FSM will be put into an error state. This function should not + be called directly but by one of the macros + + fips_signal_error (description) + fips_signal_fatal_error (description) + + where DESCRIPTION is a string describing the error. */ +void +_gcry_fips_signal_error (const char *srcfile, int srcline, const char *srcfunc, + int is_fatal, const char *description) +{ + if (!fips_mode ()) + return; /* Not required. */ + + /* Set new state before printing an error. */ + fips_new_state (is_fatal? STATE_FATALERROR : STATE_ERROR); + + /* Print error. */ + log_info ("%serror in libgcrypt, file %s, line %d%s%s: %s\n", + is_fatal? "fatal ":"", + srcfile, srcline, + srcfunc? ", function ":"", srcfunc? srcfunc:"", + description? description : "no description available"); +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " + "%serror in file %s, line %d%s%s: %s", + is_fatal? "fatal ":"", + srcfile, srcline, + srcfunc? ", function ":"", srcfunc? srcfunc:"", + description? description : "no description available"); +#endif /*HAVE_SYSLOG*/ +} + + +/* Perform a state transition to NEW_STATE. If this is an invalid + transition, the module will go into a fatal error state. */ +static void +fips_new_state (enum module_states new_state) +{ + int ok = 0; + enum module_states last_state; + + lock_fsm (); + + last_state = current_state; + switch (current_state) + { + case STATE_POWERON: + if (new_state == STATE_INIT + || new_state == STATE_ERROR + || new_state == STATE_FATALERROR) + ok = 1; + break; + + case STATE_INIT: + if (new_state == STATE_SELFTEST + || new_state == STATE_ERROR + || new_state == STATE_FATALERROR) + ok = 1; + break; + + case STATE_SELFTEST: + if (new_state == STATE_OPERATIONAL + || new_state == STATE_ERROR + || new_state == STATE_FATALERROR) + ok = 1; + break; + + case STATE_OPERATIONAL: + if (new_state == STATE_SHUTDOWN + || new_state == STATE_SELFTEST + || new_state == STATE_ERROR + || new_state == STATE_FATALERROR) + ok = 1; + break; + + case STATE_ERROR: + if (new_state == STATE_SHUTDOWN + || new_state == STATE_ERROR + || new_state == STATE_FATALERROR + || new_state == STATE_SELFTEST) + ok = 1; + break; + + case STATE_FATALERROR: + if (new_state == STATE_SHUTDOWN ) + ok = 1; + break; + + case STATE_SHUTDOWN: + /* We won't see any transition *from* Shutdown because the only + allowed new state is Power-Off and that one can't be + represented. */ + break; + + } + + if (ok) + { + current_state = new_state; + } + + unlock_fsm (); + + if (!ok || _gcry_log_verbosity (2)) + log_info ("libgcrypt state transition %s => %s %s\n", + state2str (last_state), state2str (new_state), + ok? "granted":"denied"); + + if (!ok) + { + /* Invalid state transition. Halting library. */ +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_ERR, + "Libgcrypt error: invalid state transition %s => %s", + state2str (last_state), state2str (new_state)); +#endif /*HAVE_SYSLOG*/ + fips_noreturn (); + } + else if (new_state == STATE_ERROR || new_state == STATE_FATALERROR) + { +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, + "Libgcrypt notice: state transition %s => %s", + state2str (last_state), state2str (new_state)); +#endif /*HAVE_SYSLOG*/ + } +} + + + + +/* This function should be called to ensure that the execution shall + not continue. */ +void +_gcry_fips_noreturn (void) +{ +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_ERR, "Libgcrypt terminated the application"); +#endif /*HAVE_SYSLOG*/ + fflush (NULL); + abort (); + /*NOTREACHED*/ +} diff --git a/grub-core/lib/libgcrypt/src/g10lib.h b/grub-core/lib/libgcrypt/src/g10lib.h new file mode 100644 index 0000000..6bde20f --- /dev/null +++ b/grub-core/lib/libgcrypt/src/g10lib.h @@ -0,0 +1,302 @@ +/* g10lib.h - Internal definitions for libgcrypt + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 + * 2007, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* This header is to be used inside of libgcrypt in place of gcrypt.h. + This way we can better distinguish between internal and external + usage of gcrypt.h. */ + +#ifndef G10LIB_H +#define G10LIB_H 1 + +#ifdef _GCRYPT_H +#error gcrypt.h already included +#endif + +#ifndef _GCRYPT_IN_LIBGCRYPT +#error something is wrong with config.h +#endif + +#include <stdio.h> +#include <stdarg.h> + +#include "visibility.h" +#include "types.h" + + + + +/* Attribute handling macros. */ + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) +#define JNLIB_GCC_M_FUNCTION 1 +#define JNLIB_GCC_A_NR __attribute__ ((noreturn)) +#define JNLIB_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a))) +#define JNLIB_GCC_A_NR_PRINTF( f, a ) \ + __attribute__ ((noreturn, format (printf,f,a))) +#define GCC_ATTR_NORETURN __attribute__ ((__noreturn__)) +#else +#define JNLIB_GCC_A_NR +#define JNLIB_GCC_A_PRINTF( f, a ) +#define JNLIB_GCC_A_NR_PRINTF( f, a ) +#define GCC_ATTR_NORETURN +#endif + +#if __GNUC__ >= 3 +/* According to glibc this attribute is available since 2.8 however we + better play safe and use it only with gcc 3 or newer. */ +#define GCC_ATTR_FORMAT_ARG(a) __attribute__ ((format_arg (a))) +#else +#define GCC_ATTR_FORMAT_ARG(a) +#endif + + +/* Gettext macros. */ + +/* Some handy macros */ +#ifndef STR +#define STR(v) #v +#endif +#define STR2(v) STR(v) +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) + + + +/*-- src/global.c -*/ +int _gcry_global_is_operational (void); +gcry_error_t _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr); +void _gcry_check_heap (const void *a); +int _gcry_get_debug_flag (unsigned int mask); + + +/*-- src/misc.c --*/ + +#if defined(JNLIB_GCC_M_FUNCTION) || __STDC_VERSION__ >= 199901L +void _gcry_bug (const char *file, int line, + const char *func) GCC_ATTR_NORETURN; +void _gcry_assert_failed (const char *expr, const char *file, int line, + const char *func) GCC_ATTR_NORETURN; +#else +void _gcry_bug (const char *file, int line); +void _gcry_assert_failed (const char *expr, const char *file, int line); +#endif + +const char *_gcry_gettext (const char *key) GCC_ATTR_FORMAT_ARG(1); +void _gcry_fatal_error(int rc, const char *text ) JNLIB_GCC_A_NR; +void _gcry_log( int level, const char *fmt, ... ) JNLIB_GCC_A_PRINTF(2,3); +void _gcry_log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); +void _gcry_log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); +void _gcry_log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void _gcry_log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +int _gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... ) + JNLIB_GCC_A_PRINTF(2,3); +void _gcry_log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void _gcry_log_printf ( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void _gcry_log_printhex (const char *text, const void *buffer, size_t length); + +void _gcry_set_log_verbosity( int level ); +int _gcry_log_verbosity( int level ); + +#ifdef JNLIB_GCC_M_FUNCTION +#define BUG() _gcry_bug( __FILE__ , __LINE__, __FUNCTION__ ) +#define gcry_assert(expr) ((expr)? (void)0 \ + : _gcry_assert_failed (STR(expr), __FILE__, __LINE__, __FUNCTION__)) +#elif __STDC_VERSION__ >= 199901L +#define BUG() _gcry_bug( __FILE__ , __LINE__, __func__ ) +#define gcry_assert(expr) ((expr)? (void)0 \ + : _gcry_assert_failed (STR(expr), __FILE__, __LINE__, __func__)) +#else +#define BUG() _gcry_bug( __FILE__ , __LINE__ ) +#define gcry_assert(expr) ((expr)? (void)0 \ + : _gcry_assert_failed (STR(expr), __FILE__, __LINE__)) +#endif + + +#define log_bug _gcry_log_bug +#define log_fatal _gcry_log_fatal +#define log_error _gcry_log_error +#define log_info _gcry_log_info +#define log_debug _gcry_log_debug +#define log_printf _gcry_log_printf +#define log_printhex _gcry_log_printhex + + +/*-- src/hwfeatures.c --*/ +/* (Do not change these values unless synced with the asm code.) */ +#define HWF_PADLOCK_RNG 1 +#define HWF_PADLOCK_AES 2 +#define HWF_PADLOCK_SHA 4 +#define HWF_PADLOCK_MMUL 8 + +#define HWF_INTEL_AESNI 256 + + +unsigned int _gcry_get_hw_features (void); +void _gcry_detect_hw_features (unsigned int); + + +/*-- mpi/mpiutil.c --*/ +const char *_gcry_mpi_get_hw_config (void); + + +/*-- cipher/pubkey.c --*/ + +/* FIXME: shouldn't this go into mpi.h? */ +#ifndef mpi_powm +#define mpi_powm(w,b,e,m) gcry_mpi_powm( (w), (b), (e), (m) ) +#endif + +/*-- primegen.c --*/ +gcry_mpi_t _gcry_generate_secret_prime (unsigned int nbits, + gcry_random_level_t random_level, + int (*extra_check)(void*, gcry_mpi_t), + void *extra_check_arg); +gcry_mpi_t _gcry_generate_public_prime (unsigned int nbits, + gcry_random_level_t random_level, + int (*extra_check)(void*, gcry_mpi_t), + void *extra_check_arg); +gcry_mpi_t _gcry_generate_elg_prime (int mode, + unsigned int pbits, unsigned int qbits, + gcry_mpi_t g, gcry_mpi_t **factors); +gcry_mpi_t _gcry_derive_x931_prime (const gcry_mpi_t xp, + const gcry_mpi_t xp1, const gcry_mpi_t xp2, + const gcry_mpi_t e, + gcry_mpi_t *r_p1, gcry_mpi_t *r_p2); +gpg_err_code_t _gcry_generate_fips186_2_prime + (unsigned int pbits, unsigned int qbits, + const void *seed, size_t seedlen, + gcry_mpi_t *r_q, gcry_mpi_t *r_p, + int *r_counter, + void **r_seed, size_t *r_seedlen); +gpg_err_code_t _gcry_generate_fips186_3_prime + (unsigned int pbits, unsigned int qbits, + const void *seed, size_t seedlen, + gcry_mpi_t *r_q, gcry_mpi_t *r_p, + int *r_counter, + void **r_seed, size_t *r_seedlen, int *r_hashalgo); + + +/* Replacements of missing functions (missing-string.c). */ +#ifndef HAVE_STPCPY +char *stpcpy (char *a, const char *b); +#endif +#ifndef HAVE_STRCASECMP +int strcasecmp (const char *a, const char *b) _GCRY_GCC_ATTR_PURE; +#endif + + +/* Macros used to rename missing functions. */ +#ifndef HAVE_STRTOUL +#define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c))) +#endif +#ifndef HAVE_MEMMOVE +#define memmove(d, s, n) bcopy((s), (d), (n)) +#endif +#ifndef HAVE_STRICMP +#define stricmp(a,b) strcasecmp( (a), (b) ) +#endif +#ifndef HAVE_ATEXIT +#define atexit(a) (on_exit((a),0)) +#endif +#ifndef HAVE_RAISE +#define raise(a) kill(getpid(), (a)) +#endif + + +/* Stack burning. */ + +void _gcry_burn_stack (int bytes); + + +/* To avoid that a compiler optimizes certain memset calls away, these + macros may be used instead. */ +#define wipememory2(_ptr,_set,_len) do { \ + volatile char *_vptr=(volatile char *)(_ptr); \ + size_t _vlen=(_len); \ + while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ + } while(0) +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + + + +/* Digit predicates. */ + +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define octdigitp(p) (*(p) >= '0' && *(p) <= '7') +#define alphap(a) ( (*(a) >= 'A' && *(a) <= 'Z') \ + || (*(a) >= 'a' && *(a) <= 'z')) +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) + + +/*-- sexp.c --*/ +gcry_error_t _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff, + const char *format, va_list arg_ptr); +char *_gcry_sexp_nth_string (const gcry_sexp_t list, int number); + + +/*-- fips.c --*/ + +void _gcry_initialize_fips_mode (int force); + +int _gcry_fips_mode (void); +#define fips_mode() _gcry_fips_mode () + +int _gcry_enforced_fips_mode (void); + +void _gcry_set_enforced_fips_mode (void); + +void _gcry_inactivate_fips_mode (const char *text); +int _gcry_is_fips_mode_inactive (void); + + +void _gcry_fips_signal_error (const char *srcfile, + int srcline, + const char *srcfunc, + int is_fatal, + const char *description); +#ifdef JNLIB_GCC_M_FUNCTION +# define fips_signal_error(a) \ + _gcry_fips_signal_error (__FILE__, __LINE__, __FUNCTION__, 0, (a)) +# define fips_signal_fatal_error(a) \ + _gcry_fips_signal_error (__FILE__, __LINE__, __FUNCTION__, 1, (a)) +#else +# define fips_signal_error(a) \ + _gcry_fips_signal_error (__FILE__, __LINE__, NULL, 0, (a)) +# define fips_signal_fatal_error(a) \ + _gcry_fips_signal_error (__FILE__, __LINE__, NULL, 1, (a)) +#endif + +int _gcry_fips_is_operational (void); +#define fips_is_operational() (_gcry_global_is_operational ()) +#define fips_not_operational() (GCRY_GPG_ERR_NOT_OPERATIONAL) + +int _gcry_fips_test_operational (void); +int _gcry_fips_test_error_or_operational (void); + +gpg_err_code_t _gcry_fips_run_selftests (int extended); + +void _gcry_fips_noreturn (void); +#define fips_noreturn() (_gcry_fips_noreturn ()) + + + +#endif /* G10LIB_H */ diff --git a/grub-core/lib/libgcrypt/src/gcrypt-module.h b/grub-core/lib/libgcrypt/src/gcrypt-module.h new file mode 100644 index 0000000..f39e2b5 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/gcrypt-module.h @@ -0,0 +1,240 @@ +/* gcrypt-module.h - GNU Cryptographic Library Interface + Copyright (C) 2003, 2007 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* + This file contains the necessary declarations/definitions for + working with Libgcrypt modules. + */ + +#ifndef _GCRYPT_MODULE_H +#define _GCRYPT_MODULE_H + +#ifdef __cplusplus +extern "C" { +#if 0 /* keep Emacsens's auto-indent happy */ +} +#endif +#endif + +/* The interfaces using the module system reserve a certain range of + IDs for application use. These IDs are not valid within Libgcrypt + but Libgcrypt makes sure never to allocate such a module ID. */ +#define GCRY_MODULE_ID_USER 1024 +#define GCRY_MODULE_ID_USER_LAST 4095 + + +/* This type represents a `module'. */ +typedef struct gcry_module *gcry_module_t; + +/* Check that the library fulfills the version requirement. */ + +/* Type for the cipher_setkey function. */ +typedef gcry_err_code_t (*gcry_cipher_setkey_t) (void *c, + const unsigned char *key, + unsigned keylen); + +/* Type for the cipher_encrypt function. */ +typedef void (*gcry_cipher_encrypt_t) (void *c, + unsigned char *outbuf, + const unsigned char *inbuf); + +/* Type for the cipher_decrypt function. */ +typedef void (*gcry_cipher_decrypt_t) (void *c, + unsigned char *outbuf, + const unsigned char *inbuf); + +/* Type for the cipher_stencrypt function. */ +typedef void (*gcry_cipher_stencrypt_t) (void *c, + unsigned char *outbuf, + const unsigned char *inbuf, + unsigned int n); + +/* Type for the cipher_stdecrypt function. */ +typedef void (*gcry_cipher_stdecrypt_t) (void *c, + unsigned char *outbuf, + const unsigned char *inbuf, + unsigned int n); + +typedef struct gcry_cipher_oid_spec +{ + const char *oid; + int mode; +} gcry_cipher_oid_spec_t; + +/* Module specification structure for ciphers. */ +typedef struct gcry_cipher_spec +{ + const char *name; + const char **aliases; + gcry_cipher_oid_spec_t *oids; + size_t blocksize; + size_t keylen; + size_t contextsize; + gcry_cipher_setkey_t setkey; + gcry_cipher_encrypt_t encrypt; + gcry_cipher_decrypt_t decrypt; + gcry_cipher_stencrypt_t stencrypt; + gcry_cipher_stdecrypt_t stdecrypt; +} gcry_cipher_spec_t; + +/* Register a new cipher module whose specification can be found in + CIPHER. On success, a new algorithm ID is stored in ALGORITHM_ID + and a pointer representing this module is stored in MODULE. */ +gcry_error_t gcry_cipher_register (gcry_cipher_spec_t *cipher, + int *algorithm_id, + gcry_module_t *module) + /* */ _GCRY_ATTR_INTERNAL; + + +/* Unregister the cipher identified by MODULE, which must have been + registered with gcry_cipher_register. */ +void gcry_cipher_unregister (gcry_module_t module) + /* */ _GCRY_ATTR_INTERNAL; + +/* ********************** */ + +/* Type for the pk_generate function. */ +typedef gcry_err_code_t (*gcry_pk_generate_t) (int algo, + unsigned int nbits, + unsigned long use_e, + gcry_mpi_t *skey, + gcry_mpi_t **retfactors); + +/* Type for the pk_check_secret_key function. */ +typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo, + gcry_mpi_t *skey); + +/* Type for the pk_encrypt function. */ +typedef gcry_err_code_t (*gcry_pk_encrypt_t) (int algo, + gcry_mpi_t *resarr, + gcry_mpi_t data, + gcry_mpi_t *pkey, + int flags); + +/* Type for the pk_decrypt function. */ +typedef gcry_err_code_t (*gcry_pk_decrypt_t) (int algo, + gcry_mpi_t *result, + gcry_mpi_t *data, + gcry_mpi_t *skey, + int flags); + +/* Type for the pk_sign function. */ +typedef gcry_err_code_t (*gcry_pk_sign_t) (int algo, + gcry_mpi_t *resarr, + gcry_mpi_t data, + gcry_mpi_t *skey); + +/* Type for the pk_verify function. */ +typedef gcry_err_code_t (*gcry_pk_verify_t) (int algo, + gcry_mpi_t hash, + gcry_mpi_t *data, + gcry_mpi_t *pkey, + int (*cmp) (void *, gcry_mpi_t), + void *opaquev); + +/* Type for the pk_get_nbits function. */ +typedef unsigned (*gcry_pk_get_nbits_t) (int algo, gcry_mpi_t *pkey); + +/* Module specification structure for message digests. */ +typedef struct gcry_pk_spec +{ + const char *name; + const char **aliases; + const char *elements_pkey; + const char *elements_skey; + const char *elements_enc; + const char *elements_sig; + const char *elements_grip; + int use; + gcry_pk_generate_t generate; + gcry_pk_check_secret_key_t check_secret_key; + gcry_pk_encrypt_t encrypt; + gcry_pk_decrypt_t decrypt; + gcry_pk_sign_t sign; + gcry_pk_verify_t verify; + gcry_pk_get_nbits_t get_nbits; +} gcry_pk_spec_t; + +/* Register a new pubkey module whose specification can be found in + PUBKEY. On success, a new algorithm ID is stored in ALGORITHM_ID + and a pointer representhing this module is stored in MODULE. */ +gcry_error_t gcry_pk_register (gcry_pk_spec_t *pubkey, + unsigned int *algorithm_id, + gcry_module_t *module) + /* */ _GCRY_ATTR_INTERNAL; + +/* Unregister the pubkey identified by ID, which must have been + registered with gcry_pk_register. */ +void gcry_pk_unregister (gcry_module_t module) + /* */ _GCRY_ATTR_INTERNAL; + +/* ********************** */ + +/* Type for the md_init function. */ +typedef void (*gcry_md_init_t) (void *c); + +/* Type for the md_write function. */ +typedef void (*gcry_md_write_t) (void *c, const void *buf, size_t nbytes); + +/* Type for the md_final function. */ +typedef void (*gcry_md_final_t) (void *c); + +/* Type for the md_read function. */ +typedef unsigned char *(*gcry_md_read_t) (void *c); + +typedef struct gcry_md_oid_spec +{ + const char *oidstring; +} gcry_md_oid_spec_t; + +/* Module specification structure for message digests. */ +typedef struct gcry_md_spec +{ + const char *name; + unsigned char *asnoid; + int asnlen; + gcry_md_oid_spec_t *oids; + int mdlen; + gcry_md_init_t init; + gcry_md_write_t write; + gcry_md_final_t final; + gcry_md_read_t read; + size_t contextsize; /* allocate this amount of context */ +} gcry_md_spec_t; + +/* Register a new digest module whose specification can be found in + DIGEST. On success, a new algorithm ID is stored in ALGORITHM_ID + and a pointer representhing this module is stored in MODULE. */ +gcry_error_t gcry_md_register (gcry_md_spec_t *digest, + unsigned int *algorithm_id, + gcry_module_t *module) + /* */ _GCRY_ATTR_INTERNAL; + +/* Unregister the digest identified by ID, which must have been + registered with gcry_digest_register. */ +void gcry_md_unregister (gcry_module_t module) + /* */ _GCRY_ATTR_INTERNAL; + +#if 0 /* keep Emacsens's auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif +#endif diff --git a/grub-core/lib/libgcrypt/src/gcrypt.h.in b/grub-core/lib/libgcrypt/src/gcrypt.h.in new file mode 100644 index 0000000..b65184e --- /dev/null +++ b/grub-core/lib/libgcrypt/src/gcrypt.h.in @@ -0,0 +1,1760 @@ +/* gcrypt.h - GNU Cryptographic Library Interface -*- c -*- + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 + 2007, 2008, 2009, 2010, 2011, + 2012 Free Software Foundation, Inc. + Copyright (C) 2012, 2013 g10 Code GmbH + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see <http://www.gnu.org/licenses/>. + + File: @configure_input@ */ + +#ifndef _GCRYPT_H +#define _GCRYPT_H + +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include <gpg-error.h> + +#include <sys/types.h> + +#if defined _WIN32 || defined __WIN32__ +# include <winsock2.h> +# include <ws2tcpip.h> +# include <time.h> +# ifndef __GNUC__ + typedef long ssize_t; + typedef int pid_t; +# endif /*!__GNUC__*/ +#else +# include <sys/socket.h> +# include <sys/time.h> +#@INSERT_SYS_SELECT_H@ +#endif /*!_WIN32*/ + +@FALLBACK_SOCKLEN_T@ + +/* This is required for error code compatibility. */ +#define _GCRY_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GCRYPT + +#ifdef __cplusplus +extern "C" { +#if 0 /* (Keep Emacsens' auto-indent happy.) */ +} +#endif +#endif + +/* The version of this header should match the one of the library. It + should not be used by a program because gcry_check_version() should + return the same version. The purpose of this macro is to let + autoconf (using the AM_PATH_GCRYPT macro) check that this header + matches the installed library. */ +#define GCRYPT_VERSION "@VERSION@" + +/* The version number of this header. It may be used to handle minor + API incompatibilities. */ +#define GCRYPT_VERSION_NUMBER @VERSION_NUMBER@ + + +/* Internal: We can't use the convenience macros for the multi + precision integer functions when building this library. */ +#ifdef _GCRYPT_IN_LIBGCRYPT +#ifndef GCRYPT_NO_MPI_MACROS +#define GCRYPT_NO_MPI_MACROS 1 +#endif +#endif + +/* We want to use gcc attributes when possible. Warning: Don't use + these macros in your programs: As indicated by the leading + underscore they are subject to change without notice. */ +#ifdef __GNUC__ + +#define _GCRY_GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) + +#if _GCRY_GCC_VERSION >= 30100 +#define _GCRY_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#if _GCRY_GCC_VERSION >= 29600 +#define _GCRY_GCC_ATTR_PURE __attribute__ ((__pure__)) +#endif + +#if _GCRY_GCC_VERSION >= 30200 +#define _GCRY_GCC_ATTR_MALLOC __attribute__ ((__malloc__)) +#endif + +#endif /*__GNUC__*/ + +#ifndef _GCRY_GCC_ATTR_DEPRECATED +#define _GCRY_GCC_ATTR_DEPRECATED +#endif +#ifndef _GCRY_GCC_ATTR_PURE +#define _GCRY_GCC_ATTR_PURE +#endif +#ifndef _GCRY_GCC_ATTR_MALLOC +#define _GCRY_GCC_ATTR_MALLOC +#endif + +/* Make up an attribute to mark functions and types as deprecated but + allow internal use by Libgcrypt. */ +#ifdef _GCRYPT_IN_LIBGCRYPT +#define _GCRY_ATTR_INTERNAL +#else +#define _GCRY_ATTR_INTERNAL _GCRY_GCC_ATTR_DEPRECATED +#endif + +/* Wrappers for the libgpg-error library. */ + +typedef gpg_error_t gcry_error_t; +typedef gpg_err_code_t gcry_err_code_t; +typedef gpg_err_source_t gcry_err_source_t; + +static GPG_ERR_INLINE gcry_error_t +gcry_err_make (gcry_err_source_t source, gcry_err_code_t code) +{ + return gpg_err_make (source, code); +} + +/* The user can define GPG_ERR_SOURCE_DEFAULT before including this + file to specify a default source for gpg_error. */ +#ifndef GCRY_ERR_SOURCE_DEFAULT +#define GCRY_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_USER_1 +#endif + +static GPG_ERR_INLINE gcry_error_t +gcry_error (gcry_err_code_t code) +{ + return gcry_err_make (GCRY_ERR_SOURCE_DEFAULT, code); +} + +static GPG_ERR_INLINE gcry_err_code_t +gcry_err_code (gcry_error_t err) +{ + return gpg_err_code (err); +} + + +static GPG_ERR_INLINE gcry_err_source_t +gcry_err_source (gcry_error_t err) +{ + return gpg_err_source (err); +} + +/* Return a pointer to a string containing a description of the error + code in the error value ERR. */ +const char *gcry_strerror (gcry_error_t err); + +/* Return a pointer to a string containing a description of the error + source in the error value ERR. */ +const char *gcry_strsource (gcry_error_t err); + +/* Retrieve the error code for the system error ERR. This returns + GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report + this). */ +gcry_err_code_t gcry_err_code_from_errno (int err); + +/* Retrieve the system error for the error code CODE. This returns 0 + if CODE is not a system error code. */ +int gcry_err_code_to_errno (gcry_err_code_t code); + +/* Return an error value with the error source SOURCE and the system + error ERR. */ +gcry_error_t gcry_err_make_from_errno (gcry_err_source_t source, int err); + +/* Return an error value with the system error ERR. */ +gcry_err_code_t gcry_error_from_errno (int err); + + +/* The data object used to hold a multi precision integer. */ +struct gcry_mpi; +typedef struct gcry_mpi *gcry_mpi_t; + +#ifndef GCRYPT_NO_DEPRECATED +typedef struct gcry_mpi *GCRY_MPI _GCRY_GCC_ATTR_DEPRECATED; +typedef struct gcry_mpi *GcryMPI _GCRY_GCC_ATTR_DEPRECATED; +#endif + + + +/* Check that the library fulfills the version requirement. */ +const char *gcry_check_version (const char *req_version); + +/* Codes for function dispatchers. */ + +/* Codes used with the gcry_control function. */ +enum gcry_ctl_cmds + { + GCRYCTL_SET_KEY = 1, + GCRYCTL_SET_IV = 2, + GCRYCTL_CFB_SYNC = 3, + GCRYCTL_RESET = 4, /* e.g. for MDs */ + GCRYCTL_FINALIZE = 5, + GCRYCTL_GET_KEYLEN = 6, + GCRYCTL_GET_BLKLEN = 7, + GCRYCTL_TEST_ALGO = 8, + GCRYCTL_IS_SECURE = 9, + GCRYCTL_GET_ASNOID = 10, + GCRYCTL_ENABLE_ALGO = 11, + GCRYCTL_DISABLE_ALGO = 12, + GCRYCTL_DUMP_RANDOM_STATS = 13, + GCRYCTL_DUMP_SECMEM_STATS = 14, + GCRYCTL_GET_ALGO_NPKEY = 15, + GCRYCTL_GET_ALGO_NSKEY = 16, + GCRYCTL_GET_ALGO_NSIGN = 17, + GCRYCTL_GET_ALGO_NENCR = 18, + GCRYCTL_SET_VERBOSITY = 19, + GCRYCTL_SET_DEBUG_FLAGS = 20, + GCRYCTL_CLEAR_DEBUG_FLAGS = 21, + GCRYCTL_USE_SECURE_RNDPOOL= 22, + GCRYCTL_DUMP_MEMORY_STATS = 23, + GCRYCTL_INIT_SECMEM = 24, + GCRYCTL_TERM_SECMEM = 25, + GCRYCTL_DISABLE_SECMEM_WARN = 27, + GCRYCTL_SUSPEND_SECMEM_WARN = 28, + GCRYCTL_RESUME_SECMEM_WARN = 29, + GCRYCTL_DROP_PRIVS = 30, + GCRYCTL_ENABLE_M_GUARD = 31, + GCRYCTL_START_DUMP = 32, + GCRYCTL_STOP_DUMP = 33, + GCRYCTL_GET_ALGO_USAGE = 34, + GCRYCTL_IS_ALGO_ENABLED = 35, + GCRYCTL_DISABLE_INTERNAL_LOCKING = 36, + GCRYCTL_DISABLE_SECMEM = 37, + GCRYCTL_INITIALIZATION_FINISHED = 38, + GCRYCTL_INITIALIZATION_FINISHED_P = 39, + GCRYCTL_ANY_INITIALIZATION_P = 40, + GCRYCTL_SET_CBC_CTS = 41, + GCRYCTL_SET_CBC_MAC = 42, + GCRYCTL_SET_CTR = 43, + GCRYCTL_ENABLE_QUICK_RANDOM = 44, + GCRYCTL_SET_RANDOM_SEED_FILE = 45, + GCRYCTL_UPDATE_RANDOM_SEED_FILE = 46, + GCRYCTL_SET_THREAD_CBS = 47, + GCRYCTL_FAST_POLL = 48, + GCRYCTL_SET_RANDOM_DAEMON_SOCKET = 49, + GCRYCTL_USE_RANDOM_DAEMON = 50, + GCRYCTL_FAKED_RANDOM_P = 51, + GCRYCTL_SET_RNDEGD_SOCKET = 52, + GCRYCTL_PRINT_CONFIG = 53, + GCRYCTL_OPERATIONAL_P = 54, + GCRYCTL_FIPS_MODE_P = 55, + GCRYCTL_FORCE_FIPS_MODE = 56, + GCRYCTL_SELFTEST = 57, + /* Note: 58 .. 62 are used internally. */ + GCRYCTL_DISABLE_HWF = 63, + GCRYCTL_SET_ENFORCED_FIPS_FLAG = 64 + }; + +/* Perform various operations defined by CMD. */ +gcry_error_t gcry_control (enum gcry_ctl_cmds CMD, ...); + + +/* S-expression management. */ + +/* The object to represent an S-expression as used with the public key + functions. */ +struct gcry_sexp; +typedef struct gcry_sexp *gcry_sexp_t; + +#ifndef GCRYPT_NO_DEPRECATED +typedef struct gcry_sexp *GCRY_SEXP _GCRY_GCC_ATTR_DEPRECATED; +typedef struct gcry_sexp *GcrySexp _GCRY_GCC_ATTR_DEPRECATED; +#endif + +/* The possible values for the S-expression format. */ +enum gcry_sexp_format + { + GCRYSEXP_FMT_DEFAULT = 0, + GCRYSEXP_FMT_CANON = 1, + GCRYSEXP_FMT_BASE64 = 2, + GCRYSEXP_FMT_ADVANCED = 3 + }; + +/* Create an new S-expression object from BUFFER of size LENGTH and + return it in RETSEXP. With AUTODETECT set to 0 the data in BUFFER + is expected to be in canonized format. */ +gcry_error_t gcry_sexp_new (gcry_sexp_t *retsexp, + const void *buffer, size_t length, + int autodetect); + + /* Same as gcry_sexp_new but allows to pass a FREEFNC which has the + effect to transfer ownership of BUFFER to the created object. */ +gcry_error_t gcry_sexp_create (gcry_sexp_t *retsexp, + void *buffer, size_t length, + int autodetect, void (*freefnc) (void *)); + +/* Scan BUFFER and return a new S-expression object in RETSEXP. This + function expects a printf like string in BUFFER. */ +gcry_error_t gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, + const char *buffer, size_t length); + +/* Same as gcry_sexp_sscan but expects a string in FORMAT and can thus + only be used for certain encodings. */ +gcry_error_t gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, + const char *format, ...); + +/* Like gcry_sexp_build, but uses an array instead of variable + function arguments. */ +gcry_error_t gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff, + const char *format, void **arg_list); + +/* Release the S-expression object SEXP */ +void gcry_sexp_release (gcry_sexp_t sexp); + +/* Calculate the length of an canonized S-expresion in BUFFER and + check for a valid encoding. */ +size_t gcry_sexp_canon_len (const unsigned char *buffer, size_t length, + size_t *erroff, gcry_error_t *errcode); + +/* Copies the S-expression object SEXP into BUFFER using the format + specified in MODE. */ +size_t gcry_sexp_sprint (gcry_sexp_t sexp, int mode, void *buffer, + size_t maxlength); + +/* Dumps the S-expression object A in a format suitable for debugging + to Libgcrypt's logging stream. */ +void gcry_sexp_dump (const gcry_sexp_t a); + +gcry_sexp_t gcry_sexp_cons (const gcry_sexp_t a, const gcry_sexp_t b); +gcry_sexp_t gcry_sexp_alist (const gcry_sexp_t *array); +gcry_sexp_t gcry_sexp_vlist (const gcry_sexp_t a, ...); +gcry_sexp_t gcry_sexp_append (const gcry_sexp_t a, const gcry_sexp_t n); +gcry_sexp_t gcry_sexp_prepend (const gcry_sexp_t a, const gcry_sexp_t n); + +/* Scan the S-expression for a sublist with a type (the car of the + list) matching the string TOKEN. If TOKLEN is not 0, the token is + assumed to be raw memory of this length. The function returns a + newly allocated S-expression consisting of the found sublist or + `NULL' when not found. */ +gcry_sexp_t gcry_sexp_find_token (gcry_sexp_t list, + const char *tok, size_t toklen); +/* Return the length of the LIST. For a valid S-expression this + should be at least 1. */ +int gcry_sexp_length (const gcry_sexp_t list); + +/* Create and return a new S-expression from the element with index + NUMBER in LIST. Note that the first element has the index 0. If + there is no such element, `NULL' is returned. */ +gcry_sexp_t gcry_sexp_nth (const gcry_sexp_t list, int number); + +/* Create and return a new S-expression from the first element in + LIST; this called the "type" and should always exist and be a + string. `NULL' is returned in case of a problem. */ +gcry_sexp_t gcry_sexp_car (const gcry_sexp_t list); + +/* Create and return a new list form all elements except for the first + one. Note, that this function may return an invalid S-expression + because it is not guaranteed, that the type exists and is a string. + However, for parsing a complex S-expression it might be useful for + intermediate lists. Returns `NULL' on error. */ +gcry_sexp_t gcry_sexp_cdr (const gcry_sexp_t list); + +gcry_sexp_t gcry_sexp_cadr (const gcry_sexp_t list); + + +/* This function is used to get data from a LIST. A pointer to the + actual data with index NUMBER is returned and the length of this + data will be stored to DATALEN. If there is no data at the given + index or the index represents another list, `NULL' is returned. + *Note:* The returned pointer is valid as long as LIST is not + modified or released. */ +const char *gcry_sexp_nth_data (const gcry_sexp_t list, int number, + size_t *datalen); + +/* This function is used to get and convert data from a LIST. The + data is assumed to be a Nul terminated string. The caller must + release the returned value using `gcry_free'. If there is no data + at the given index, the index represents a list or the value can't + be converted to a string, `NULL' is returned. */ +char *gcry_sexp_nth_string (gcry_sexp_t list, int number); + +/* This function is used to get and convert data from a LIST. This + data is assumed to be an MPI stored in the format described by + MPIFMT and returned as a standard Libgcrypt MPI. The caller must + release this returned value using `gcry_mpi_release'. If there is + no data at the given index, the index represents a list or the + value can't be converted to an MPI, `NULL' is returned. */ +gcry_mpi_t gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt); + + + +/******************************************* + * * + * Multi Precision Integer Functions * + * * + *******************************************/ + +/* Different formats of external big integer representation. */ +enum gcry_mpi_format + { + GCRYMPI_FMT_NONE= 0, + GCRYMPI_FMT_STD = 1, /* Twos complement stored without length. */ + GCRYMPI_FMT_PGP = 2, /* As used by OpenPGP (unsigned only). */ + GCRYMPI_FMT_SSH = 3, /* As used by SSH (like STD but with length). */ + GCRYMPI_FMT_HEX = 4, /* Hex format. */ + GCRYMPI_FMT_USG = 5 /* Like STD but unsigned. */ + }; + +/* Flags used for creating big integers. */ +enum gcry_mpi_flag + { + GCRYMPI_FLAG_SECURE = 1, /* Allocate the number in "secure" memory. */ + GCRYMPI_FLAG_OPAQUE = 2 /* The number is not a real one but just + a way to store some bytes. This is + useful for encrypted big integers. */ + }; + + +/* Allocate a new big integer object, initialize it with 0 and + initially allocate memory for a number of at least NBITS. */ +gcry_mpi_t gcry_mpi_new (unsigned int nbits); + +/* Same as gcry_mpi_new() but allocate in "secure" memory. */ +gcry_mpi_t gcry_mpi_snew (unsigned int nbits); + +/* Release the number A and free all associated resources. */ +void gcry_mpi_release (gcry_mpi_t a); + +/* Create a new number with the same value as A. */ +gcry_mpi_t gcry_mpi_copy (const gcry_mpi_t a); + +/* Store the big integer value U in W. */ +gcry_mpi_t gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u); + +/* Store the unsigned integer value U in W. */ +gcry_mpi_t gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u); + +/* Swap the values of A and B. */ +void gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b); + +/* Compare the big integer number U and V returning 0 for equality, a + positive value for U > V and a negative for U < V. */ +int gcry_mpi_cmp (const gcry_mpi_t u, const gcry_mpi_t v); + +/* Compare the big integer number U with the unsigned integer V + returning 0 for equality, a positive value for U > V and a negative + for U < V. */ +int gcry_mpi_cmp_ui (const gcry_mpi_t u, unsigned long v); + +/* Convert the external representation of an integer stored in BUFFER + with a length of BUFLEN into a newly create MPI returned in + RET_MPI. If NSCANNED is not NULL, it will receive the number of + bytes actually scanned after a successful operation. */ +gcry_error_t gcry_mpi_scan (gcry_mpi_t *ret_mpi, enum gcry_mpi_format format, + const void *buffer, size_t buflen, + size_t *nscanned); + +/* Convert the big integer A into the external representation + described by FORMAT and store it in the provided BUFFER which has + been allocated by the user with a size of BUFLEN bytes. NWRITTEN + receives the actual length of the external representation unless it + has been passed as NULL. */ +gcry_error_t gcry_mpi_print (enum gcry_mpi_format format, + unsigned char *buffer, size_t buflen, + size_t *nwritten, + const gcry_mpi_t a); + +/* Convert the big integer A int the external representation described + by FORMAT and store it in a newly allocated buffer which address + will be put into BUFFER. NWRITTEN receives the actual lengths of the + external representation. */ +gcry_error_t gcry_mpi_aprint (enum gcry_mpi_format format, + unsigned char **buffer, size_t *nwritten, + const gcry_mpi_t a); + +/* Dump the value of A in a format suitable for debugging to + Libgcrypt's logging stream. Note that one leading space but no + trailing space or linefeed will be printed. It is okay to pass + NULL for A. */ +void gcry_mpi_dump (const gcry_mpi_t a); + + +/* W = U + V. */ +void gcry_mpi_add (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v); + +/* W = U + V. V is an unsigned integer. */ +void gcry_mpi_add_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v); + +/* W = U + V mod M. */ +void gcry_mpi_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m); + +/* W = U - V. */ +void gcry_mpi_sub (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v); + +/* W = U - V. V is an unsigned integer. */ +void gcry_mpi_sub_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v ); + +/* W = U - V mod M */ +void gcry_mpi_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m); + +/* W = U * V. */ +void gcry_mpi_mul (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v); + +/* W = U * V. V is an unsigned integer. */ +void gcry_mpi_mul_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v ); + +/* W = U * V mod M. */ +void gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m); + +/* W = U * (2 ^ CNT). */ +void gcry_mpi_mul_2exp (gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt); + +/* Q = DIVIDEND / DIVISOR, R = DIVIDEND % DIVISOR, + Q or R may be passed as NULL. ROUND should be negative or 0. */ +void gcry_mpi_div (gcry_mpi_t q, gcry_mpi_t r, + gcry_mpi_t dividend, gcry_mpi_t divisor, int round); + +/* R = DIVIDEND % DIVISOR */ +void gcry_mpi_mod (gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor); + +/* W = B ^ E mod M. */ +void gcry_mpi_powm (gcry_mpi_t w, + const gcry_mpi_t b, const gcry_mpi_t e, + const gcry_mpi_t m); + +/* Set G to the greatest common divisor of A and B. + Return true if the G is 1. */ +int gcry_mpi_gcd (gcry_mpi_t g, gcry_mpi_t a, gcry_mpi_t b); + +/* Set X to the multiplicative inverse of A mod M. + Return true if the value exists. */ +int gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t m); + + +/* Return the number of bits required to represent A. */ +unsigned int gcry_mpi_get_nbits (gcry_mpi_t a); + +/* Return true when bit number N (counting from 0) is set in A. */ +int gcry_mpi_test_bit (gcry_mpi_t a, unsigned int n); + +/* Set bit number N in A. */ +void gcry_mpi_set_bit (gcry_mpi_t a, unsigned int n); + +/* Clear bit number N in A. */ +void gcry_mpi_clear_bit (gcry_mpi_t a, unsigned int n); + +/* Set bit number N in A and clear all bits greater than N. */ +void gcry_mpi_set_highbit (gcry_mpi_t a, unsigned int n); + +/* Clear bit number N in A and all bits greater than N. */ +void gcry_mpi_clear_highbit (gcry_mpi_t a, unsigned int n); + +/* Shift the value of A by N bits to the right and store the result in X. */ +void gcry_mpi_rshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n); + +/* Shift the value of A by N bits to the left and store the result in X. */ +void gcry_mpi_lshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n); + +/* Store NBITS of the value P points to in A and mark A as an opaque + value. WARNING: Never use an opaque MPI for anything thing else then + gcry_mpi_release, gcry_mpi_get_opaque. */ +gcry_mpi_t gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits); + +/* Return a pointer to an opaque value stored in A and return its size + in NBITS. Note that the returned pointer is still owned by A and + that the function should never be used for an non-opaque MPI. */ +void *gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits); + +/* Set the FLAG for the big integer A. Currently only the flag + GCRYMPI_FLAG_SECURE is allowed to convert A into an big intger + stored in "secure" memory. */ +void gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag); + +/* Clear FLAG for the big integer A. Note that this function is + currently useless as no flags are allowed. */ +void gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag); + +/* Return true when the FLAG is set for A. */ +int gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag); + +/* Unless the GCRYPT_NO_MPI_MACROS is used, provide a couple of + convenience macros for the big integer functions. */ +#ifndef GCRYPT_NO_MPI_MACROS +#define mpi_new(n) gcry_mpi_new( (n) ) +#define mpi_secure_new( n ) gcry_mpi_snew( (n) ) +#define mpi_release(a) \ + do \ + { \ + gcry_mpi_release ((a)); \ + (a) = NULL; \ + } \ + while (0) + +#define mpi_copy( a ) gcry_mpi_copy( (a) ) +#define mpi_set( w, u) gcry_mpi_set( (w), (u) ) +#define mpi_set_ui( w, u) gcry_mpi_set_ui( (w), (u) ) +#define mpi_cmp( u, v ) gcry_mpi_cmp( (u), (v) ) +#define mpi_cmp_ui( u, v ) gcry_mpi_cmp_ui( (u), (v) ) + +#define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v)) +#define mpi_add(w,u,v) gcry_mpi_add ((w),(u),(v)) +#define mpi_addm(w,u,v,m) gcry_mpi_addm ((w),(u),(v),(m)) +#define mpi_sub_ui(w,u,v) gcry_mpi_sub_ui ((w),(u),(v)) +#define mpi_sub(w,u,v) gcry_mpi_sub ((w),(u),(v)) +#define mpi_subm(w,u,v,m) gcry_mpi_subm ((w),(u),(v),(m)) +#define mpi_mul_ui(w,u,v) gcry_mpi_mul_ui ((w),(u),(v)) +#define mpi_mul_2exp(w,u,v) gcry_mpi_mul_2exp ((w),(u),(v)) +#define mpi_mul(w,u,v) gcry_mpi_mul ((w),(u),(v)) +#define mpi_mulm(w,u,v,m) gcry_mpi_mulm ((w),(u),(v),(m)) +#define mpi_powm(w,b,e,m) gcry_mpi_powm ( (w), (b), (e), (m) ) +#define mpi_tdiv(q,r,a,m) gcry_mpi_div ( (q), (r), (a), (m), 0) +#define mpi_fdiv(q,r,a,m) gcry_mpi_div ( (q), (r), (a), (m), -1) +#define mpi_mod(r,a,m) gcry_mpi_mod ((r), (a), (m)) +#define mpi_gcd(g,a,b) gcry_mpi_gcd ( (g), (a), (b) ) +#define mpi_invm(g,a,b) gcry_mpi_invm ( (g), (a), (b) ) + +#define mpi_get_nbits(a) gcry_mpi_get_nbits ((a)) +#define mpi_test_bit(a,b) gcry_mpi_test_bit ((a),(b)) +#define mpi_set_bit(a,b) gcry_mpi_set_bit ((a),(b)) +#define mpi_set_highbit(a,b) gcry_mpi_set_highbit ((a),(b)) +#define mpi_clear_bit(a,b) gcry_mpi_clear_bit ((a),(b)) +#define mpi_clear_highbit(a,b) gcry_mpi_clear_highbit ((a),(b)) +#define mpi_rshift(a,b,c) gcry_mpi_rshift ((a),(b),(c)) +#define mpi_lshift(a,b,c) gcry_mpi_lshift ((a),(b),(c)) + +#define mpi_set_opaque(a,b,c) gcry_mpi_set_opaque( (a), (b), (c) ) +#define mpi_get_opaque(a,b) gcry_mpi_get_opaque( (a), (b) ) +#endif /* GCRYPT_NO_MPI_MACROS */ + + + +/************************************ + * * + * Symmetric Cipher Functions * + * * + ************************************/ + +/* The data object used to hold a handle to an encryption object. */ +struct gcry_cipher_handle; +typedef struct gcry_cipher_handle *gcry_cipher_hd_t; + +#ifndef GCRYPT_NO_DEPRECATED +typedef struct gcry_cipher_handle *GCRY_CIPHER_HD _GCRY_GCC_ATTR_DEPRECATED; +typedef struct gcry_cipher_handle *GcryCipherHd _GCRY_GCC_ATTR_DEPRECATED; +#endif + +/* All symmetric encryption algorithms are identified by their IDs. + More IDs may be registered at runtime. */ +enum gcry_cipher_algos + { + GCRY_CIPHER_NONE = 0, + GCRY_CIPHER_IDEA = 1, + GCRY_CIPHER_3DES = 2, + GCRY_CIPHER_CAST5 = 3, + GCRY_CIPHER_BLOWFISH = 4, + GCRY_CIPHER_SAFER_SK128 = 5, + GCRY_CIPHER_DES_SK = 6, + GCRY_CIPHER_AES = 7, + GCRY_CIPHER_AES192 = 8, + GCRY_CIPHER_AES256 = 9, + GCRY_CIPHER_TWOFISH = 10, + + /* Other cipher numbers are above 300 for OpenPGP reasons. */ + GCRY_CIPHER_ARCFOUR = 301, /* Fully compatible with RSA's RC4 (tm). */ + GCRY_CIPHER_DES = 302, /* Yes, this is single key 56 bit DES. */ + GCRY_CIPHER_TWOFISH128 = 303, + GCRY_CIPHER_SERPENT128 = 304, + GCRY_CIPHER_SERPENT192 = 305, + GCRY_CIPHER_SERPENT256 = 306, + GCRY_CIPHER_RFC2268_40 = 307, /* Ron's Cipher 2 (40 bit). */ + GCRY_CIPHER_RFC2268_128 = 308, /* Ron's Cipher 2 (128 bit). */ + GCRY_CIPHER_SEED = 309, /* 128 bit cipher described in RFC4269. */ + GCRY_CIPHER_CAMELLIA128 = 310, + GCRY_CIPHER_CAMELLIA192 = 311, + GCRY_CIPHER_CAMELLIA256 = 312 + }; + +/* The Rijndael algorithm is basically AES, so provide some macros. */ +#define GCRY_CIPHER_AES128 GCRY_CIPHER_AES +#define GCRY_CIPHER_RIJNDAEL GCRY_CIPHER_AES +#define GCRY_CIPHER_RIJNDAEL128 GCRY_CIPHER_AES128 +#define GCRY_CIPHER_RIJNDAEL192 GCRY_CIPHER_AES192 +#define GCRY_CIPHER_RIJNDAEL256 GCRY_CIPHER_AES256 + +/* The supported encryption modes. Note that not all of them are + supported for each algorithm. */ +enum gcry_cipher_modes + { + GCRY_CIPHER_MODE_NONE = 0, /* Not yet specified. */ + GCRY_CIPHER_MODE_ECB = 1, /* Electronic codebook. */ + GCRY_CIPHER_MODE_CFB = 2, /* Cipher feedback. */ + GCRY_CIPHER_MODE_CBC = 3, /* Cipher block chaining. */ + GCRY_CIPHER_MODE_STREAM = 4, /* Used with stream ciphers. */ + GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */ + GCRY_CIPHER_MODE_CTR = 6, /* Counter. */ + GCRY_CIPHER_MODE_AESWRAP= 7 /* AES-WRAP algorithm. */ + }; + +/* Flags used with the open function. */ +enum gcry_cipher_flags + { + GCRY_CIPHER_SECURE = 1, /* Allocate in secure memory. */ + GCRY_CIPHER_ENABLE_SYNC = 2, /* Enable CFB sync mode. */ + GCRY_CIPHER_CBC_CTS = 4, /* Enable CBC cipher text stealing (CTS). */ + GCRY_CIPHER_CBC_MAC = 8 /* Enable CBC message auth. code (MAC). */ + }; + + +/* Create a handle for algorithm ALGO to be used in MODE. FLAGS may + be given as an bitwise OR of the gcry_cipher_flags values. */ +gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle, + int algo, int mode, unsigned int flags); + +/* Close the cioher handle H and release all resource. */ +void gcry_cipher_close (gcry_cipher_hd_t h); + +/* Perform various operations on the cipher object H. */ +gcry_error_t gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, + size_t buflen); + +/* Retrieve various information about the cipher object H. */ +gcry_error_t gcry_cipher_info (gcry_cipher_hd_t h, int what, void *buffer, + size_t *nbytes); + +/* Retrieve various information about the cipher algorithm ALGO. */ +gcry_error_t gcry_cipher_algo_info (int algo, int what, void *buffer, + size_t *nbytes); + +/* Map the cipher algorithm whose ID is contained in ALGORITHM to a + string representation of the algorithm name. For unknown algorithm + IDs this function returns "?". */ +const char *gcry_cipher_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE; + +/* Map the algorithm name NAME to an cipher algorithm ID. Return 0 if + the algorithm name is not known. */ +int gcry_cipher_map_name (const char *name) _GCRY_GCC_ATTR_PURE; + +/* Given an ASN.1 object identifier in standard IETF dotted decimal + format in STRING, return the encryption mode associated with that + OID or 0 if not known or applicable. */ +int gcry_cipher_mode_from_oid (const char *string) _GCRY_GCC_ATTR_PURE; + +/* Encrypt the plaintext of size INLEN in IN using the cipher handle H + into the buffer OUT which has an allocated length of OUTSIZE. For + most algorithms it is possible to pass NULL for in and 0 for INLEN + and do a in-place decryption of the data provided in OUT. */ +gcry_error_t gcry_cipher_encrypt (gcry_cipher_hd_t h, + void *out, size_t outsize, + const void *in, size_t inlen); + +/* The counterpart to gcry_cipher_encrypt. */ +gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t h, + void *out, size_t outsize, + const void *in, size_t inlen); + +/* Set KEY of length KEYLEN bytes for the cipher handle HD. */ +gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t hd, + const void *key, size_t keylen); + + +/* Set initialization vector IV of length IVLEN for the cipher handle HD. */ +gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t hd, + const void *iv, size_t ivlen); + + +/* Reset the handle to the state after open. */ +#define gcry_cipher_reset(h) gcry_cipher_ctl ((h), GCRYCTL_RESET, NULL, 0) + +/* Perform the OpenPGP sync operation if this is enabled for the + cipher handle H. */ +#define gcry_cipher_sync(h) gcry_cipher_ctl( (h), GCRYCTL_CFB_SYNC, NULL, 0) + +/* Enable or disable CTS in future calls to gcry_encrypt(). CBC mode only. */ +#define gcry_cipher_cts(h,on) gcry_cipher_ctl( (h), GCRYCTL_SET_CBC_CTS, \ + NULL, on ) + +/* Set counter for CTR mode. (CTR,CTRLEN) must denote a buffer of + block size length, or (NULL,0) to set the CTR to the all-zero block. */ +gpg_error_t gcry_cipher_setctr (gcry_cipher_hd_t hd, + const void *ctr, size_t ctrlen); + +/* Retrieve the key length in bytes used with algorithm A. */ +size_t gcry_cipher_get_algo_keylen (int algo); + +/* Retrieve the block length in bytes used with algorithm A. */ +size_t gcry_cipher_get_algo_blklen (int algo); + +/* Return 0 if the algorithm A is available for use. */ +#define gcry_cipher_test_algo(a) \ + gcry_cipher_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL ) + +/* Get a list consisting of the IDs of the loaded cipher modules. If + LIST is zero, write the number of loaded cipher modules to + LIST_LENGTH and return. If LIST is non-zero, the first + *LIST_LENGTH algorithm IDs are stored in LIST, which must be of + according size. In case there are less cipher modules than + *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */ +gcry_error_t gcry_cipher_list (int *list, int *list_length); + + +/************************************ + * * + * Asymmetric Cipher Functions * + * * + ************************************/ + +/* The algorithms and their IDs we support. */ +enum gcry_pk_algos + { + GCRY_PK_RSA = 1, + GCRY_PK_RSA_E = 2, /* (deprecated) */ + GCRY_PK_RSA_S = 3, /* (deprecated) */ + GCRY_PK_ELG_E = 16, + GCRY_PK_DSA = 17, + GCRY_PK_ELG = 20, + GCRY_PK_ECDSA = 301, + GCRY_PK_ECDH = 302 + }; + +/* Flags describing usage capabilities of a PK algorithm. */ +#define GCRY_PK_USAGE_SIGN 1 /* Good for signatures. */ +#define GCRY_PK_USAGE_ENCR 2 /* Good for encryption. */ +#define GCRY_PK_USAGE_CERT 4 /* Good to certify other keys. */ +#define GCRY_PK_USAGE_AUTH 8 /* Good for authentication. */ +#define GCRY_PK_USAGE_UNKN 128 /* Unknown usage flag. */ + +/* Encrypt the DATA using the public key PKEY and store the result as + a newly created S-expression at RESULT. */ +gcry_error_t gcry_pk_encrypt (gcry_sexp_t *result, + gcry_sexp_t data, gcry_sexp_t pkey); + +/* Decrypt the DATA using the private key SKEY and store the result as + a newly created S-expression at RESULT. */ +gcry_error_t gcry_pk_decrypt (gcry_sexp_t *result, + gcry_sexp_t data, gcry_sexp_t skey); + +/* Sign the DATA using the private key SKEY and store the result as + a newly created S-expression at RESULT. */ +gcry_error_t gcry_pk_sign (gcry_sexp_t *result, + gcry_sexp_t data, gcry_sexp_t skey); + +/* Check the signature SIGVAL on DATA using the public key PKEY. */ +gcry_error_t gcry_pk_verify (gcry_sexp_t sigval, + gcry_sexp_t data, gcry_sexp_t pkey); + +/* Check that private KEY is sane. */ +gcry_error_t gcry_pk_testkey (gcry_sexp_t key); + +/* Generate a new key pair according to the parameters given in + S_PARMS. The new key pair is returned in as an S-expression in + R_KEY. */ +gcry_error_t gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms); + +/* Catch all function for miscellaneous operations. */ +gcry_error_t gcry_pk_ctl (int cmd, void *buffer, size_t buflen); + +/* Retrieve information about the public key algorithm ALGO. */ +gcry_error_t gcry_pk_algo_info (int algo, int what, + void *buffer, size_t *nbytes); + +/* Map the public key algorithm whose ID is contained in ALGORITHM to + a string representation of the algorithm name. For unknown + algorithm IDs this functions returns "?". */ +const char *gcry_pk_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE; + +/* Map the algorithm NAME to a public key algorithm Id. Return 0 if + the algorithm name is not known. */ +int gcry_pk_map_name (const char* name) _GCRY_GCC_ATTR_PURE; + +/* Return what is commonly referred as the key length for the given + public or private KEY. */ +unsigned int gcry_pk_get_nbits (gcry_sexp_t key) _GCRY_GCC_ATTR_PURE; + +/* Please note that keygrip is still experimental and should not be + used without contacting the author. */ +unsigned char *gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array); + +/* Return the name of the curve matching KEY. */ +const char *gcry_pk_get_curve (gcry_sexp_t key, int iterator, + unsigned int *r_nbits); + +/* Return an S-expression with the parameters of the named ECC curve + NAME. ALGO must be set to an ECC algorithm. */ +gcry_sexp_t gcry_pk_get_param (int algo, const char *name); + +/* Return 0 if the public key algorithm A is available for use. */ +#define gcry_pk_test_algo(a) \ + gcry_pk_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL ) + +/* Get a list consisting of the IDs of the loaded pubkey modules. If + LIST is zero, write the number of loaded pubkey modules to + LIST_LENGTH and return. If LIST is non-zero, the first + *LIST_LENGTH algorithm IDs are stored in LIST, which must be of + according size. In case there are less pubkey modules than + *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */ +gcry_error_t gcry_pk_list (int *list, int *list_length); + + + +/************************************ + * * + * Cryptograhic Hash Functions * + * * + ************************************/ + +/* Algorithm IDs for the hash functions we know about. Not all of them + are implemnted. */ +enum gcry_md_algos + { + GCRY_MD_NONE = 0, + GCRY_MD_MD5 = 1, + GCRY_MD_SHA1 = 2, + GCRY_MD_RMD160 = 3, + GCRY_MD_MD2 = 5, + GCRY_MD_TIGER = 6, /* TIGER/192 as used by gpg <= 1.3.2. */ + GCRY_MD_HAVAL = 7, /* HAVAL, 5 pass, 160 bit. */ + GCRY_MD_SHA256 = 8, + GCRY_MD_SHA384 = 9, + GCRY_MD_SHA512 = 10, + GCRY_MD_SHA224 = 11, + GCRY_MD_MD4 = 301, + GCRY_MD_CRC32 = 302, + GCRY_MD_CRC32_RFC1510 = 303, + GCRY_MD_CRC24_RFC2440 = 304, + GCRY_MD_WHIRLPOOL = 305, + GCRY_MD_TIGER1 = 306, /* TIGER fixed. */ + GCRY_MD_TIGER2 = 307 /* TIGER2 variant. */ + }; + +/* Flags used with the open function. */ +enum gcry_md_flags + { + GCRY_MD_FLAG_SECURE = 1, /* Allocate all buffers in "secure" memory. */ + GCRY_MD_FLAG_HMAC = 2 /* Make an HMAC out of this algorithm. */ + }; + +/* (Forward declaration.) */ +struct gcry_md_context; + +/* This object is used to hold a handle to a message digest object. + This structure is private - only to be used by the public gcry_md_* + macros. */ +typedef struct gcry_md_handle +{ + /* Actual context. */ + struct gcry_md_context *ctx; + + /* Buffer management. */ + int bufpos; + int bufsize; + unsigned char buf[1]; +} *gcry_md_hd_t; + +/* Compatibility types, do not use them. */ +#ifndef GCRYPT_NO_DEPRECATED +typedef struct gcry_md_handle *GCRY_MD_HD _GCRY_GCC_ATTR_DEPRECATED; +typedef struct gcry_md_handle *GcryMDHd _GCRY_GCC_ATTR_DEPRECATED; +#endif + +/* Create a message digest object for algorithm ALGO. FLAGS may be + given as an bitwise OR of the gcry_md_flags values. ALGO may be + given as 0 if the algorithms to be used are later set using + gcry_md_enable. */ +gcry_error_t gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags); + +/* Release the message digest object HD. */ +void gcry_md_close (gcry_md_hd_t hd); + +/* Add the message digest algorithm ALGO to the digest object HD. */ +gcry_error_t gcry_md_enable (gcry_md_hd_t hd, int algo); + +/* Create a new digest object as an exact copy of the object HD. */ +gcry_error_t gcry_md_copy (gcry_md_hd_t *bhd, gcry_md_hd_t ahd); + +/* Reset the digest object HD to its initial state. */ +void gcry_md_reset (gcry_md_hd_t hd); + +/* Perform various operations on the digest object HD. */ +gcry_error_t gcry_md_ctl (gcry_md_hd_t hd, int cmd, + void *buffer, size_t buflen); + +/* Pass LENGTH bytes of data in BUFFER to the digest object HD so that + it can update the digest values. This is the actual hash + function. */ +void gcry_md_write (gcry_md_hd_t hd, const void *buffer, size_t length); + +/* Read out the final digest from HD return the digest value for + algorithm ALGO. */ +unsigned char *gcry_md_read (gcry_md_hd_t hd, int algo); + +/* Convenience function to calculate the hash from the data in BUFFER + of size LENGTH using the algorithm ALGO avoiding the creating of a + hash object. The hash is returned in the caller provided buffer + DIGEST which must be large enough to hold the digest of the given + algorithm. */ +void gcry_md_hash_buffer (int algo, void *digest, + const void *buffer, size_t length); + +/* Retrieve the algorithm used with HD. This does not work reliable + if more than one algorithm is enabled in HD. */ +int gcry_md_get_algo (gcry_md_hd_t hd); + +/* Retrieve the length in bytes of the digest yielded by algorithm + ALGO. */ +unsigned int gcry_md_get_algo_dlen (int algo); + +/* Return true if the the algorithm ALGO is enabled in the digest + object A. */ +int gcry_md_is_enabled (gcry_md_hd_t a, int algo); + +/* Return true if the digest object A is allocated in "secure" memory. */ +int gcry_md_is_secure (gcry_md_hd_t a); + +/* Retrieve various information about the object H. */ +gcry_error_t gcry_md_info (gcry_md_hd_t h, int what, void *buffer, + size_t *nbytes); + +/* Retrieve various information about the algorithm ALGO. */ +gcry_error_t gcry_md_algo_info (int algo, int what, void *buffer, + size_t *nbytes); + +/* Map the digest algorithm id ALGO to a string representation of the + algorithm name. For unknown algorithms this function returns + "?". */ +const char *gcry_md_algo_name (int algo) _GCRY_GCC_ATTR_PURE; + +/* Map the algorithm NAME to a digest algorithm Id. Return 0 if + the algorithm name is not known. */ +int gcry_md_map_name (const char* name) _GCRY_GCC_ATTR_PURE; + +/* For use with the HMAC feature, the set MAC key to the KEY of + KEYLEN bytes. */ +gcry_error_t gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen); + +/* Start or stop debugging for digest handle HD; i.e. create a file + named dbgmd-<n>.<suffix> while hashing. If SUFFIX is NULL, + debugging stops and the file will be closed. */ +void gcry_md_debug (gcry_md_hd_t hd, const char *suffix); + + +/* Update the hash(s) of H with the character C. This is a buffered + version of the gcry_md_write function. */ +#define gcry_md_putc(h,c) \ + do { \ + gcry_md_hd_t h__ = (h); \ + if( (h__)->bufpos == (h__)->bufsize ) \ + gcry_md_write( (h__), NULL, 0 ); \ + (h__)->buf[(h__)->bufpos++] = (c) & 0xff; \ + } while(0) + +/* Finalize the digest calculation. This is not really needed because + gcry_md_read() does this implicitly. */ +#define gcry_md_final(a) \ + gcry_md_ctl ((a), GCRYCTL_FINALIZE, NULL, 0) + +/* Return 0 if the algorithm A is available for use. */ +#define gcry_md_test_algo(a) \ + gcry_md_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL ) + +/* Return an DER encoded ASN.1 OID for the algorithm A in buffer B. N + must point to size_t variable with the available size of buffer B. + After return it will receive the actual size of the returned + OID. */ +#define gcry_md_get_asnoid(a,b,n) \ + gcry_md_algo_info((a), GCRYCTL_GET_ASNOID, (b), (n)) + +/* Enable debugging for digest object A; i.e. create files named + dbgmd-<n>.<string> while hashing. B is a string used as the suffix + for the filename. This macro is deprecated, use gcry_md_debug. */ +#ifndef GCRYPT_NO_DEPRECATED +#define gcry_md_start_debug(a,b) \ + gcry_md_ctl( (a), GCRYCTL_START_DUMP, (b), 0 ) + +/* Disable the debugging of A. This macro is deprecated, use + gcry_md_debug. */ +#define gcry_md_stop_debug(a,b) \ + gcry_md_ctl( (a), GCRYCTL_STOP_DUMP, (b), 0 ) +#endif + +/* Get a list consisting of the IDs of the loaded message digest + modules. If LIST is zero, write the number of loaded message + digest modules to LIST_LENGTH and return. If LIST is non-zero, the + first *LIST_LENGTH algorithm IDs are stored in LIST, which must be + of according size. In case there are less message digest modules + than *LIST_LENGTH, *LIST_LENGTH is updated to the correct + number. */ +gcry_error_t gcry_md_list (int *list, int *list_length); + + +#if !defined(GCRYPT_NO_DEPRECATED) || defined(_GCRYPT_IN_LIBGCRYPT) +/* Alternative interface for asymmetric cryptography. This interface + is deprecated. */ + +/* The algorithm IDs. */ +typedef enum gcry_ac_id + { + GCRY_AC_RSA = 1, + GCRY_AC_DSA = 17, + GCRY_AC_ELG = 20, + GCRY_AC_ELG_E = 16 + } +gcry_ac_id_t _GCRY_ATTR_INTERNAL; + +/* Key types. */ +typedef enum gcry_ac_key_type + { + GCRY_AC_KEY_SECRET, + GCRY_AC_KEY_PUBLIC + } +gcry_ac_key_type_t _GCRY_ATTR_INTERNAL; + +/* Encoding methods. */ +typedef enum gcry_ac_em + { + GCRY_AC_EME_PKCS_V1_5, + GCRY_AC_EMSA_PKCS_V1_5 + } +gcry_ac_em_t _GCRY_ATTR_INTERNAL; + +/* Encryption and Signature schemes. */ +typedef enum gcry_ac_scheme + { + GCRY_AC_ES_PKCS_V1_5, + GCRY_AC_SSA_PKCS_V1_5 + } +gcry_ac_scheme_t _GCRY_ATTR_INTERNAL; + +/* AC data. */ +#define GCRY_AC_FLAG_DEALLOC (1 << 0) +#define GCRY_AC_FLAG_COPY (1 << 1) +#define GCRY_AC_FLAG_NO_BLINDING (1 << 2) + +/* This type represents a `data set'. */ +typedef struct gcry_ac_data *gcry_ac_data_t _GCRY_ATTR_INTERNAL; + +/* This type represents a single `key', either a secret one or a + public one. */ +typedef struct gcry_ac_key *gcry_ac_key_t _GCRY_ATTR_INTERNAL; + +/* This type represents a `key pair' containing a secret and a public + key. */ +typedef struct gcry_ac_key_pair *gcry_ac_key_pair_t _GCRY_ATTR_INTERNAL; + +/* This type represents a `handle' that is needed by functions + performing cryptographic operations. */ +typedef struct gcry_ac_handle *gcry_ac_handle_t _GCRY_ATTR_INTERNAL; + +typedef gpg_error_t (*gcry_ac_data_read_cb_t) (void *opaque, + unsigned char *buffer, + size_t *buffer_n) + /* */ _GCRY_ATTR_INTERNAL; + +typedef gpg_error_t (*gcry_ac_data_write_cb_t) (void *opaque, + unsigned char *buffer, + size_t buffer_n) + /* */ _GCRY_ATTR_INTERNAL; + +typedef enum + { + GCRY_AC_IO_READABLE, + GCRY_AC_IO_WRITABLE + } +gcry_ac_io_mode_t _GCRY_ATTR_INTERNAL; + +typedef enum + { + GCRY_AC_IO_STRING, + GCRY_AC_IO_CALLBACK + } +gcry_ac_io_type_t _GCRY_ATTR_INTERNAL; + +typedef struct gcry_ac_io +{ + /* This is an INTERNAL structure, do NOT use manually. */ + gcry_ac_io_mode_t mode _GCRY_ATTR_INTERNAL; + gcry_ac_io_type_t type _GCRY_ATTR_INTERNAL; + union + { + union + { + struct + { + gcry_ac_data_read_cb_t cb; + void *opaque; + } callback; + struct + { + unsigned char *data; + size_t data_n; + } string; + void *opaque; + } readable; + union + { + struct + { + gcry_ac_data_write_cb_t cb; + void *opaque; + } callback; + struct + { + unsigned char **data; + size_t *data_n; + } string; + void *opaque; + } writable; + } io _GCRY_ATTR_INTERNAL; +} +gcry_ac_io_t _GCRY_ATTR_INTERNAL; + +/* The caller of gcry_ac_key_pair_generate can provide one of these + structures in order to influence the key generation process in an + algorithm-specific way. */ +typedef struct gcry_ac_key_spec_rsa +{ + gcry_mpi_t e; /* E to use. */ +} gcry_ac_key_spec_rsa_t _GCRY_ATTR_INTERNAL; + +/* Structure used for passing data to the implementation of the + `EME-PKCS-V1_5' encoding method. */ +typedef struct gcry_ac_eme_pkcs_v1_5 +{ + size_t key_size; +} gcry_ac_eme_pkcs_v1_5_t _GCRY_ATTR_INTERNAL; + +typedef enum gcry_md_algos gcry_md_algo_t _GCRY_ATTR_INTERNAL; + +/* Structure used for passing data to the implementation of the + `EMSA-PKCS-V1_5' encoding method. */ +typedef struct gcry_ac_emsa_pkcs_v1_5 +{ + gcry_md_algo_t md; + size_t em_n; +} gcry_ac_emsa_pkcs_v1_5_t _GCRY_ATTR_INTERNAL; + +/* Structure used for passing data to the implementation of the + `SSA-PKCS-V1_5' signature scheme. */ +typedef struct gcry_ac_ssa_pkcs_v1_5 +{ + gcry_md_algo_t md; +} gcry_ac_ssa_pkcs_v1_5_t _GCRY_ATTR_INTERNAL; +#endif /* !GCRYPT_NO_DEPRECATED || !_GCRYPT_IN_LIBGCRYPT */ + + +#ifndef GCRYPT_NO_DEPRECATED +/* Returns a new, empty data set in DATA. */ +gcry_error_t gcry_ac_data_new (gcry_ac_data_t *data) + /* */ _GCRY_ATTR_INTERNAL; + +/* Destroy the data set DATA. */ +void gcry_ac_data_destroy (gcry_ac_data_t data) + /* */ _GCRY_ATTR_INTERNAL; + +/* Create a copy of the data set DATA and store it in DATA_CP. */ +gcry_error_t gcry_ac_data_copy (gcry_ac_data_t *data_cp, + gcry_ac_data_t data) + /* */ _GCRY_ATTR_INTERNAL; + +/* Return the number of named MPI values inside of the data set + DATA. */ +unsigned int gcry_ac_data_length (gcry_ac_data_t data) + /* */ _GCRY_ATTR_INTERNAL; + +/* Destroy any values contained in the data set DATA. */ +void gcry_ac_data_clear (gcry_ac_data_t data) + /* */ _GCRY_ATTR_INTERNAL; + +/* Add the value MPI to DATA with the label NAME. If FLAGS contains + GCRY_AC_FLAG_DATA_COPY, the data set will contain copies of NAME + and MPI. If FLAGS contains GCRY_AC_FLAG_DATA_DEALLOC or + GCRY_AC_FLAG_DATA_COPY, the values contained in the data set will + be deallocated when they are to be removed from the data set. */ +gcry_error_t gcry_ac_data_set (gcry_ac_data_t data, unsigned int flags, + const char *name, gcry_mpi_t mpi) + /* */ _GCRY_ATTR_INTERNAL; + +/* Store the value labelled with NAME found in DATA in MPI. If FLAGS + contains GCRY_AC_FLAG_COPY, store a copy of the MPI value contained + in the data set. MPI may be NULL. */ +gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t data, unsigned int flags, + const char *name, gcry_mpi_t *mpi) + /* */ _GCRY_ATTR_INTERNAL; + +/* Stores in NAME and MPI the named MPI value contained in the data + set DATA with the index IDX. If FLAGS contains GCRY_AC_FLAG_COPY, + store copies of the values contained in the data set. NAME or MPI + may be NULL. */ +gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int flags, + unsigned int idx, + const char **name, gcry_mpi_t *mpi) + /* */ _GCRY_ATTR_INTERNAL; + +/* Convert the data set DATA into a new S-Expression, which is to be + stored in SEXP, according to the identifiers contained in + IDENTIFIERS. */ +gcry_error_t gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp, + const char **identifiers) + /* */ _GCRY_ATTR_INTERNAL; + +/* Create a new data set, which is to be stored in DATA_SET, from the + S-Expression SEXP, according to the identifiers contained in + IDENTIFIERS. */ +gcry_error_t gcry_ac_data_from_sexp (gcry_ac_data_t *data, gcry_sexp_t sexp, + const char **identifiers) + /* */ _GCRY_ATTR_INTERNAL; + +/* Initialize AC_IO according to MODE, TYPE and the variable list of + arguments. The list of variable arguments to specify depends on + the given TYPE. */ +void gcry_ac_io_init (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode, + gcry_ac_io_type_t type, ...) + /* */ _GCRY_ATTR_INTERNAL; + +/* Initialize AC_IO according to MODE, TYPE and the variable list of + arguments AP. The list of variable arguments to specify depends on + the given TYPE. */ +void gcry_ac_io_init_va (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode, + gcry_ac_io_type_t type, va_list ap) + /* */ _GCRY_ATTR_INTERNAL; + +/* Create a new ac handle. */ +gcry_error_t gcry_ac_open (gcry_ac_handle_t *handle, + gcry_ac_id_t algorithm, unsigned int flags) + /* */ _GCRY_ATTR_INTERNAL; + +/* Destroy an ac handle. */ +void gcry_ac_close (gcry_ac_handle_t handle) + /* */ _GCRY_ATTR_INTERNAL; + +/* Initialize a key from a given data set. */ +gcry_error_t gcry_ac_key_init (gcry_ac_key_t *key, gcry_ac_handle_t handle, + gcry_ac_key_type_t type, gcry_ac_data_t data) + /* */ _GCRY_ATTR_INTERNAL; + +/* Generates a new key pair via the handle HANDLE of NBITS bits and + stores it in KEY_PAIR. In case non-standard settings are wanted, a + pointer to a structure of type gcry_ac_key_spec_<algorithm>_t, + matching the selected algorithm, can be given as KEY_SPEC. + MISC_DATA is not used yet. */ +gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t handle, + unsigned int nbits, void *spec, + gcry_ac_key_pair_t *key_pair, + gcry_mpi_t **misc_data) + /* */ _GCRY_ATTR_INTERNAL; + +/* Returns the key of type WHICH out of the key pair KEY_PAIR. */ +gcry_ac_key_t gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair, + gcry_ac_key_type_t which) + /* */ _GCRY_ATTR_INTERNAL; + +/* Returns the data set contained in the key KEY. */ +gcry_ac_data_t gcry_ac_key_data_get (gcry_ac_key_t key) + /* */ _GCRY_ATTR_INTERNAL; + +/* Verifies that the key KEY is sane via HANDLE. */ +gcry_error_t gcry_ac_key_test (gcry_ac_handle_t handle, gcry_ac_key_t key) + /* */ _GCRY_ATTR_INTERNAL; + +/* Stores the number of bits of the key KEY in NBITS via HANDLE. */ +gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t handle, + gcry_ac_key_t key, unsigned int *nbits) + /* */ _GCRY_ATTR_INTERNAL; + +/* Writes the 20 byte long key grip of the key KEY to KEY_GRIP via + HANDLE. */ +gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t handle, gcry_ac_key_t key, + unsigned char *key_grip) + /* */ _GCRY_ATTR_INTERNAL; + +/* Destroy a key. */ +void gcry_ac_key_destroy (gcry_ac_key_t key) + /* */ _GCRY_ATTR_INTERNAL; + +/* Destroy a key pair. */ +void gcry_ac_key_pair_destroy (gcry_ac_key_pair_t key_pair) + /* */ _GCRY_ATTR_INTERNAL; + +/* Encodes a message according to the encoding method METHOD. OPTIONS + must be a pointer to a method-specific structure + (gcry_ac_em*_t). */ +gcry_error_t gcry_ac_data_encode (gcry_ac_em_t method, + unsigned int flags, void *options, + gcry_ac_io_t *io_read, + gcry_ac_io_t *io_write) + /* */ _GCRY_ATTR_INTERNAL; + +/* Decodes a message according to the encoding method METHOD. OPTIONS + must be a pointer to a method-specific structure + (gcry_ac_em*_t). */ +gcry_error_t gcry_ac_data_decode (gcry_ac_em_t method, + unsigned int flags, void *options, + gcry_ac_io_t *io_read, + gcry_ac_io_t *io_write) + /* */ _GCRY_ATTR_INTERNAL; + +/* Encrypt the plain text MPI value DATA_PLAIN with the key KEY under + the control of the flags FLAGS and store the resulting data set + into DATA_ENCRYPTED. */ +gcry_error_t gcry_ac_data_encrypt (gcry_ac_handle_t handle, + unsigned int flags, + gcry_ac_key_t key, + gcry_mpi_t data_plain, + gcry_ac_data_t *data_encrypted) + /* */ _GCRY_ATTR_INTERNAL; + +/* Decrypt the decrypted data contained in the data set DATA_ENCRYPTED + with the key KEY under the control of the flags FLAGS and store the + resulting plain text MPI value in DATA_PLAIN. */ +gcry_error_t gcry_ac_data_decrypt (gcry_ac_handle_t handle, + unsigned int flags, + gcry_ac_key_t key, + gcry_mpi_t *data_plain, + gcry_ac_data_t data_encrypted) + /* */ _GCRY_ATTR_INTERNAL; + +/* Sign the data contained in DATA with the key KEY and store the + resulting signature in the data set DATA_SIGNATURE. */ +gcry_error_t gcry_ac_data_sign (gcry_ac_handle_t handle, + gcry_ac_key_t key, + gcry_mpi_t data, + gcry_ac_data_t *data_signature) + /* */ _GCRY_ATTR_INTERNAL; + +/* Verify that the signature contained in the data set DATA_SIGNATURE + is indeed the result of signing the data contained in DATA with the + secret key belonging to the public key KEY. */ +gcry_error_t gcry_ac_data_verify (gcry_ac_handle_t handle, + gcry_ac_key_t key, + gcry_mpi_t data, + gcry_ac_data_t data_signature) + /* */ _GCRY_ATTR_INTERNAL; + +/* Encrypts the plain text readable from IO_MESSAGE through HANDLE + with the public key KEY according to SCHEME, FLAGS and OPTS. If + OPTS is not NULL, it has to be a pointer to a structure specific to + the chosen scheme (gcry_ac_es_*_t). The encrypted message is + written to IO_CIPHER. */ +gcry_error_t gcry_ac_data_encrypt_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_cipher) + /* */ _GCRY_ATTR_INTERNAL; + +/* Decrypts the cipher text readable from IO_CIPHER through HANDLE + with the secret key KEY according to SCHEME, @var{flags} and OPTS. + If OPTS is not NULL, it has to be a pointer to a structure specific + to the chosen scheme (gcry_ac_es_*_t). The decrypted message is + written to IO_MESSAGE. */ +gcry_error_t gcry_ac_data_decrypt_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_cipher, + gcry_ac_io_t *io_message) + /* */ _GCRY_ATTR_INTERNAL; + +/* Signs the message readable from IO_MESSAGE through HANDLE with the + secret key KEY according to SCHEME, FLAGS and OPTS. If OPTS is not + NULL, it has to be a pointer to a structure specific to the chosen + scheme (gcry_ac_ssa_*_t). The signature is written to + IO_SIGNATURE. */ +gcry_error_t gcry_ac_data_sign_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_signature) + /* */ _GCRY_ATTR_INTERNAL; + +/* Verifies through HANDLE that the signature readable from + IO_SIGNATURE is indeed the result of signing the message readable + from IO_MESSAGE with the secret key belonging to the public key KEY + according to SCHEME and OPTS. If OPTS is not NULL, it has to be an + anonymous structure (gcry_ac_ssa_*_t) specific to the chosen + scheme. */ +gcry_error_t gcry_ac_data_verify_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_signature) + /* */ _GCRY_ATTR_INTERNAL; + +/* Store the textual representation of the algorithm whose id is given + in ALGORITHM in NAME. This function is deprecated; use + gcry_pk_algo_name. */ +gcry_error_t gcry_ac_id_to_name (gcry_ac_id_t algorithm, + const char **name) + /* */ _GCRY_GCC_ATTR_DEPRECATED; +/* Store the numeric ID of the algorithm whose textual representation + is contained in NAME in ALGORITHM. This function is deprecated; + use gcry_pk_map_name. */ +gcry_error_t gcry_ac_name_to_id (const char *name, + gcry_ac_id_t *algorithm) + /* */ _GCRY_GCC_ATTR_DEPRECATED; +#endif /*GCRYPT_NO_DEPRECATED*/ + + +/****************************** + * * + * Key Derivation Functions * + * * + ******************************/ + +/* Algorithm IDs for the KDFs. */ +enum gcry_kdf_algos + { + GCRY_KDF_NONE = 0, + GCRY_KDF_SIMPLE_S2K = 16, + GCRY_KDF_SALTED_S2K = 17, + GCRY_KDF_ITERSALTED_S2K = 19, + GCRY_KDF_PBKDF1 = 33, + GCRY_KDF_PBKDF2 = 34 + }; + +/* Derive a key from a passphrase. */ +gpg_error_t gcry_kdf_derive (const void *passphrase, size_t passphraselen, + int algo, int subalgo, + const void *salt, size_t saltlen, + unsigned long iterations, + size_t keysize, void *keybuffer); + + + + +/************************************ + * * + * Random Generating Functions * + * * + ************************************/ + +/* The possible values for the random quality. The rule of thumb is + to use STRONG for session keys and VERY_STRONG for key material. + WEAK is usually an alias for STRONG and should not be used anymore + (except with gcry_mpi_randomize); use gcry_create_nonce instead. */ +typedef enum gcry_random_level + { + GCRY_WEAK_RANDOM = 0, + GCRY_STRONG_RANDOM = 1, + GCRY_VERY_STRONG_RANDOM = 2 + } +gcry_random_level_t; + +/* Fill BUFFER with LENGTH bytes of random, using random numbers of + quality LEVEL. */ +void gcry_randomize (void *buffer, size_t length, + enum gcry_random_level level); + +/* Add the external random from BUFFER with LENGTH bytes into the + pool. QUALITY should either be -1 for unknown or in the range of 0 + to 100 */ +gcry_error_t gcry_random_add_bytes (const void *buffer, size_t length, + int quality); + +/* If random numbers are used in an application, this macro should be + called from time to time so that new stuff gets added to the + internal pool of the RNG. */ +#define gcry_fast_random_poll() gcry_control (GCRYCTL_FAST_POLL, NULL) + + +/* Return NBYTES of allocated random using a random numbers of quality + LEVEL. */ +void *gcry_random_bytes (size_t nbytes, enum gcry_random_level level) + _GCRY_GCC_ATTR_MALLOC; + +/* Return NBYTES of allocated random using a random numbers of quality + LEVEL. The random numbers are created returned in "secure" + memory. */ +void *gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level) + _GCRY_GCC_ATTR_MALLOC; + + +/* Set the big integer W to a random value of NBITS using a random + generator with quality LEVEL. Note that by using a level of + GCRY_WEAK_RANDOM gcry_create_nonce is used internally. */ +void gcry_mpi_randomize (gcry_mpi_t w, + unsigned int nbits, enum gcry_random_level level); + + +/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */ +void gcry_create_nonce (void *buffer, size_t length); + + + + + +/*******************************/ +/* */ +/* Prime Number Functions */ +/* */ +/*******************************/ + +/* Mode values passed to a gcry_prime_check_func_t. */ +#define GCRY_PRIME_CHECK_AT_FINISH 0 +#define GCRY_PRIME_CHECK_AT_GOT_PRIME 1 +#define GCRY_PRIME_CHECK_AT_MAYBE_PRIME 2 + +/* The function should return 1 if the operation shall continue, 0 to + reject the prime candidate. */ +typedef int (*gcry_prime_check_func_t) (void *arg, int mode, + gcry_mpi_t candidate); + +/* Flags for gcry_prime_generate(): */ + +/* Allocate prime numbers and factors in secure memory. */ +#define GCRY_PRIME_FLAG_SECRET (1 << 0) + +/* Make sure that at least one prime factor is of size + `FACTOR_BITS'. */ +#define GCRY_PRIME_FLAG_SPECIAL_FACTOR (1 << 1) + +/* Generate a new prime number of PRIME_BITS bits and store it in + PRIME. If FACTOR_BITS is non-zero, one of the prime factors of + (prime - 1) / 2 must be FACTOR_BITS bits long. If FACTORS is + non-zero, allocate a new, NULL-terminated array holding the prime + factors and store it in FACTORS. FLAGS might be used to influence + the prime number generation process. */ +gcry_error_t gcry_prime_generate (gcry_mpi_t *prime, + unsigned int prime_bits, + unsigned int factor_bits, + gcry_mpi_t **factors, + gcry_prime_check_func_t cb_func, + void *cb_arg, + gcry_random_level_t random_level, + unsigned int flags); + +/* Find a generator for PRIME where the factorization of (prime-1) is + in the NULL terminated array FACTORS. Return the generator as a + newly allocated MPI in R_G. If START_G is not NULL, use this as + teh start for the search. */ +gcry_error_t gcry_prime_group_generator (gcry_mpi_t *r_g, + gcry_mpi_t prime, + gcry_mpi_t *factors, + gcry_mpi_t start_g); + + +/* Convenience function to release the FACTORS array. */ +void gcry_prime_release_factors (gcry_mpi_t *factors); + + +/* Check wether the number X is prime. */ +gcry_error_t gcry_prime_check (gcry_mpi_t x, unsigned int flags); + + + +/************************************ + * * + * Miscellaneous Stuff * + * * + ************************************/ + +/* Log levels used by the internal logging facility. */ +enum gcry_log_levels + { + GCRY_LOG_CONT = 0, /* (Continue the last log line.) */ + GCRY_LOG_INFO = 10, + GCRY_LOG_WARN = 20, + GCRY_LOG_ERROR = 30, + GCRY_LOG_FATAL = 40, + GCRY_LOG_BUG = 50, + GCRY_LOG_DEBUG = 100 + }; + +/* Type for progress handlers. */ +typedef void (*gcry_handler_progress_t) (void *, const char *, int, int, int); + +/* Type for memory allocation handlers. */ +typedef void *(*gcry_handler_alloc_t) (size_t n); + +/* Type for secure memory check handlers. */ +typedef int (*gcry_handler_secure_check_t) (const void *); + +/* Type for memory reallocation handlers. */ +typedef void *(*gcry_handler_realloc_t) (void *p, size_t n); + +/* Type for memory free handlers. */ +typedef void (*gcry_handler_free_t) (void *); + +/* Type for out-of-memory handlers. */ +typedef int (*gcry_handler_no_mem_t) (void *, size_t, unsigned int); + +/* Type for fatal error handlers. */ +typedef void (*gcry_handler_error_t) (void *, int, const char *); + +/* Type for logging handlers. */ +typedef void (*gcry_handler_log_t) (void *, int, const char *, va_list); + +/* Certain operations can provide progress information. This function + is used to register a handler for retrieving these information. */ +void gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data); + + +/* Register a custom memory allocation functions. */ +void gcry_set_allocation_handler ( + gcry_handler_alloc_t func_alloc, + gcry_handler_alloc_t func_alloc_secure, + gcry_handler_secure_check_t func_secure_check, + gcry_handler_realloc_t func_realloc, + gcry_handler_free_t func_free); + +/* Register a function used instead of the internal out of memory + handler. */ +void gcry_set_outofcore_handler (gcry_handler_no_mem_t h, void *opaque); + +/* Register a function used instead of the internal fatal error + handler. */ +void gcry_set_fatalerror_handler (gcry_handler_error_t fnc, void *opaque); + +/* Register a function used instead of the internal logging + facility. */ +void gcry_set_log_handler (gcry_handler_log_t f, void *opaque); + +/* Reserved for future use. */ +void gcry_set_gettext_handler (const char *(*f)(const char*)); + +/* Libgcrypt uses its own memory allocation. It is important to use + gcry_free () to release memory allocated by libgcrypt. */ +void *gcry_malloc (size_t n) _GCRY_GCC_ATTR_MALLOC; +void *gcry_calloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC; +void *gcry_malloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC; +void *gcry_calloc_secure (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC; +void *gcry_realloc (void *a, size_t n); +char *gcry_strdup (const char *string) _GCRY_GCC_ATTR_MALLOC; +void *gcry_xmalloc (size_t n) _GCRY_GCC_ATTR_MALLOC; +void *gcry_xcalloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC; +void *gcry_xmalloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC; +void *gcry_xcalloc_secure (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC; +void *gcry_xrealloc (void *a, size_t n); +char *gcry_xstrdup (const char * a) _GCRY_GCC_ATTR_MALLOC; +void gcry_free (void *a); + +/* Return true if A is allocated in "secure" memory. */ +int gcry_is_secure (const void *a) _GCRY_GCC_ATTR_PURE; + +/* Return true if Libgcrypt is in FIPS mode. */ +#define gcry_fips_mode_active() !!gcry_control (GCRYCTL_FIPS_MODE_P, 0) + + +/* Include support for Libgcrypt modules. */ +#include <gcrypt-module.h> + +#if 0 /* (Keep Emacsens' auto-indent happy.) */ +{ +#endif +#ifdef __cplusplus +} +#endif +#endif /* _GCRYPT_H */ +/* +@emacs_local_vars_begin@ +@emacs_local_vars_read_only@ +@emacs_local_vars_end@ +*/ diff --git a/grub-core/lib/libgcrypt/src/gcryptrnd.c b/grub-core/lib/libgcrypt/src/gcryptrnd.c new file mode 100644 index 0000000..b13931b --- /dev/null +++ b/grub-core/lib/libgcrypt/src/gcryptrnd.c @@ -0,0 +1,680 @@ +/* gcryptrnd.c - Libgcrypt Random Number Daemon + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * Gcryptend is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * Gcryptrnd is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* We require vsyslog pth + We need to test for: setrlimit + + We should also prioritize requests. This is best done by putting + the requests into queues and have a main thread processing these + queues. + + */ + +#include <config.h> +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <assert.h> +#include <time.h> +#include <sys/times.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <syslog.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <errno.h> +#include <pth.h> +#include <gcrypt.h> + +#define PGM "gcryptrnd" +#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION +#define BUGREPORT_LINE "\nReport bugs to <bug-libgcrypt@gnupg.org>.\n" + +/* Pth wrapper function definitions. */ +GCRY_THREAD_OPTION_PTH_IMPL; + + +/* Flag set to true if we have been daemonized. */ +static int running_detached; +/* Flag indicating that a shutdown has been requested. */ +static int shutdown_pending; +/* Counter for active connections. */ +static int active_connections; + + + +/* Local prototypes. */ +static void serve (int listen_fd); + + + + + +/* To avoid that a compiler optimizes certain memset calls away, these + macros may be used instead. */ +#define wipememory2(_ptr,_set,_len) do { \ + volatile char *_vptr=(volatile char *)(_ptr); \ + size_t _vlen=(_len); \ + while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ + } while(0) +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + + + + +/* Error printing utility. PRIORITY should be one of syslog's + priority levels. This functions prints to the stderr or syslog + depending on whether we are already daemonized. */ +static void +logit (int priority, const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format) ; + if (running_detached) + { + vsyslog (priority, format, arg_ptr); + } + else + { + fputs (PGM ": ", stderr); + vfprintf (stderr, format, arg_ptr); + putc ('\n', stderr); + } + va_end (arg_ptr); +} + +/* Callback used by libgcrypt for logging. */ +static void +my_gcry_logger (void *dummy, int level, const char *format, va_list arg_ptr) +{ + (void)dummy; + + /* Map the log levels. */ + switch (level) + { + case GCRY_LOG_CONT: level = LOG_INFO /* FIXME */; break; + case GCRY_LOG_INFO: level = LOG_INFO; break; + case GCRY_LOG_WARN: level = LOG_WARNING; break; + case GCRY_LOG_ERROR:level = LOG_ERR; break; + case GCRY_LOG_FATAL:level = LOG_CRIT; break; + case GCRY_LOG_BUG: level = LOG_CRIT; break; + case GCRY_LOG_DEBUG:level = LOG_DEBUG; break; + default: level = LOG_ERR; break; + } + if (running_detached) + { + vsyslog (level, format, arg_ptr); + } + else + { + fputs (PGM ": ", stderr); + vfprintf (stderr, format, arg_ptr); + if (!*format || format[strlen (format)-1] != '\n') + putc ('\n', stderr); + } +} + + +/* The cleanup handler - used to wipe out the secure memory. */ +static void +cleanup (void) +{ + gcry_control (GCRYCTL_TERM_SECMEM ); +} + + +/* Make us a daemon and open the syslog. */ +static void +daemonize (void) +{ + int i; + pid_t pid; + + fflush (NULL); + + pid = fork (); + if (pid == (pid_t)-1) + { + logit (LOG_CRIT, "fork failed: %s", strerror (errno)); + exit (1); + } + if (pid) + exit (0); + + if (setsid() == -1) + { + logit (LOG_CRIT, "setsid() failed: %s", strerror(errno)); + exit (1); + } + + signal (SIGHUP, SIG_IGN); + + pid = fork (); + if (pid == (pid_t)-1) + { + logit (LOG_CRIT, PGM ": second fork failed: %s", strerror (errno)); + exit (1); + } + if (pid) + exit (0); /* First child exits. */ + + running_detached = 1; + + if (chdir("/")) + { + logit (LOG_CRIT, "chdir(\"/\") failed: %s", strerror (errno)); + exit (1); + } + umask (0); + + for (i=0; i <= 2; i++) + close (i); + + openlog (PGM, LOG_PID, LOG_DAEMON); +} + + +static void +disable_core_dumps (void) +{ +#ifdef HAVE_SETRLIMIT + struct rlimit limit; + + if (getrlimit (RLIMIT_CORE, &limit)) + limit.rlim_max = 0; + limit.rlim_cur = 0; + if( !setrlimit (RLIMIT_CORE, &limit) ) + return 0; + if (errno != EINVAL && errno != ENOSYS) + logit (LOG_ERR, "can't disable core dumps: %s\n", strerror (errno)); +#endif /* HAVE_SETRLIMIT */ +} + + + +static void +print_version (int with_help) +{ + fputs (MYVERSION_LINE "\n" + "Copyright (C) 2006 Free Software Foundation, Inc.\n" + "License GPLv2+: GNU GPL version 2 or later " + "<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", + stdout); + + if (with_help) + fputs ("\n" + "Usage: " PGM " [OPTIONS] [SOCKETNAME]\n" + "Start Libgcrypt's random number daemon listening" + " on socket SOCKETNAME\n" + "SOCKETNAME defaults to XXX\n" + "\n" + " --no-detach do not deatach from the console\n" + " --version print version of the program and exit\n" + " --help display this help and exit\n" + BUGREPORT_LINE, stdout ); + + exit (0); +} + +static int +print_usage (void) +{ + fputs ("usage: " PGM " [OPTIONS] [SOCKETNAME]\n", stderr); + fputs (" (use --help to display options)\n", stderr); + exit (1); +} + + +int +main (int argc, char **argv) +{ + int no_detach = 0; + gpg_error_t err; + struct sockaddr_un *srvr_addr; + socklen_t addrlen; + int fd; + int rc; + const char *socketname = "/var/run/libgcrypt/S.gcryptrnd"; + + + if (argc) + { + argc--; argv++; + } + while (argc && **argv == '-' && (*argv)[1] == '-') + { + if (!(*argv)[2]) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--version")) + print_version (0); + else if (!strcmp (*argv, "--help")) + print_version (1); + else if (!strcmp (*argv, "--no-detach")) + { + no_detach = 1; + argc--; argv++; + } + else + print_usage (); + } + + if (argc == 1) + socketname = argv[0]; + else if (argc > 1) + print_usage (); + + if (!no_detach) + daemonize (); + + signal (SIGPIPE, SIG_IGN); + + logit (LOG_NOTICE, "started version " VERSION ); + + /* Libgcrypt requires us to register the threading model before we + do anything else with it. Note that this also calls pth_init. We + do the initialization while already running as a daemon to avoid + overhead with double initialization of Libgcrypt. */ + err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); + if (err) + { + logit (LOG_CRIT, "can't register GNU Pth with Libgcrypt: %s", + gpg_strerror (err)); + exit (1); + } + + /* Check that the libgcrypt version is sufficient. */ + if (!gcry_check_version (VERSION) ) + { + logit (LOG_CRIT, "libgcrypt is too old (need %s, have %s)", + VERSION, gcry_check_version (NULL) ); + exit (1); + } + + /* Register the logging callback and tell Libcgrypt to put the + random pool into secure memory. */ + gcry_set_log_handler (my_gcry_logger, NULL); + gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); + + /* Obviously we don't want to allow any core dumps. */ + disable_core_dumps (); + + /* Initialize the secure memory stuff which will also drop any extra + privileges we have. */ + gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + + /* Register a cleanup handler. */ + atexit (cleanup); + + /* Create and listen on the socket. */ + fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + logit (LOG_CRIT, "can't create socket: %s", strerror (errno)); + exit (1); + } + srvr_addr = gcry_xmalloc (sizeof *srvr_addr); + memset (srvr_addr, 0, sizeof *srvr_addr); + srvr_addr->sun_family = AF_UNIX; + if (strlen (socketname) + 1 >= sizeof (srvr_addr->sun_path)) + { + logit (LOG_CRIT, "socket name `%s' too long", socketname); + exit (1); + } + strcpy (srvr_addr->sun_path, socketname); + addrlen = (offsetof (struct sockaddr_un, sun_path) + + strlen (srvr_addr->sun_path) + 1); + rc = bind (fd, (struct sockaddr*) srvr_addr, addrlen); + if (rc == -1 && errno == EADDRINUSE) + { + remove (socketname); + rc = bind (fd, (struct sockaddr*) srvr_addr, addrlen); + } + if (rc == -1) + { + logit (LOG_CRIT, "error binding socket to `%s': %s", + srvr_addr->sun_path, strerror (errno)); + close (fd); + exit (1); + } + + if (listen (fd, 5 ) == -1) + { + logit (LOG_CRIT, "listen() failed: %s", strerror (errno)); + close (fd); + exit (1); + } + + logit (LOG_INFO, "listening on socket `%s', fd=%d", + srvr_addr->sun_path, fd); + + serve (fd); + close (fd); + + logit (LOG_NOTICE, "stopped version " VERSION ); + return 0; +} + + +/* Send LENGTH bytes of BUFFER to file descriptor FD. Returns 0 on + success or another value on write error. */ +static int +writen (int fd, const void *buffer, size_t length) +{ + while (length) + { + ssize_t n = pth_write (fd, buffer, length); + if (n < 0) + { + logit (LOG_ERR, "connection %d: write error: %s", + fd, strerror (errno)); + return -1; /* write error */ + } + length -= n; + buffer = (const char*)buffer + n; + } + return 0; /* Okay */ +} + + +/* Send an error response back. Returns 0 on success. */ +static int +send_error (int fd, int errcode) +{ + unsigned char buf[2]; + + buf[0] = errcode; + buf[1] = 0; + return writen (fd, buf, 2 ); +} + +/* Send a pong response back. Returns 0 on success or another value + on write error. */ +static int +send_pong (int fd) +{ + return writen (fd, "\x00\x04pong", 6); +} + +/* Send a nonce of size LENGTH back. Return 0 on success. */ +static int +send_nonce (int fd, int length) +{ + unsigned char buf[2+255]; + int rc; + + assert (length >= 0 && length <= 255); + buf[0] = 0; + buf[1] = length; + gcry_create_nonce (buf+2, length); + rc = writen (fd, buf, 2+length ); + wipememory (buf+2, length); + return rc; +} + +/* Send a random of size LENGTH with quality LEVEL back. Return 0 on + success. */ +static int +send_random (int fd, int length, int level) +{ + unsigned char buf[2+255]; + int rc; + + assert (length >= 0 && length <= 255); + assert (level == GCRY_STRONG_RANDOM || level == GCRY_VERY_STRONG_RANDOM); + buf[0] = 0; + buf[1] = length; + /* Note that we don't bother putting the random stuff into secure + memory because this daemon is anyway intended to be run under + root and it is questionable whether the kernel buffers etc. are + equally well protected. */ + gcry_randomize (buf+2, length, level); + rc = writen (fd, buf, 2+length ); + wipememory (buf+2, length); + return rc; +} + +/* Main processing loop for a connection. + + A request is made up of: + + 1 byte Total length of request; must be 3 + 1 byte Command + 0 = Ping + 10 = GetNonce + 11 = GetStrongRandom + 12 = GetVeryStrongRandom + (all other values are reserved) + 1 byte Number of requested bytes. + This is ignored for command Ping. + + A response is made up of: + + 1 byte Error Code + 0 = Everything is fine + 1 = Bad Command + 0xff = Other error. + (For a bad request the connection will simply be closed) + 1 byte Length of data + n byte data + + The requests are read as long as the connection is open. + + + */ +static void +connection_loop (int fd) +{ + unsigned char request[3]; + unsigned char *p; + int nleft, n; + int rc; + + for (;;) + { + for (nleft=3, p=request; nleft > 0; ) + { + n = pth_read (fd, p, nleft); + if (!n && p == request) + return; /* Client terminated connection. */ + if (n <= 0) + { + logit (LOG_ERR, "connection %d: read error: %s", + fd, n? strerror (errno) : "Unexpected EOF"); + return; + } + p += n; + nleft -= n; + } + if (request[0] != 3) + { + logit (LOG_ERR, "connection %d: invalid length (%d) of request", + fd, request[0]); + return; + } + + switch (request[1]) + { + case 0: /* Ping */ + rc = send_pong (fd); + break; + case 10: /* GetNonce */ + rc = send_nonce (fd, request[2]); + break; + case 11: /* GetStrongRandom */ + rc = send_random (fd, request[2], GCRY_STRONG_RANDOM); + break; + case 12: /* GetVeryStrongRandom */ + rc = send_random (fd, request[2], GCRY_VERY_STRONG_RANDOM); + break; + + default: /* Invalid command */ + rc = send_error (fd, 1); + break; + } + if (rc) + break; /* A write error occurred while sending the response. */ + } +} + + + +/* Entry point for a connection's thread. */ +static void * +connection_thread (void *arg) +{ + int fd = (int)arg; + + active_connections++; + logit (LOG_INFO, "connection handler for fd %d started", fd); + + connection_loop (fd); + + close (fd); + logit (LOG_INFO, "connection handler for fd %d terminated", fd); + active_connections--; + + return NULL; +} + + +/* This signal handler is called from the main loop between acepting + connections. It is called on the regular stack, thus no special + caution needs to be taken. It returns true to indicate that the + process should terminate. */ +static int +handle_signal (int signo) +{ + switch (signo) + { + case SIGHUP: + logit (LOG_NOTICE, "SIGHUP received - re-reading configuration"); + break; + + case SIGUSR1: + logit (LOG_NOTICE, "SIGUSR1 received - no action defined"); + break; + + case SIGUSR2: + logit (LOG_NOTICE, "SIGUSR2 received - no action defined"); + break; + + case SIGTERM: + if (!shutdown_pending) + logit (LOG_NOTICE, "SIGTERM received - shutting down ..."); + else + logit (LOG_NOTICE, "SIGTERM received - still %d active connections", + active_connections); + shutdown_pending++; + if (shutdown_pending > 2) + { + logit (LOG_NOTICE, "shutdown forced"); + return 1; + } + break; + + case SIGINT: + logit (LOG_NOTICE, "SIGINT received - immediate shutdown"); + return 1; + + default: + logit (LOG_NOTICE, "signal %d received - no action defined\n", signo); + } + return 0; +} + + + +/* Main server loop. This is called with the FD of the listening + socket. */ +static void +serve (int listen_fd) +{ + pth_attr_t tattr; + pth_event_t ev; + sigset_t sigs; + int signo; + struct sockaddr_un paddr; + socklen_t plen = sizeof (paddr); + int fd; + + tattr = pth_attr_new(); + pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); + pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024); + pth_attr_set (tattr, PTH_ATTR_NAME, "connection"); + + sigemptyset (&sigs); + sigaddset (&sigs, SIGHUP); + sigaddset (&sigs, SIGUSR1); + sigaddset (&sigs, SIGUSR2); + sigaddset (&sigs, SIGINT); + sigaddset (&sigs, SIGTERM); + ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); + + for (;;) + { + if (shutdown_pending) + { + if (!active_connections) + break; /* Ready. */ + + /* Do not accept anymore connections but wait for existing + connections to terminate. */ + signo = 0; + pth_wait (ev); + if (pth_event_occurred (ev) && signo) + if (handle_signal (signo)) + break; /* Stop the loop. */ + continue; + } + + gcry_fast_random_poll (); + fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); + if (fd == -1) + { + if (pth_event_occurred (ev)) + { + if (handle_signal (signo)) + break; /* Stop the loop. */ + continue; + } + logit (LOG_WARNING, "accept failed: %s - waiting 1s\n", + strerror (errno)); + gcry_fast_random_poll (); + pth_sleep (1); + continue; + } + + if (!pth_spawn (tattr, connection_thread, (void*)fd)) + { + logit (LOG_ERR, "error spawning connection handler: %s\n", + strerror (errno) ); + close (fd); + } + } + + pth_event_free (ev, PTH_FREE_ALL); +} diff --git a/grub-core/lib/libgcrypt/src/getrandom.c b/grub-core/lib/libgcrypt/src/getrandom.c new file mode 100644 index 0000000..f9bb5c0 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/getrandom.c @@ -0,0 +1,326 @@ +/* getrandom.c - Libgcrypt Random Number client + * Copyright (C) 2006 Free Software Foundation, Inc. + * + * Getrandom is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * Getrandom is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <config.h> +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <errno.h> + +#define PGM "getrandom" +#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION +#define BUGREPORT_LINE "\nReport bugs to <bug-libgcrypt@gnupg.org>.\n" + + +static void +logit (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format) ; + fputs (PGM ": ", stderr); + vfprintf (stderr, format, arg_ptr); + putc ('\n', stderr); + va_end (arg_ptr); +} + + +/* Send LENGTH bytes of BUFFER to file descriptor FD. Returns 0 on + success or another value on write error. */ +static int +writen (int fd, const void *buffer, size_t length) +{ + while (length) + { + ssize_t n; + + do + n = write (fd, buffer, length); + while (n < 0 && errno == EINTR); + if (n < 0) + { + logit ("write error: %s", strerror (errno)); + return -1; /* write error */ + } + length -= n; + buffer = (const char *)buffer + n; + } + return 0; /* Okay */ +} + + + + +static void +print_version (int with_help) +{ + fputs (MYVERSION_LINE "\n" + "Copyright (C) 2006 Free Software Foundation, Inc.\n" + "License GPLv2+: GNU GPL version 2 or later " + "<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", + stdout); + + if (with_help) + fputs ("\n" + "Usage: " PGM " [OPTIONS] NBYTES\n" + "Connect to libgcrypt's random number daemon and " + "return random numbers" + "\n" + " --nonce Return weak random suitable for a nonce\n" + " --very-strong Return very strong random\n" + " --ping Send a ping\n" + " --socket NAME Name of sockket to connect to\n" + " --hex Return result as a hex dump\n" + " --verbose Show what we are doing\n" + " --version Print version of the program and exit\n" + " --help Display this help and exit\n" + BUGREPORT_LINE, stdout ); + + exit (0); +} + +static int +print_usage (void) +{ + fputs ("usage: " PGM " [OPTIONS] NBYTES\n", stderr); + fputs (" (use --help to display options)\n", stderr); + exit (1); +} + + +int +main (int argc, char **argv) +{ + struct sockaddr_un *srvr_addr; + socklen_t addrlen; + int fd; + int rc; + unsigned char buffer[300]; + int nleft, nread; + const char *socketname = "/var/run/libgcrypt/S.gcryptrnd"; + int do_ping = 0; + int get_nonce = 0; + int get_very_strong = 0; + int req_nbytes, nbytes, n; + int verbose = 0; + int fail = 0; + int do_hex = 0; + + if (argc) + { + argc--; argv++; + } + while (argc && **argv == '-' && (*argv)[1] == '-') + { + if (!(*argv)[2]) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--version")) + print_version (0); + else if (!strcmp (*argv, "--help")) + print_version (1); + else if (!strcmp (*argv, "--socket") && argc > 1 ) + { + argc--; argv++; + socketname = *argv; + argc--; argv++; + } + else if (!strcmp (*argv, "--nonce")) + { + argc--; argv++; + get_nonce = 1; + } + else if (!strcmp (*argv, "--very-strong")) + { + argc--; argv++; + get_very_strong = 1; + } + else if (!strcmp (*argv, "--ping")) + { + argc--; argv++; + do_ping = 1; + } + else if (!strcmp (*argv, "--hex")) + { + argc--; argv++; + do_hex = 1; + } + else if (!strcmp (*argv, "--verbose")) + { + argc--; argv++; + verbose = 1; + } + else + print_usage (); + } + + + if (!argc && do_ping) + ; /* This is allowed. */ + else if (argc != 1) + print_usage (); + req_nbytes = argc? atoi (*argv) : 0; + + if (req_nbytes < 0) + print_usage (); + + /* Create a socket. */ + fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + logit ("can't create socket: %s", strerror (errno)); + exit (1); + } + srvr_addr = malloc (sizeof *srvr_addr); + if (!srvr_addr) + { + logit ("malloc failed: %s", strerror (errno)); + exit (1); + } + memset (srvr_addr, 0, sizeof *srvr_addr); + srvr_addr->sun_family = AF_UNIX; + if (strlen (socketname) + 1 >= sizeof (srvr_addr->sun_path)) + { + logit ("socket name `%s' too long", socketname); + exit (1); + } + strcpy (srvr_addr->sun_path, socketname); + addrlen = (offsetof (struct sockaddr_un, sun_path) + + strlen (srvr_addr->sun_path) + 1); + rc = connect (fd, (struct sockaddr*) srvr_addr, addrlen); + if (rc == -1) + { + logit ("error connecting socket `%s': %s", + srvr_addr->sun_path, strerror (errno)); + close (fd); + exit (1); + } + + do + { + nbytes = req_nbytes > 255? 255 : req_nbytes; + req_nbytes -= nbytes; + + buffer[0] = 3; + if (do_ping) + buffer[1] = 0; + else if (get_nonce) + buffer[1] = 10; + else if (get_very_strong) + buffer[1] = 12; + else + buffer[1] = 11; + buffer[2] = nbytes; + if (writen (fd, buffer, 3)) + fail = 1; + else + { + for (nleft=2, nread=0; nleft > 0; ) + { + do + n = read (fd, buffer+nread, nleft); + while (n < 0 && errno == EINTR); + if (n < 0) + { + logit ("read error: %s", strerror (errno)); + exit (1); + } + nleft -= n; + nread += n; + if (nread && buffer[0]) + { + logit ("server returned error code %d", buffer[0]); + exit (1); + } + } + if (verbose) + logit ("received response with %d bytes of data", buffer[1]); + if (buffer[1] < nbytes) + { + logit ("warning: server returned less bytes than requested"); + fail = 1; + } + else if (buffer[1] > nbytes && !do_ping) + { + logit ("warning: server returned more bytes than requested"); + fail = 1; + } + nbytes = buffer[1]; + if (nbytes > sizeof buffer) + { + logit ("buffer too short to receive data"); + exit (1); + } + + for (nleft=nbytes, nread=0; nleft > 0; ) + { + do + n = read (fd, buffer+nread, nleft); + while (n < 0 && errno == EINTR); + if (n < 0) + { + logit ("read error: %s", strerror (errno)); + exit (1); + } + nleft -= n; + nread += n; + } + + if (do_hex) + { + for (n=0; n < nbytes; n++) + { + if (!n) + ; + else if (!(n % 16)) + putchar ('\n'); + else + putchar (' '); + printf ("%02X", buffer[n]); + } + if (nbytes) + putchar ('\n'); + } + else + { + if (fwrite (buffer, nbytes, 1, stdout) != 1) + { + logit ("error writing to stdout: %s", strerror (errno)); + fail = 1; + } + } + } + } + while (!fail && req_nbytes); + + close (fd); + free (srvr_addr); + return fail? 1 : 0; +} diff --git a/grub-core/lib/libgcrypt/src/global.c b/grub-core/lib/libgcrypt/src/global.c new file mode 100644 index 0000000..9b9d531 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/global.c @@ -0,0 +1,1123 @@ +/* global.c - global control functions + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 + * 2004, 2005, 2006, 2008, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <limits.h> +#include <errno.h> +#include <unistd.h> +#ifdef HAVE_SYSLOG +# include <syslog.h> +#endif /*HAVE_SYSLOG*/ + +#include "g10lib.h" +#include "cipher.h" +#include "stdmem.h" /* our own memory allocator */ +#include "secmem.h" /* our own secmem allocator */ +#include "ath.h" + + + +/**************** + * flag bits: 0 : general cipher debug + * 1 : general MPI debug + */ +static unsigned int debug_flags; + +/* gcry_control (GCRYCTL_SET_FIPS_MODE), sets this flag so that the + initialization code switched fips mode on. */ +static int force_fips_mode; + +/* Controlled by global_init(). */ +static int any_init_done; + +/* A table to map hardware features to a string. */ +static struct +{ + unsigned int flag; + const char *desc; +} hwflist[] = + { + { HWF_PADLOCK_RNG, "padlock-rng" }, + { HWF_PADLOCK_AES, "padlock-aes" }, + { HWF_PADLOCK_SHA, "padlock-sha" }, + { HWF_PADLOCK_MMUL,"padlock-mmul"}, + { HWF_INTEL_AESNI, "intel-aesni" }, + { 0, NULL} + }; + +/* A bit vector with the hardware features which shall not be used. + This variable must be set prior to any initialization. */ +static unsigned int disabled_hw_features; + + +/* Memory management. */ + +static gcry_handler_alloc_t alloc_func; +static gcry_handler_alloc_t alloc_secure_func; +static gcry_handler_secure_check_t is_secure_func; +static gcry_handler_realloc_t realloc_func; +static gcry_handler_free_t free_func; +static gcry_handler_no_mem_t outofcore_handler; +static void *outofcore_handler_value; +static int no_secure_memory; + + + + + +/* This is our handmade constructor. It gets called by any function + likely to be called at startup. The suggested way for an + application to make sure that this has been called is by using + gcry_check_version. */ +static void +global_init (void) +{ + gcry_error_t err = 0; + + if (any_init_done) + return; + any_init_done = 1; + + /* Initialize our portable thread/mutex wrapper. */ + err = ath_init (); + if (err) + goto fail; + + /* See whether the system is in FIPS mode. This needs to come as + early as possible put after the ATH has been initialized. */ + _gcry_initialize_fips_mode (force_fips_mode); + + /* Before we do any other initialization we need to test available + hardware features. */ + _gcry_detect_hw_features (disabled_hw_features); + + err = _gcry_cipher_init (); + if (err) + goto fail; + err = _gcry_md_init (); + if (err) + goto fail; + err = _gcry_pk_init (); + if (err) + goto fail; +#if 0 + /* Hmmm, as of now ac_init does nothing. */ + if ( !fips_mode () ) + { + err = _gcry_ac_init (); + if (err) + goto fail; + } +#endif + + return; + + fail: + BUG (); +} + + +/* This function is called by the macro fips_is_operational and makes + sure that the minimal initialization has been done. This is far + from a perfect solution and hides problems with an improper + initialization but at least in single-threaded mode it should work + reliable. + + The reason we need this is that a lot of applications don't use + Libgcrypt properly by not running any initialization code at all. + They just call a Libgcrypt function and that is all what they want. + Now with the FIPS mode, that has the side effect of entering FIPS + mode (for security reasons, FIPS mode is the default if no + initialization has been done) and bailing out immediately because + the FSM is in the wrong state. If we always run the init code, + Libgcrypt can test for FIPS mode and at least if not in FIPS mode, + it will behave as before. Note that this on-the-fly initialization + is only done for the cryptographic functions subject to FIPS mode + and thus not all API calls will do such an initialization. */ +int +_gcry_global_is_operational (void) +{ + if (!any_init_done) + { +#ifdef HAVE_SYSLOG + syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " + "missing initialization - please fix the application"); +#endif /*HAVE_SYSLOG*/ + global_init (); + } + return _gcry_fips_is_operational (); +} + + + + +/* Version number parsing. */ + +/* This function parses the first portion of the version number S and + stores it in *NUMBER. On success, this function returns a pointer + into S starting with the first character, which is not part of the + initial number portion; on failure, NULL is returned. */ +static const char* +parse_version_number( const char *s, int *number ) +{ + int val = 0; + + if( *s == '0' && isdigit(s[1]) ) + return NULL; /* leading zeros are not allowed */ + for ( ; isdigit(*s); s++ ) { + val *= 10; + val += *s - '0'; + } + *number = val; + return val < 0? NULL : s; +} + +/* This function breaks up the complete string-representation of the + version number S, which is of the following struture: <major + number>.<minor number>.<micro number><patch level>. The major, + minor and micro number components will be stored in *MAJOR, *MINOR + and *MICRO. + + On success, the last component, the patch level, will be returned; + in failure, NULL will be returned. */ + +static const char * +parse_version_string( const char *s, int *major, int *minor, int *micro ) +{ + s = parse_version_number( s, major ); + if( !s || *s != '.' ) + return NULL; + s++; + s = parse_version_number( s, minor ); + if( !s || *s != '.' ) + return NULL; + s++; + s = parse_version_number( s, micro ); + if( !s ) + return NULL; + return s; /* patchlevel */ +} + +/* If REQ_VERSION is non-NULL, check that the version of the library + is at minimum the requested one. Returns the string representation + of the library version if the condition is satisfied; return NULL + if the requested version is newer than that of the library. + + If a NULL is passed to this function, no check is done, but the + string representation of the library is simply returned. */ +const char * +gcry_check_version( const char *req_version ) +{ + const char *ver = VERSION; + int my_major, my_minor, my_micro; + int rq_major, rq_minor, rq_micro; + const char *my_plvl; + + if (req_version && req_version[0] == 1 && req_version[1] == 1) + return _gcry_compat_identification (); + + /* Initialize library. */ + global_init (); + + if ( !req_version ) + /* Caller wants our version number. */ + return ver; + + /* Parse own version number. */ + my_plvl = parse_version_string( ver, &my_major, &my_minor, &my_micro ); + if ( !my_plvl ) + /* very strange our own version is bogus. Shouldn't we use + assert() here and bail out in case this happens? -mo. */ + return NULL; + + /* Parse requested version number. */ + if (!parse_version_string (req_version, &rq_major, &rq_minor, &rq_micro)) + return NULL; /* req version string is invalid, this can happen. */ + + /* Compare version numbers. */ + if ( my_major > rq_major + || (my_major == rq_major && my_minor > rq_minor) + || (my_major == rq_major && my_minor == rq_minor && my_micro > rq_micro) + || (my_major == rq_major && my_minor == rq_minor + && my_micro == rq_micro)) + { + return ver; + } + + return NULL; +} + + +static void +print_config ( int (*fnc)(FILE *fp, const char *format, ...), FILE *fp) +{ + unsigned int hwf; + int i; + + fnc (fp, "version:%s:\n", VERSION); + fnc (fp, "ciphers:%s:\n", LIBGCRYPT_CIPHERS); + fnc (fp, "pubkeys:%s:\n", LIBGCRYPT_PUBKEY_CIPHERS); + fnc (fp, "digests:%s:\n", LIBGCRYPT_DIGESTS); + fnc (fp, "rnd-mod:" +#if USE_RNDEGD + "egd:" +#endif +#if USE_RNDLINUX + "linux:" +#endif +#if USE_RNDUNIX + "unix:" +#endif +#if USE_RNDW32 + "w32:" +#endif + "\n"); + fnc (fp, "mpi-asm:%s:\n", _gcry_mpi_get_hw_config ()); + hwf = _gcry_get_hw_features (); + fnc (fp, "hwflist:"); + for (i=0; hwflist[i].desc; i++) + if ( (hwf & hwflist[i].flag) ) + fnc (fp, "%s:", hwflist[i].desc); + fnc (fp, "\n"); + /* We use y/n instead of 1/0 for the simple reason that Emacsen's + compile error parser would accidently flag that line when printed + during "make check" as an error. */ + fnc (fp, "fips-mode:%c:%c:\n", + fips_mode ()? 'y':'n', + _gcry_enforced_fips_mode ()? 'y':'n' ); +} + + + + +/* Command dispatcher function, acting as general control + function. */ +gcry_error_t +_gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr) +{ + static int init_finished = 0; + gcry_err_code_t err = 0; + + switch (cmd) + { + case GCRYCTL_ENABLE_M_GUARD: + _gcry_private_enable_m_guard (); + break; + + case GCRYCTL_ENABLE_QUICK_RANDOM: + _gcry_enable_quick_random_gen (); + break; + + case GCRYCTL_FAKED_RANDOM_P: + /* Return an error if the RNG is faked one (e.g. enabled by + ENABLE_QUICK_RANDOM. */ + if (_gcry_random_is_faked ()) + err = GPG_ERR_GENERAL; /* Use as TRUE value. */ + break; + + case GCRYCTL_DUMP_RANDOM_STATS: + _gcry_random_dump_stats (); + break; + + case GCRYCTL_DUMP_MEMORY_STATS: + /*m_print_stats("[fixme: prefix]");*/ + break; + + case GCRYCTL_DUMP_SECMEM_STATS: + _gcry_secmem_dump_stats (); + break; + + case GCRYCTL_DROP_PRIVS: + global_init (); + _gcry_secmem_init (0); + break; + + case GCRYCTL_DISABLE_SECMEM: + global_init (); + no_secure_memory = 1; + break; + + case GCRYCTL_INIT_SECMEM: + global_init (); + _gcry_secmem_init (va_arg (arg_ptr, unsigned int)); + if ((_gcry_secmem_get_flags () & GCRY_SECMEM_FLAG_NOT_LOCKED)) + err = GPG_ERR_GENERAL; + break; + + case GCRYCTL_TERM_SECMEM: + global_init (); + _gcry_secmem_term (); + break; + + case GCRYCTL_DISABLE_SECMEM_WARN: + _gcry_secmem_set_flags ((_gcry_secmem_get_flags () + | GCRY_SECMEM_FLAG_NO_WARNING)); + break; + + case GCRYCTL_SUSPEND_SECMEM_WARN: + _gcry_secmem_set_flags ((_gcry_secmem_get_flags () + | GCRY_SECMEM_FLAG_SUSPEND_WARNING)); + break; + + case GCRYCTL_RESUME_SECMEM_WARN: + _gcry_secmem_set_flags ((_gcry_secmem_get_flags () + & ~GCRY_SECMEM_FLAG_SUSPEND_WARNING)); + break; + + case GCRYCTL_USE_SECURE_RNDPOOL: + global_init (); + _gcry_secure_random_alloc (); /* Put random number into secure memory. */ + break; + + case GCRYCTL_SET_RANDOM_SEED_FILE: + _gcry_set_random_seed_file (va_arg (arg_ptr, const char *)); + break; + + case GCRYCTL_UPDATE_RANDOM_SEED_FILE: + if ( fips_is_operational () ) + _gcry_update_random_seed_file (); + break; + + case GCRYCTL_SET_VERBOSITY: + _gcry_set_log_verbosity (va_arg (arg_ptr, int)); + break; + + case GCRYCTL_SET_DEBUG_FLAGS: + debug_flags |= va_arg (arg_ptr, unsigned int); + break; + + case GCRYCTL_CLEAR_DEBUG_FLAGS: + debug_flags &= ~va_arg (arg_ptr, unsigned int); + break; + + case GCRYCTL_DISABLE_INTERNAL_LOCKING: + /* Not used anymore. */ + global_init (); + break; + + case GCRYCTL_ANY_INITIALIZATION_P: + if (any_init_done) + err = GPG_ERR_GENERAL; + break; + + case GCRYCTL_INITIALIZATION_FINISHED_P: + if (init_finished) + err = GPG_ERR_GENERAL; /* Yes. */ + break; + + case GCRYCTL_INITIALIZATION_FINISHED: + /* This is a hook which should be used by an application after + all initialization has been done and right before any threads + are started. It is not really needed but the only way to be + really sure that all initialization for thread-safety has + been done. */ + if (! init_finished) + { + global_init (); + /* Do only a basic random initialization, i.e. init the + mutexes. */ + _gcry_random_initialize (0); + init_finished = 1; + /* Force us into operational state if in FIPS mode. */ + (void)fips_is_operational (); + } + break; + + case GCRYCTL_SET_THREAD_CBS: + err = ath_install (va_arg (arg_ptr, void *), any_init_done); + if (! err) + global_init (); + break; + + case GCRYCTL_FAST_POLL: + /* We need to do make sure that the random pool is really + initialized so that the poll function is not a NOP. */ + _gcry_random_initialize (1); + + if ( fips_is_operational () ) + _gcry_fast_random_poll (); + break; + + case GCRYCTL_SET_RNDEGD_SOCKET: +#if USE_RNDEGD + err = _gcry_rndegd_set_socket_name (va_arg (arg_ptr, const char *)); +#else + err = gpg_error (GPG_ERR_NOT_SUPPORTED); +#endif + break; + + case GCRYCTL_SET_RANDOM_DAEMON_SOCKET: + _gcry_set_random_daemon_socket (va_arg (arg_ptr, const char *)); + break; + + case GCRYCTL_USE_RANDOM_DAEMON: + /* We need to do make sure that the random pool is really + initialized so that the poll function is not a NOP. */ + _gcry_random_initialize (1); + _gcry_use_random_daemon (!! va_arg (arg_ptr, int)); + break; + + /* This command dumps information pertaining to the + configuration of libgcrypt to the given stream. It may be + used before the initialization has been finished but not + before a gcry_version_check. */ + case GCRYCTL_PRINT_CONFIG: + { + FILE *fp = va_arg (arg_ptr, FILE *); + print_config (fp?fprintf:_gcry_log_info_with_dummy_fp, fp); + } + break; + + case GCRYCTL_OPERATIONAL_P: + /* Returns true if the library is in an operational state. This + is always true for non-fips mode. */ + if (_gcry_fips_test_operational ()) + err = GPG_ERR_GENERAL; /* Used as TRUE value */ + break; + + case GCRYCTL_FIPS_MODE_P: + if (fips_mode () + && !_gcry_is_fips_mode_inactive () + && !no_secure_memory) + err = GPG_ERR_GENERAL; /* Used as TRUE value */ + break; + + case GCRYCTL_FORCE_FIPS_MODE: + /* Performing this command puts the library into fips mode. If + the library has already been initialized into fips mode, a + selftest is triggered. It is not possible to put the libraty + into fips mode after having passed the initialization. */ + if (!any_init_done) + { + /* Not yet intialized at all. Set a flag so that we are put + into fips mode during initialization. */ + force_fips_mode = 1; + } + else + { + /* Already initialized. If we are already operational we + run a selftest. If not we use the is_operational call to + force us into operational state if possible. */ + if (_gcry_fips_test_error_or_operational ()) + _gcry_fips_run_selftests (1); + if (_gcry_fips_is_operational ()) + err = GPG_ERR_GENERAL; /* Used as TRUE value */ + } + break; + + case GCRYCTL_SELFTEST: + /* Run a selftest. This works in fips mode as well as in + standard mode. In contrast to the power-up tests, we use an + extended version of the selftests. Returns 0 on success or an + error code. */ + global_init (); + err = _gcry_fips_run_selftests (1); + break; + +#if _GCRY_GCC_VERSION >= 40600 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wswitch" +#endif + case 58: /* Init external random test. */ + { + void **rctx = va_arg (arg_ptr, void **); + unsigned int flags = va_arg (arg_ptr, unsigned int); + const void *key = va_arg (arg_ptr, const void *); + size_t keylen = va_arg (arg_ptr, size_t); + const void *seed = va_arg (arg_ptr, const void *); + size_t seedlen = va_arg (arg_ptr, size_t); + const void *dt = va_arg (arg_ptr, const void *); + size_t dtlen = va_arg (arg_ptr, size_t); + if (!fips_is_operational ()) + err = fips_not_operational (); + else + err = _gcry_random_init_external_test (rctx, flags, key, keylen, + seed, seedlen, dt, dtlen); + } + break; + case 59: /* Run external random test. */ + { + void *ctx = va_arg (arg_ptr, void *); + void *buffer = va_arg (arg_ptr, void *); + size_t buflen = va_arg (arg_ptr, size_t); + if (!fips_is_operational ()) + err = fips_not_operational (); + else + err = _gcry_random_run_external_test (ctx, buffer, buflen); + } + break; + case 60: /* Deinit external random test. */ + { + void *ctx = va_arg (arg_ptr, void *); + _gcry_random_deinit_external_test (ctx); + } + break; + case 61: /* RFU */ + break; + case 62: /* RFU */ + break; +#if _GCRY_GCC_VERSION >= 40600 +# pragma GCC diagnostic pop +#endif + + case GCRYCTL_DISABLE_HWF: + { + const char *name = va_arg (arg_ptr, const char *); + int i; + + for (i=0; hwflist[i].desc; i++) + if (!strcmp (hwflist[i].desc, name)) + { + disabled_hw_features |= hwflist[i].flag; + break; + } + if (!hwflist[i].desc) + err = GPG_ERR_INV_NAME; + } + break; + + case GCRYCTL_SET_ENFORCED_FIPS_FLAG: + if (!any_init_done) + { + /* Not yet intialized at all. Set the enforced fips mode flag */ + _gcry_set_enforced_fips_mode (); + } + else + err = GPG_ERR_GENERAL; + break; + + default: + err = GPG_ERR_INV_OP; + } + + return gcry_error (err); +} + + +/* Command dispatcher function, acting as general control + function. */ +gcry_error_t +gcry_control (enum gcry_ctl_cmds cmd, ...) +{ + gcry_error_t err; + va_list arg_ptr; + + va_start (arg_ptr, cmd); + err = _gcry_vcontrol (cmd, arg_ptr); + va_end(arg_ptr); + return err; +} + + + +/* Return a pointer to a string containing a description of the error + code in the error value ERR. */ +const char * +gcry_strerror (gcry_error_t err) +{ + return gpg_strerror (err); +} + +/* Return a pointer to a string containing a description of the error + source in the error value ERR. */ +const char * +gcry_strsource (gcry_error_t err) +{ + return gpg_strsource (err); +} + +/* Retrieve the error code for the system error ERR. This returns + GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report + this). */ +gcry_err_code_t +gcry_err_code_from_errno (int err) +{ + return gpg_err_code_from_errno (err); +} + + +/* Retrieve the system error for the error code CODE. This returns 0 + if CODE is not a system error code. */ +int +gcry_err_code_to_errno (gcry_err_code_t code) +{ + return gpg_err_code_from_errno (code); +} + + +/* Return an error value with the error source SOURCE and the system + error ERR. */ +gcry_error_t +gcry_err_make_from_errno (gpg_err_source_t source, int err) +{ + return gpg_err_make_from_errno (source, err); +} + + +/* Return an error value with the system error ERR. */ +gcry_err_code_t +gcry_error_from_errno (int err) +{ + return gcry_error (gpg_err_code_from_errno (err)); +} + + +/* Set custom allocation handlers. This is in general not useful + * because the libgcrypt allocation functions are guaranteed to + * provide proper allocation handlers which zeroize memory if needed. + * NOTE: All 5 functions should be set. */ +void +gcry_set_allocation_handler (gcry_handler_alloc_t new_alloc_func, + gcry_handler_alloc_t new_alloc_secure_func, + gcry_handler_secure_check_t new_is_secure_func, + gcry_handler_realloc_t new_realloc_func, + gcry_handler_free_t new_free_func) +{ + global_init (); + + if (fips_mode ()) + { + /* We do not want to enforce the fips mode, but merely set a + flag so that the application may check whether it is still in + fips mode. */ + _gcry_inactivate_fips_mode ("custom allocation handler"); + } + + alloc_func = new_alloc_func; + alloc_secure_func = new_alloc_secure_func; + is_secure_func = new_is_secure_func; + realloc_func = new_realloc_func; + free_func = new_free_func; +} + + + +/**************** + * Set an optional handler which is called in case the xmalloc functions + * ran out of memory. This handler may do one of these things: + * o free some memory and return true, so that the xmalloc function + * tries again. + * o Do whatever it like and return false, so that the xmalloc functions + * use the default fatal error handler. + * o Terminate the program and don't return. + * + * The handler function is called with 3 arguments: The opaque value set with + * this function, the requested memory size, and a flag with these bits + * currently defined: + * bit 0 set = secure memory has been requested. + */ +void +gcry_set_outofcore_handler( int (*f)( void*, size_t, unsigned int ), + void *value ) +{ + global_init (); + + if (fips_mode () ) + { + log_info ("out of core handler ignored in FIPS mode\n"); + return; + } + + outofcore_handler = f; + outofcore_handler_value = value; +} + +/* Return the no_secure_memory flag. */ +static int +get_no_secure_memory (void) +{ + if (!no_secure_memory) + return 0; + if (_gcry_enforced_fips_mode ()) + { + no_secure_memory = 0; + return 0; + } + return no_secure_memory; +} + + +static gcry_err_code_t +do_malloc (size_t n, unsigned int flags, void **mem) +{ + gcry_err_code_t err = 0; + void *m; + + if ((flags & GCRY_ALLOC_FLAG_SECURE) && !get_no_secure_memory ()) + { + if (alloc_secure_func) + m = (*alloc_secure_func) (n); + else + m = _gcry_private_malloc_secure (n); + } + else + { + if (alloc_func) + m = (*alloc_func) (n); + else + m = _gcry_private_malloc (n); + } + + if (!m) + { + /* Make sure that ERRNO has been set in case a user supplied + memory handler didn't it correctly. */ + if (!errno) + gpg_err_set_errno (ENOMEM); + err = gpg_err_code_from_errno (errno); + } + else + *mem = m; + + return err; +} + +void * +gcry_malloc (size_t n) +{ + void *mem = NULL; + + do_malloc (n, 0, &mem); + + return mem; +} + +void * +gcry_malloc_secure (size_t n) +{ + void *mem = NULL; + + do_malloc (n, GCRY_ALLOC_FLAG_SECURE, &mem); + + return mem; +} + +int +gcry_is_secure (const void *a) +{ + if (get_no_secure_memory ()) + return 0; + if (is_secure_func) + return is_secure_func (a) ; + return _gcry_private_is_secure (a); +} + +void +_gcry_check_heap( const void *a ) +{ + (void)a; + + /* FIXME: implement this*/ +#if 0 + if( some_handler ) + some_handler(a) + else + _gcry_private_check_heap(a) +#endif +} + +void * +gcry_realloc (void *a, size_t n) +{ + void *p; + + /* To avoid problems with non-standard realloc implementations and + our own secmem_realloc, we divert to malloc and free here. */ + if (!a) + return gcry_malloc (n); + if (!n) + { + gcry_free (a); + return NULL; + } + + if (realloc_func) + p = realloc_func (a, n); + else + p = _gcry_private_realloc (a, n); + if (!p && !errno) + gpg_err_set_errno (ENOMEM); + return p; +} + +void +gcry_free (void *p) +{ + int save_errno; + + if (!p) + return; + + /* In case ERRNO is set we better save it so that the free machinery + may not accidently change ERRNO. We restore it only if it was + already set to comply with the usual C semantic for ERRNO. */ + save_errno = errno; + if (free_func) + free_func (p); + else + _gcry_private_free (p); + + if (save_errno) + gpg_err_set_errno (save_errno); +} + +void * +gcry_calloc (size_t n, size_t m) +{ + size_t bytes; + void *p; + + bytes = n * m; /* size_t is unsigned so the behavior on overflow is + defined. */ + if (m && bytes / m != n) + { + gpg_err_set_errno (ENOMEM); + return NULL; + } + + p = gcry_malloc (bytes); + if (p) + memset (p, 0, bytes); + return p; +} + +void * +gcry_calloc_secure (size_t n, size_t m) +{ + size_t bytes; + void *p; + + bytes = n * m; /* size_t is unsigned so the behavior on overflow is + defined. */ + if (m && bytes / m != n) + { + gpg_err_set_errno (ENOMEM); + return NULL; + } + + p = gcry_malloc_secure (bytes); + if (p) + memset (p, 0, bytes); + return p; +} + + +/* Create and return a copy of the null-terminated string STRING. If + it is contained in secure memory, the copy will be contained in + secure memory as well. In an out-of-memory condition, NULL is + returned. */ +char * +gcry_strdup (const char *string) +{ + char *string_cp = NULL; + size_t string_n = 0; + + string_n = strlen (string); + + if (gcry_is_secure (string)) + string_cp = gcry_malloc_secure (string_n + 1); + else + string_cp = gcry_malloc (string_n + 1); + + if (string_cp) + strcpy (string_cp, string); + + return string_cp; +} + + +void * +gcry_xmalloc( size_t n ) +{ + void *p; + + while ( !(p = gcry_malloc( n )) ) + { + if ( fips_mode () + || !outofcore_handler + || !outofcore_handler (outofcore_handler_value, n, 0) ) + { + _gcry_fatal_error (gpg_err_code_from_errno (errno), NULL); + } + } + return p; +} + +void * +gcry_xrealloc( void *a, size_t n ) +{ + void *p; + + while ( !(p = gcry_realloc( a, n )) ) + { + if ( fips_mode () + || !outofcore_handler + || !outofcore_handler (outofcore_handler_value, n, + gcry_is_secure(a)? 3:2 ) ) + { + _gcry_fatal_error (gpg_err_code_from_errno (errno), NULL ); + } + } + return p; +} + +void * +gcry_xmalloc_secure( size_t n ) +{ + void *p; + + while ( !(p = gcry_malloc_secure( n )) ) + { + if ( fips_mode () + || !outofcore_handler + || !outofcore_handler (outofcore_handler_value, n, 1) ) + { + _gcry_fatal_error (gpg_err_code_from_errno (errno), + _("out of core in secure memory")); + } + } + return p; +} + + +void * +gcry_xcalloc( size_t n, size_t m ) +{ + size_t nbytes; + void *p; + + nbytes = n * m; + if (m && nbytes / m != n) + { + gpg_err_set_errno (ENOMEM); + _gcry_fatal_error(gpg_err_code_from_errno (errno), NULL ); + } + + p = gcry_xmalloc ( nbytes ); + memset ( p, 0, nbytes ); + return p; +} + +void * +gcry_xcalloc_secure( size_t n, size_t m ) +{ + size_t nbytes; + void *p; + + nbytes = n * m; + if (m && nbytes / m != n) + { + gpg_err_set_errno (ENOMEM); + _gcry_fatal_error(gpg_err_code_from_errno (errno), NULL ); + } + + p = gcry_xmalloc_secure ( nbytes ); + memset ( p, 0, nbytes ); + return p; +} + +char * +gcry_xstrdup (const char *string) +{ + char *p; + + while ( !(p = gcry_strdup (string)) ) + { + size_t n = strlen (string); + int is_sec = !!gcry_is_secure (string); + + if (fips_mode () + || !outofcore_handler + || !outofcore_handler (outofcore_handler_value, n, is_sec) ) + { + _gcry_fatal_error (gpg_err_code_from_errno (errno), + is_sec? _("out of core in secure memory"):NULL); + } + } + + return p; +} + + +int +_gcry_get_debug_flag (unsigned int mask) +{ + if ( fips_mode () ) + return 0; + return (debug_flags & mask); +} + + + +/* It is often useful to get some feedback of long running operations. + This function may be used to register a handler for this. + The callback function CB is used as: + + void cb (void *opaque, const char *what, int printchar, + int current, int total); + + Where WHAT is a string identifying the the type of the progress + output, PRINTCHAR the character usually printed, CURRENT the amount + of progress currently done and TOTAL the expected amount of + progress. A value of 0 for TOTAL indicates that there is no + estimation available. + + Defined values for WHAT: + + "need_entropy" X 0 number-of-bytes-required + When running low on entropy + "primegen" '\n' 0 0 + Prime generated + '!' + Need to refresh the prime pool + '<','>' + Number of bits adjusted + '^' + Looking for a generator + '.' + Fermat tests on 10 candidates failed + ':' + Restart with a new random value + '+' + Rabin Miller test passed + "pk_elg" '+','-','.','\n' 0 0 + Only used in debugging mode. + "pk_dsa" + Only used in debugging mode. +*/ +void +gcry_set_progress_handler (void (*cb)(void *,const char*,int, int, int), + void *cb_data) +{ +#if USE_DSA + _gcry_register_pk_dsa_progress (cb, cb_data); +#endif +#if USE_ELGAMAL + _gcry_register_pk_elg_progress (cb, cb_data); +#endif + _gcry_register_primegen_progress (cb, cb_data); + _gcry_register_random_progress (cb, cb_data); +} diff --git a/grub-core/lib/libgcrypt/src/hmac256.c b/grub-core/lib/libgcrypt/src/hmac256.c new file mode 100644 index 0000000..f3bc092 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/hmac256.c @@ -0,0 +1,793 @@ +/* hmac256.c - Standalone HMAC implementation + * Copyright (C) 2003, 2006, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* + This is a standalone HMAC-SHA-256 implementation based on the code + from ../cipher/sha256.c. It is a second implementation to allow + comparing against the standard implementations and to be used for + internal consistency checks. It should not be used for sensitive + data because no mechanisms to clear the stack etc are used. + + This module may be used standalone and requires only a few + standard definitions to be provided in a config.h file. + + Types: + + u32 - unsigned 32 bit type. + + Constants: + + WORDS_BIGENDIAN Defined to 1 on big endian systems. + inline If defined, it should yield the keyword used + to inline a function. + HAVE_U32_TYPEDEF Defined if the u32 type is available. + SIZEOF_UNSIGNED_INT Defined to the size in bytes of an unsigned int. + SIZEOF_UNSIGNED_LONG Defined to the size in bytes of an unsigned long. + + STANDALONE Compile a test driver similar to the + sha1sum tool. This driver uses a self-test + identically to the one used by Libcgrypt + for testing this included module. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <errno.h> +#if defined(__WIN32) && defined(STANDALONE) +# include <fcntl.h> /* We need setmode(). */ +#endif + +/* For a native WindowsCE binary we need to include gpg-error.h to + provide a replacement for strerror. In other cases we need a + replacement macro for gpg_err_set_errno. */ +#ifdef __MINGW32CE__ +# include <gpg-error.h> +#else +# define gpg_err_set_errno(a) (errno = (a)) +#endif + +#include "hmac256.h" + + + +#ifndef HAVE_U32_TYPEDEF +# undef u32 /* Undef a possible macro with that name. */ +# if SIZEOF_UNSIGNED_INT == 4 + typedef unsigned int u32; +# elif SIZEOF_UNSIGNED_LONG == 4 + typedef unsigned long u32; +# else +# error no typedef for u32 +# endif +# define HAVE_U32_TYPEDEF +#endif + + + + +/* The context used by this module. */ +struct hmac256_context +{ + u32 h0, h1, h2, h3, h4, h5, h6, h7; + u32 nblocks; + int count; + int finalized:1; + int use_hmac:1; + unsigned char buf[64]; + unsigned char opad[64]; +}; + + +/* Rotate a 32 bit word. */ +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +ror(u32 x, int n) +{ + __asm__("rorl %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else +#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) +#endif + +#define my_wipememory2(_ptr,_set,_len) do { \ + volatile char *_vptr=(volatile char *)(_ptr); \ + size_t _vlen=(_len); \ + while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ + } while(0) +#define my_wipememory(_ptr,_len) my_wipememory2(_ptr,0,_len) + + + + +/* + The SHA-256 core: Transform the message X which consists of 16 + 32-bit-words. See FIPS 180-2 for details. + */ +static void +transform (hmac256_context_t hd, const void *data_arg) +{ + const unsigned char *data = data_arg; + +#define Cho(x,y,z) (z ^ (x & (y ^ z))) /* (4.2) same as SHA-1's F1 */ +#define Maj(x,y,z) ((x & y) | (z & (x|y))) /* (4.3) same as SHA-1's F3 */ +#define Sum0(x) (ror ((x), 2) ^ ror ((x), 13) ^ ror ((x), 22)) /* (4.4) */ +#define Sum1(x) (ror ((x), 6) ^ ror ((x), 11) ^ ror ((x), 25)) /* (4.5) */ +#define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */ +#define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */ +#define R(a,b,c,d,e,f,g,h,k,w) do \ + { \ + t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + (k) + (w); \ + t2 = Sum0((a)) + Maj((a),(b),(c)); \ + h = g; \ + g = f; \ + f = e; \ + e = d + t1; \ + d = c; \ + c = b; \ + b = a; \ + a = t1 + t2; \ + } while (0) + + static const u32 K[64] = + { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + + u32 a, b, c, d, e, f, g, h, t1, t2; + u32 x[16]; + u32 w[64]; + int i; + + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + f = hd->h5; + g = hd->h6; + h = hd->h7; + +#ifdef WORDS_BIGENDIAN + memcpy (x, data, 64); +#else /*!WORDS_BIGENDIAN*/ + { + unsigned char *p2; + + for (i=0, p2=(unsigned char*)x; i < 16; i++, p2 += 4 ) + { + p2[3] = *data++; + p2[2] = *data++; + p2[1] = *data++; + p2[0] = *data++; + } + } +#endif /*!WORDS_BIGENDIAN*/ + + for (i=0; i < 16; i++) + w[i] = x[i]; + for (; i < 64; i++) + w[i] = S1(w[i-2]) + w[i-7] + S0(w[i-15]) + w[i-16]; + + for (i=0; i < 64; i++) + R(a,b,c,d,e,f,g,h,K[i],w[i]); + + hd->h0 += a; + hd->h1 += b; + hd->h2 += c; + hd->h3 += d; + hd->h4 += e; + hd->h5 += f; + hd->h6 += g; + hd->h7 += h; +} +#undef Cho +#undef Maj +#undef Sum0 +#undef Sum1 +#undef S0 +#undef S1 +#undef R + + +/* Finalize the current SHA256 calculation. */ +static void +finalize (hmac256_context_t hd) +{ + u32 t, msb, lsb; + unsigned char *p; + + if (hd->finalized) + return; /* Silently ignore a finalized context. */ + + _gcry_hmac256_update (hd, NULL, 0); /* Flush. */ + + t = hd->nblocks; + /* Multiply by 64 to make a byte count. */ + lsb = t << 6; + msb = t >> 26; + /* Add the count. */ + t = lsb; + if ((lsb += hd->count) < t) + msb++; + /* Multiply by 8 to make a bit count. */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if (hd->count < 56) + { /* Enough room. */ + hd->buf[hd->count++] = 0x80; /* pad */ + while (hd->count < 56) + hd->buf[hd->count++] = 0; /* pad */ + } + else + { /* Need one extra block. */ + hd->buf[hd->count++] = 0x80; /* pad character */ + while (hd->count < 64) + hd->buf[hd->count++] = 0; + _gcry_hmac256_update (hd, NULL, 0); /* Flush. */; + memset (hd->buf, 0, 56 ); /* Zero out next next block. */ + } + /* Append the 64 bit count. */ + hd->buf[56] = msb >> 24; + hd->buf[57] = msb >> 16; + hd->buf[58] = msb >> 8; + hd->buf[59] = msb; + hd->buf[60] = lsb >> 24; + hd->buf[61] = lsb >> 16; + hd->buf[62] = lsb >> 8; + hd->buf[63] = lsb; + transform (hd, hd->buf); + + /* Store the digest into hd->buf. */ + p = hd->buf; +#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ + *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) + X(0); + X(1); + X(2); + X(3); + X(4); + X(5); + X(6); + X(7); +#undef X + hd->finalized = 1; +} + + + +/* Create a new context. On error NULL is returned and errno is set + appropriately. If KEY is given the function computes HMAC using + this key; with KEY given as NULL, a plain SHA-256 digest is + computed. */ +hmac256_context_t +_gcry_hmac256_new (const void *key, size_t keylen) +{ + hmac256_context_t hd; + + hd = malloc (sizeof *hd); + if (!hd) + return NULL; + + hd->h0 = 0x6a09e667; + hd->h1 = 0xbb67ae85; + hd->h2 = 0x3c6ef372; + hd->h3 = 0xa54ff53a; + hd->h4 = 0x510e527f; + hd->h5 = 0x9b05688c; + hd->h6 = 0x1f83d9ab; + hd->h7 = 0x5be0cd19; + hd->nblocks = 0; + hd->count = 0; + hd->finalized = 0; + hd->use_hmac = 0; + + if (key) + { + int i; + unsigned char ipad[64]; + + memset (ipad, 0, 64); + memset (hd->opad, 0, 64); + if (keylen <= 64) + { + memcpy (ipad, key, keylen); + memcpy (hd->opad, key, keylen); + } + else + { + hmac256_context_t tmphd; + + tmphd = _gcry_hmac256_new (NULL, 0); + if (!tmphd) + { + free (hd); + return NULL; + } + _gcry_hmac256_update (tmphd, key, keylen); + finalize (tmphd); + memcpy (ipad, tmphd->buf, 32); + memcpy (hd->opad, tmphd->buf, 32); + _gcry_hmac256_release (tmphd); + } + for (i=0; i < 64; i++) + { + ipad[i] ^= 0x36; + hd->opad[i] ^= 0x5c; + } + hd->use_hmac = 1; + _gcry_hmac256_update (hd, ipad, 64); + my_wipememory (ipad, 64); + } + + return hd; +} + +/* Release a context created by _gcry_hmac256_new. CTX may be NULL + in which case the function does nothing. */ +void +_gcry_hmac256_release (hmac256_context_t ctx) +{ + if (ctx) + { + /* Note: We need to take care not to modify errno. */ + if (ctx->use_hmac) + my_wipememory (ctx->opad, 64); + free (ctx); + } +} + + +/* Update the message digest with the contents of BUFFER containing + LENGTH bytes. */ +void +_gcry_hmac256_update (hmac256_context_t hd, + const void *buffer, size_t length) +{ + const unsigned char *inbuf = buffer; + + if (hd->finalized) + return; /* Silently ignore a finalized context. */ + + if (hd->count == 64) + { + /* Flush the buffer. */ + transform (hd, hd->buf); + hd->count = 0; + hd->nblocks++; + } + if (!inbuf) + return; /* Only flushing was requested. */ + if (hd->count) + { + for (; length && hd->count < 64; length--) + hd->buf[hd->count++] = *inbuf++; + _gcry_hmac256_update (hd, NULL, 0); /* Flush. */ + if (!length) + return; + } + + + while (length >= 64) + { + transform (hd, inbuf); + hd->count = 0; + hd->nblocks++; + length -= 64; + inbuf += 64; + } + for (; length && hd->count < 64; length--) + hd->buf[hd->count++] = *inbuf++; +} + + +/* Finalize an operation and return the digest. If R_DLEN is not NULL + the length of the digest will be stored at that address. The + returned value is valid as long as the context exists. On error + NULL is returned. */ +const void * +_gcry_hmac256_finalize (hmac256_context_t hd, size_t *r_dlen) +{ + finalize (hd); + if (hd->use_hmac) + { + hmac256_context_t tmphd; + + tmphd = _gcry_hmac256_new (NULL, 0); + if (!tmphd) + { + free (hd); + return NULL; + } + _gcry_hmac256_update (tmphd, hd->opad, 64); + _gcry_hmac256_update (tmphd, hd->buf, 32); + finalize (tmphd); + memcpy (hd->buf, tmphd->buf, 32); + _gcry_hmac256_release (tmphd); + } + if (r_dlen) + *r_dlen = 32; + return (void*)hd->buf; +} + + +/* Convenience function to compute the HMAC-SHA256 of one file. The + user needs to provide a buffer RESULT of at least 32 bytes, he + needs to put the size of the buffer into RESULTSIZE and the + FILENAME. KEY and KEYLEN are as described for _gcry_hmac256_new. + On success the function returns the valid length of the result + buffer (which will be 32) or -1 on error. On error ERRNO is set + appropriate. */ +int +_gcry_hmac256_file (void *result, size_t resultsize, const char *filename, + const void *key, size_t keylen) +{ + FILE *fp; + hmac256_context_t hd; + size_t buffer_size, nread, digestlen; + char *buffer; + const unsigned char *digest; + + fp = fopen (filename, "rb"); + if (!fp) + return -1; + + hd = _gcry_hmac256_new (key, keylen); + if (!hd) + { + fclose (fp); + return -1; + } + + buffer_size = 32768; + buffer = malloc (buffer_size); + if (!buffer) + { + fclose (fp); + _gcry_hmac256_release (hd); + return -1; + } + + while ( (nread = fread (buffer, 1, buffer_size, fp))) + _gcry_hmac256_update (hd, buffer, nread); + + free (buffer); + + if (ferror (fp)) + { + fclose (fp); + _gcry_hmac256_release (hd); + return -1; + } + + fclose (fp); + + digest = _gcry_hmac256_finalize (hd, &digestlen); + if (!digest) + { + _gcry_hmac256_release (hd); + return -1; + } + + if (digestlen > resultsize) + { + _gcry_hmac256_release (hd); + gpg_err_set_errno (EINVAL); + return -1; + } + memcpy (result, digest, digestlen); + _gcry_hmac256_release (hd); + + return digestlen; +} + + + +#ifdef STANDALONE +static int +selftest (void) +{ + static struct + { + const char * const desc; + const char * const data; + const char * const key; + const unsigned char expect[32]; + } tv[] = + { + { "data-28 key-4", + "what do ya want for nothing?", + "Jefe", + { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, + 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, + 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, + 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 } }, + + { "data-9 key-20", + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b", + { 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, + 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, + 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, + 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 } }, + + { "data-50 key-20", + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa", + { 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, + 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, + 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, + 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe } }, + + { "data-50 key-26", + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" + "\x11\x12\x13\x14\x15\x16\x17\x18\x19", + { 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, + 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, + 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, + 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b } }, + + { "data-54 key-131", + "Test Using Larger Than Block-Size Key - Hash Key First", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + { 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, + 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, + 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, + 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 } }, + + { "data-152 key-131", + "This is a test using a larger than block-size key and a larger " + "than block-size data. The key needs to be hashed before being " + "used by the HMAC algorithm.", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa", + { 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, + 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, + 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, + 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2 } }, + + { NULL } + }; + int tvidx; + + for (tvidx=0; tv[tvidx].desc; tvidx++) + { + hmac256_context_t hmachd; + const unsigned char *digest; + size_t dlen; + + hmachd = _gcry_hmac256_new (tv[tvidx].key, strlen (tv[tvidx].key)); + if (!hmachd) + return -1; + _gcry_hmac256_update (hmachd, tv[tvidx].data, strlen (tv[tvidx].data)); + digest = _gcry_hmac256_finalize (hmachd, &dlen); + if (!digest) + { + _gcry_hmac256_release (hmachd); + return -1; + } + if (dlen != sizeof (tv[tvidx].expect) + || memcmp (digest, tv[tvidx].expect, sizeof (tv[tvidx].expect))) + { + _gcry_hmac256_release (hmachd); + return -1; + } + _gcry_hmac256_release (hmachd); + } + + return 0; /* Succeeded. */ +} + + +int +main (int argc, char **argv) +{ + const char *pgm; + int last_argc = -1; + const char *key; + size_t keylen; + FILE *fp; + hmac256_context_t hd; + const unsigned char *digest; + char buffer[4096]; + size_t n, dlen, idx; + int use_stdin = 0; + int use_binary = 0; + + assert (sizeof (u32) == 4); +#ifdef __WIN32 + setmode (fileno (stdin), O_BINARY); +#endif + + if (argc) + { + pgm = strrchr (*argv, '/'); + if (pgm) + pgm++; + else + pgm = *argv; + argc--; argv++; + } + else + pgm = "?"; + + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--version")) + { + fputs ("hmac256 (Libgcrypt) " VERSION "\n" + "Copyright (C) 2008 Free Software Foundation, Inc.\n" + "License LGPLv2.1+: GNU LGPL version 2.1 or later " + "<http://gnu.org/licenses/old-licenses/lgpl-2.1.html>\n" + "This is free software: you are free to change and " + "redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", + stdout); + exit (0); + } + else if (!strcmp (*argv, "--binary")) + { + argc--; argv++; + use_binary = 1; + } + } + + if (argc < 1) + { + fprintf (stderr, "usage: %s [--binary] key [filename]\n", pgm); + exit (1); + } + +#ifdef __WIN32 + if (use_binary) + setmode (fileno (stdout), O_BINARY); +#endif + + key = *argv; + argc--, argv++; + keylen = strlen (key); + use_stdin = !argc; + + if (selftest ()) + { + fprintf (stderr, "%s: fatal error: self-test failed\n", pgm); + exit (2); + } + + for (; argc || use_stdin; argv++, argc--) + { + const char *fname = use_stdin? "-" : *argv; + fp = use_stdin? stdin : fopen (fname, "rb"); + if (!fp) + { + fprintf (stderr, "%s: can't open `%s': %s\n", + pgm, fname, strerror (errno)); + exit (1); + } + hd = _gcry_hmac256_new (key, keylen); + if (!hd) + { + fprintf (stderr, "%s: can't allocate context: %s\n", + pgm, strerror (errno)); + exit (1); + } + while ( (n = fread (buffer, 1, sizeof buffer, fp))) + _gcry_hmac256_update (hd, buffer, n); + if (ferror (fp)) + { + fprintf (stderr, "%s: error reading `%s': %s\n", + pgm, fname, strerror (errno)); + exit (1); + } + if (!use_stdin) + fclose (fp); + + digest = _gcry_hmac256_finalize (hd, &dlen); + if (!digest) + { + fprintf (stderr, "%s: error computing HMAC: %s\n", + pgm, strerror (errno)); + exit (1); + } + if (use_binary) + { + if (fwrite (digest, dlen, 1, stdout) != 1) + { + fprintf (stderr, "%s: error writing output: %s\n", + pgm, strerror (errno)); + exit (1); + } + } + else + { + for (idx=0; idx < dlen; idx++) + printf ("%02x", digest[idx]); + _gcry_hmac256_release (hd); + if (use_stdin) + { + putchar ('\n'); + break; + } + printf (" %s\n", fname); + } + } + + return 0; +} +#endif /*STANDALONE*/ + + +/* +Local Variables: +compile-command: "cc -Wall -g -I.. -DSTANDALONE -o hmac256 hmac256.c" +End: +*/ diff --git a/grub-core/lib/libgcrypt/src/hmac256.h b/grub-core/lib/libgcrypt/src/hmac256.h new file mode 100644 index 0000000..df28e72 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/hmac256.h @@ -0,0 +1,36 @@ +/* hmac256.h - Declarations for _gcry_hmac256 + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HMAC256_H +#define HMAC256_H + + +struct hmac256_context; +typedef struct hmac256_context *hmac256_context_t; + +hmac256_context_t _gcry_hmac256_new (const void *key, size_t keylen); +void _gcry_hmac256_update (hmac256_context_t hd, const void *buf, size_t len); +const void *_gcry_hmac256_finalize (hmac256_context_t hd, size_t *r_dlen); +void _gcry_hmac256_release (hmac256_context_t hd); + +int _gcry_hmac256_file (void *result, size_t resultsize, const char *filename, + const void *key, size_t keylen); + + +#endif /*HMAC256_H*/ diff --git a/grub-core/lib/libgcrypt/src/hwfeatures.c b/grub-core/lib/libgcrypt/src/hwfeatures.c new file mode 100644 index 0000000..c356798 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/hwfeatures.c @@ -0,0 +1,192 @@ +/* hwfeatures.c - Detect hardware features. + * Copyright (C) 2007, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> + +#include "g10lib.h" + +/* A bit vector describing the hardware features currently + available. */ +static unsigned int hw_features; + + +/* Return a bit vector describing the available hardware features. + The HWF_ constants are used to test for them. */ +unsigned int +_gcry_get_hw_features (void) +{ + return hw_features; +} + + +#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) +static void +detect_ia32_gnuc (void) +{ + /* The code here is only useful for the PadLock engine thus we don't + build it if that support has been disabled. */ + int has_cpuid = 0; + char vendor_id[12+1]; + + /* Detect the CPUID feature by testing some undefined behaviour (16 + vs 32 bit pushf/popf). */ + asm volatile + ("pushf\n\t" /* Copy flags to EAX. */ + "popl %%eax\n\t" + "movl %%eax, %%ecx\n\t" /* Save flags into ECX. */ + "xorl $0x200000, %%eax\n\t" /* Toggle ID bit and copy it to the flags. */ + "pushl %%eax\n\t" + "popf\n\t" + "pushf\n\t" /* Copy changed flags again to EAX. */ + "popl %%eax\n\t" + "pushl %%ecx\n\t" /* Restore flags from ECX. */ + "popf\n\t" + "xorl %%eax, %%ecx\n\t" /* Compare flags against saved flags. */ + "jz .Lno_cpuid%=\n\t" /* Toggling did not work, thus no CPUID. */ + "movl $1, %0\n" /* Worked. true -> HAS_CPUID. */ + ".Lno_cpuid%=:\n\t" + : "+r" (has_cpuid) + : + : "%eax", "%ecx", "cc" + ); + + if (!has_cpuid) + return; /* No way. */ + + asm volatile + ("pushl %%ebx\n\t" /* Save GOT register. */ + "xorl %%eax, %%eax\n\t" /* 0 -> EAX. */ + "cpuid\n\t" /* Get vendor ID. */ + "movl %%ebx, (%0)\n\t" /* EBX,EDX,ECX -> VENDOR_ID. */ + "movl %%edx, 4(%0)\n\t" + "movl %%ecx, 8(%0)\n\t" + "popl %%ebx\n" + : + : "S" (&vendor_id[0]) + : "%eax", "%ecx", "%edx", "cc" + ); + vendor_id[12] = 0; + + if (0) + ; /* Just to make "else if" and ifdef macros look pretty. */ +#ifdef ENABLE_PADLOCK_SUPPORT + else if (!strcmp (vendor_id, "CentaurHauls")) + { + /* This is a VIA CPU. Check what PadLock features we have. */ + asm volatile + ("pushl %%ebx\n\t" /* Save GOT register. */ + "movl $0xC0000000, %%eax\n\t" /* Check for extended centaur */ + "cpuid\n\t" /* feature flags. */ + "popl %%ebx\n\t" /* Restore GOT register. */ + "cmpl $0xC0000001, %%eax\n\t" + "jb .Lready%=\n\t" /* EAX < 0xC0000000 => no padlock. */ + + "pushl %%ebx\n\t" /* Save GOT register. */ + "movl $0xC0000001, %%eax\n\t" /* Ask for the extended */ + "cpuid\n\t" /* feature flags. */ + "popl %%ebx\n\t" /* Restore GOT register. */ + + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0x0C, %%eax\n\t" /* Test bits 2 and 3 to see whether */ + "cmpl $0x0C, %%eax\n\t" /* the RNG exists and is enabled. */ + "jnz .Lno_rng%=\n\t" + "orl $1, %0\n" /* Set our HWF_PADLOCK_RNG bit. */ + + ".Lno_rng%=:\n\t" + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0xC0, %%eax\n\t" /* Test bits 6 and 7 to see whether */ + "cmpl $0xC0, %%eax\n\t" /* the ACE exists and is enabled. */ + "jnz .Lno_ace%=\n\t" + "orl $2, %0\n" /* Set our HWF_PADLOCK_AES bit. */ + + ".Lno_ace%=:\n\t" + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0xC00, %%eax\n\t" /* Test bits 10, 11 to see whether */ + "cmpl $0xC00, %%eax\n\t" /* the PHE exists and is enabled. */ + "jnz .Lno_phe%=\n\t" + "orl $4, %0\n" /* Set our HWF_PADLOCK_SHA bit. */ + + ".Lno_phe%=:\n\t" + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0x3000, %%eax\n\t" /* Test bits 12, 13 to see whether */ + "cmpl $0x3000, %%eax\n\t" /* MONTMUL exists and is enabled. */ + "jnz .Lready%=\n\t" + "orl $8, %0\n" /* Set our HWF_PADLOCK_MMUL bit. */ + + ".Lready%=:\n" + : "+r" (hw_features) + : + : "%eax", "%edx", "cc" + ); + } +#endif /*ENABLE_PADLOCK_SUPPORT*/ + else if (!strcmp (vendor_id, "GenuineIntel")) + { + /* This is an Intel CPU. */ + asm volatile + ("pushl %%ebx\n\t" /* Save GOT register. */ + "movl $1, %%eax\n\t" /* Get CPU info and feature flags. */ + "cpuid\n" + "popl %%ebx\n\t" /* Restore GOT register. */ + "testl $0x02000000, %%ecx\n\t" /* Test bit 25. */ + "jz .Lno_aes%=\n\t" /* No AES support. */ + "orl $256, %0\n" /* Set our HWF_INTEL_AES bit. */ + + ".Lno_aes%=:\n" + : "+r" (hw_features) + : + : "%eax", "%ecx", "%edx", "cc" + ); + } + else if (!strcmp (vendor_id, "AuthenticAMD")) + { + /* This is an AMD CPU. */ + + } +} +#endif /* __i386__ && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ */ + + +/* Detect the available hardware features. This function is called + once right at startup and we assume that no other threads are + running. */ +void +_gcry_detect_hw_features (unsigned int disabled_features) +{ + hw_features = 0; + + if (fips_mode ()) + return; /* Hardware support is not to be evaluated. */ + +#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 +#ifdef __GNUC__ + detect_ia32_gnuc (); +#endif +#elif defined (__i386__) && SIZEOF_UNSIGNED_LONG == 8 +#ifdef __GNUC__ +#endif +#endif + + hw_features &= ~disabled_features; +} diff --git a/grub-core/lib/libgcrypt/src/libgcrypt-config.in b/grub-core/lib/libgcrypt/src/libgcrypt-config.in new file mode 100644 index 0000000..c052638 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/libgcrypt-config.in @@ -0,0 +1,189 @@ +#!/bin/sh +# Copyright (C) 1999, 2002, 2003, 2004, 2011 Free Software Foundation, Inc. +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# File: @configure_input@ + +# General. +prefix="@prefix@" +exec_prefix="@exec_prefix@" +version="@VERSION@" +includedir="@includedir@" +libdir="@libdir@" +gpg_error_libs="@GPG_ERROR_LIBS@" +gpg_error_cflags="@GPG_ERROR_CFLAGS@" + +# libgcrypt values. +libs="@LIBGCRYPT_CONFIG_LIBS@" +cflags="@LIBGCRYPT_CONFIG_CFLAGS@" + +# API info +api_version="@LIBGCRYPT_CONFIG_API_VERSION@" + +# Configured for host +my_host="@LIBGCRYPT_CONFIG_HOST@" + +# Misc information. +symmetric_ciphers="@LIBGCRYPT_CIPHERS@" +asymmetric_ciphers="@LIBGCRYPT_PUBKEY_CIPHERS@" +digests="@LIBGCRYPT_DIGESTS@" + +# State variables. +echo_libs=no +echo_cflags=no +echo_prefix=no +echo_algorithms=no +echo_exec_prefix=no +echo_version=no +echo_api_version=no +echo_host=no + +# Prints usage information. +usage() +{ + cat <<EOF +Usage: $0 [OPTIONS] +Options: + [--prefix] + [--exec-prefix] + [--version] + [--api-version] + [--libs] + [--cflags] + [--algorithms] + [--host] +EOF + exit $1 +} + +if test $# -eq 0; then + # Nothing to do. + usage 1 1>&2 +fi + +while test $# -gt 0; do + case "$1" in + # Set up `optarg'. + --*=*) + optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` + ;; + *) + optarg="" + ;; + esac + + case $1 in + --thread=*) + echo "$0: --thread option obsolete: use the thread callback interface" 1>&2 + exit 1 + ;; + --prefix=*) + # For compatibility reasons with old M4 macros, we ignore + # setting of prefix. + ;; + --prefix) + echo_prefix=yes + ;; + --exec-prefix=*) + ;; + --exec-prefix) + echo_exec_prefix=yes + ;; + --version) + echo_version=yes + ;; + --api-version) + echo_api_version=yes + ;; + --cflags) + echo_cflags=yes + ;; + --libs) + echo_libs=yes + ;; + --algorithms) + echo_algorithms=yes + ;; + --host) + echo_host=yes + ;; + *) + usage 1 1>&2 + ;; + esac + shift +done + +if test "$echo_prefix" = "yes"; then + echo "$prefix" +fi + +if test "$echo_exec_prefix" = "yes"; then + echo "$exec_prefix" +fi + +if test "$echo_cflags" = "yes"; then + includes="" + cflags_final="$cflags" + + # Set up `includes'. + if test "x$includedir" != "x/usr/include" -a "x$includedir" != "x/include"; then + includes="-I$includedir" + fi + # Set up `cflags_final'. + cflags_final="$cflags_final $gpg_error_cflags" + + tmp="" + for i in $includes $cflags_final; do + if echo "$tmp" | fgrep -v -- "$i" >/dev/null; then + tmp="$tmp $i" + fi + done + echo $tmp +fi + +if test "$echo_libs" = "yes"; then + libdirs="" + libs_final="$libs" + + # Set up `libdirs'. + if test "x$libdir" != "x/usr/lib" -a "x$libdir" != "x/lib"; then + libdirs="-L$libdir" + fi + + # Set up `libs_final'. + libs_final="$libs_final $gpg_error_libs" + + tmp="" + for i in $libdirs $libs_final; do + if echo "$tmp" | fgrep -v -- "$i" >/dev/null; then + tmp="$tmp $i" + fi + done + echo $tmp +fi + +if test "$echo_version" = "yes"; then + echo "$version" +fi + +if test "$echo_api_version" = "yes"; then + echo "$api_version" +fi + +if test "$echo_host" = "yes"; then + echo "$my_host" +fi + +if test "$echo_algorithms" = "yes"; then + echo "Symmetric cipher algorithms: $symmetric_ciphers" + echo "Public-key cipher algorithms: $asymmetric_ciphers" + echo "Message digest algorithms: $digests" +fi diff --git a/grub-core/lib/libgcrypt/src/libgcrypt.def b/grub-core/lib/libgcrypt/src/libgcrypt.def new file mode 100644 index 0000000..031b941 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/libgcrypt.def @@ -0,0 +1,239 @@ +;; libgcrypt.defs - Exported symbols for W32 +;; Copyright (C) 2003, 2007 Free Software Foundation, Inc. +;; +;; This file is part of Libgcrypt. +;; +;; Libgcrypt is free software; you can redistribute it and/or modify +;; it under the terms of the GNU Lesser General Public License as +;; published by the Free Software Foundation; either version 2.1 of +;; the License, or (at your option) any later version. +;; +;; Libgcrypt is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU Lesser General Public License for more details. +;; +;; You should have received a copy of the GNU Lesser General Public +;; License along with this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +;; + +;; Note: This file should be updated manually and the ordinals shall +;; never be changed. Also check libgcrypt.vers and visibility.h. + + +EXPORTS + gcry_check_version @1 + gcry_control @2 + + gcry_malloc @3 + gcry_calloc @4 + gcry_malloc_secure @5 + gcry_calloc_secure @6 + gcry_realloc @7 + gcry_strdup @8 + gcry_xmalloc @9 + gcry_xcalloc @10 + gcry_xmalloc_secure @11 + gcry_xcalloc_secure @12 + gcry_xrealloc @13 + gcry_xstrdup @14 + gcry_is_secure @15 + gcry_free @16 + + gcry_set_progress_handler @17 + gcry_set_allocation_handler @18 + gcry_set_outofcore_handler @19 + gcry_set_fatalerror_handler @20 + gcry_set_log_handler @21 + gcry_set_gettext_handler @22 + + gcry_strerror @23 + gcry_strsource @24 + gcry_err_code_from_errno @25 + gcry_err_code_to_errno @26 + gcry_err_make_from_errno @27 + gcry_error_from_errno @28 + + gcry_sexp_new @29 + gcry_sexp_create @30 + gcry_sexp_sscan @31 + gcry_sexp_build @32 + gcry_sexp_build_array @33 + gcry_sexp_release @34 + gcry_sexp_canon_len @35 + gcry_sexp_sprint @36 + gcry_sexp_dump @37 + gcry_sexp_cons @38 + gcry_sexp_alist @39 + gcry_sexp_vlist @40 + gcry_sexp_append @41 + gcry_sexp_prepend @42 + gcry_sexp_find_token @43 + gcry_sexp_length @44 + gcry_sexp_nth @45 + gcry_sexp_car @46 + gcry_sexp_cdr @47 + gcry_sexp_cadr @48 + gcry_sexp_nth_data @49 + gcry_sexp_nth_mpi @50 + + gcry_mpi_new @51 + gcry_mpi_snew @52 + gcry_mpi_release @53 + gcry_mpi_copy @54 + gcry_mpi_set @55 + gcry_mpi_set_ui @56 + gcry_mpi_swap @57 + gcry_mpi_cmp @58 + gcry_mpi_cmp_ui @59 + gcry_mpi_scan @60 + gcry_mpi_print @61 + gcry_mpi_aprint @62 + gcry_mpi_dump @63 + gcry_mpi_add @64 + gcry_mpi_add_ui @65 + gcry_mpi_addm @66 + gcry_mpi_sub @67 + gcry_mpi_sub_ui @68 + gcry_mpi_subm @69 + gcry_mpi_mul @70 + gcry_mpi_mul_ui @71 + gcry_mpi_mulm @72 + gcry_mpi_mul_2exp @73 + gcry_mpi_div @74 + gcry_mpi_mod @75 + gcry_mpi_powm @76 + gcry_mpi_gcd @77 + gcry_mpi_invm @78 + gcry_mpi_get_nbits @79 + gcry_mpi_test_bit @80 + gcry_mpi_set_bit @81 + gcry_mpi_clear_bit @82 + gcry_mpi_set_highbit @83 + gcry_mpi_clear_highbit @84 + gcry_mpi_rshift @85 + gcry_mpi_set_opaque @86 + gcry_mpi_get_opaque @87 + gcry_mpi_set_flag @88 + gcry_mpi_clear_flag @89 + gcry_mpi_get_flag @90 + + + gcry_cipher_open @92 + gcry_cipher_close @93 + gcry_cipher_ctl @94 + gcry_cipher_info @95 + gcry_cipher_algo_info @96 + gcry_cipher_algo_name @97 + gcry_cipher_map_name @98 + gcry_cipher_mode_from_oid @99 + gcry_cipher_encrypt @100 + gcry_cipher_decrypt @101 + gcry_cipher_get_algo_keylen @102 + gcry_cipher_get_algo_blklen @103 + gcry_cipher_list @104 + + gcry_pk_encrypt @105 + gcry_pk_decrypt @106 + gcry_pk_sign @107 + gcry_pk_verify @108 + gcry_pk_testkey @109 + gcry_pk_genkey @110 + gcry_pk_ctl @111 + gcry_pk_algo_info @112 + gcry_pk_algo_name @113 + gcry_pk_map_name @114 + gcry_pk_get_nbits @115 + gcry_pk_get_keygrip @116 + gcry_pk_list @117 + + gcry_ac_data_new @118 + gcry_ac_data_destroy @119 + gcry_ac_data_set @120 + gcry_ac_data_copy @121 + gcry_ac_data_length @122 + gcry_ac_data_get_name @123 + gcry_ac_data_get_index @124 + gcry_ac_data_clear @125 + gcry_ac_open @126 + gcry_ac_close @127 + gcry_ac_key_init @128 + gcry_ac_key_pair_generate @129 + gcry_ac_key_pair_extract @130 + gcry_ac_key_data_get @131 + gcry_ac_key_test @132 + gcry_ac_key_get_nbits @133 + gcry_ac_key_get_grip @134 + gcry_ac_key_destroy @135 + gcry_ac_key_pair_destroy @136 + gcry_ac_data_encrypt @137 + gcry_ac_data_decrypt @138 + gcry_ac_data_sign @139 + gcry_ac_data_verify @140 + gcry_ac_id_to_name @141 + gcry_ac_name_to_id @142 + + gcry_md_open @143 + gcry_md_close @144 + gcry_md_enable @145 + gcry_md_copy @146 + gcry_md_reset @147 + gcry_md_ctl @148 + gcry_md_write @149 + gcry_md_read @150 + gcry_md_hash_buffer @151 + gcry_md_get_algo @152 + gcry_md_get_algo_dlen @153 + gcry_md_is_enabled @154 + gcry_md_is_secure @155 + gcry_md_info @156 + gcry_md_algo_info @157 + gcry_md_algo_name @158 + gcry_md_map_name @159 + gcry_md_setkey @160 + gcry_md_list @161 + + gcry_randomize @162 + gcry_random_add_bytes @163 + gcry_random_bytes @164 + gcry_random_bytes_secure @165 + gcry_mpi_randomize @166 + + gcry_prime_generate @167 + gcry_prime_group_generator @168 + gcry_prime_release_factors @169 + gcry_prime_check @170 + + gcry_create_nonce @171 + + gcry_md_debug @172 + + gcry_cipher_register @173 + gcry_cipher_unregister @174 + gcry_md_register @175 + gcry_md_unregister @176 + gcry_pk_register @177 + gcry_pk_unregister @178 + + gcry_ac_data_from_sexp @179 + gcry_ac_data_to_sexp @180 + gcry_ac_io_init @181 + gcry_ac_io_init_va @182 + gcry_ac_data_encrypt_scheme @183 + gcry_ac_data_decrypt_scheme @184 + gcry_ac_data_sign_scheme @185 + gcry_ac_data_verify_scheme @186 + + gcry_sexp_nth_string @187 + + gcry_cipher_setkey @188 + gcry_cipher_setiv @189 + gcry_cipher_setctr @190 + + gcry_mpi_lshift @191 + + gcry_pk_get_curve @192 + gcry_pk_get_param @193 + + gcry_kdf_derive @194 diff --git a/grub-core/lib/libgcrypt/src/libgcrypt.m4 b/grub-core/lib/libgcrypt/src/libgcrypt.m4 new file mode 100644 index 0000000..831dc0c --- /dev/null +++ b/grub-core/lib/libgcrypt/src/libgcrypt.m4 @@ -0,0 +1,123 @@ +dnl Autoconf macros for libgcrypt +dnl Copyright (C) 2002, 2004 Free Software Foundation, Inc. +dnl +dnl This file is free software; as a special exception the author gives +dnl unlimited permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl +dnl This file is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + +dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS. +dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed +dnl with the API version to also check the API compatibility. Example: +dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed +dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using +dnl this features allows to prevent build against newer versions of libgcrypt +dnl with a changed API. +dnl +AC_DEFUN([AM_PATH_LIBGCRYPT], +[ AC_ARG_WITH(libgcrypt-prefix, + AC_HELP_STRING([--with-libgcrypt-prefix=PFX], + [prefix where LIBGCRYPT is installed (optional)]), + libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="") + if test x$libgcrypt_config_prefix != x ; then + if test x${LIBGCRYPT_CONFIG+set} != xset ; then + LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config + fi + fi + + AC_PATH_TOOL(LIBGCRYPT_CONFIG, libgcrypt-config, no) + tmp=ifelse([$1], ,1:1.2.0,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_libgcrypt_api=0 + min_libgcrypt_version="$tmp" + fi + + AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) + ok=no + if test "$LIBGCRYPT_CONFIG" != "no" ; then + req_major=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` + major=`echo $libgcrypt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $libgcrypt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + micro=`echo $libgcrypt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -gt "$req_minor"; then + ok=yes + else + if test "$minor" -eq "$req_minor"; then + if test "$micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + AC_MSG_RESULT([yes ($libgcrypt_config_version)]) + else + AC_MSG_RESULT(no) + fi + if test $ok = yes; then + # If we have a recent libgcrypt, we should also check that the + # API is compatible + if test "$req_libgcrypt_api" -gt 0 ; then + tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + AC_MSG_CHECKING([LIBGCRYPT API version]) + if test "$req_libgcrypt_api" -eq "$tmp" ; then + AC_MSG_RESULT([okay]) + else + ok=no + AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp]) + fi + fi + fi + fi + if test $ok = yes; then + LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` + LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` + ifelse([$2], , :, [$2]) + if test x"$host" != x ; then + libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` + if test x"$libgcrypt_config_host" != xnone ; then + if test x"$libgcrypt_config_host" != x"$host" ; then + AC_MSG_WARN([[ +*** +*** The config script $LIBGCRYPT_CONFIG was +*** built for $libgcrypt_config_host and thus may not match the +*** used host $host. +*** You may want to use the configure option --with-libgcrypt-prefix +*** to specify a matching config script. +***]]) + fi + fi + fi + else + LIBGCRYPT_CFLAGS="" + LIBGCRYPT_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(LIBGCRYPT_CFLAGS) + AC_SUBST(LIBGCRYPT_LIBS) +]) diff --git a/grub-core/lib/libgcrypt/src/libgcrypt.vers b/grub-core/lib/libgcrypt/src/libgcrypt.vers new file mode 100644 index 0000000..5a617cc --- /dev/null +++ b/grub-core/lib/libgcrypt/src/libgcrypt.vers @@ -0,0 +1,111 @@ +# libgcrypt.vers - What symbols to export -*- std -*- +# Copyright (C) 2002, 2004, 2008 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +# NOTE: When adding new functions, please make sure to add them to +# visibility.h and libgcrypt.def as well. + +GCRYPT_1.2 { + global: + gcry_check_version; gcry_control; + gcry_set_allocation_handler; gcry_set_fatalerror_handler; + gcry_set_gettext_handler; gcry_set_log_handler; + gcry_set_outofcore_handler; gcry_set_progress_handler; + + gcry_err_code_from_errno; gcry_err_code_to_errno; + gcry_err_make_from_errno; gcry_error_from_errno; + gcry_strerror; gcry_strsource; + + gcry_free; gcry_malloc; gcry_malloc_secure; gcry_calloc; + gcry_calloc_secure; gcry_realloc; gcry_strdup; gcry_is_secure; + gcry_xcalloc; gcry_xcalloc_secure; gcry_xmalloc; + gcry_xmalloc_secure; gcry_xrealloc; gcry_xstrdup; + + gcry_md_algo_info; gcry_md_algo_name; gcry_md_close; + gcry_md_copy; gcry_md_ctl; gcry_md_enable; gcry_md_get; + gcry_md_get_algo; gcry_md_get_algo_dlen; gcry_md_hash_buffer; + gcry_md_info; gcry_md_is_enabled; gcry_md_is_secure; + gcry_md_list; gcry_md_map_name; gcry_md_open; gcry_md_read; + gcry_md_register; gcry_md_reset; gcry_md_setkey; + gcry_md_unregister; gcry_md_write; gcry_md_debug; + + gcry_cipher_algo_info; gcry_cipher_algo_name; gcry_cipher_close; + gcry_cipher_ctl; gcry_cipher_decrypt; gcry_cipher_encrypt; + gcry_cipher_get_algo_blklen; gcry_cipher_get_algo_keylen; + gcry_cipher_info; gcry_cipher_list; gcry_cipher_map_name; + gcry_cipher_mode_from_oid; gcry_cipher_open; + gcry_cipher_register; gcry_cipher_unregister; + gcry_cipher_setkey; gcry_cipher_setiv; gcry_cipher_setctr; + + gcry_pk_algo_info; gcry_pk_algo_name; gcry_pk_ctl; + gcry_pk_decrypt; gcry_pk_encrypt; gcry_pk_genkey; + gcry_pk_get_keygrip; gcry_pk_get_nbits; gcry_pk_list; + gcry_pk_map_name; gcry_pk_register; gcry_pk_sign; + gcry_pk_testkey; gcry_pk_unregister; gcry_pk_verify; + gcry_pk_get_curve; gcry_pk_get_param; + + gcry_ac_data_new; gcry_ac_data_destroy; gcry_ac_data_copy; + gcry_ac_data_length; gcry_ac_data_clear; gcry_ac_data_set; + gcry_ac_data_get_name; gcry_ac_data_get_index; gcry_ac_open; + gcry_ac_close; gcry_ac_key_init; gcry_ac_key_pair_generate; + gcry_ac_key_pair_extract; gcry_ac_key_data_get; gcry_ac_key_test; + gcry_ac_key_get_nbits; gcry_ac_key_get_grip; gcry_ac_key_destroy; + gcry_ac_key_pair_destroy; gcry_ac_data_encrypt; gcry_ac_data_decrypt; + gcry_ac_data_sign; gcry_ac_data_verify; gcry_ac_id_to_name; + gcry_ac_name_to_id; gcry_ac_list; gcry_ac_data_encode; + gcry_ac_data_decode; gcry_ac_mpi_to_os; gcry_ac_mpi_to_os_alloc; + gcry_ac_os_to_mpi; gcry_ac_data_encrypt_scheme; + gcry_ac_data_decrypt_scheme; + gcry_ac_data_sign_scheme; gcry_ac_data_verify_scheme; + gcry_ac_data_to_sexp; gcry_ac_data_from_sexp; + gcry_ac_io_init; gcry_ac_io_init_va; + + gcry_kdf_derive; + + gcry_prime_check; gcry_prime_generate; + gcry_prime_group_generator; gcry_prime_release_factors; + + gcry_random_add_bytes; gcry_random_bytes; gcry_random_bytes_secure; + gcry_randomize; gcry_create_nonce; + + gcry_sexp_alist; gcry_sexp_append; gcry_sexp_build; + gcry_sexp_build_array; gcry_sexp_cadr; gcry_sexp_canon_len; + gcry_sexp_car; gcry_sexp_cdr; gcry_sexp_cons; gcry_sexp_create; + gcry_sexp_dump; gcry_sexp_find_token; gcry_sexp_length; + gcry_sexp_new; gcry_sexp_nth; gcry_sexp_nth_data; + gcry_sexp_nth_mpi; gcry_sexp_prepend; gcry_sexp_release; + gcry_sexp_sprint; gcry_sexp_sscan; gcry_sexp_vlist; + gcry_sexp_nth_string; + + gcry_mpi_add; gcry_mpi_add_ui; gcry_mpi_addm; gcry_mpi_aprint; + gcry_mpi_clear_bit; gcry_mpi_clear_flag; gcry_mpi_clear_highbit; + gcry_mpi_cmp; gcry_mpi_cmp_ui; gcry_mpi_copy; gcry_mpi_div; + gcry_mpi_dump; gcry_mpi_gcd; gcry_mpi_get_flag; gcry_mpi_get_nbits; + gcry_mpi_get_opaque; gcry_mpi_invm; gcry_mpi_mod; gcry_mpi_mul; + gcry_mpi_mul_2exp; gcry_mpi_mul_ui; gcry_mpi_mulm; gcry_mpi_new; + gcry_mpi_powm; gcry_mpi_print; gcry_mpi_randomize; gcry_mpi_release; + gcry_mpi_rshift; gcry_mpi_scan; gcry_mpi_set; gcry_mpi_set_bit; + gcry_mpi_set_flag; gcry_mpi_set_highbit; gcry_mpi_set_opaque; + gcry_mpi_set_ui; gcry_mpi_snew; gcry_mpi_sub; gcry_mpi_sub_ui; + gcry_mpi_subm; gcry_mpi_swap; gcry_mpi_test_bit; + gcry_mpi_lshift; + + local: + *; + +}; diff --git a/grub-core/lib/libgcrypt/src/misc.c b/grub-core/lib/libgcrypt/src/misc.c new file mode 100644 index 0000000..17bd546 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/misc.c @@ -0,0 +1,298 @@ +/* misc.c + * Copyright (C) 1999, 2001, 2002, 2003, 2007, + * 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> + +#include "g10lib.h" +#include "secmem.h" + +static int verbosity_level = 0; + +static void (*fatal_error_handler)(void*,int, const char*) = NULL; +static void *fatal_error_handler_value = 0; +static void (*log_handler)(void*,int, const char*, va_list) = NULL; +static void *log_handler_value = 0; + +static const char *(*user_gettext_handler)( const char * ) = NULL; + +void +gcry_set_gettext_handler( const char *(*f)(const char*) ) +{ + user_gettext_handler = f; +} + + +const char * +_gcry_gettext( const char *key ) +{ + if( user_gettext_handler ) + return user_gettext_handler( key ); + /* FIXME: switch the domain to gnupg and restore later */ + return key; +} + +void +gcry_set_fatalerror_handler( void (*fnc)(void*,int, const char*), void *value) +{ + fatal_error_handler_value = value; + fatal_error_handler = fnc; +} + +static void +write2stderr( const char *s ) +{ + /* Dummy variable to silence gcc warning. */ + int res = write( 2, s, strlen(s) ); + (void) res; +} + +/* + * This function is called for fatal errors. A caller might want to + * set his own handler because this function simply calls abort(). + */ +void +_gcry_fatal_error (int rc, const char *text) +{ + if ( !text ) /* get a default text */ + text = gpg_strerror (rc); + + if (fatal_error_handler && !fips_mode () ) + fatal_error_handler (fatal_error_handler_value, rc, text); + + fips_signal_fatal_error (text); + write2stderr("\nFatal error: "); + write2stderr(text); + write2stderr("\n"); + _gcry_secmem_term (); + abort (); +} + +void +gcry_set_log_handler( void (*f)(void*,int, const char*, va_list ), + void *opaque ) +{ + log_handler = f; + log_handler_value = opaque; +} + +void +_gcry_set_log_verbosity( int level ) +{ + verbosity_level = level; +} + +int +_gcry_log_verbosity( int level ) +{ + return verbosity_level >= level; +} + +/**************** + * This is our log function which prints all log messages to stderr or + * using the function defined with gcry_set_log_handler(). + */ +static void +_gcry_logv( int level, const char *fmt, va_list arg_ptr ) +{ + if (log_handler) + log_handler (log_handler_value, level, fmt, arg_ptr); + else + { + switch (level) + { + case GCRY_LOG_CONT: break; + case GCRY_LOG_INFO: break; + case GCRY_LOG_WARN: break; + case GCRY_LOG_ERROR: break; + case GCRY_LOG_FATAL: fputs("Fatal: ",stderr ); break; + case GCRY_LOG_BUG: fputs("Ohhhh jeeee: ", stderr); break; + case GCRY_LOG_DEBUG: fputs("DBG: ", stderr ); break; + default: fprintf(stderr,"[Unknown log level %d]: ", level ); break; + } + vfprintf(stderr,fmt,arg_ptr) ; + } + + if ( level == GCRY_LOG_FATAL || level == GCRY_LOG_BUG ) + { + fips_signal_fatal_error ("internal error (fatal or bug)"); + _gcry_secmem_term (); + abort (); + } +} + + +void +_gcry_log( int level, const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + _gcry_logv( level, fmt, arg_ptr ); + va_end(arg_ptr); +} + + +#if defined(JNLIB_GCC_M_FUNCTION) || __STDC_VERSION__ >= 199901L +void +_gcry_bug( const char *file, int line, const char *func ) +{ + _gcry_log( GCRY_LOG_BUG, + ("... this is a bug (%s:%d:%s)\n"), file, line, func ); + abort(); /* never called, but it makes the compiler happy */ +} +void +_gcry_assert_failed (const char *expr, const char *file, int line, + const char *func) +{ + _gcry_log (GCRY_LOG_BUG, + ("Assertion `%s' failed (%s:%d:%s)\n"), expr, file, line, func ); + abort(); /* Never called, but it makes the compiler happy. */ +} +#else +void +_gcry_bug( const char *file, int line ) +{ + _gcry_log( GCRY_LOG_BUG, + _("you found a bug ... (%s:%d)\n"), file, line); + abort(); /* never called, but it makes the compiler happy */ +} +void +_gcry_assert_failed (const char *expr, const char *file, int line) +{ + _gcry_log (GCRY_LOG_BUG, + ("Assertion `%s' failed (%s:%d)\n"), expr, file, line); + abort(); /* Never called, but it makes the compiler happy. */ +} +#endif + +void +_gcry_log_info( const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + _gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr ); + va_end(arg_ptr); +} + +int +_gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... ) +{ + va_list arg_ptr; + + (void)fp; + va_start( arg_ptr, fmt ) ; + _gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr ); + va_end(arg_ptr); + return 0; +} + +void +_gcry_log_error( const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + _gcry_logv( GCRY_LOG_ERROR, fmt, arg_ptr ); + va_end(arg_ptr); +} + + +void +_gcry_log_fatal( const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + _gcry_logv( GCRY_LOG_FATAL, fmt, arg_ptr ); + va_end(arg_ptr); + abort(); /* never called, but it makes the compiler happy */ +} + +void +_gcry_log_bug( const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + _gcry_logv( GCRY_LOG_BUG, fmt, arg_ptr ); + va_end(arg_ptr); + abort(); /* never called, but it makes the compiler happy */ +} + +void +_gcry_log_debug( const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + _gcry_logv( GCRY_LOG_DEBUG, fmt, arg_ptr ); + va_end(arg_ptr); +} + + +void +_gcry_log_printf (const char *fmt, ...) +{ + va_list arg_ptr; + + if (fmt) + { + va_start( arg_ptr, fmt ) ; + _gcry_logv (GCRY_LOG_CONT, fmt, arg_ptr); + va_end(arg_ptr); + } +} + +/* Print a hexdump of BUFFER. With TEXT of NULL print just the raw + dump, with TEXT an empty string, print a trailing linefeed, + otherwise print an entire debug line. */ +void +_gcry_log_printhex (const char *text, const void *buffer, size_t length) +{ + if (text && *text) + log_debug ("%s ", text); + if (length) + { + const unsigned char *p = buffer; + log_printf ("%02X", *p); + for (length--, p++; length--; p++) + log_printf (" %02X", *p); + } + if (text) + log_printf ("\n"); +} + + +void +_gcry_burn_stack (int bytes) +{ + char buf[64]; + + wipememory (buf, sizeof buf); + bytes -= sizeof buf; + if (bytes > 0) + _gcry_burn_stack (bytes); +} diff --git a/grub-core/lib/libgcrypt/src/missing-string.c b/grub-core/lib/libgcrypt/src/missing-string.c new file mode 100644 index 0000000..4756c00 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/missing-string.c @@ -0,0 +1,54 @@ +/* missing-string.c - missing string utilities + * Copyright (C) 1994, 1998, 1999, 2000, 2001, + * 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "g10lib.h" + + +#ifndef HAVE_STPCPY +char * +stpcpy(char *a,const char *b) +{ + while( *b ) + *a++ = *b++; + *a = 0; + + return (char*)a; +} +#endif + + +#ifndef HAVE_STRCASECMP +int +strcasecmp( const char *a, const char *b ) +{ + for( ; *a && *b; a++, b++ ) { + if( *a != *b && toupper(*a) != toupper(*b) ) + break; + } + return *(const byte*)a - *(const byte*)b; +} +#endif diff --git a/grub-core/lib/libgcrypt/src/module.c b/grub-core/lib/libgcrypt/src/module.c new file mode 100644 index 0000000..32f668d --- /dev/null +++ b/grub-core/lib/libgcrypt/src/module.c @@ -0,0 +1,212 @@ +/* module.c - Module management for libgcrypt. + * Copyright (C) 2003, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <errno.h> +#include "g10lib.h" + +/* Please match these numbers with the allocated algorithm + numbers. */ +#define MODULE_ID_MIN 600 +#define MODULE_ID_LAST 65500 +#define MODULE_ID_USER GCRY_MODULE_ID_USER +#define MODULE_ID_USER_LAST GCRY_MODULE_ID_USER_LAST + +#if MODULE_ID_MIN >= MODULE_ID_USER +#error Need to implement a different search strategy +#endif + +/* Internal function. Generate a new, unique module ID for a module + that should be inserted into the module chain starting at + MODULES. */ +static gcry_err_code_t +_gcry_module_id_new (gcry_module_t modules, unsigned int *id_new) +{ + unsigned int mod_id; + gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_module_t module; + + /* Search for unused ID. */ + for (mod_id = MODULE_ID_MIN; mod_id < MODULE_ID_LAST; mod_id++) + { + if (mod_id == MODULE_ID_USER) + { + mod_id = MODULE_ID_USER_LAST; + continue; + } + + /* Search for a module with the current ID. */ + for (module = modules; module; module = module->next) + if (mod_id == module->mod_id) + break; + + if (! module) + /* None found -> the ID is available for use. */ + break; + } + + if (mod_id < MODULE_ID_LAST) + /* Done. */ + *id_new = mod_id; + else + /* No free ID found. */ + err = GPG_ERR_INTERNAL; + + return err; +} + +/* Add a module specification to the list ENTRIES. The new module has + it's use-counter set to one. */ +gcry_err_code_t +_gcry_module_add (gcry_module_t *entries, unsigned int mod_id, + void *spec, void *extraspec, gcry_module_t *module) +{ + gcry_err_code_t err = 0; + gcry_module_t entry; + + if (! mod_id) + err = _gcry_module_id_new (*entries, &mod_id); + + if (! err) + { + entry = gcry_malloc (sizeof (struct gcry_module)); + if (! entry) + err = gpg_err_code_from_errno (errno); + } + + if (! err) + { + /* Fill new module entry. */ + entry->flags = 0; + entry->counter = 1; + entry->spec = spec; + entry->extraspec = extraspec; + entry->mod_id = mod_id; + + /* Link it into the list. */ + entry->next = *entries; + entry->prevp = entries; + if (*entries) + (*entries)->prevp = &entry->next; + *entries = entry; + + /* And give it to the caller. */ + if (module) + *module = entry; + } + return err; +} + +/* Internal function. Unlink CIPHER_ENTRY from the list of registered + ciphers and destroy it. */ +static void +_gcry_module_drop (gcry_module_t entry) +{ + *entry->prevp = entry->next; + if (entry->next) + entry->next->prevp = entry->prevp; + + gcry_free (entry); +} + +/* Lookup a module specification by it's ID. After a successful + lookup, the module has it's resource counter incremented. */ +gcry_module_t +_gcry_module_lookup_id (gcry_module_t entries, unsigned int mod_id) +{ + gcry_module_t entry; + + for (entry = entries; entry; entry = entry->next) + if (entry->mod_id == mod_id) + { + entry->counter++; + break; + } + + return entry; +} + +/* Lookup a module specification. After a successful lookup, the + module has it's resource counter incremented. FUNC is a function + provided by the caller, which is responsible for identifying the + wanted module. */ +gcry_module_t +_gcry_module_lookup (gcry_module_t entries, void *data, + gcry_module_lookup_t func) +{ + gcry_module_t entry; + + for (entry = entries; entry; entry = entry->next) + if ((*func) (entry->spec, data)) + { + entry->counter++; + break; + } + + return entry; +} + +/* Release a module. In case the use-counter reaches zero, destroy + the module. Passing MODULE as NULL is a dummy operation (similar + to free()). */ +void +_gcry_module_release (gcry_module_t module) +{ + if (module && ! --module->counter) + _gcry_module_drop (module); +} + +/* Add a reference to a module. */ +void +_gcry_module_use (gcry_module_t module) +{ + ++module->counter; +} + +/* If LIST is zero, write the number of modules identified by MODULES + to LIST_LENGTH and return. If LIST is non-zero, the first + *LIST_LENGTH algorithm IDs are stored in LIST, which must be of + according size. In case there are less cipher modules than + *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */ +gcry_err_code_t +_gcry_module_list (gcry_module_t modules, + int *list, int *list_length) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_module_t module; + int length, i; + + for (module = modules, length = 0; module; module = module->next, length++); + + if (list) + { + if (length > *list_length) + length = *list_length; + + for (module = modules, i = 0; i < length; module = module->next, i++) + list[i] = module->mod_id; + + if (length < *list_length) + *list_length = length; + } + else + *list_length = length; + + return err; +} diff --git a/grub-core/lib/libgcrypt/src/mpi.h b/grub-core/lib/libgcrypt/src/mpi.h new file mode 100644 index 0000000..5883196 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/mpi.h @@ -0,0 +1,266 @@ +/* mpi.h - Multi Precision Integers + * Copyright (C) 1994, 1996, 1998, + * 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + */ + +#ifndef G10_MPI_H +#define G10_MPI_H + +#include <config.h> +#include <stdio.h> +#include <string.h> + +#include "types.h" +#include "../mpi/mpi-asm-defs.h" + +#include "g10lib.h" + +#ifndef _GCRYPT_IN_LIBGCRYPT +#error this file should only be used inside libgcrypt +#endif + +#ifndef BITS_PER_MPI_LIMB +#if BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_INT + typedef unsigned int mpi_limb_t; + typedef signed int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG + typedef unsigned long int mpi_limb_t; + typedef signed long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG_LONG + typedef unsigned long long int mpi_limb_t; + typedef signed long long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_SHORT + typedef unsigned short int mpi_limb_t; + typedef signed short int mpi_limb_signed_t; +#else +#error BYTES_PER_MPI_LIMB does not match any C type +#endif +#define BITS_PER_MPI_LIMB (8*BYTES_PER_MPI_LIMB) +#endif /*BITS_PER_MPI_LIMB*/ + +#define DBG_MPI _gcry_get_debug_flag( 2 ); + +struct gcry_mpi +{ + int alloced; /* Array size (# of allocated limbs). */ + int nlimbs; /* Number of valid limbs. */ + int sign; /* Indicates a negative number and is also used + for opaque MPIs to store the length. */ + unsigned int flags; /* Bit 0: Array to be allocated in secure memory space.*/ + /* Bit 2: the limb is a pointer to some m_alloced data.*/ + mpi_limb_t *d; /* Array with the limbs */ +}; + +#define MPI_NULL NULL + +#define mpi_get_nlimbs(a) ((a)->nlimbs) +#define mpi_is_neg(a) ((a)->sign) + +/*-- mpiutil.c --*/ + +#ifdef M_DEBUG +# define mpi_alloc(n) _gcry_mpi_debug_alloc((n), M_DBGINFO( __LINE__ ) ) +# define mpi_alloc_secure(n) _gcry_mpi_debug_alloc_secure((n), M_DBGINFO( __LINE__ ) ) +# define mpi_free(a) _gcry_mpi_debug_free((a), M_DBGINFO(__LINE__) ) +# define mpi_resize(a,b) _gcry_mpi_debug_resize((a),(b), M_DBGINFO(__LINE__) ) +# define mpi_copy(a) _gcry_mpi_debug_copy((a), M_DBGINFO(__LINE__) ) + gcry_mpi_t _gcry_mpi_debug_alloc( unsigned nlimbs, const char *info ); + gcry_mpi_t _gcry_mpi_debug_alloc_secure( unsigned nlimbs, const char *info ); + void _gcry_mpi_debug_free( gcry_mpi_t a, const char *info ); + void _gcry_mpi_debug_resize( gcry_mpi_t a, unsigned nlimbs, const char *info ); + gcry_mpi_t _gcry_mpi_debug_copy( gcry_mpi_t a, const char *info ); +#else +# define mpi_alloc(n) _gcry_mpi_alloc((n) ) +# define mpi_alloc_secure(n) _gcry_mpi_alloc_secure((n) ) +# define mpi_free(a) _gcry_mpi_free((a) ) +# define mpi_resize(a,b) _gcry_mpi_resize((a),(b)) +# define mpi_copy(a) _gcry_mpi_copy((a)) + gcry_mpi_t _gcry_mpi_alloc( unsigned nlimbs ); + gcry_mpi_t _gcry_mpi_alloc_secure( unsigned nlimbs ); + void _gcry_mpi_free( gcry_mpi_t a ); + void _gcry_mpi_resize( gcry_mpi_t a, unsigned nlimbs ); + gcry_mpi_t _gcry_mpi_copy( gcry_mpi_t a ); +#endif + +#define gcry_mpi_copy _gcry_mpi_copy + +#define mpi_is_opaque(a) ((a) && ((a)->flags&4)) +#define mpi_is_secure(a) ((a) && ((a)->flags&1)) +#define mpi_clear(a) _gcry_mpi_clear ((a)) +#define mpi_alloc_like(a) _gcry_mpi_alloc_like((a)) +#define mpi_set(a,b) gcry_mpi_set ((a),(b)) +#define mpi_set_ui(a,b) gcry_mpi_set_ui ((a),(b)) +#define mpi_get_ui(a,b) _gcry_mpi_get_ui ((a),(b)) +#define mpi_alloc_set_ui(a) _gcry_mpi_alloc_set_ui ((a)) +#define mpi_m_check(a) _gcry_mpi_m_check ((a)) +#define mpi_swap(a,b) _gcry_mpi_swap ((a),(b)) +#define mpi_new(n) _gcry_mpi_new ((n)) +#define mpi_snew(n) _gcry_mpi_snew ((n)) + +void _gcry_mpi_clear( gcry_mpi_t a ); +gcry_mpi_t _gcry_mpi_alloc_like( gcry_mpi_t a ); +gcry_mpi_t _gcry_mpi_alloc_set_ui( unsigned long u); +gcry_err_code_t _gcry_mpi_get_ui (gcry_mpi_t w, ulong *u); +gcry_err_code_t gcry_mpi_get_ui (gcry_mpi_t w, ulong *u); +void _gcry_mpi_m_check( gcry_mpi_t a ); +void _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b); +gcry_mpi_t _gcry_mpi_new (unsigned int nbits); +gcry_mpi_t _gcry_mpi_snew (unsigned int nbits); + +/*-- mpicoder.c --*/ +void _gcry_log_mpidump( const char *text, gcry_mpi_t a ); +u32 _gcry_mpi_get_keyid( gcry_mpi_t a, u32 *keyid ); +byte *_gcry_mpi_get_buffer( gcry_mpi_t a, unsigned *nbytes, int *sign ); +byte *_gcry_mpi_get_secure_buffer( gcry_mpi_t a, unsigned *nbytes, int *sign ); +void _gcry_mpi_set_buffer ( gcry_mpi_t a, const void *buffer, + unsigned int nbytes, int sign ); + +#define log_mpidump _gcry_log_mpidump + +/*-- mpi-add.c --*/ +#define mpi_add_ui(w,u,v) gcry_mpi_add_ui((w),(u),(v)) +#define mpi_add(w,u,v) gcry_mpi_add ((w),(u),(v)) +#define mpi_addm(w,u,v,m) gcry_mpi_addm ((w),(u),(v),(m)) +#define mpi_sub_ui(w,u,v) gcry_mpi_sub_ui ((w),(u),(v)) +#define mpi_sub(w,u,v) gcry_mpi_sub ((w),(u),(v)) +#define mpi_subm(w,u,v,m) gcry_mpi_subm ((w),(u),(v),(m)) + + +/*-- mpi-mul.c --*/ +#define mpi_mul_ui(w,u,v) gcry_mpi_mul_ui ((w),(u),(v)) +#define mpi_mul_2exp(w,u,v) gcry_mpi_mul_2exp ((w),(u),(v)) +#define mpi_mul(w,u,v) gcry_mpi_mul ((w),(u),(v)) +#define mpi_mulm(w,u,v,m) gcry_mpi_mulm ((w),(u),(v),(m)) + + +/*-- mpi-div.c --*/ +#define mpi_fdiv_r_ui(a,b,c) _gcry_mpi_fdiv_r_ui((a),(b),(c)) +#define mpi_fdiv_r(a,b,c) _gcry_mpi_fdiv_r((a),(b),(c)) +#define mpi_fdiv_q(a,b,c) _gcry_mpi_fdiv_q((a),(b),(c)) +#define mpi_fdiv_qr(a,b,c,d) _gcry_mpi_fdiv_qr((a),(b),(c),(d)) +#define mpi_tdiv_r(a,b,c) _gcry_mpi_tdiv_r((a),(b),(c)) +#define mpi_tdiv_qr(a,b,c,d) _gcry_mpi_tdiv_qr((a),(b),(c),(d)) +#define mpi_tdiv_q_2exp(a,b,c) _gcry_mpi_tdiv_q_2exp((a),(b),(c)) +#define mpi_divisible_ui(a,b) _gcry_mpi_divisible_ui((a),(b)) + +ulong _gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor ); +void _gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor ); +void _gcry_mpi_fdiv_q( gcry_mpi_t quot, gcry_mpi_t dividend, gcry_mpi_t divisor ); +void _gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor ); +void _gcry_mpi_tdiv_r( gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den); +void _gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den); +void _gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned count ); +int _gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor ); + + +/*-- mpi-mod.c --*/ +#define mpi_mod(r,a,m) _gcry_mpi_mod ((r), (a), (m)) +#define mpi_barrett_init(m,f) _gcry_mpi_barrett_init ((m),(f)) +#define mpi_barrett_free(c) _gcry_mpi_barrett_free ((c)) +#define mpi_mod_barrett(r,a,c) _gcry_mpi_mod_barrett ((r), (a), (c)) +#define mpi_mul_barrett(r,u,v,c) _gcry_mpi_mul_barrett ((r), (u), (v), (c)) + +void _gcry_mpi_mod (gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor); + +/* Context used with Barrett reduction. */ +struct barrett_ctx_s; +typedef struct barrett_ctx_s *mpi_barrett_t; + +mpi_barrett_t _gcry_mpi_barrett_init (gcry_mpi_t m, int copy); +void _gcry_mpi_barrett_free (mpi_barrett_t ctx); +void _gcry_mpi_mod_barrett (gcry_mpi_t r, gcry_mpi_t x, mpi_barrett_t ctx); +void _gcry_mpi_mul_barrett (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, + mpi_barrett_t ctx); + + + +/*-- mpi-gcd.c --*/ + +/*-- mpi-mpow.c --*/ +#define mpi_mulpowm(a,b,c,d) _gcry_mpi_mulpowm ((a),(b),(c),(d)) +void _gcry_mpi_mulpowm( gcry_mpi_t res, gcry_mpi_t *basearray, gcry_mpi_t *exparray, gcry_mpi_t mod); + +/*-- mpi-cmp.c --*/ +#define mpi_cmp_ui(a,b) gcry_mpi_cmp_ui ((a),(b)) +#define mpi_cmp(a,b) gcry_mpi_cmp ((a),(b)) +int gcry_mpi_cmp_ui( gcry_mpi_t u, ulong v ); +int gcry_mpi_cmp( gcry_mpi_t u, gcry_mpi_t v ); + +/*-- mpi-scan.c --*/ +#define mpi_trailing_zeros(a) _gcry_mpi_trailing_zeros ((a)) +int _gcry_mpi_getbyte( gcry_mpi_t a, unsigned idx ); +void _gcry_mpi_putbyte( gcry_mpi_t a, unsigned idx, int value ); +unsigned _gcry_mpi_trailing_zeros( gcry_mpi_t a ); + +/*-- mpi-bit.c --*/ +#define mpi_normalize(a) _gcry_mpi_normalize ((a)) +#define mpi_get_nbits(a) gcry_mpi_get_nbits ((a)) +#define mpi_test_bit(a,b) gcry_mpi_test_bit ((a),(b)) +#define mpi_set_bit(a,b) gcry_mpi_set_bit ((a),(b)) +#define mpi_set_highbit(a,b) gcry_mpi_set_highbit ((a),(b)) +#define mpi_clear_bit(a,b) gcry_mpi_clear_bit ((a),(b)) +#define mpi_clear_highbit(a,b) gcry_mpi_clear_highbit ((a),(b)) +#define mpi_rshift(a,b,c) gcry_mpi_rshift ((a),(b),(c)) +#define mpi_lshift(a,b,c) gcry_mpi_lshift ((a),(b),(c)) + +void _gcry_mpi_normalize( gcry_mpi_t a ); + +/*-- mpi-inv.c --*/ +#define mpi_invm(a,b,c) gcry_mpi_invm ((a),(b),(c)) + +/*-- ec.c --*/ + +/* Object to represent a point in projective coordinates. */ +struct mpi_point_s; +typedef struct mpi_point_s mpi_point_t; +struct mpi_point_s +{ + gcry_mpi_t x; + gcry_mpi_t y; + gcry_mpi_t z; +}; + +/* Context used with elliptic curve functions. */ +struct mpi_ec_ctx_s; +typedef struct mpi_ec_ctx_s *mpi_ec_t; + +void _gcry_mpi_ec_point_init (mpi_point_t *p); +void _gcry_mpi_ec_point_free (mpi_point_t *p); +mpi_ec_t _gcry_mpi_ec_init (gcry_mpi_t p, gcry_mpi_t a); +void _gcry_mpi_ec_free (mpi_ec_t ctx); +int _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t *point, + mpi_ec_t ctx); +void _gcry_mpi_ec_dup_point (mpi_point_t *result, + mpi_point_t *point, mpi_ec_t ctx); +void _gcry_mpi_ec_add_points (mpi_point_t *result, + mpi_point_t *p1, mpi_point_t *p2, + mpi_ec_t ctx); +void _gcry_mpi_ec_mul_point (mpi_point_t *result, + gcry_mpi_t scalar, mpi_point_t *point, + mpi_ec_t ctx); + + + +#endif /*G10_MPI_H*/ diff --git a/grub-core/lib/libgcrypt/src/secmem.c b/grub-core/lib/libgcrypt/src/secmem.c new file mode 100644 index 0000000..2beb234 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/secmem.c @@ -0,0 +1,696 @@ +/* secmem.c - memory allocation from a secure heap + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003, 2007 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <stdarg.h> +#include <unistd.h> +#include <stddef.h> + +#if defined(HAVE_MLOCK) || defined(HAVE_MMAP) +#include <sys/mman.h> +#include <sys/types.h> +#include <fcntl.h> +#ifdef USE_CAPABILITIES +#include <sys/capability.h> +#endif +#endif + +#include "ath.h" +#include "g10lib.h" +#include "secmem.h" + +#if defined (MAP_ANON) && ! defined (MAP_ANONYMOUS) +#define MAP_ANONYMOUS MAP_ANON +#endif + +#define MINIMUM_POOL_SIZE 16384 +#define STANDARD_POOL_SIZE 32768 +#define DEFAULT_PAGE_SIZE 4096 + +typedef struct memblock +{ + unsigned size; /* Size of the memory available to the + user. */ + int flags; /* See below. */ + PROPERLY_ALIGNED_TYPE aligned; +} memblock_t; + +/* This flag specifies that the memory block is in use. */ +#define MB_FLAG_ACTIVE (1 << 0) + +/* The pool of secure memory. */ +static void *pool; + +/* Size of POOL in bytes. */ +static size_t pool_size; + +/* True, if the memory pool is ready for use. May be checked in an + atexit function. */ +static volatile int pool_okay; + +/* True, if the memory pool is mmapped. */ +static volatile int pool_is_mmapped; + +/* FIXME? */ +static int disable_secmem; +static int show_warning; +static int not_locked; +static int no_warning; +static int suspend_warning; + +/* Stats. */ +static unsigned int cur_alloced, cur_blocks; + +/* Lock protecting accesses to the memory pool. */ +static ath_mutex_t secmem_lock; + +/* Convenient macros. */ +#define SECMEM_LOCK ath_mutex_lock (&secmem_lock) +#define SECMEM_UNLOCK ath_mutex_unlock (&secmem_lock) + +/* The size of the memblock structure; this does not include the + memory that is available to the user. */ +#define BLOCK_HEAD_SIZE \ + offsetof (memblock_t, aligned) + +/* Convert an address into the according memory block structure. */ +#define ADDR_TO_BLOCK(addr) \ + (memblock_t *) ((char *) addr - BLOCK_HEAD_SIZE) + +/* Check whether P points into the pool. */ +static int +ptr_into_pool_p (const void *p) +{ + /* We need to convert pointers to addresses. This is required by + C-99 6.5.8 to avoid undefined behaviour. Using size_t is at + least only implementation defined. See also + http://lists.gnupg.org/pipermail/gcrypt-devel/2007-February/001102.html + */ + size_t p_addr = (size_t)p; + size_t pool_addr = (size_t)pool; + + return p_addr >= pool_addr && p_addr < pool_addr+pool_size; +} + +/* Update the stats. */ +static void +stats_update (size_t add, size_t sub) +{ + if (add) + { + cur_alloced += add; + cur_blocks++; + } + if (sub) + { + cur_alloced -= sub; + cur_blocks--; + } +} + +/* Return the block following MB or NULL, if MB is the last block. */ +static memblock_t * +mb_get_next (memblock_t *mb) +{ + memblock_t *mb_next; + + mb_next = (memblock_t *) ((char *) mb + BLOCK_HEAD_SIZE + mb->size); + + if (! ptr_into_pool_p (mb_next)) + mb_next = NULL; + + return mb_next; +} + +/* Return the block preceding MB or NULL, if MB is the first + block. */ +static memblock_t * +mb_get_prev (memblock_t *mb) +{ + memblock_t *mb_prev, *mb_next; + + if (mb == pool) + mb_prev = NULL; + else + { + mb_prev = (memblock_t *) pool; + while (1) + { + mb_next = mb_get_next (mb_prev); + if (mb_next == mb) + break; + else + mb_prev = mb_next; + } + } + + return mb_prev; +} + +/* If the preceding block of MB and/or the following block of MB + exist and are not active, merge them to form a bigger block. */ +static void +mb_merge (memblock_t *mb) +{ + memblock_t *mb_prev, *mb_next; + + mb_prev = mb_get_prev (mb); + mb_next = mb_get_next (mb); + + if (mb_prev && (! (mb_prev->flags & MB_FLAG_ACTIVE))) + { + mb_prev->size += BLOCK_HEAD_SIZE + mb->size; + mb = mb_prev; + } + if (mb_next && (! (mb_next->flags & MB_FLAG_ACTIVE))) + mb->size += BLOCK_HEAD_SIZE + mb_next->size; +} + +/* Return a new block, which can hold SIZE bytes. */ +static memblock_t * +mb_get_new (memblock_t *block, size_t size) +{ + memblock_t *mb, *mb_split; + + for (mb = block; ptr_into_pool_p (mb); mb = mb_get_next (mb)) + if (! (mb->flags & MB_FLAG_ACTIVE) && mb->size >= size) + { + /* Found a free block. */ + mb->flags |= MB_FLAG_ACTIVE; + + if (mb->size - size > BLOCK_HEAD_SIZE) + { + /* Split block. */ + + mb_split = (memblock_t *) (((char *) mb) + BLOCK_HEAD_SIZE + size); + mb_split->size = mb->size - size - BLOCK_HEAD_SIZE; + mb_split->flags = 0; + + mb->size = size; + + mb_merge (mb_split); + + } + + break; + } + + if (! ptr_into_pool_p (mb)) + { + gpg_err_set_errno (ENOMEM); + mb = NULL; + } + + return mb; +} + +/* Print a warning message. */ +static void +print_warn (void) +{ + if (!no_warning) + log_info (_("Warning: using insecure memory!\n")); +} + +/* Lock the memory pages into core and drop privileges. */ +static void +lock_pool (void *p, size_t n) +{ +#if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK) + int err; + + cap_set_proc (cap_from_text ("cap_ipc_lock+ep")); + err = mlock (p, n); + if (err && errno) + err = errno; + cap_set_proc (cap_from_text ("cap_ipc_lock+p")); + + if (err) + { + if (errno != EPERM +#ifdef EAGAIN /* OpenBSD returns this */ + && errno != EAGAIN +#endif +#ifdef ENOSYS /* Some SCOs return this (function not implemented) */ + && errno != ENOSYS +#endif +#ifdef ENOMEM /* Linux might return this. */ + && errno != ENOMEM +#endif + ) + log_error ("can't lock memory: %s\n", strerror (err)); + show_warning = 1; + not_locked = 1; + } + +#elif defined(HAVE_MLOCK) + uid_t uid; + int err; + + uid = getuid (); + +#ifdef HAVE_BROKEN_MLOCK + /* Under HP/UX mlock segfaults if called by non-root. Note, we have + noch checked whether mlock does really work under AIX where we + also detected a broken nlock. Note further, that using plock () + is not a good idea under AIX. */ + if (uid) + { + errno = EPERM; + err = errno; + } + else + { + err = mlock (p, n); + if (err && errno) + err = errno; + } +#else /* !HAVE_BROKEN_MLOCK */ + err = mlock (p, n); + if (err && errno) + err = errno; +#endif /* !HAVE_BROKEN_MLOCK */ + + if (uid && ! geteuid ()) + { + /* check that we really dropped the privs. + * Note: setuid(0) should always fail */ + if (setuid (uid) || getuid () != geteuid () || !setuid (0)) + log_fatal ("failed to reset uid: %s\n", strerror (errno)); + } + + if (err) + { + if (errno != EPERM +#ifdef EAGAIN /* OpenBSD returns this. */ + && errno != EAGAIN +#endif +#ifdef ENOSYS /* Some SCOs return this (function not implemented). */ + && errno != ENOSYS +#endif +#ifdef ENOMEM /* Linux might return this. */ + && errno != ENOMEM +#endif + ) + log_error ("can't lock memory: %s\n", strerror (err)); + show_warning = 1; + not_locked = 1; + } + +#elif defined ( __QNX__ ) + /* QNX does not page at all, so the whole secure memory stuff does + * not make much sense. However it is still of use because it + * wipes out the memory on a free(). + * Therefore it is sufficient to suppress the warning. */ + (void)p; + (void)n; +#elif defined (HAVE_DOSISH_SYSTEM) || defined (__CYGWIN__) + /* It does not make sense to print such a warning, given the fact that + * this whole Windows !@#$% and their user base are inherently insecure. */ + (void)p; + (void)n; +#elif defined (__riscos__) + /* No virtual memory on RISC OS, so no pages are swapped to disc, + * besides we don't have mmap, so we don't use it! ;-) + * But don't complain, as explained above. */ + (void)p; + (void)n; +#else + (void)p; + (void)n; + log_info ("Please note that you don't have secure memory on this system\n"); +#endif +} + +/* Initialize POOL. */ +static void +init_pool (size_t n) +{ + size_t pgsize; + long int pgsize_val; + memblock_t *mb; + + pool_size = n; + + if (disable_secmem) + log_bug ("secure memory is disabled"); + +#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) + pgsize_val = sysconf (_SC_PAGESIZE); +#elif defined(HAVE_GETPAGESIZE) + pgsize_val = getpagesize (); +#else + pgsize_val = -1; +#endif + pgsize = (pgsize_val != -1 && pgsize_val > 0)? pgsize_val:DEFAULT_PAGE_SIZE; + + +#if HAVE_MMAP + pool_size = (pool_size + pgsize - 1) & ~(pgsize - 1); +#ifdef MAP_ANONYMOUS + pool = mmap (0, pool_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +#else /* map /dev/zero instead */ + { + int fd; + + fd = open ("/dev/zero", O_RDWR); + if (fd == -1) + { + log_error ("can't open /dev/zero: %s\n", strerror (errno)); + pool = (void *) -1; + } + else + { + pool = mmap (0, pool_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + close (fd); + } + } +#endif + if (pool == (void *) -1) + log_info ("can't mmap pool of %u bytes: %s - using malloc\n", + (unsigned) pool_size, strerror (errno)); + else + { + pool_is_mmapped = 1; + pool_okay = 1; + } + +#endif + if (!pool_okay) + { + pool = malloc (pool_size); + if (!pool) + log_fatal ("can't allocate memory pool of %u bytes\n", + (unsigned) pool_size); + else + pool_okay = 1; + } + + /* Initialize first memory block. */ + mb = (memblock_t *) pool; + mb->size = pool_size; + mb->flags = 0; +} + +void +_gcry_secmem_set_flags (unsigned flags) +{ + int was_susp; + + SECMEM_LOCK; + + was_susp = suspend_warning; + no_warning = flags & GCRY_SECMEM_FLAG_NO_WARNING; + suspend_warning = flags & GCRY_SECMEM_FLAG_SUSPEND_WARNING; + + /* and now issue the warning if it is not longer suspended */ + if (was_susp && !suspend_warning && show_warning) + { + show_warning = 0; + print_warn (); + } + + SECMEM_UNLOCK; +} + +unsigned int +_gcry_secmem_get_flags (void) +{ + unsigned flags; + + SECMEM_LOCK; + + flags = no_warning ? GCRY_SECMEM_FLAG_NO_WARNING : 0; + flags |= suspend_warning ? GCRY_SECMEM_FLAG_SUSPEND_WARNING : 0; + flags |= not_locked ? GCRY_SECMEM_FLAG_NOT_LOCKED : 0; + + SECMEM_UNLOCK; + + return flags; +} + + +/* See _gcry_secmem_init. This function is expected to be called with + the secmem lock held. */ +static void +secmem_init (size_t n) +{ + if (!n) + { +#ifdef USE_CAPABILITIES + /* drop all capabilities */ + cap_set_proc (cap_from_text ("all-eip")); + +#elif !defined(HAVE_DOSISH_SYSTEM) + uid_t uid; + + disable_secmem = 1; + uid = getuid (); + if (uid != geteuid ()) + { + if (setuid (uid) || getuid () != geteuid () || !setuid (0)) + log_fatal ("failed to drop setuid\n"); + } +#endif + } + else + { + if (n < MINIMUM_POOL_SIZE) + n = MINIMUM_POOL_SIZE; + if (! pool_okay) + { + init_pool (n); + lock_pool (pool, n); + } + else + log_error ("Oops, secure memory pool already initialized\n"); + } +} + + + +/* Initialize the secure memory system. If running with the necessary + privileges, the secure memory pool will be locked into the core in + order to prevent page-outs of the data. Furthermore allocated + secure memory will be wiped out when released. */ +void +_gcry_secmem_init (size_t n) +{ + SECMEM_LOCK; + + secmem_init (n); + + SECMEM_UNLOCK; +} + + +static void * +_gcry_secmem_malloc_internal (size_t size) +{ + memblock_t *mb; + + if (!pool_okay) + { + /* Try to initialize the pool if the user forgot about it. */ + secmem_init (STANDARD_POOL_SIZE); + if (!pool_okay) + { + log_info (_("operation is not possible without " + "initialized secure memory\n")); + gpg_err_set_errno (ENOMEM); + return NULL; + } + } + if (not_locked && fips_mode ()) + { + log_info (_("secure memory pool is not locked while in FIPS mode\n")); + gpg_err_set_errno (ENOMEM); + return NULL; + } + if (show_warning && !suspend_warning) + { + show_warning = 0; + print_warn (); + } + + /* Blocks are always a multiple of 32. */ + size = ((size + 31) / 32) * 32; + + mb = mb_get_new ((memblock_t *) pool, size); + if (mb) + stats_update (size, 0); + + return mb ? &mb->aligned.c : NULL; +} + +void * +_gcry_secmem_malloc (size_t size) +{ + void *p; + + SECMEM_LOCK; + p = _gcry_secmem_malloc_internal (size); + SECMEM_UNLOCK; + + return p; +} + +static void +_gcry_secmem_free_internal (void *a) +{ + memblock_t *mb; + int size; + + if (!a) + return; + + mb = ADDR_TO_BLOCK (a); + size = mb->size; + + /* This does not make much sense: probably this memory is held in the + * cache. We do it anyway: */ +#define MB_WIPE_OUT(byte) \ + wipememory2 ((memblock_t *) ((char *) mb + BLOCK_HEAD_SIZE), (byte), size); + + MB_WIPE_OUT (0xff); + MB_WIPE_OUT (0xaa); + MB_WIPE_OUT (0x55); + MB_WIPE_OUT (0x00); + + stats_update (0, size); + + mb->flags &= ~MB_FLAG_ACTIVE; + + /* Update stats. */ + + mb_merge (mb); +} + +/* Wipe out and release memory. */ +void +_gcry_secmem_free (void *a) +{ + SECMEM_LOCK; + _gcry_secmem_free_internal (a); + SECMEM_UNLOCK; +} + +/* Realloc memory. */ +void * +_gcry_secmem_realloc (void *p, size_t newsize) +{ + memblock_t *mb; + size_t size; + void *a; + + SECMEM_LOCK; + + mb = (memblock_t *) ((char *) p - ((size_t) &((memblock_t *) 0)->aligned.c)); + size = mb->size; + if (newsize < size) + { + /* It is easier to not shrink the memory. */ + a = p; + } + else + { + a = _gcry_secmem_malloc_internal (newsize); + if (a) + { + memcpy (a, p, size); + memset ((char *) a + size, 0, newsize - size); + _gcry_secmem_free_internal (p); + } + } + + SECMEM_UNLOCK; + + return a; +} + + +/* Return true if P points into the secure memory area. */ +int +_gcry_private_is_secure (const void *p) +{ + return pool_okay && ptr_into_pool_p (p); +} + + +/**************** + * Warning: This code might be called by an interrupt handler + * and frankly, there should really be such a handler, + * to make sure that the memory is wiped out. + * We hope that the OS wipes out mlocked memory after + * receiving a SIGKILL - it really should do so, otherwise + * there is no chance to get the secure memory cleaned. + */ +void +_gcry_secmem_term () +{ + if (!pool_okay) + return; + + wipememory2 (pool, 0xff, pool_size); + wipememory2 (pool, 0xaa, pool_size); + wipememory2 (pool, 0x55, pool_size); + wipememory2 (pool, 0x00, pool_size); +#if HAVE_MMAP + if (pool_is_mmapped) + munmap (pool, pool_size); +#endif + pool = NULL; + pool_okay = 0; + pool_size = 0; + not_locked = 0; +} + + +void +_gcry_secmem_dump_stats () +{ +#if 1 + SECMEM_LOCK; + + if (pool_okay) + log_info ("secmem usage: %u/%lu bytes in %u blocks\n", + cur_alloced, (unsigned long)pool_size, cur_blocks); + SECMEM_UNLOCK; +#else + memblock_t *mb; + int i; + + SECMEM_LOCK; + + for (i = 0, mb = (memblock_t *) pool; + ptr_into_pool_p (mb); + mb = mb_get_next (mb), i++) + log_info ("SECMEM: [%s] block: %i; size: %i\n", + (mb->flags & MB_FLAG_ACTIVE) ? "used" : "free", + i, + mb->size); + SECMEM_UNLOCK; +#endif +} diff --git a/grub-core/lib/libgcrypt/src/secmem.h b/grub-core/lib/libgcrypt/src/secmem.h new file mode 100644 index 0000000..29e151a --- /dev/null +++ b/grub-core/lib/libgcrypt/src/secmem.h @@ -0,0 +1,39 @@ +/* secmem.h - internal definitions for secmem + * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef G10_SECMEM_H +#define G10_SECMEM_H 1 + +void _gcry_secmem_init (size_t npool); +void _gcry_secmem_term (void); +void *_gcry_secmem_malloc (size_t size) _GCRY_GCC_ATTR_MALLOC; +void *_gcry_secmem_realloc (void *a, size_t newsize); +void _gcry_secmem_free (void *a); +void _gcry_secmem_dump_stats (void); +void _gcry_secmem_set_flags (unsigned flags); +unsigned _gcry_secmem_get_flags(void); +int _gcry_private_is_secure (const void *p); + +/* Flags for _gcry_secmem_{set,get}_flags. */ +#define GCRY_SECMEM_FLAG_NO_WARNING (1 << 0) +#define GCRY_SECMEM_FLAG_SUSPEND_WARNING (1 << 1) +#define GCRY_SECMEM_FLAG_NOT_LOCKED (1 << 2) + +#endif /* G10_SECMEM_H */ diff --git a/grub-core/lib/libgcrypt/src/sexp.c b/grub-core/lib/libgcrypt/src/sexp.c new file mode 100644 index 0000000..78013fd --- /dev/null +++ b/grub-core/lib/libgcrypt/src/sexp.c @@ -0,0 +1,2045 @@ +/* sexp.c - S-Expression handling + * Copyright (C) 1999, 2000, 2001, 2002, 2003, + * 2004, 2006, 2007, 2008, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <errno.h> + +#define GCRYPT_NO_MPI_MACROS 1 +#include "g10lib.h" + +typedef struct gcry_sexp *NODE; +typedef unsigned short DATALEN; + +struct gcry_sexp +{ + byte d[1]; +}; + +#define ST_STOP 0 +#define ST_DATA 1 /* datalen follows */ +#define ST_HINT 2 /* datalen follows */ +#define ST_OPEN 3 +#define ST_CLOSE 4 + +/* the atoi macros assume that the buffer has only valid digits */ +#define atoi_1(p) (*(p) - '0' ) +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) + +#define TOKEN_SPECIALS "-./_:*+=" + +static gcry_error_t +vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, + const char *buffer, size_t length, int argflag, + void **arg_list, va_list arg_ptr); + +static gcry_error_t +sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, + const char *buffer, size_t length, int argflag, + void **arg_list, ...); + +/* Return true if P points to a byte containing a whitespace according + to the S-expressions definition. */ +#undef whitespacep +static GPG_ERR_INLINE int +whitespacep (const char *p) +{ + switch (*p) + { + case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1; + default: return 0; + } +} + + +#if 0 +static void +dump_mpi( gcry_mpi_t a ) +{ + char buffer[1000]; + size_t n = 1000; + + if( !a ) + fputs("[no MPI]", stderr ); + else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) ) + fputs("[MPI too large to print]", stderr ); + else + fputs( buffer, stderr ); +} +#endif + +static void +dump_string (const byte *p, size_t n, int delim ) +{ + for (; n; n--, p++ ) + { + if ((*p & 0x80) || iscntrl( *p ) || *p == delim ) + { + if( *p == '\n' ) + log_printf ("\\n"); + else if( *p == '\r' ) + log_printf ("\\r"); + else if( *p == '\f' ) + log_printf ("\\f"); + else if( *p == '\v' ) + log_printf ("\\v"); + else if( *p == '\b' ) + log_printf ("\\b"); + else if( !*p ) + log_printf ("\\0"); + else + log_printf ("\\x%02x", *p ); + } + else + log_printf ("%c", *p); + } +} + + +void +gcry_sexp_dump (const gcry_sexp_t a) +{ + const byte *p; + int indent = 0; + int type; + + if (!a) + { + log_printf ( "[nil]\n"); + return; + } + + p = a->d; + while ( (type = *p) != ST_STOP ) + { + p++; + switch ( type ) + { + case ST_OPEN: + log_printf ("%*s[open]\n", 2*indent, ""); + indent++; + break; + case ST_CLOSE: + if( indent ) + indent--; + log_printf ("%*s[close]\n", 2*indent, ""); + break; + case ST_DATA: { + DATALEN n; + memcpy ( &n, p, sizeof n ); + p += sizeof n; + log_printf ("%*s[data=\"", 2*indent, "" ); + dump_string (p, n, '\"' ); + log_printf ("\"]\n"); + p += n; + } + break; + default: + log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type); + break; + } + } +} + +/**************** + * Pass list through except when it is an empty list - in that case + * return NULL and release the passed list. + */ +static gcry_sexp_t +normalize ( gcry_sexp_t list ) +{ + unsigned char *p; + + if ( !list ) + return NULL; + p = list->d; + if ( *p == ST_STOP ) + { + /* this is "" */ + gcry_sexp_release ( list ); + return NULL; + } + if ( *p == ST_OPEN && p[1] == ST_CLOSE ) + { + /* this is "()" */ + gcry_sexp_release ( list ); + return NULL; + } + + return list; +} + +/* Create a new S-expression object by reading LENGTH bytes from + BUFFER, assuming it is canonical encoded or autodetected encoding + when AUTODETECT is set to 1. With FREEFNC not NULL, ownership of + the buffer is transferred to the newly created object. FREEFNC + should be the freefnc used to release BUFFER; there is no guarantee + at which point this function is called; most likey you want to use + free() or gcry_free(). + + Passing LENGTH and AUTODETECT as 0 is allowed to indicate that + BUFFER points to a valid canonical encoded S-expression. A LENGTH + of 0 and AUTODETECT 1 indicates that buffer points to a + null-terminated string. + + This function returns 0 and and the pointer to the new object in + RETSEXP or an error code in which case RETSEXP is set to NULL. */ +gcry_error_t +gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length, + int autodetect, void (*freefnc)(void*) ) +{ + gcry_error_t errcode; + gcry_sexp_t se; + + if (!retsexp) + return gcry_error (GPG_ERR_INV_ARG); + *retsexp = NULL; + if (autodetect < 0 || autodetect > 1 || !buffer) + return gcry_error (GPG_ERR_INV_ARG); + + if (!length && !autodetect) + { /* What a brave caller to assume that there is really a canonical + encoded S-expression in buffer */ + length = gcry_sexp_canon_len (buffer, 0, NULL, &errcode); + if (!length) + return errcode; + } + else if (!length && autodetect) + { /* buffer is a string */ + length = strlen ((char *)buffer); + } + + errcode = sexp_sscan (&se, NULL, buffer, length, 0, NULL); + if (errcode) + return errcode; + + *retsexp = se; + if (freefnc) + { + /* For now we release the buffer immediately. As soon as we + have changed the internal represenation of S-expression to + the canoncial format - which has the advantage of faster + parsing - we will use this function as a closure in our + GCRYSEXP object and use the BUFFER directly. */ + freefnc (buffer); + } + return gcry_error (GPG_ERR_NO_ERROR); +} + +/* Same as gcry_sexp_create but don't transfer ownership */ +gcry_error_t +gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length, + int autodetect) +{ + return gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL); +} + + +/**************** + * Release resource of the given SEXP object. + */ +void +gcry_sexp_release( gcry_sexp_t sexp ) +{ + if (sexp) + { + if (gcry_is_secure (sexp)) + { + /* Extra paranoid wiping. */ + const byte *p = sexp->d; + int type; + + while ( (type = *p) != ST_STOP ) + { + p++; + switch ( type ) + { + case ST_OPEN: + break; + case ST_CLOSE: + break; + case ST_DATA: + { + DATALEN n; + memcpy ( &n, p, sizeof n ); + p += sizeof n; + p += n; + } + break; + default: + break; + } + } + wipememory (sexp->d, p - sexp->d); + } + gcry_free ( sexp ); + } +} + + +/**************** + * Make a pair from lists a and b, don't use a or b later on. + * Special behaviour: If one is a single element list we put the + * element straight into the new pair. + */ +gcry_sexp_t +gcry_sexp_cons( const gcry_sexp_t a, const gcry_sexp_t b ) +{ + (void)a; + (void)b; + + /* NYI: Implementation should be quite easy with our new data + representation */ + BUG (); + return NULL; +} + + +/**************** + * Make a list from all items in the array the end of the array is marked + * with a NULL. + */ +gcry_sexp_t +gcry_sexp_alist( const gcry_sexp_t *array ) +{ + (void)array; + + /* NYI: Implementation should be quite easy with our new data + representation. */ + BUG (); + return NULL; +} + +/**************** + * Make a list from all items, the end of list is indicated by a NULL + */ +gcry_sexp_t +gcry_sexp_vlist( const gcry_sexp_t a, ... ) +{ + (void)a; + /* NYI: Implementation should be quite easy with our new data + representation. */ + BUG (); + return NULL; +} + + +/**************** + * Append n to the list a + * Returns: a new ist (which maybe a) + */ +gcry_sexp_t +gcry_sexp_append( const gcry_sexp_t a, const gcry_sexp_t n ) +{ + (void)a; + (void)n; + /* NYI: Implementation should be quite easy with our new data + representation. */ + BUG (); + return NULL; +} + +gcry_sexp_t +gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n ) +{ + (void)a; + (void)n; + /* NYI: Implementation should be quite easy with our new data + representation. */ + BUG (); + return NULL; +} + + + +/**************** + * Locate token in a list. The token must be the car of a sublist. + * Returns: A new list with this sublist or NULL if not found. + */ +gcry_sexp_t +gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen ) +{ + const byte *p; + DATALEN n; + + if ( !list ) + return NULL; + + if ( !toklen ) + toklen = strlen(tok); + + p = list->d; + while ( *p != ST_STOP ) + { + if ( *p == ST_OPEN && p[1] == ST_DATA ) + { + const byte *head = p; + + p += 2; + memcpy ( &n, p, sizeof n ); + p += sizeof n; + if ( n == toklen && !memcmp( p, tok, toklen ) ) + { /* found it */ + gcry_sexp_t newlist; + byte *d; + int level = 1; + + /* Look for the end of the list. */ + for ( p += n; level; p++ ) + { + if ( *p == ST_DATA ) + { + memcpy ( &n, ++p, sizeof n ); + p += sizeof n + n; + p--; /* Compensate for later increment. */ + } + else if ( *p == ST_OPEN ) + { + level++; + } + else if ( *p == ST_CLOSE ) + { + level--; + } + else if ( *p == ST_STOP ) + { + BUG (); + } + } + n = p - head; + + newlist = gcry_malloc ( sizeof *newlist + n ); + if (!newlist) + { + /* No way to return an error code, so we can only + return Not Found. */ + return NULL; + } + d = newlist->d; + memcpy ( d, head, n ); d += n; + *d++ = ST_STOP; + return normalize ( newlist ); + } + p += n; + } + else if ( *p == ST_DATA ) + { + memcpy ( &n, ++p, sizeof n ); p += sizeof n; + p += n; + } + else + p++; + } + return NULL; +} + +/**************** + * Return the length of the given list + */ +int +gcry_sexp_length( const gcry_sexp_t list ) +{ + const byte *p; + DATALEN n; + int type; + int length = 0; + int level = 0; + + if ( !list ) + return 0; + + p = list->d; + while ( (type=*p) != ST_STOP ) { + p++; + if ( type == ST_DATA ) { + memcpy ( &n, p, sizeof n ); + p += sizeof n + n; + if ( level == 1 ) + length++; + } + else if ( type == ST_OPEN ) { + if ( level == 1 ) + length++; + level++; + } + else if ( type == ST_CLOSE ) { + level--; + } + } + return length; +} + + +/* Return the internal lengths offset of LIST. That is the size of + the buffer from the first ST_OPEN, which is retruned at R_OFF, to + the corresponding ST_CLOSE inclusive. */ +static size_t +get_internal_buffer (const gcry_sexp_t list, size_t *r_off) +{ + const unsigned char *p; + DATALEN n; + int type; + int level = 0; + + *r_off = 0; + if (list) + { + p = list->d; + while ( (type=*p) != ST_STOP ) + { + p++; + if (type == ST_DATA) + { + memcpy (&n, p, sizeof n); + p += sizeof n + n; + } + else if (type == ST_OPEN) + { + if (!level) + *r_off = (p-1) - list->d; + level++; + } + else if ( type == ST_CLOSE ) + { + level--; + if (!level) + return p - list->d; + } + } + } + return 0; /* Not a proper list. */ +} + + + +/* Extract the CAR of the given list. May return NULL for bad lists + or memory failure. */ +gcry_sexp_t +gcry_sexp_nth( const gcry_sexp_t list, int number ) +{ + const byte *p; + DATALEN n; + gcry_sexp_t newlist; + byte *d; + int level = 0; + + if ( !list || list->d[0] != ST_OPEN ) + return NULL; + p = list->d; + + while ( number > 0 ) { + p++; + if ( *p == ST_DATA ) { + memcpy ( &n, ++p, sizeof n ); + p += sizeof n + n; + p--; + if ( !level ) + number--; + } + else if ( *p == ST_OPEN ) { + level++; + } + else if ( *p == ST_CLOSE ) { + level--; + if ( !level ) + number--; + } + else if ( *p == ST_STOP ) { + return NULL; + } + } + p++; + + if ( *p == ST_DATA ) { + memcpy ( &n, p, sizeof n ); + /* Allocate 1 (=sizeof *newlist) byte for ST_OPEN + 1 byte for ST_DATA + sizeof n byte for n + n byte for the data + 1 byte for ST_CLOSE + 1 byte for ST_STOP */ + newlist = gcry_malloc ( sizeof *newlist + 1 + sizeof n + n + 2 ); + if (!newlist) + return NULL; + d = newlist->d; + *d = ST_OPEN; /* Put the ST_OPEN flag */ + d++; /* Move forward */ + /* Copy ST_DATA, n and the data from p to d */ + memcpy ( d, p, 1 + sizeof n + n ); + d += 1 + sizeof n + n; /* Move after the data copied */ + *d = ST_CLOSE; /* Put the ST_CLOSE flag */ + d++; /* Move forward */ + *d = ST_STOP; /* Put the ST_STOP flag */ + } + else if ( *p == ST_OPEN ) { + const byte *head = p; + + level = 1; + do { + p++; + if ( *p == ST_DATA ) { + memcpy ( &n, ++p, sizeof n ); + p += sizeof n + n; + p--; + } + else if ( *p == ST_OPEN ) { + level++; + } + else if ( *p == ST_CLOSE ) { + level--; + } + else if ( *p == ST_STOP ) { + BUG (); + } + } while ( level ); + n = p + 1 - head; + + newlist = gcry_malloc ( sizeof *newlist + n ); + if (!newlist) + return NULL; + d = newlist->d; + memcpy ( d, head, n ); d += n; + *d++ = ST_STOP; + } + else + newlist = NULL; + + return normalize (newlist); +} + +gcry_sexp_t +gcry_sexp_car( const gcry_sexp_t list ) +{ + return gcry_sexp_nth ( list, 0 ); +} + + +/* Helper to get data from the car. The returned value is valid as + long as the list is not modified. */ +static const char * +sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen) +{ + const byte *p; + DATALEN n; + int level = 0; + + *datalen = 0; + if ( !list ) + return NULL; + + p = list->d; + if ( *p == ST_OPEN ) + p++; /* Yep, a list. */ + else if (number) + return NULL; /* Not a list but N > 0 requested. */ + + /* Skip over N elements. */ + while ( number > 0 ) + { + if ( *p == ST_DATA ) + { + memcpy ( &n, ++p, sizeof n ); + p += sizeof n + n; + p--; + if ( !level ) + number--; + } + else if ( *p == ST_OPEN ) + { + level++; + } + else if ( *p == ST_CLOSE ) + { + level--; + if ( !level ) + number--; + } + else if ( *p == ST_STOP ) + { + return NULL; + } + p++; + } + + /* If this is data, return it. */ + if ( *p == ST_DATA ) + { + memcpy ( &n, ++p, sizeof n ); + *datalen = n; + return (const char*)p + sizeof n; + } + + return NULL; +} + + +/* Get data from the car. The returned value is valid as long as the + list is not modified. */ +const char * +gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen ) +{ + return sexp_nth_data (list, number, datalen); +} + + +/* Get a string from the car. The returned value is a malloced string + and needs to be freed by the caller. */ +char * +gcry_sexp_nth_string (const gcry_sexp_t list, int number) +{ + const char *s; + size_t n; + char *buf; + + s = sexp_nth_data (list, number, &n); + if (!s || n < 1 || (n+1) < 1) + return NULL; + buf = gcry_malloc (n+1); + if (!buf) + return NULL; + memcpy (buf, s, n); + buf[n] = 0; + return buf; +} + +/* + * Get a MPI from the car + */ +gcry_mpi_t +gcry_sexp_nth_mpi( gcry_sexp_t list, int number, int mpifmt ) +{ + const char *s; + size_t n; + gcry_mpi_t a; + + if ( !mpifmt ) + mpifmt = GCRYMPI_FMT_STD; + + s = sexp_nth_data (list, number, &n); + if (!s) + return NULL; + + if ( gcry_mpi_scan ( &a, mpifmt, s, n, NULL ) ) + return NULL; + + return a; +} + + +/**************** + * Get the CDR + */ +gcry_sexp_t +gcry_sexp_cdr( const gcry_sexp_t list ) +{ + const byte *p; + const byte *head; + DATALEN n; + gcry_sexp_t newlist; + byte *d; + int level = 0; + int skip = 1; + + if ( !list || list->d[0] != ST_OPEN ) + return NULL; + p = list->d; + + while ( skip > 0 ) { + p++; + if ( *p == ST_DATA ) { + memcpy ( &n, ++p, sizeof n ); + p += sizeof n + n; + p--; + if ( !level ) + skip--; + } + else if ( *p == ST_OPEN ) { + level++; + } + else if ( *p == ST_CLOSE ) { + level--; + if ( !level ) + skip--; + } + else if ( *p == ST_STOP ) { + return NULL; + } + } + p++; + + head = p; + level = 0; + do { + if ( *p == ST_DATA ) { + memcpy ( &n, ++p, sizeof n ); + p += sizeof n + n; + p--; + } + else if ( *p == ST_OPEN ) { + level++; + } + else if ( *p == ST_CLOSE ) { + level--; + } + else if ( *p == ST_STOP ) { + return NULL; + } + p++; + } while ( level ); + n = p - head; + + newlist = gcry_malloc ( sizeof *newlist + n + 2 ); + if (!newlist) + return NULL; + d = newlist->d; + *d++ = ST_OPEN; + memcpy ( d, head, n ); d += n; + *d++ = ST_CLOSE; + *d++ = ST_STOP; + + return normalize (newlist); +} + +gcry_sexp_t +gcry_sexp_cadr ( const gcry_sexp_t list ) +{ + gcry_sexp_t a, b; + + a = gcry_sexp_cdr ( list ); + b = gcry_sexp_car ( a ); + gcry_sexp_release ( a ); + return b; +} + + + +static int +hextobyte( const byte *s ) +{ + int c=0; + + if( *s >= '0' && *s <= '9' ) + c = 16 * (*s - '0'); + else if( *s >= 'A' && *s <= 'F' ) + c = 16 * (10 + *s - 'A'); + else if( *s >= 'a' && *s <= 'f' ) { + c = 16 * (10 + *s - 'a'); + } + s++; + if( *s >= '0' && *s <= '9' ) + c += *s - '0'; + else if( *s >= 'A' && *s <= 'F' ) + c += 10 + *s - 'A'; + else if( *s >= 'a' && *s <= 'f' ) { + c += 10 + *s - 'a'; + } + return c; +} + +struct make_space_ctx { + gcry_sexp_t sexp; + size_t allocated; + byte *pos; +}; + +static gpg_err_code_t +make_space ( struct make_space_ctx *c, size_t n ) +{ + size_t used = c->pos - c->sexp->d; + + if ( used + n + sizeof(DATALEN) + 1 >= c->allocated ) + { + gcry_sexp_t newsexp; + byte *newhead; + size_t newsize; + + newsize = c->allocated + 2*(n+sizeof(DATALEN)+1); + if (newsize <= c->allocated) + return GPG_ERR_TOO_LARGE; + newsexp = gcry_realloc ( c->sexp, sizeof *newsexp + newsize - 1); + if (!newsexp) + return gpg_err_code_from_errno (errno); + c->allocated = newsize; + newhead = newsexp->d; + c->pos = newhead + used; + c->sexp = newsexp; + } + return 0; +} + + +/* Unquote STRING of LENGTH and store it into BUF. The surrounding + quotes are must already be removed from STRING. We assume that the + quoted string is syntacillay correct. */ +static size_t +unquote_string (const char *string, size_t length, unsigned char *buf) +{ + int esc = 0; + const unsigned char *s = (const unsigned char*)string; + unsigned char *d = buf; + size_t n = length; + + for (; n; n--, s++) + { + if (esc) + { + switch (*s) + { + case 'b': *d++ = '\b'; break; + case 't': *d++ = '\t'; break; + case 'v': *d++ = '\v'; break; + case 'n': *d++ = '\n'; break; + case 'f': *d++ = '\f'; break; + case 'r': *d++ = '\r'; break; + case '"': *d++ = '\"'; break; + case '\'': *d++ = '\''; break; + case '\\': *d++ = '\\'; break; + + case '\r': /* ignore CR[,LF] */ + if (n>1 && s[1] == '\n') + { + s++; n--; + } + break; + + case '\n': /* ignore LF[,CR] */ + if (n>1 && s[1] == '\r') + { + s++; n--; + } + break; + + case 'x': /* hex value */ + if (n>2 && hexdigitp (s+1) && hexdigitp (s+2)) + { + s++; n--; + *d++ = xtoi_2 (s); + s++; n--; + } + break; + + default: + if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2)) + { + *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2); + s += 2; + n -= 2; + } + break; + } + esc = 0; + } + else if( *s == '\\' ) + esc = 1; + else + *d++ = *s; + } + + return d - buf; +} + +/**************** + * Scan the provided buffer and return the S expression in our internal + * format. Returns a newly allocated expression. If erroff is not NULL and + * a parsing error has occurred, the offset into buffer will be returned. + * If ARGFLAG is true, the function supports some printf like + * expressions. + * These are: + * %m - MPI + * %s - string (no autoswitch to secure allocation) + * %d - integer stored as string (no autoswitch to secure allocation) + * %b - memory buffer; this takes _two_ arguments: an integer with the + * length of the buffer and a pointer to the buffer. + * %S - Copy an gcry_sexp_t here. The S-expression needs to be a + * regular one, starting with a parenthesis. + * (no autoswitch to secure allocation) + * all other format elements are currently not defined and return an error. + * this includes the "%%" sequence becauce the percent sign is not an + * allowed character. + * FIXME: We should find a way to store the secure-MPIs not in the string + * but as reference to somewhere - this can help us to save huge amounts + * of secure memory. The problem is, that if only one element is secure, all + * other elements are automagicaly copied to secure memory too, so the most + * common operation gcry_sexp_cdr_mpi() will always return a secure MPI + * regardless whether it is needed or not. + */ +static gcry_error_t +vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, + const char *buffer, size_t length, int argflag, + void **arg_list, va_list arg_ptr) +{ + gcry_err_code_t err = 0; + static const char tokenchars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789-./_:*+="; + const char *p; + size_t n; + const char *digptr = NULL; + const char *quoted = NULL; + const char *tokenp = NULL; + const char *hexfmt = NULL; + const char *base64 = NULL; + const char *disphint = NULL; + const char *percent = NULL; + int hexcount = 0; + int quoted_esc = 0; + int datalen = 0; + size_t dummy_erroff; + struct make_space_ctx c; + int arg_counter = 0; + int level = 0; + + if (!erroff) + erroff = &dummy_erroff; + + /* Depending on whether ARG_LIST is non-zero or not, this macro gives + us the next argument, either from the variable argument list as + specified by ARG_PTR or from the argument array ARG_LIST. */ +#define ARG_NEXT(storage, type) \ + do \ + { \ + if (!arg_list) \ + storage = va_arg (arg_ptr, type); \ + else \ + storage = *((type *) (arg_list[arg_counter++])); \ + } \ + while (0) + + /* The MAKE_SPACE macro is used before each store operation to + ensure that the buffer is large enough. It requires a global + context named C and jumps out to the label LEAVE on error! It + also sets ERROFF using the variables BUFFER and P. */ +#define MAKE_SPACE(n) do { \ + gpg_err_code_t _ms_err = make_space (&c, (n)); \ + if (_ms_err) \ + { \ + err = _ms_err; \ + *erroff = p - buffer; \ + goto leave; \ + } \ + } while (0) + + /* The STORE_LEN macro is used to store the length N at buffer P. */ +#define STORE_LEN(p,n) do { \ + DATALEN ashort = (n); \ + memcpy ( (p), &ashort, sizeof(ashort) ); \ + (p) += sizeof (ashort); \ + } while (0) + + /* We assume that the internal representation takes less memory than + the provided one. However, we add space for one extra datalen so + that the code which does the ST_CLOSE can use MAKE_SPACE */ + c.allocated = length + sizeof(DATALEN); + if (buffer && length && gcry_is_secure (buffer)) + c.sexp = gcry_malloc_secure (sizeof *c.sexp + c.allocated - 1); + else + c.sexp = gcry_malloc (sizeof *c.sexp + c.allocated - 1); + if (!c.sexp) + { + err = gpg_err_code_from_errno (errno); + *erroff = 0; + goto leave; + } + c.pos = c.sexp->d; + + for (p = buffer, n = length; n; p++, n--) + { + if (tokenp && !hexfmt) + { + if (strchr (tokenchars, *p)) + continue; + else + { + datalen = p - tokenp; + MAKE_SPACE (datalen); + *c.pos++ = ST_DATA; + STORE_LEN (c.pos, datalen); + memcpy (c.pos, tokenp, datalen); + c.pos += datalen; + tokenp = NULL; + } + } + + if (quoted) + { + if (quoted_esc) + { + switch (*p) + { + case 'b': case 't': case 'v': case 'n': case 'f': + case 'r': case '"': case '\'': case '\\': + quoted_esc = 0; + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + if (!((n > 2) + && (p[1] >= '0') && (p[1] <= '7') + && (p[2] >= '0') && (p[2] <= '7'))) + { + *erroff = p - buffer; + /* Invalid octal value. */ + err = GPG_ERR_SEXP_BAD_QUOTATION; + goto leave; + } + p += 2; + n -= 2; + quoted_esc = 0; + break; + + case 'x': + if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2))) + { + *erroff = p - buffer; + /* Invalid hex value. */ + err = GPG_ERR_SEXP_BAD_QUOTATION; + goto leave; + } + p += 2; + n -= 2; + quoted_esc = 0; + break; + + case '\r': + /* ignore CR[,LF] */ + if (n && (p[1] == '\n')) + { + p++; + n--; + } + quoted_esc = 0; + break; + + case '\n': + /* ignore LF[,CR] */ + if (n && (p[1] == '\r')) + { + p++; + n--; + } + quoted_esc = 0; + break; + + default: + *erroff = p - buffer; + /* Invalid quoted string escape. */ + err = GPG_ERR_SEXP_BAD_QUOTATION; + goto leave; + } + } + else if (*p == '\\') + quoted_esc = 1; + else if (*p == '\"') + { + /* Keep it easy - we know that the unquoted string will + never be larger. */ + unsigned char *save; + size_t len; + + quoted++; /* Skip leading quote. */ + MAKE_SPACE (p - quoted); + *c.pos++ = ST_DATA; + save = c.pos; + STORE_LEN (c.pos, 0); /* Will be fixed up later. */ + len = unquote_string (quoted, p - quoted, c.pos); + c.pos += len; + STORE_LEN (save, len); + quoted = NULL; + } + } + else if (hexfmt) + { + if (isxdigit (*p)) + hexcount++; + else if (*p == '#') + { + if ((hexcount & 1)) + { + *erroff = p - buffer; + err = GPG_ERR_SEXP_ODD_HEX_NUMBERS; + goto leave; + } + + datalen = hexcount / 2; + MAKE_SPACE (datalen); + *c.pos++ = ST_DATA; + STORE_LEN (c.pos, datalen); + for (hexfmt++; hexfmt < p; hexfmt++) + { + if (whitespacep (hexfmt)) + continue; + *c.pos++ = hextobyte ((const unsigned char*)hexfmt); + hexfmt++; + } + hexfmt = NULL; + } + else if (!whitespacep (p)) + { + *erroff = p - buffer; + err = GPG_ERR_SEXP_BAD_HEX_CHAR; + goto leave; + } + } + else if (base64) + { + if (*p == '|') + base64 = NULL; + } + else if (digptr) + { + if (digitp (p)) + ; + else if (*p == ':') + { + datalen = atoi (digptr); /* FIXME: check for overflow. */ + digptr = NULL; + if (datalen > n - 1) + { + *erroff = p - buffer; + /* Buffer too short. */ + err = GPG_ERR_SEXP_STRING_TOO_LONG; + goto leave; + } + /* Make a new list entry. */ + MAKE_SPACE (datalen); + *c.pos++ = ST_DATA; + STORE_LEN (c.pos, datalen); + memcpy (c.pos, p + 1, datalen); + c.pos += datalen; + n -= datalen; + p += datalen; + } + else if (*p == '\"') + { + digptr = NULL; /* We ignore the optional length. */ + quoted = p; + quoted_esc = 0; + } + else if (*p == '#') + { + digptr = NULL; /* We ignore the optional length. */ + hexfmt = p; + hexcount = 0; + } + else if (*p == '|') + { + digptr = NULL; /* We ignore the optional length. */ + base64 = p; + } + else + { + *erroff = p - buffer; + err = GPG_ERR_SEXP_INV_LEN_SPEC; + goto leave; + } + } + else if (percent) + { + if (*p == 'm' || *p == 'M') + { + /* Insert an MPI. */ + gcry_mpi_t m; + size_t nm = 0; + int mpifmt = *p == 'm'? GCRYMPI_FMT_STD: GCRYMPI_FMT_USG; + + ARG_NEXT (m, gcry_mpi_t); + + if (gcry_mpi_get_flag (m, GCRYMPI_FLAG_OPAQUE)) + { + void *mp; + unsigned int nbits; + + mp = gcry_mpi_get_opaque (m, &nbits); + nm = (nbits+7)/8; + if (mp && nm) + { + MAKE_SPACE (nm); + if (!gcry_is_secure (c.sexp->d) + && gcry_mpi_get_flag (m, GCRYMPI_FLAG_SECURE)) + { + /* We have to switch to secure allocation. */ + gcry_sexp_t newsexp; + byte *newhead; + + newsexp = gcry_malloc_secure (sizeof *newsexp + + c.allocated - 1); + if (!newsexp) + { + err = gpg_err_code_from_errno (errno); + goto leave; + } + newhead = newsexp->d; + memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d)); + c.pos = newhead + (c.pos - c.sexp->d); + gcry_free (c.sexp); + c.sexp = newsexp; + } + + *c.pos++ = ST_DATA; + STORE_LEN (c.pos, nm); + memcpy (c.pos, mp, nm); + c.pos += nm; + } + } + else + { + if (gcry_mpi_print (mpifmt, NULL, 0, &nm, m)) + BUG (); + + MAKE_SPACE (nm); + if (!gcry_is_secure (c.sexp->d) + && gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE)) + { + /* We have to switch to secure allocation. */ + gcry_sexp_t newsexp; + byte *newhead; + + newsexp = gcry_malloc_secure (sizeof *newsexp + + c.allocated - 1); + if (!newsexp) + { + err = gpg_err_code_from_errno (errno); + goto leave; + } + newhead = newsexp->d; + memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d)); + c.pos = newhead + (c.pos - c.sexp->d); + gcry_free (c.sexp); + c.sexp = newsexp; + } + + *c.pos++ = ST_DATA; + STORE_LEN (c.pos, nm); + if (gcry_mpi_print (mpifmt, c.pos, nm, &nm, m)) + BUG (); + c.pos += nm; + } + } + else if (*p == 's') + { + /* Insert an string. */ + const char *astr; + size_t alen; + + ARG_NEXT (astr, const char *); + alen = strlen (astr); + + MAKE_SPACE (alen); + *c.pos++ = ST_DATA; + STORE_LEN (c.pos, alen); + memcpy (c.pos, astr, alen); + c.pos += alen; + } + else if (*p == 'b') + { + /* Insert a memory buffer. */ + const char *astr; + int alen; + + ARG_NEXT (alen, int); + ARG_NEXT (astr, const char *); + + MAKE_SPACE (alen); + if (alen + && !gcry_is_secure (c.sexp->d) + && gcry_is_secure (astr)) + { + /* We have to switch to secure allocation. */ + gcry_sexp_t newsexp; + byte *newhead; + + newsexp = gcry_malloc_secure (sizeof *newsexp + + c.allocated - 1); + if (!newsexp) + { + err = gpg_err_code_from_errno (errno); + goto leave; + } + newhead = newsexp->d; + memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d)); + c.pos = newhead + (c.pos - c.sexp->d); + gcry_free (c.sexp); + c.sexp = newsexp; + } + + *c.pos++ = ST_DATA; + STORE_LEN (c.pos, alen); + memcpy (c.pos, astr, alen); + c.pos += alen; + } + else if (*p == 'd') + { + /* Insert an integer as string. */ + int aint; + size_t alen; + char buf[35]; + + ARG_NEXT (aint, int); + sprintf (buf, "%d", aint); + alen = strlen (buf); + MAKE_SPACE (alen); + *c.pos++ = ST_DATA; + STORE_LEN (c.pos, alen); + memcpy (c.pos, buf, alen); + c.pos += alen; + } + else if (*p == 'u') + { + /* Insert an unsigned integer as string. */ + unsigned int aint; + size_t alen; + char buf[35]; + + ARG_NEXT (aint, unsigned int); + sprintf (buf, "%u", aint); + alen = strlen (buf); + MAKE_SPACE (alen); + *c.pos++ = ST_DATA; + STORE_LEN (c.pos, alen); + memcpy (c.pos, buf, alen); + c.pos += alen; + } + else if (*p == 'S') + { + /* Insert a gcry_sexp_t. */ + gcry_sexp_t asexp; + size_t alen, aoff; + + ARG_NEXT (asexp, gcry_sexp_t); + alen = get_internal_buffer (asexp, &aoff); + if (alen) + { + MAKE_SPACE (alen); + memcpy (c.pos, asexp->d + aoff, alen); + c.pos += alen; + } + } + else + { + *erroff = p - buffer; + /* Invalid format specifier. */ + err = GPG_ERR_SEXP_INV_LEN_SPEC; + goto leave; + } + percent = NULL; + } + else if (*p == '(') + { + if (disphint) + { + *erroff = p - buffer; + /* Open display hint. */ + err = GPG_ERR_SEXP_UNMATCHED_DH; + goto leave; + } + MAKE_SPACE (0); + *c.pos++ = ST_OPEN; + level++; + } + else if (*p == ')') + { + /* Walk up. */ + if (disphint) + { + *erroff = p - buffer; + /* Open display hint. */ + err = GPG_ERR_SEXP_UNMATCHED_DH; + goto leave; + } + MAKE_SPACE (0); + *c.pos++ = ST_CLOSE; + level--; + } + else if (*p == '\"') + { + quoted = p; + quoted_esc = 0; + } + else if (*p == '#') + { + hexfmt = p; + hexcount = 0; + } + else if (*p == '|') + base64 = p; + else if (*p == '[') + { + if (disphint) + { + *erroff = p - buffer; + /* Open display hint. */ + err = GPG_ERR_SEXP_NESTED_DH; + goto leave; + } + disphint = p; + } + else if (*p == ']') + { + if (!disphint) + { + *erroff = p - buffer; + /* Open display hint. */ + err = GPG_ERR_SEXP_UNMATCHED_DH; + goto leave; + } + disphint = NULL; + } + else if (digitp (p)) + { + if (*p == '0') + { + /* A length may not begin with zero. */ + *erroff = p - buffer; + err = GPG_ERR_SEXP_ZERO_PREFIX; + goto leave; + } + digptr = p; + } + else if (strchr (tokenchars, *p)) + tokenp = p; + else if (whitespacep (p)) + ; + else if (*p == '{') + { + /* fixme: handle rescanning: we can do this by saving our + current state and start over at p+1 -- Hmmm. At this + point here we are in a well defined state, so we don't + need to save it. Great. */ + *erroff = p - buffer; + err = GPG_ERR_SEXP_UNEXPECTED_PUNC; + goto leave; + } + else if (strchr ("&\\", *p)) + { + /* Reserved punctuation. */ + *erroff = p - buffer; + err = GPG_ERR_SEXP_UNEXPECTED_PUNC; + goto leave; + } + else if (argflag && (*p == '%')) + percent = p; + else + { + /* Bad or unavailable. */ + *erroff = p - buffer; + err = GPG_ERR_SEXP_BAD_CHARACTER; + goto leave; + } + } + MAKE_SPACE (0); + *c.pos++ = ST_STOP; + + if (level && !err) + err = GPG_ERR_SEXP_UNMATCHED_PAREN; + + leave: + if (err) + { + /* Error -> deallocate. */ + if (c.sexp) + { + /* Extra paranoid wipe on error. */ + if (gcry_is_secure (c.sexp)) + wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1); + gcry_free (c.sexp); + } + /* This might be expected by existing code... */ + *retsexp = NULL; + } + else + *retsexp = normalize (c.sexp); + + return gcry_error (err); +#undef MAKE_SPACE +#undef STORE_LEN +} + + +static gcry_error_t +sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, + const char *buffer, size_t length, int argflag, + void **arg_list, ...) +{ + gcry_error_t rc; + va_list arg_ptr; + + va_start (arg_ptr, arg_list); + rc = vsexp_sscan (retsexp, erroff, buffer, length, argflag, + arg_list, arg_ptr); + va_end (arg_ptr); + + return rc; +} + + +gcry_error_t +gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...) +{ + gcry_error_t rc; + va_list arg_ptr; + + va_start (arg_ptr, format); + rc = vsexp_sscan (retsexp, erroff, format, strlen(format), 1, + NULL, arg_ptr); + va_end (arg_ptr); + + return rc; +} + + +gcry_error_t +_gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff, + const char *format, va_list arg_ptr) +{ + return vsexp_sscan (retsexp, erroff, format, strlen(format), 1, + NULL, arg_ptr); +} + + +/* Like gcry_sexp_build, but uses an array instead of variable + function arguments. */ +gcry_error_t +gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff, + const char *format, void **arg_list) +{ + return sexp_sscan (retsexp, erroff, format, strlen(format), 1, arg_list); +} + + +gcry_error_t +gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, + const char *buffer, size_t length) +{ + return sexp_sscan (retsexp, erroff, buffer, length, 0, NULL); +} + + +/* Figure out a suitable encoding for BUFFER of LENGTH. + Returns: 0 = Binary + 1 = String possible + 2 = Token possible +*/ +static int +suitable_encoding (const unsigned char *buffer, size_t length) +{ + const unsigned char *s; + int maybe_token = 1; + + if (!length) + return 1; + + for (s=buffer; length; s++, length--) + { + if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)) + && !strchr ("\b\t\v\n\f\r\"\'\\", *s)) + return 0; /*binary*/ + if ( maybe_token + && !alphap (s) && !digitp (s) && !strchr (TOKEN_SPECIALS, *s)) + maybe_token = 0; + } + s = buffer; + if ( maybe_token && !digitp (s) ) + return 2; + return 1; +} + + +static int +convert_to_hex (const unsigned char *src, size_t len, char *dest) +{ + int i; + + if (dest) + { + *dest++ = '#'; + for (i=0; i < len; i++, dest += 2 ) + sprintf (dest, "%02X", src[i]); + *dest++ = '#'; + } + return len*2+2; +} + +static int +convert_to_string (const unsigned char *s, size_t len, char *dest) +{ + if (dest) + { + char *p = dest; + *p++ = '\"'; + for (; len; len--, s++ ) + { + switch (*s) + { + case '\b': *p++ = '\\'; *p++ = 'b'; break; + case '\t': *p++ = '\\'; *p++ = 't'; break; + case '\v': *p++ = '\\'; *p++ = 'v'; break; + case '\n': *p++ = '\\'; *p++ = 'n'; break; + case '\f': *p++ = '\\'; *p++ = 'f'; break; + case '\r': *p++ = '\\'; *p++ = 'r'; break; + case '\"': *p++ = '\\'; *p++ = '\"'; break; + case '\'': *p++ = '\\'; *p++ = '\''; break; + case '\\': *p++ = '\\'; *p++ = '\\'; break; + default: + if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))) + { + sprintf (p, "\\x%02x", *s); + p += 4; + } + else + *p++ = *s; + } + } + *p++ = '\"'; + return p - dest; + } + else + { + int count = 2; + for (; len; len--, s++ ) + { + switch (*s) + { + case '\b': + case '\t': + case '\v': + case '\n': + case '\f': + case '\r': + case '\"': + case '\'': + case '\\': count += 2; break; + default: + if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))) + count += 4; + else + count++; + } + } + return count; + } +} + + + +static int +convert_to_token (const unsigned char *src, size_t len, char *dest) +{ + if (dest) + memcpy (dest, src, len); + return len; +} + + +/**************** + * Print SEXP to buffer using the MODE. Returns the length of the + * SEXP in buffer or 0 if the buffer is too short (We have at least an + * empty list consisting of 2 bytes). If a buffer of NULL is provided, + * the required length is returned. + */ +size_t +gcry_sexp_sprint (const gcry_sexp_t list, int mode, + void *buffer, size_t maxlength ) +{ + static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP }; + const unsigned char *s; + char *d; + DATALEN n; + char numbuf[20]; + size_t len = 0; + int i, indent = 0; + + s = list? list->d : empty; + d = buffer; + while ( *s != ST_STOP ) + { + switch ( *s ) + { + case ST_OPEN: + s++; + if ( mode != GCRYSEXP_FMT_CANON ) + { + if (indent) + len++; + len += indent; + } + len++; + if ( buffer ) + { + if ( len >= maxlength ) + return 0; + if ( mode != GCRYSEXP_FMT_CANON ) + { + if (indent) + *d++ = '\n'; + for (i=0; i < indent; i++) + *d++ = ' '; + } + *d++ = '('; + } + indent++; + break; + case ST_CLOSE: + s++; + len++; + if ( buffer ) + { + if ( len >= maxlength ) + return 0; + *d++ = ')'; + } + indent--; + if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON) + { + len++; + len += indent; + if (buffer) + { + if (len >= maxlength) + return 0; + *d++ = '\n'; + for (i=0; i < indent; i++) + *d++ = ' '; + } + } + break; + case ST_DATA: + s++; + memcpy ( &n, s, sizeof n ); s += sizeof n; + if (mode == GCRYSEXP_FMT_ADVANCED) + { + int type; + size_t nn; + + switch ( (type=suitable_encoding (s, n))) + { + case 1: nn = convert_to_string (s, n, NULL); break; + case 2: nn = convert_to_token (s, n, NULL); break; + default: nn = convert_to_hex (s, n, NULL); break; + } + len += nn; + if (buffer) + { + if (len >= maxlength) + return 0; + switch (type) + { + case 1: convert_to_string (s, n, d); break; + case 2: convert_to_token (s, n, d); break; + default: convert_to_hex (s, n, d); break; + } + d += nn; + } + if (s[n] != ST_CLOSE) + { + len++; + if (buffer) + { + if (len >= maxlength) + return 0; + *d++ = ' '; + } + } + } + else + { + sprintf (numbuf, "%u:", (unsigned int)n ); + len += strlen (numbuf) + n; + if ( buffer ) + { + if ( len >= maxlength ) + return 0; + d = stpcpy ( d, numbuf ); + memcpy ( d, s, n ); d += n; + } + } + s += n; + break; + default: + BUG (); + } + } + if ( mode != GCRYSEXP_FMT_CANON ) + { + len++; + if (buffer) + { + if ( len >= maxlength ) + return 0; + *d++ = '\n'; + } + } + if (buffer) + { + if ( len >= maxlength ) + return 0; + *d++ = 0; /* for convenience we make a C string */ + } + else + len++; /* we need one byte more for this */ + + return len; +} + + +/* Scan a canonical encoded buffer with implicit length values and + return the actual length this S-expression uses. For a valid S-Exp + it should never return 0. If LENGTH is not zero, the maximum + length to scan is given - this can be used for syntax checks of + data passed from outside. errorcode and erroff may both be passed as + NULL. */ +size_t +gcry_sexp_canon_len (const unsigned char *buffer, size_t length, + size_t *erroff, gcry_error_t *errcode) +{ + const unsigned char *p; + const unsigned char *disphint = NULL; + unsigned int datalen = 0; + size_t dummy_erroff; + gcry_error_t dummy_errcode; + size_t count = 0; + int level = 0; + + if (!erroff) + erroff = &dummy_erroff; + if (!errcode) + errcode = &dummy_errcode; + + *errcode = gcry_error (GPG_ERR_NO_ERROR); + *erroff = 0; + if (!buffer) + return 0; + if (*buffer != '(') + { + *errcode = gcry_error (GPG_ERR_SEXP_NOT_CANONICAL); + return 0; + } + + for (p=buffer; ; p++, count++ ) + { + if (length && count >= length) + { + *erroff = count; + *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG); + return 0; + } + + if (datalen) + { + if (*p == ':') + { + if (length && (count+datalen) >= length) + { + *erroff = count; + *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG); + return 0; + } + count += datalen; + p += datalen; + datalen = 0; + } + else if (digitp(p)) + datalen = datalen*10 + atoi_1(p); + else + { + *erroff = count; + *errcode = gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC); + return 0; + } + } + else if (*p == '(') + { + if (disphint) + { + *erroff = count; + *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); + return 0; + } + level++; + } + else if (*p == ')') + { /* walk up */ + if (!level) + { + *erroff = count; + *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_PAREN); + return 0; + } + if (disphint) + { + *erroff = count; + *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); + return 0; + } + if (!--level) + return ++count; /* ready */ + } + else if (*p == '[') + { + if (disphint) + { + *erroff = count; + *errcode = gcry_error (GPG_ERR_SEXP_NESTED_DH); + return 0; + } + disphint = p; + } + else if (*p == ']') + { + if ( !disphint ) + { + *erroff = count; + *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH); + return 0; + } + disphint = NULL; + } + else if (digitp (p) ) + { + if (*p == '0') + { + *erroff = count; + *errcode = gcry_error (GPG_ERR_SEXP_ZERO_PREFIX); + return 0; + } + datalen = atoi_1 (p); + } + else if (*p == '&' || *p == '\\') + { + *erroff = count; + *errcode = gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC); + return 0; + } + else + { + *erroff = count; + *errcode = gcry_error (GPG_ERR_SEXP_BAD_CHARACTER); + return 0; + } + } +} diff --git a/grub-core/lib/libgcrypt/src/stdmem.c b/grub-core/lib/libgcrypt/src/stdmem.c new file mode 100644 index 0000000..189da37 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/stdmem.c @@ -0,0 +1,242 @@ +/* stdmem.c - private memory allocator + * Copyright (C) 1998, 2000, 2002, 2005, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +/* + * Description of the layered memory management in Libgcrypt: + * + * [User] + * | + * | + * \ / + * global.c: [MM entrance points] -----> [user callbacks] + * | | + * | | + * \ / \ / + * + * stdmem.c: [non-secure handlers] [secure handlers] + * + * | | + * | | + * \ / \ / + * + * stdmem.c: [ memory guard ] + * + * | | + * | | + * \ / \ / + * + * libc: [ MM functions ] secmem.c: [ secure MM functions] + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <errno.h> + +#include "g10lib.h" +#include "stdmem.h" +#include "secmem.h" + + + +#define MAGIC_NOR_BYTE 0x55 +#define MAGIC_SEC_BYTE 0xcc +#define MAGIC_END_BYTE 0xaa + +#if SIZEOF_UNSIGNED_LONG == 8 +#define EXTRA_ALIGN 4 +#else +#define EXTRA_ALIGN 0 +#endif + + +static int use_m_guard = 0; + +/**************** + * Warning: Never use this function after any of the functions + * here have been used. + */ +void +_gcry_private_enable_m_guard (void) +{ + use_m_guard = 1; +} + + +/* + * Allocate memory of size n. + * Return NULL if we are out of memory. + */ +void * +_gcry_private_malloc (size_t n) +{ + if (!n) + { + gpg_err_set_errno (EINVAL); + return NULL; /* Allocating 0 bytes is undefined - we better return + an error to detect such coding errors. */ + } + + if (use_m_guard) + { + char *p; + + if ( !(p = malloc (n + EXTRA_ALIGN+5)) ) + return NULL; + ((byte*)p)[EXTRA_ALIGN+0] = n; + ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; + ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; + ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_NOR_BYTE; + p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE; + return p+EXTRA_ALIGN+4; + } + else + { + return malloc( n ); + } +} + + +/* + * Allocate memory of size N from the secure memory pool. Return NULL + * if we are out of memory. + */ +void * +_gcry_private_malloc_secure (size_t n) +{ + if (!n) + { + gpg_err_set_errno (EINVAL); + return NULL; /* Allocating 0 bytes is undefined - better return an + error to detect such coding errors. */ + } + + if (use_m_guard) + { + char *p; + + if ( !(p = _gcry_secmem_malloc (n +EXTRA_ALIGN+ 5)) ) + return NULL; + ((byte*)p)[EXTRA_ALIGN+0] = n; + ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; + ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; + ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_SEC_BYTE; + p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE; + return p+EXTRA_ALIGN+4; + } + else + { + return _gcry_secmem_malloc( n ); + } +} + + +/* + * Realloc and clear the old space + * Return NULL if there is not enough memory. + */ +void * +_gcry_private_realloc ( void *a, size_t n ) +{ + if (use_m_guard) + { + unsigned char *p = a; + char *b; + size_t len; + + if (!a) + return _gcry_private_malloc(n); + + _gcry_private_check_heap(p); + len = p[-4]; + len |= p[-3] << 8; + len |= p[-2] << 16; + if( len >= n ) /* We don't shrink for now. */ + return a; + if (p[-1] == MAGIC_SEC_BYTE) + b = _gcry_private_malloc_secure(n); + else + b = _gcry_private_malloc(n); + if (!b) + return NULL; + memcpy (b, a, len); + memset (b+len, 0, n-len); + _gcry_private_free (p); + return b; + } + else if ( _gcry_private_is_secure(a) ) + { + return _gcry_secmem_realloc( a, n ); + } + else + { + return realloc( a, n ); + } +} + + +void +_gcry_private_check_heap (const void *a) +{ + if (use_m_guard) + { + const byte *p = a; + size_t len; + + if (!p) + return; + + if ( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) ) + _gcry_log_fatal ("memory at %p corrupted (underflow=%02x)\n", p, p[-1]); + len = p[-4]; + len |= p[-3] << 8; + len |= p[-2] << 16; + if ( p[len] != MAGIC_END_BYTE ) + _gcry_log_fatal ("memory at %p corrupted (overflow=%02x)\n", p, p[-1]); + } +} + + +/* + * Free a memory block allocated by this or the secmem module + */ +void +_gcry_private_free (void *a) +{ + unsigned char *p = a; + + if (!p) + return; + if (use_m_guard ) + { + _gcry_private_check_heap(p); + if ( _gcry_private_is_secure(a) ) + _gcry_secmem_free(p-EXTRA_ALIGN-4); + else + { + free(p-EXTRA_ALIGN-4); + } + } + else if ( _gcry_private_is_secure(a) ) + _gcry_secmem_free(p); + else + free(p); +} diff --git a/grub-core/lib/libgcrypt/src/stdmem.h b/grub-core/lib/libgcrypt/src/stdmem.h new file mode 100644 index 0000000..b476e7e --- /dev/null +++ b/grub-core/lib/libgcrypt/src/stdmem.h @@ -0,0 +1,32 @@ +/* stdmem.h - internal definitions for stdmem + * Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef G10_STDMEM_H +#define G10_STDMEM_H 1 + +void _gcry_private_enable_m_guard(void); + +void *_gcry_private_malloc (size_t n) _GCRY_GCC_ATTR_MALLOC; +void *_gcry_private_malloc_secure (size_t n) _GCRY_GCC_ATTR_MALLOC; +void *_gcry_private_realloc (void *a, size_t n); +void _gcry_private_check_heap (const void *a); +void _gcry_private_free (void *a); + +#endif /* G10_STDMEM_H */ diff --git a/grub-core/lib/libgcrypt/src/types.h b/grub-core/lib/libgcrypt/src/types.h new file mode 100644 index 0000000..ee0a62b --- /dev/null +++ b/grub-core/lib/libgcrypt/src/types.h @@ -0,0 +1,128 @@ +/* types.h - some common typedefs + * Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef GCRYPT_TYPES_H +#define GCRYPT_TYPES_H + + +/* The AC_CHECK_SIZEOF() in configure fails for some machines. + * we provide some fallback values here */ +#if !SIZEOF_UNSIGNED_SHORT +#undef SIZEOF_UNSIGNED_SHORT +#define SIZEOF_UNSIGNED_SHORT 2 +#endif +#if !SIZEOF_UNSIGNED_INT +#undef SIZEOF_UNSIGNED_INT +#define SIZEOF_UNSIGNED_INT 4 +#endif +#if !SIZEOF_UNSIGNED_LONG +#undef SIZEOF_UNSIGNED_LONG +#define SIZEOF_UNSIGNED_LONG 4 +#endif + + +#include <sys/types.h> + + +#ifndef HAVE_BYTE_TYPEDEF +#undef byte /* maybe there is a macro with this name */ +/* Windows typedefs byte in the rpc headers. Avoid warning about + double definition. */ +#if !(defined(_WIN32) && defined(cbNDRContext)) + typedef unsigned char byte; +#endif +#define HAVE_BYTE_TYPEDEF +#endif + +#ifndef HAVE_USHORT_TYPEDEF +#undef ushort /* maybe there is a macro with this name */ + typedef unsigned short ushort; +#define HAVE_USHORT_TYPEDEF +#endif + +#ifndef HAVE_ULONG_TYPEDEF +#undef ulong /* maybe there is a macro with this name */ + typedef unsigned long ulong; +#define HAVE_ULONG_TYPEDEF +#endif + +#ifndef HAVE_U16_TYPEDEF +#undef u16 /* maybe there is a macro with this name */ +#if SIZEOF_UNSIGNED_INT == 2 + typedef unsigned int u16; +#elif SIZEOF_UNSIGNED_SHORT == 2 + typedef unsigned short u16; +#else +#error no typedef for u16 +#endif +#define HAVE_U16_TYPEDEF +#endif + +#ifndef HAVE_U32_TYPEDEF +#undef u32 /* maybe there is a macro with this name */ +#if SIZEOF_UNSIGNED_INT == 4 + typedef unsigned int u32; +#elif SIZEOF_UNSIGNED_LONG == 4 + typedef unsigned long u32; +#else +#error no typedef for u32 +#endif +#define HAVE_U32_TYPEDEF +#endif + +/**************** + * Warning: Some systems segfault when this u64 typedef and + * the dummy code in cipher/md.c is not available. Examples are + * Solaris and IRIX. + */ +#ifndef HAVE_U64_TYPEDEF +#undef u64 /* maybe there is a macro with this name */ +#if SIZEOF_UNSIGNED_INT == 8 + typedef unsigned int u64; +#define U64_C(c) (c ## U) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UNSIGNED_LONG == 8 + typedef unsigned long u64; +#define U64_C(c) (c ## UL) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UNSIGNED_LONG_LONG == 8 + typedef unsigned long long u64; +#define U64_C(c) (c ## ULL) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UINT64_T == 8 + typedef uint64_t u64; +#define U64_C(c) (UINT64_C(c)) +#define HAVE_U64_TYPEDEF +#endif +#endif + +typedef union { + int a; + short b; + char c[1]; + long d; +#ifdef HAVE_U64_TYPEDEF + u64 e; +#endif + float f; + double g; +} PROPERLY_ALIGNED_TYPE; + +#endif /*GCRYPT_TYPES_H*/ diff --git a/grub-core/lib/libgcrypt/src/versioninfo.rc.in b/grub-core/lib/libgcrypt/src/versioninfo.rc.in new file mode 100644 index 0000000..3199521 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/versioninfo.rc.in @@ -0,0 +1,51 @@ +/* versioninfo.rc.in - for libgcrypt + * Copyright (C) 2005, 2006 g10 Code GmbH + * + * This file is free software; as a special exception the author gives + * unlimited permission to copy and/or distribute it, with or without + * modifications, as long as this notice is preserved. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* This file is processed by configure to create versioninfo.rc */ + +#line __LINE__ "versioninfo.rc.in" + +#include <afxres.h> + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @BUILD_FILEVERSION@ + PRODUCTVERSION @BUILD_FILEVERSION@ + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x21L +#else + FILEFLAGS 0x20L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Provided under the terms of the GNU Lesser General Public License (LGPLv2.1+).\0" + VALUE "CompanyName", "g10 Code GmbH\0" + VALUE "FileDescription", "Libgcrypt - The GNU Crypto Library\0" + VALUE "FileVersion", "@LIBGCRYPT_LT_CURRENT@.@LIBGCRYPT_LT_AGE@.@LIBGCRYPT_LT_REVISION@.@BUILD_REVISION@\0" + VALUE "InternalName", "libgcrypt\0" + VALUE "LegalCopyright", "Copyright © 2012 Free Software Foundation, Inc.\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "libgcrypt.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "libgcrypt\0" + VALUE "ProductVersion", "@VERSION@\0" + VALUE "SpecialBuild", "@BUILD_TIMESTAMP@\0" + END + END +END diff --git a/grub-core/lib/libgcrypt/src/visibility.c b/grub-core/lib/libgcrypt/src/visibility.c new file mode 100644 index 0000000..2fccb01 --- /dev/null +++ b/grub-core/lib/libgcrypt/src/visibility.c @@ -0,0 +1,1486 @@ +/* visibility.c - Wrapper for all public functions. + * Copyright (C) 2007, 2008, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdarg.h> + +#define _GCRY_INCLUDED_BY_VISIBILITY_C +#include "g10lib.h" +#include "cipher-proto.h" + + + +const char * +gcry_strerror (gcry_error_t err) +{ + return _gcry_strerror (err); +} + +const char * +gcry_strsource (gcry_error_t err) +{ + return _gcry_strsource (err); +} + +gcry_err_code_t +gcry_err_code_from_errno (int err) +{ + return _gcry_err_code_from_errno (err); +} + +int +gcry_err_code_to_errno (gcry_err_code_t code) +{ + return _gcry_err_code_to_errno (code); +} + +gcry_error_t +gcry_err_make_from_errno (gcry_err_source_t source, int err) +{ + return _gcry_err_make_from_errno (source, err); +} + +gcry_err_code_t +gcry_error_from_errno (int err) +{ + return _gcry_error_from_errno (err); +} + +const char * +gcry_check_version (const char *req_version) +{ + return _gcry_check_version (req_version); +} + +gcry_error_t +gcry_control (enum gcry_ctl_cmds cmd, ...) +{ + gcry_error_t err; + va_list arg_ptr; + + va_start (arg_ptr, cmd); + err = _gcry_vcontrol (cmd, arg_ptr); + va_end(arg_ptr); + return err; +} + +gcry_error_t +gcry_sexp_new (gcry_sexp_t *retsexp, + const void *buffer, size_t length, + int autodetect) +{ + return _gcry_sexp_new (retsexp, buffer, length, autodetect); +} + +gcry_error_t +gcry_sexp_create (gcry_sexp_t *retsexp, + void *buffer, size_t length, + int autodetect, void (*freefnc) (void *)) +{ + return _gcry_sexp_create (retsexp, buffer, length, + autodetect, freefnc); +} + +gcry_error_t +gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, + const char *buffer, size_t length) +{ + return _gcry_sexp_sscan (retsexp, erroff, buffer, length); +} + +gcry_error_t +gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, + const char *format, ...) +{ + gcry_error_t err; + va_list arg_ptr; + + va_start (arg_ptr, format); + err = _gcry_sexp_vbuild (retsexp, erroff, format, arg_ptr); + va_end (arg_ptr); + return err; +} + +gcry_error_t +gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff, + const char *format, void **arg_list) +{ + return _gcry_sexp_build_array (retsexp, erroff, format, arg_list); +} + +void +gcry_sexp_release (gcry_sexp_t sexp) +{ + _gcry_sexp_release (sexp); +} + +size_t +gcry_sexp_canon_len (const unsigned char *buffer, size_t length, + size_t *erroff, gcry_error_t *errcode) +{ + return _gcry_sexp_canon_len (buffer, length, erroff, errcode); +} + +size_t +gcry_sexp_sprint (gcry_sexp_t sexp, int mode, void *buffer, size_t maxlength) +{ + return _gcry_sexp_sprint (sexp, mode, buffer, maxlength); +} + +void +gcry_sexp_dump (const gcry_sexp_t a) +{ + _gcry_sexp_dump (a); +} + +gcry_sexp_t +gcry_sexp_cons (const gcry_sexp_t a, const gcry_sexp_t b) +{ + return _gcry_sexp_cons (a, b); +} + +gcry_sexp_t +gcry_sexp_alist (const gcry_sexp_t *array) +{ + return _gcry_sexp_alist (array); +} + +gcry_sexp_t +gcry_sexp_vlist (const gcry_sexp_t a, ...) +{ + /* This is not yet implemented in sexp.c. */ + (void)a; + BUG (); + return NULL; +} + +gcry_sexp_t +gcry_sexp_append (const gcry_sexp_t a, const gcry_sexp_t n) +{ + return _gcry_sexp_append (a, n); +} + +gcry_sexp_t +gcry_sexp_prepend (const gcry_sexp_t a, const gcry_sexp_t n) +{ + return _gcry_sexp_prepend (a, n); +} + + +gcry_sexp_t +gcry_sexp_find_token (gcry_sexp_t list, const char *tok, size_t toklen) +{ + return _gcry_sexp_find_token (list, tok, toklen); +} + +int +gcry_sexp_length (const gcry_sexp_t list) +{ + return _gcry_sexp_length (list); +} + +gcry_sexp_t +gcry_sexp_nth (const gcry_sexp_t list, int number) +{ + return _gcry_sexp_nth (list, number); +} + +gcry_sexp_t +gcry_sexp_car (const gcry_sexp_t list) +{ + return _gcry_sexp_car (list); +} + +gcry_sexp_t +gcry_sexp_cdr (const gcry_sexp_t list) +{ + return _gcry_sexp_cdr (list); +} + +gcry_sexp_t +gcry_sexp_cadr (const gcry_sexp_t list) +{ + return _gcry_sexp_cadr (list); +} + +const char * +gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen) +{ + return _gcry_sexp_nth_data (list, number, datalen); +} + +char * +gcry_sexp_nth_string (gcry_sexp_t list, int number) +{ + return _gcry_sexp_nth_string (list, number); +} + +gcry_mpi_t +gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt) +{ + return _gcry_sexp_nth_mpi (list, number, mpifmt); +} + +gcry_mpi_t +gcry_mpi_new (unsigned int nbits) +{ + return _gcry_mpi_new (nbits); +} + +gcry_mpi_t +gcry_mpi_snew (unsigned int nbits) +{ + return _gcry_mpi_snew (nbits); +} + +void +gcry_mpi_release (gcry_mpi_t a) +{ + _gcry_mpi_release (a); +} + +gcry_mpi_t +gcry_mpi_copy (const gcry_mpi_t a) +{ + return _gcry_mpi_copy (a); +} + +gcry_mpi_t +gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u) +{ + return _gcry_mpi_set (w, u); +} + +gcry_mpi_t +gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u) +{ + return _gcry_mpi_set_ui (w, u); +} + +void +gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b) +{ + _gcry_mpi_swap (a, b); +} + +int +gcry_mpi_cmp (const gcry_mpi_t u, const gcry_mpi_t v) +{ + return _gcry_mpi_cmp (u, v); +} + +int +gcry_mpi_cmp_ui (const gcry_mpi_t u, unsigned long v) +{ + return _gcry_mpi_cmp_ui (u, v); +} + +gcry_error_t +gcry_mpi_scan (gcry_mpi_t *ret_mpi, enum gcry_mpi_format format, + const void *buffer, size_t buflen, + size_t *nscanned) +{ + return _gcry_mpi_scan (ret_mpi, format, buffer, buflen, nscanned); +} + +gcry_error_t +gcry_mpi_print (enum gcry_mpi_format format, + unsigned char *buffer, size_t buflen, + size_t *nwritten, + const gcry_mpi_t a) +{ + return _gcry_mpi_print (format, buffer, buflen, nwritten, a); +} + +gcry_error_t +gcry_mpi_aprint (enum gcry_mpi_format format, + unsigned char **buffer, size_t *nwritten, + const gcry_mpi_t a) +{ + return _gcry_mpi_aprint (format, buffer, nwritten, a); +} + +void +gcry_mpi_dump (const gcry_mpi_t a) +{ + _gcry_mpi_dump (a); +} + +void +gcry_mpi_add (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v) +{ + _gcry_mpi_add (w, u, v); +} + +void +gcry_mpi_add_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v) +{ + _gcry_mpi_add_ui (w, u, v); +} + +void +gcry_mpi_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) +{ + _gcry_mpi_addm (w, u, v, m); +} + +void +gcry_mpi_sub (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v) +{ + _gcry_mpi_sub (w, u, v); +} + +void +gcry_mpi_sub_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v ) +{ + _gcry_mpi_sub_ui (w, u, v); +} + +void +gcry_mpi_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) +{ + _gcry_mpi_subm (w, u, v, m); +} + +void +gcry_mpi_mul (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v) +{ + _gcry_mpi_mul (w, u, v); +} + +void +gcry_mpi_mul_ui (gcry_mpi_t w, gcry_mpi_t u, unsigned long v ) +{ + _gcry_mpi_mul_ui (w, u, v); +} + +void +gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m) +{ + _gcry_mpi_mulm (w, u, v, m); +} + +void +gcry_mpi_mul_2exp (gcry_mpi_t w, gcry_mpi_t u, unsigned long cnt) +{ + _gcry_mpi_mul_2exp (w, u, cnt); +} + +void +gcry_mpi_div (gcry_mpi_t q, gcry_mpi_t r, + gcry_mpi_t dividend, gcry_mpi_t divisor, int round) +{ + _gcry_mpi_div (q, r, dividend, divisor, round); +} + +void +gcry_mpi_mod (gcry_mpi_t r, gcry_mpi_t dividend, gcry_mpi_t divisor) +{ + _gcry_mpi_mod (r, dividend, divisor); +} + +void +gcry_mpi_powm (gcry_mpi_t w, const gcry_mpi_t b, const gcry_mpi_t e, + const gcry_mpi_t m) +{ + _gcry_mpi_powm (w, b, e, m); +} + +int +gcry_mpi_gcd (gcry_mpi_t g, gcry_mpi_t a, gcry_mpi_t b) +{ + return _gcry_mpi_gcd (g, a, b); +} + +int +gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t m) +{ + return _gcry_mpi_invm (x, a, m); +} + + +unsigned int +gcry_mpi_get_nbits (gcry_mpi_t a) +{ + return _gcry_mpi_get_nbits (a); +} + +int +gcry_mpi_test_bit (gcry_mpi_t a, unsigned int n) +{ + return _gcry_mpi_test_bit (a, n); +} + +void +gcry_mpi_set_bit (gcry_mpi_t a, unsigned int n) +{ + _gcry_mpi_set_bit (a, n); +} + +void +gcry_mpi_clear_bit (gcry_mpi_t a, unsigned int n) +{ + _gcry_mpi_clear_bit (a, n); +} + +void +gcry_mpi_set_highbit (gcry_mpi_t a, unsigned int n) +{ + _gcry_mpi_set_highbit (a, n); +} + +void +gcry_mpi_clear_highbit (gcry_mpi_t a, unsigned int n) +{ + _gcry_mpi_clear_highbit (a, n); +} + +void +gcry_mpi_rshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n) +{ + _gcry_mpi_rshift (x, a, n); +} + +void +gcry_mpi_lshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n) +{ + _gcry_mpi_lshift (x, a, n); +} + +gcry_mpi_t +gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits) +{ + return _gcry_mpi_set_opaque (a, p, nbits); +} + +void * +gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits) +{ + return _gcry_mpi_get_opaque (a, nbits); +} + +void +gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag) +{ + _gcry_mpi_set_flag (a, flag); +} + +void +gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag) +{ + _gcry_mpi_clear_flag (a, flag); +} + +int +gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag) +{ + return _gcry_mpi_get_flag (a, flag); +} + +gcry_error_t +gcry_cipher_open (gcry_cipher_hd_t *handle, + int algo, int mode, unsigned int flags) +{ + if (!fips_is_operational ()) + { + *handle = NULL; + return gpg_error (fips_not_operational ()); + } + + return _gcry_cipher_open (handle, algo, mode, flags); +} + +void +gcry_cipher_close (gcry_cipher_hd_t h) +{ + _gcry_cipher_close (h); +} + +gcry_error_t +gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_cipher_setkey (hd, key, keylen); +} + +gcry_error_t +gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_cipher_setiv (hd, iv, ivlen); +} + +gpg_error_t +gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_cipher_setctr (hd, ctr, ctrlen); +} + + +gcry_error_t +gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_cipher_ctl (h, cmd, buffer, buflen); +} + +gcry_error_t +gcry_cipher_info (gcry_cipher_hd_t h, int what, void *buffer, size_t *nbytes) +{ + return _gcry_cipher_info (h, what, buffer, nbytes); +} + +gcry_error_t +gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_cipher_algo_info (algo, what, buffer, nbytes); +} + +const char * +gcry_cipher_algo_name (int algorithm) +{ + return _gcry_cipher_algo_name (algorithm); +} + +int +gcry_cipher_map_name (const char *name) +{ + return _gcry_cipher_map_name (name); +} + +int +gcry_cipher_mode_from_oid (const char *string) +{ + return _gcry_cipher_mode_from_oid (string); +} + +gcry_error_t +gcry_cipher_encrypt (gcry_cipher_hd_t h, + void *out, size_t outsize, + const void *in, size_t inlen) +{ + if (!fips_is_operational ()) + { + /* Make sure that the plaintext will never make it to OUT. */ + if (out) + memset (out, 0x42, outsize); + return gpg_error (fips_not_operational ()); + } + + return _gcry_cipher_encrypt (h, out, outsize, in, inlen); +} + +gcry_error_t +gcry_cipher_decrypt (gcry_cipher_hd_t h, + void *out, size_t outsize, + const void *in, size_t inlen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_cipher_decrypt (h, out, outsize, in, inlen); +} + +size_t +gcry_cipher_get_algo_keylen (int algo) +{ + return _gcry_cipher_get_algo_keylen (algo); +} + +size_t +gcry_cipher_get_algo_blklen (int algo) +{ + return _gcry_cipher_get_algo_blklen (algo); +} + +gcry_error_t +gcry_cipher_list (int *list, int *list_length) +{ + return _gcry_cipher_list (list, list_length); +} + +gcry_error_t +gcry_pk_encrypt (gcry_sexp_t *result, gcry_sexp_t data, gcry_sexp_t pkey) +{ + if (!fips_is_operational ()) + { + *result = NULL; + return gpg_error (fips_not_operational ()); + } + return _gcry_pk_encrypt (result, data, pkey); +} + +gcry_error_t +gcry_pk_decrypt (gcry_sexp_t *result, gcry_sexp_t data, gcry_sexp_t skey) +{ + if (!fips_is_operational ()) + { + *result = NULL; + return gpg_error (fips_not_operational ()); + } + return _gcry_pk_decrypt (result, data, skey); +} + +gcry_error_t +gcry_pk_sign (gcry_sexp_t *result, gcry_sexp_t data, gcry_sexp_t skey) +{ + if (!fips_is_operational ()) + { + *result = NULL; + return gpg_error (fips_not_operational ()); + } + return _gcry_pk_sign (result, data, skey); +} + +gcry_error_t +gcry_pk_verify (gcry_sexp_t sigval, gcry_sexp_t data, gcry_sexp_t pkey) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + return _gcry_pk_verify (sigval, data, pkey); +} + +gcry_error_t +gcry_pk_testkey (gcry_sexp_t key) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + return _gcry_pk_testkey (key); +} + +gcry_error_t +gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) +{ + if (!fips_is_operational ()) + { + *r_key = NULL; + return gpg_error (fips_not_operational ()); + } + return _gcry_pk_genkey (r_key, s_parms); +} + +gcry_error_t +gcry_pk_ctl (int cmd, void *buffer, size_t buflen) +{ + return _gcry_pk_ctl (cmd, buffer, buflen); +} + +gcry_error_t +gcry_pk_algo_info (int algo, int what, void *buffer, size_t *nbytes) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_pk_algo_info (algo, what, buffer, nbytes); +} + +const char * +gcry_pk_algo_name (int algorithm) +{ + return _gcry_pk_algo_name (algorithm); +} + +int +gcry_pk_map_name (const char *name) +{ + return _gcry_pk_map_name (name); +} + +unsigned int +gcry_pk_get_nbits (gcry_sexp_t key) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + return 0; + } + + return _gcry_pk_get_nbits (key); +} + +unsigned char * +gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + return NULL; + } + return _gcry_pk_get_keygrip (key, array); +} + +const char * +gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + return NULL; + } + return _gcry_pk_get_curve (key, iterator, r_nbits); +} + +gcry_sexp_t +gcry_pk_get_param (int algo, const char *name) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + return NULL; + } + return _gcry_pk_get_param (algo, name); +} + +gcry_error_t +gcry_pk_list (int *list, int *list_length) +{ + return _gcry_pk_list (list, list_length); +} + +gcry_error_t +gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags) +{ + if (!fips_is_operational ()) + { + *h = NULL; + return gpg_error (fips_not_operational ()); + } + + return _gcry_md_open (h, algo, flags); +} + +void +gcry_md_close (gcry_md_hd_t hd) +{ + _gcry_md_close (hd); +} + +gcry_error_t +gcry_md_enable (gcry_md_hd_t hd, int algo) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + return _gcry_md_enable (hd, algo); +} + +gcry_error_t +gcry_md_copy (gcry_md_hd_t *bhd, gcry_md_hd_t ahd) +{ + if (!fips_is_operational ()) + { + *bhd = NULL; + return gpg_error (fips_not_operational ()); + } + return _gcry_md_copy (bhd, ahd); +} + +void +gcry_md_reset (gcry_md_hd_t hd) +{ + _gcry_md_reset (hd); +} + +gcry_error_t +gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + return _gcry_md_ctl (hd, cmd, buffer, buflen); +} + +void +gcry_md_write (gcry_md_hd_t hd, const void *buffer, size_t length) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + return; + } + _gcry_md_write (hd, buffer, length); +} + +unsigned char * +gcry_md_read (gcry_md_hd_t hd, int algo) +{ + return _gcry_md_read (hd, algo); +} + +void +gcry_md_hash_buffer (int algo, void *digest, + const void *buffer, size_t length) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + fips_signal_error ("called in non-operational state"); + } + _gcry_md_hash_buffer (algo, digest, buffer, length); +} + +int +gcry_md_get_algo (gcry_md_hd_t hd) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + fips_signal_error ("used in non-operational state"); + return 0; + } + return _gcry_md_get_algo (hd); +} + +unsigned int +gcry_md_get_algo_dlen (int algo) +{ + return _gcry_md_get_algo_dlen (algo); +} + +int +gcry_md_is_enabled (gcry_md_hd_t a, int algo) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + return 0; + } + + return _gcry_md_is_enabled (a, algo); +} + +int +gcry_md_is_secure (gcry_md_hd_t a) +{ + return _gcry_md_is_secure (a); +} + +gcry_error_t +gcry_md_info (gcry_md_hd_t h, int what, void *buffer, size_t *nbytes) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_md_info (h, what, buffer, nbytes); +} + +gcry_error_t +gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes) +{ + return _gcry_md_algo_info (algo, what, buffer, nbytes); +} + +const char * +gcry_md_algo_name (int algo) +{ + return _gcry_md_algo_name (algo); +} + +int +gcry_md_map_name (const char* name) +{ + return _gcry_md_map_name (name); +} + +gcry_error_t +gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + return _gcry_md_setkey (hd, key, keylen); +} + +void +gcry_md_debug (gcry_md_hd_t hd, const char *suffix) +{ + _gcry_md_debug (hd, suffix); +} + +gcry_error_t +gcry_md_list (int *list, int *list_length) +{ + return _gcry_md_list (list, list_length); +} + +gcry_error_t +gcry_ac_data_new (gcry_ac_data_t *data) +{ + return _gcry_ac_data_new (data); +} + +void +gcry_ac_data_destroy (gcry_ac_data_t data) +{ + _gcry_ac_data_destroy (data); +} + +gcry_error_t +gcry_ac_data_copy (gcry_ac_data_t *data_cp, gcry_ac_data_t data) +{ + return _gcry_ac_data_copy (data_cp, data); +} + +unsigned int +gcry_ac_data_length (gcry_ac_data_t data) +{ + return _gcry_ac_data_length (data); +} + +void +gcry_ac_data_clear (gcry_ac_data_t data) +{ + _gcry_ac_data_clear (data); +} + +gcry_error_t +gcry_ac_data_set (gcry_ac_data_t data, unsigned int flags, + const char *name, gcry_mpi_t mpi) +{ + return _gcry_ac_data_set (data, flags, name, mpi); +} + +gcry_error_t +gcry_ac_data_get_name (gcry_ac_data_t data, unsigned int flags, + const char *name, gcry_mpi_t *mpi) +{ + return _gcry_ac_data_get_name (data, flags, name, mpi); +} + +gcry_error_t +gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int flags, + unsigned int idx, const char **name, gcry_mpi_t *mpi) +{ + return _gcry_ac_data_get_index (data, flags, idx, name, mpi); +} + +gcry_error_t +gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp, + const char **identifiers) +{ + return _gcry_ac_data_to_sexp (data, sexp, identifiers); +} + +gcry_error_t +gcry_ac_data_from_sexp (gcry_ac_data_t *data, gcry_sexp_t sexp, + const char **identifiers) +{ + return _gcry_ac_data_from_sexp (data, sexp, identifiers); +} + +void +gcry_ac_io_init (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode, + gcry_ac_io_type_t type, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, type); + _gcry_ac_io_init_va (ac_io, mode, type, arg_ptr); + va_end (arg_ptr); +} + +void +gcry_ac_io_init_va (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode, + gcry_ac_io_type_t type, va_list ap) +{ + _gcry_ac_io_init_va (ac_io, mode, type, ap); +} + +gcry_error_t +gcry_ac_open (gcry_ac_handle_t *handle, + gcry_ac_id_t algorithm, unsigned int flags) +{ + return _gcry_ac_open (handle, algorithm, flags); +} + +void +gcry_ac_close (gcry_ac_handle_t handle) +{ + _gcry_ac_close (handle); +} + +gcry_error_t +gcry_ac_key_init (gcry_ac_key_t *key, gcry_ac_handle_t handle, + gcry_ac_key_type_t type, gcry_ac_data_t data) +{ + return _gcry_ac_key_init (key, handle, type, data); +} + +gcry_error_t +gcry_ac_key_pair_generate (gcry_ac_handle_t handle, + unsigned int nbits, void *spec, + gcry_ac_key_pair_t *key_pair, + gcry_mpi_t **miscdata) +{ + return _gcry_ac_key_pair_generate ( handle, nbits, spec, key_pair, miscdata); +} + +gcry_ac_key_t +gcry_ac_key_pair_extract (gcry_ac_key_pair_t keypair, gcry_ac_key_type_t which) +{ + return _gcry_ac_key_pair_extract (keypair, which); +} + +gcry_ac_data_t +gcry_ac_key_data_get (gcry_ac_key_t key) +{ + return _gcry_ac_key_data_get (key); +} + +gcry_error_t +gcry_ac_key_test (gcry_ac_handle_t handle, gcry_ac_key_t key) +{ + return _gcry_ac_key_test (handle, key); +} + +gcry_error_t +gcry_ac_key_get_nbits (gcry_ac_handle_t handle, + gcry_ac_key_t key, unsigned int *nbits) +{ + return _gcry_ac_key_get_nbits (handle, key, nbits); +} + +gcry_error_t +gcry_ac_key_get_grip (gcry_ac_handle_t handle, gcry_ac_key_t key, + unsigned char *key_grip) +{ + return _gcry_ac_key_get_grip (handle, key, key_grip); +} + +void +gcry_ac_key_destroy (gcry_ac_key_t key) +{ + _gcry_ac_key_destroy (key); +} + +void +gcry_ac_key_pair_destroy (gcry_ac_key_pair_t key_pair) +{ + _gcry_ac_key_pair_destroy (key_pair); +} + +gcry_error_t +gcry_ac_data_encode (gcry_ac_em_t method, unsigned int flags, void *options, + gcry_ac_io_t *io_read, gcry_ac_io_t *io_write) +{ + return _gcry_ac_data_encode (method, flags, options, io_read, io_write); +} + +gcry_error_t +gcry_ac_data_decode (gcry_ac_em_t method, unsigned int flags, void *options, + gcry_ac_io_t *io_read, gcry_ac_io_t *io_write) +{ + return _gcry_ac_data_decode (method, flags, options, io_read, io_write); +} + +gcry_error_t +gcry_ac_data_encrypt (gcry_ac_handle_t handle, + unsigned int flags, + gcry_ac_key_t key, + gcry_mpi_t data_plain, + gcry_ac_data_t *data_encrypted) +{ + return _gcry_ac_data_encrypt (handle, flags, key, + data_plain, data_encrypted); +} + +gcry_error_t +gcry_ac_data_decrypt (gcry_ac_handle_t handle, + unsigned int flags, + gcry_ac_key_t key, + gcry_mpi_t *data_plain, + gcry_ac_data_t data_encrypted) +{ + return _gcry_ac_data_decrypt (handle, flags, key, + data_plain, data_encrypted); +} + +gcry_error_t +gcry_ac_data_sign (gcry_ac_handle_t handle, + gcry_ac_key_t key, + gcry_mpi_t data, + gcry_ac_data_t *data_signature) +{ + return _gcry_ac_data_sign (handle, key, data, data_signature); +} + +gcry_error_t +gcry_ac_data_verify (gcry_ac_handle_t handle, + gcry_ac_key_t key, + gcry_mpi_t data, + gcry_ac_data_t data_signature) +{ + return _gcry_ac_data_verify (handle, key, data, data_signature); +} + +gcry_error_t +gcry_ac_data_encrypt_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_cipher) +{ + return _gcry_ac_data_encrypt_scheme (handle, scheme, flags, opts, key, + io_message, io_cipher); +} + +gcry_error_t +gcry_ac_data_decrypt_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_cipher, + gcry_ac_io_t *io_message) +{ + return _gcry_ac_data_decrypt_scheme (handle, scheme, flags, opts, key, + io_cipher, io_message); +} + +gcry_error_t +gcry_ac_data_sign_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_signature) +{ + return _gcry_ac_data_sign_scheme (handle, scheme, flags, opts, key, + io_message, io_signature); +} + +gcry_error_t +gcry_ac_data_verify_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_signature) +{ + return _gcry_ac_data_verify_scheme (handle, scheme, flags, opts, key, + io_message, io_signature); +} + +gcry_error_t +gcry_ac_id_to_name (gcry_ac_id_t algorithm, const char **name) +{ + /* This function is deprecated. We implement it in terms of the + suggested replacement. */ + const char *tmp = _gcry_pk_algo_name (algorithm); + if (!*tmp) + return gcry_error (GPG_ERR_PUBKEY_ALGO); + *name = tmp; + return 0; +} + +gcry_error_t +gcry_ac_name_to_id (const char *name, gcry_ac_id_t *algorithm) +{ + /* This function is deprecated. We implement it in terms of the + suggested replacement. */ + int algo = _gcry_pk_map_name (name); + if (!algo) + return gcry_error (GPG_ERR_PUBKEY_ALGO); + *algorithm = algo; + return 0; +} + +gpg_error_t +gcry_kdf_derive (const void *passphrase, size_t passphraselen, + int algo, int hashalgo, + const void *salt, size_t saltlen, + unsigned long iterations, + size_t keysize, void *keybuffer) +{ + return _gcry_kdf_derive (passphrase, passphraselen, algo, hashalgo, + salt, saltlen, iterations, keysize, keybuffer); +} + +void +gcry_randomize (void *buffer, size_t length, enum gcry_random_level level) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + fips_signal_fatal_error ("called in non-operational state"); + fips_noreturn (); + } + _gcry_randomize (buffer, length, level); +} + +gcry_error_t +gcry_random_add_bytes (const void *buffer, size_t length, int quality) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + return _gcry_random_add_bytes (buffer, length, quality); +} + +void * +gcry_random_bytes (size_t nbytes, enum gcry_random_level level) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + fips_signal_fatal_error ("called in non-operational state"); + fips_noreturn (); + } + + return _gcry_random_bytes (nbytes,level); +} + +void * +gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + fips_signal_fatal_error ("called in non-operational state"); + fips_noreturn (); + } + + return _gcry_random_bytes_secure (nbytes, level); +} + +void +gcry_mpi_randomize (gcry_mpi_t w, + unsigned int nbits, enum gcry_random_level level) +{ + _gcry_mpi_randomize (w, nbits, level); +} + +void +gcry_create_nonce (void *buffer, size_t length) +{ + if (!fips_is_operational ()) + { + (void)fips_not_operational (); + fips_signal_fatal_error ("called in non-operational state"); + fips_noreturn (); + } + _gcry_create_nonce (buffer, length); +} + +gcry_error_t +gcry_prime_generate (gcry_mpi_t *prime, + unsigned int prime_bits, + unsigned int factor_bits, + gcry_mpi_t **factors, + gcry_prime_check_func_t cb_func, + void *cb_arg, + gcry_random_level_t random_level, + unsigned int flags) +{ + return _gcry_prime_generate (prime, prime_bits, factor_bits, factors, + cb_func, cb_arg, random_level, flags); +} + +gcry_error_t +gcry_prime_group_generator (gcry_mpi_t *r_g, + gcry_mpi_t prime, gcry_mpi_t *factors, + gcry_mpi_t start_g) +{ + return _gcry_prime_group_generator (r_g, prime, factors, start_g); +} + +void +gcry_prime_release_factors (gcry_mpi_t *factors) +{ + _gcry_prime_release_factors (factors); +} + +gcry_error_t +gcry_prime_check (gcry_mpi_t x, unsigned int flags) +{ + return _gcry_prime_check (x, flags); +} + +void +gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data) +{ + _gcry_set_progress_handler (cb, cb_data); +} + +void +gcry_set_allocation_handler (gcry_handler_alloc_t func_alloc, + gcry_handler_alloc_t func_alloc_secure, + gcry_handler_secure_check_t func_secure_check, + gcry_handler_realloc_t func_realloc, + gcry_handler_free_t func_free) +{ + _gcry_set_allocation_handler (func_alloc, func_alloc_secure, + func_secure_check, func_realloc, func_free); +} + +void +gcry_set_outofcore_handler (gcry_handler_no_mem_t h, void *opaque) +{ + _gcry_set_outofcore_handler (h, opaque); +} + +void +gcry_set_fatalerror_handler (gcry_handler_error_t fnc, void *opaque) +{ + _gcry_set_fatalerror_handler (fnc, opaque); +} + +void +gcry_set_log_handler (gcry_handler_log_t f, void *opaque) +{ + _gcry_set_log_handler (f, opaque); +} + +void +gcry_set_gettext_handler (const char *(*f)(const char*)) +{ + _gcry_set_gettext_handler (f); +} + +void * +gcry_malloc (size_t n) +{ + return _gcry_malloc (n); +} + +void * +gcry_calloc (size_t n, size_t m) +{ + return _gcry_calloc (n, m); +} + +void * +gcry_malloc_secure (size_t n) +{ + return _gcry_malloc_secure (n); +} + +void * +gcry_calloc_secure (size_t n, size_t m) +{ + return _gcry_calloc_secure (n,m); +} + +void * +gcry_realloc (void *a, size_t n) +{ + return _gcry_realloc (a, n); +} + +char * +gcry_strdup (const char *string) +{ + return _gcry_strdup (string); +} + +void * +gcry_xmalloc (size_t n) +{ + return _gcry_xmalloc (n); +} + +void * +gcry_xcalloc (size_t n, size_t m) +{ + return _gcry_xcalloc (n, m); +} + +void * +gcry_xmalloc_secure (size_t n) +{ + return _gcry_xmalloc_secure (n); +} + +void * +gcry_xcalloc_secure (size_t n, size_t m) +{ + return _gcry_xcalloc_secure (n, m); +} + +void * +gcry_xrealloc (void *a, size_t n) +{ + return _gcry_xrealloc (a, n); +} + +char * +gcry_xstrdup (const char *a) +{ + return _gcry_xstrdup (a); +} + +void +gcry_free (void *a) +{ + _gcry_free (a); +} + +int +gcry_is_secure (const void *a) +{ + return _gcry_is_secure (a); +} + + +gcry_error_t +gcry_cipher_register (gcry_cipher_spec_t *cipher, int *algorithm_id, + gcry_module_t *module) +{ + return _gcry_cipher_register (cipher, NULL, algorithm_id, module); +} + +void +gcry_cipher_unregister (gcry_module_t module) +{ + _gcry_cipher_unregister (module); +} + +gcry_error_t +gcry_pk_register (gcry_pk_spec_t *pubkey, unsigned int *algorithm_id, + gcry_module_t *module) +{ + return _gcry_pk_register (pubkey, NULL, algorithm_id, module); +} + +void +gcry_pk_unregister (gcry_module_t module) +{ + _gcry_pk_unregister (module); +} + +gcry_error_t +gcry_md_register (gcry_md_spec_t *digest, unsigned int *algorithm_id, + gcry_module_t *module) +{ + return _gcry_md_register (digest, NULL, algorithm_id, module); +} + +void +gcry_md_unregister (gcry_module_t module) +{ + _gcry_md_unregister (module); +} diff --git a/grub-core/lib/libgcrypt/src/visibility.h b/grub-core/lib/libgcrypt/src/visibility.h new file mode 100644 index 0000000..3c1e8aa --- /dev/null +++ b/grub-core/lib/libgcrypt/src/visibility.h @@ -0,0 +1,807 @@ +/* visibility.h - Set visibility attribute + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GCRY_VISIBILITY_H +#define GCRY_VISIBILITY_H + +/* Redefine all public symbols with an underscore unless we already + use the underscore prefixed version internally. */ +#define gcry_check_version _gcry_check_version +#define gcry_control _gcry_control + +#define gcry_set_allocation_handler _gcry_set_allocation_handler +#define gcry_set_fatalerror_handler _gcry_set_fatalerror_handler +#define gcry_set_gettext_handler _gcry_set_gettext_handler +#define gcry_set_log_handler _gcry_set_log_handler +#define gcry_set_outofcore_handler _gcry_set_outofcore_handler +#define gcry_set_progress_handler _gcry_set_progress_handler +#define gcry_err_code_from_errno _gcry_err_code_from_errno +#define gcry_err_code_to_errno _gcry_err_code_to_errno +#define gcry_err_make_from_errno _gcry_err_make_from_errno +#define gcry_error_from_errno _gcry_error_from_errno +#define gcry_strerror _gcry_strerror +#define gcry_strsource _gcry_strsource + +#define gcry_free _gcry_free +#define gcry_malloc _gcry_malloc +#define gcry_malloc_secure _gcry_malloc_secure +#define gcry_calloc _gcry_calloc +#define gcry_calloc_secure _gcry_calloc_secure +#define gcry_realloc _gcry_realloc +#define gcry_strdup _gcry_strdup +#define gcry_is_secure _gcry_is_secure +#define gcry_xcalloc _gcry_xcalloc +#define gcry_xcalloc_secure _gcry_xcalloc_secure +#define gcry_xmalloc _gcry_xmalloc +#define gcry_xmalloc_secure _gcry_xmalloc_secure +#define gcry_xrealloc _gcry_xrealloc +#define gcry_xstrdup _gcry_xstrdup + +#define gcry_md_algo_info _gcry_md_algo_info +#define gcry_md_algo_name _gcry_md_algo_name +#define gcry_md_close _gcry_md_close +#define gcry_md_copy _gcry_md_copy +#define gcry_md_ctl _gcry_md_ctl +#define gcry_md_enable _gcry_md_enable +#define gcry_md_get _gcry_md_get +#define gcry_md_get_algo _gcry_md_get_algo +#define gcry_md_get_algo_dlen _gcry_md_get_algo_dlen +#define gcry_md_hash_buffer _gcry_md_hash_buffer +#define gcry_md_info _gcry_md_info +#define gcry_md_is_enabled _gcry_md_is_enabled +#define gcry_md_is_secure _gcry_md_is_secure +#define gcry_md_list _gcry_md_list +#define gcry_md_map_name _gcry_md_map_name +#define gcry_md_open _gcry_md_open +#define gcry_md_read _gcry_md_read +/* gcry_md_register and _gcry_md_register differ. */ +#define gcry_md_unregister _gcry_md_unregister +#define gcry_md_reset _gcry_md_reset +#define gcry_md_setkey _gcry_md_setkey +#define gcry_md_write _gcry_md_write +#define gcry_md_debug _gcry_md_debug + +#define gcry_cipher_algo_info _gcry_cipher_algo_info +#define gcry_cipher_algo_name _gcry_cipher_algo_name +#define gcry_cipher_close _gcry_cipher_close +#define gcry_cipher_setkey _gcry_cipher_setkey +#define gcry_cipher_setiv _gcry_cipher_setiv +#define gcry_cipher_setctr _gcry_cipher_setctr +#define gcry_cipher_ctl _gcry_cipher_ctl +#define gcry_cipher_decrypt _gcry_cipher_decrypt +#define gcry_cipher_encrypt _gcry_cipher_encrypt +#define gcry_cipher_get_algo_blklen _gcry_cipher_get_algo_blklen +#define gcry_cipher_get_algo_keylen _gcry_cipher_get_algo_keylen +#define gcry_cipher_info _gcry_cipher_info +#define gcry_cipher_list _gcry_cipher_list +#define gcry_cipher_map_name _gcry_cipher_map_name +#define gcry_cipher_mode_from_oid _gcry_cipher_mode_from_oid +#define gcry_cipher_open _gcry_cipher_open +/* gcry_cipher_register and _gcry_cipher_register differ. */ +#define gcry_cipher_unregister _gcry_cipher_unregister + +#define gcry_pk_algo_info _gcry_pk_algo_info +#define gcry_pk_algo_name _gcry_pk_algo_name +#define gcry_pk_ctl _gcry_pk_ctl +#define gcry_pk_decrypt _gcry_pk_decrypt +#define gcry_pk_encrypt _gcry_pk_encrypt +#define gcry_pk_genkey _gcry_pk_genkey +#define gcry_pk_get_keygrip _gcry_pk_get_keygrip +#define gcry_pk_get_curve _gcry_pk_get_curve +#define gcry_pk_get_param _gcry_pk_get_param +#define gcry_pk_get_nbits _gcry_pk_get_nbits +#define gcry_pk_list _gcry_pk_list +#define gcry_pk_map_name _gcry_pk_map_name +/* gcry_pk_register and _gcry_pk_register differ. */ +#define gcry_pk_unregister _gcry_pk_unregister +#define gcry_pk_sign _gcry_pk_sign +#define gcry_pk_testkey _gcry_pk_testkey +#define gcry_pk_verify _gcry_pk_verify + +#define gcry_ac_data_new _gcry_ac_data_new +#define gcry_ac_data_destroy _gcry_ac_data_destroy +#define gcry_ac_data_copy _gcry_ac_data_copy +#define gcry_ac_data_length _gcry_ac_data_length +#define gcry_ac_data_clear _gcry_ac_data_clear +#define gcry_ac_data_set _gcry_ac_data_set +#define gcry_ac_data_get_name _gcry_ac_data_get_name +#define gcry_ac_data_get_index _gcry_ac_data_get_index +#define gcry_ac_open _gcry_ac_open +#define gcry_ac_close _gcry_ac_close +#define gcry_ac_key_init _gcry_ac_key_init +#define gcry_ac_key_pair_generate _gcry_ac_key_pair_generate +#define gcry_ac_key_pair_extract _gcry_ac_key_pair_extract +#define gcry_ac_key_data_get _gcry_ac_key_data_get +#define gcry_ac_key_test _gcry_ac_key_test +#define gcry_ac_key_get_nbits _gcry_ac_key_get_nbits +#define gcry_ac_key_get_grip _gcry_ac_key_get_grip +#define gcry_ac_key_destroy _gcry_ac_key_destroy +#define gcry_ac_key_pair_destroy _gcry_ac_key_pair_destroy +#define gcry_ac_data_encrypt _gcry_ac_data_encrypt +#define gcry_ac_data_decrypt _gcry_ac_data_decrypt +#define gcry_ac_data_sign _gcry_ac_data_sign +#define gcry_ac_data_verify _gcry_ac_data_verify +#define gcry_ac_id_to_name _gcry_ac_id_to_name +#define gcry_ac_name_to_id _gcry_ac_name_to_id +#define gcry_ac_data_encode _gcry_ac_data_encode +#define gcry_ac_data_decode _gcry_ac_data_decode +#define gcry_ac_mpi_to_os _gcry_ac_mpi_to_os +#define gcry_ac_mpi_to_os_alloc _gcry_ac_mpi_to_os_alloc +#define gcry_ac_os_to_mpi _gcry_ac_os_to_mpi +#define gcry_ac_data_encrypt_scheme _gcry_ac_data_encrypt_scheme +#define gcry_ac_data_decrypt_scheme _gcry_ac_data_decrypt_scheme +#define gcry_ac_data_sign_scheme _gcry_ac_data_sign_scheme +#define gcry_ac_data_verify_scheme _gcry_ac_data_verify_scheme +#define gcry_ac_data_to_sexp _gcry_ac_data_to_sexp +#define gcry_ac_data_from_sexp _gcry_ac_data_from_sexp +#define gcry_ac_io_init _gcry_ac_io_init +#define gcry_ac_io_init_va _gcry_ac_io_init_va + +#define gcry_kdf_derive _gcry_kdf_derive + +#define gcry_prime_check _gcry_prime_check +#define gcry_prime_generate _gcry_prime_generate +#define gcry_prime_group_generator _gcry_prime_group_generator +#define gcry_prime_release_factors _gcry_prime_release_factors + +#define gcry_random_add_bytes _gcry_random_add_bytes +#define gcry_random_bytes _gcry_random_bytes +#define gcry_random_bytes_secure _gcry_random_bytes_secure +#define gcry_randomize _gcry_randomize +#define gcry_create_nonce _gcry_create_nonce + +#define gcry_sexp_alist _gcry_sexp_alist +#define gcry_sexp_append _gcry_sexp_append +#define gcry_sexp_build _gcry_sexp_build +#define gcry_sexp_build_array _gcry_sexp_build_array +#define gcry_sexp_cadr _gcry_sexp_cadr +#define gcry_sexp_canon_len _gcry_sexp_canon_len +#define gcry_sexp_car _gcry_sexp_car +#define gcry_sexp_cdr _gcry_sexp_cdr +#define gcry_sexp_cons _gcry_sexp_cons +#define gcry_sexp_create _gcry_sexp_create +#define gcry_sexp_dump _gcry_sexp_dump +#define gcry_sexp_find_token _gcry_sexp_find_token +#define gcry_sexp_length _gcry_sexp_length +#define gcry_sexp_new _gcry_sexp_new +#define gcry_sexp_nth _gcry_sexp_nth +#define gcry_sexp_nth_data _gcry_sexp_nth_data +#define gcry_sexp_nth_mpi _gcry_sexp_nth_mpi +#define gcry_sexp_prepend _gcry_sexp_prepend +#define gcry_sexp_release _gcry_sexp_release +#define gcry_sexp_sprint _gcry_sexp_sprint +#define gcry_sexp_sscan _gcry_sexp_sscan +#define gcry_sexp_vlist _gcry_sexp_vlist +#define gcry_sexp_nth_string _gcry_sexp_nth_string + +#define gcry_mpi_add _gcry_mpi_add +#define gcry_mpi_add_ui _gcry_mpi_add_ui +#define gcry_mpi_addm _gcry_mpi_addm +#define gcry_mpi_aprint _gcry_mpi_aprint +#define gcry_mpi_clear_bit _gcry_mpi_clear_bit +#define gcry_mpi_clear_flag _gcry_mpi_clear_flag +#define gcry_mpi_clear_highbit _gcry_mpi_clear_highbit +#define gcry_mpi_cmp _gcry_mpi_cmp +#define gcry_mpi_cmp_ui _gcry_mpi_cmp_ui +#define gcry_mpi_copy _gcry_mpi_copy +#define gcry_mpi_div _gcry_mpi_div +#define gcry_mpi_dump _gcry_mpi_dump +#define gcry_mpi_gcd _gcry_mpi_gcd +#define gcry_mpi_get_flag _gcry_mpi_get_flag +#define gcry_mpi_get_nbits _gcry_mpi_get_nbits +#define gcry_mpi_get_opaque _gcry_mpi_get_opaque +#define gcry_mpi_invm _gcry_mpi_invm +#define gcry_mpi_mod _gcry_mpi_mod +#define gcry_mpi_mul _gcry_mpi_mul +#define gcry_mpi_mul_2exp _gcry_mpi_mul_2exp +#define gcry_mpi_mul_ui _gcry_mpi_mul_ui +#define gcry_mpi_mulm _gcry_mpi_mulm +#define gcry_mpi_new _gcry_mpi_new +#define gcry_mpi_powm _gcry_mpi_powm +#define gcry_mpi_print _gcry_mpi_print +#define gcry_mpi_randomize _gcry_mpi_randomize +#define gcry_mpi_release _gcry_mpi_release +#define gcry_mpi_rshift _gcry_mpi_rshift +#define gcry_mpi_lshift _gcry_mpi_lshift +#define gcry_mpi_scan _gcry_mpi_scan +#define gcry_mpi_set _gcry_mpi_set +#define gcry_mpi_set_bit _gcry_mpi_set_bit +#define gcry_mpi_set_flag _gcry_mpi_set_flag +#define gcry_mpi_set_highbit _gcry_mpi_set_highbit +#define gcry_mpi_set_opaque _gcry_mpi_set_opaque +#define gcry_mpi_set_ui _gcry_mpi_set_ui +#define gcry_mpi_snew _gcry_mpi_snew +#define gcry_mpi_sub _gcry_mpi_sub +#define gcry_mpi_sub_ui _gcry_mpi_sub_ui +#define gcry_mpi_subm _gcry_mpi_subm +#define gcry_mpi_swap _gcry_mpi_swap +#define gcry_mpi_test_bit _gcry_mpi_test_bit + + +/* Include the main header here so that public symbols are mapped to + the internal underscored ones. */ +#ifdef _GCRY_INCLUDED_BY_VISIBILITY_C + /* We need to redeclare the deprecated functions without the + deprecated attribute. */ +# define GCRYPT_NO_DEPRECATED +# include "gcrypt.h" +/* The algorithm IDs. */ + gcry_error_t gcry_ac_data_new (gcry_ac_data_t *data); + void gcry_ac_data_destroy (gcry_ac_data_t data); + gcry_error_t gcry_ac_data_copy (gcry_ac_data_t *data_cp, + gcry_ac_data_t data); + unsigned int gcry_ac_data_length (gcry_ac_data_t data); + void gcry_ac_data_clear (gcry_ac_data_t data); + gcry_error_t gcry_ac_data_set (gcry_ac_data_t data, unsigned int flags, + const char *name, gcry_mpi_t mpi); + gcry_error_t gcry_ac_data_get_name (gcry_ac_data_t data, unsigned int flags, + const char *name, gcry_mpi_t *mpi); + gcry_error_t gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int flags, + unsigned int idx, + const char **name, gcry_mpi_t *mpi); + gcry_error_t gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp, + const char **identifiers); + gcry_error_t gcry_ac_data_from_sexp (gcry_ac_data_t *data, gcry_sexp_t sexp, + const char **identifiers); + void gcry_ac_io_init (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode, + gcry_ac_io_type_t type, ...); + void gcry_ac_io_init_va (gcry_ac_io_t *ac_io, gcry_ac_io_mode_t mode, + gcry_ac_io_type_t type, va_list ap); + gcry_error_t gcry_ac_open (gcry_ac_handle_t *handle, + gcry_ac_id_t algorithm, unsigned int flags); + void gcry_ac_close (gcry_ac_handle_t handle); + gcry_error_t gcry_ac_key_init (gcry_ac_key_t *key, gcry_ac_handle_t handle, + gcry_ac_key_type_t type, gcry_ac_data_t data); + gcry_error_t gcry_ac_key_pair_generate (gcry_ac_handle_t handle, + unsigned int nbits, void *spec, + gcry_ac_key_pair_t *key_pair, + gcry_mpi_t **misc_data); + gcry_ac_key_t gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair, + gcry_ac_key_type_t which); + gcry_ac_data_t gcry_ac_key_data_get (gcry_ac_key_t key); + gcry_error_t gcry_ac_key_test (gcry_ac_handle_t handle, gcry_ac_key_t key); + gcry_error_t gcry_ac_key_get_nbits (gcry_ac_handle_t handle, + gcry_ac_key_t key, unsigned int *nbits); + gcry_error_t gcry_ac_key_get_grip (gcry_ac_handle_t handle, gcry_ac_key_t key, + unsigned char *key_grip); + void gcry_ac_key_destroy (gcry_ac_key_t key); + void gcry_ac_key_pair_destroy (gcry_ac_key_pair_t key_pair); + gcry_error_t gcry_ac_data_encode (gcry_ac_em_t method, + unsigned int flags, void *options, + gcry_ac_io_t *io_read, + gcry_ac_io_t *io_write); + gcry_error_t gcry_ac_data_decode (gcry_ac_em_t method, + unsigned int flags, void *options, + gcry_ac_io_t *io_read, + gcry_ac_io_t *io_write); + gcry_error_t gcry_ac_data_encrypt (gcry_ac_handle_t handle, + unsigned int flags, + gcry_ac_key_t key, + gcry_mpi_t data_plain, + gcry_ac_data_t *data_encrypted); + gcry_error_t gcry_ac_data_decrypt (gcry_ac_handle_t handle, + unsigned int flags, + gcry_ac_key_t key, + gcry_mpi_t *data_plain, + gcry_ac_data_t data_encrypted); + gcry_error_t gcry_ac_data_sign (gcry_ac_handle_t handle, + gcry_ac_key_t key, + gcry_mpi_t data, + gcry_ac_data_t *data_signature); + gcry_error_t gcry_ac_data_verify (gcry_ac_handle_t handle, + gcry_ac_key_t key, + gcry_mpi_t data, + gcry_ac_data_t data_signature); + gcry_error_t gcry_ac_data_encrypt_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_cipher); + gcry_error_t gcry_ac_data_decrypt_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_cipher, + gcry_ac_io_t *io_message); + gcry_error_t gcry_ac_data_sign_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_signature); + gcry_error_t gcry_ac_data_verify_scheme (gcry_ac_handle_t handle, + gcry_ac_scheme_t scheme, + unsigned int flags, void *opts, + gcry_ac_key_t key, + gcry_ac_io_t *io_message, + gcry_ac_io_t *io_signature); + gcry_error_t gcry_ac_id_to_name (gcry_ac_id_t algorithm, const char **name); + gcry_error_t gcry_ac_name_to_id (const char *name, gcry_ac_id_t *algorithm); +#else +# include "gcrypt.h" +#endif + +/* Prototypes of functions exported but not ready for use. */ +gcry_err_code_t gcry_md_get (gcry_md_hd_t hd, int algo, + unsigned char *buffer, int buflen); +void gcry_ac_mpi_to_os (gcry_mpi_t mpi, unsigned char *os, size_t os_n); +gcry_error_t gcry_ac_mpi_to_os_alloc (gcry_mpi_t mpi, unsigned char **os, + size_t *os_n); +void gcry_ac_os_to_mpi (gcry_mpi_t mpi, unsigned char *os, size_t os_n); + + + +/* Our use of the ELF visibility feature works by passing + -fvisibiliy=hidden on the command line and by explicitly marking + all exported functions as visible. + + NOTE: When adding new functions, please make sure to add them to + libgcrypt.vers and libgcrypt.def as well. */ + +#ifdef _GCRY_INCLUDED_BY_VISIBILITY_C + +/* A macro to flag a function as visible. Note that we take the + definition from the mapped name. */ +#ifdef GCRY_USE_VISIBILITY +# define MARK_VISIBLE(name) \ + extern __typeof__ (_##name) name __attribute__ ((visibility("default"))); +# define MARK_VISIBLEX(name) \ + extern __typeof__ (name) name __attribute__ ((visibility("default"))); +#else +# define MARK_VISIBLE(name) /* */ +# define MARK_VISIBLEX(name) /* */ +#endif + + +/* First undef all redefined symbols so that we set the attribute on + the correct version name. */ +#undef gcry_check_version +#undef gcry_control + +#undef gcry_set_allocation_handler +#undef gcry_set_fatalerror_handler +#undef gcry_set_gettext_handler +#undef gcry_set_log_handler +#undef gcry_set_outofcore_handler +#undef gcry_set_progress_handler +#undef gcry_err_code_from_errno +#undef gcry_err_code_to_errno +#undef gcry_err_make_from_errno +#undef gcry_error_from_errno +#undef gcry_strerror +#undef gcry_strsource + +#undef gcry_free +#undef gcry_malloc +#undef gcry_malloc_secure +#undef gcry_calloc +#undef gcry_calloc_secure +#undef gcry_realloc +#undef gcry_strdup +#undef gcry_is_secure +#undef gcry_xcalloc +#undef gcry_xcalloc_secure +#undef gcry_xmalloc +#undef gcry_xmalloc_secure +#undef gcry_xrealloc +#undef gcry_xstrdup + +#undef gcry_md_algo_info +#undef gcry_md_algo_name +#undef gcry_md_close +#undef gcry_md_copy +#undef gcry_md_ctl +#undef gcry_md_enable +#undef gcry_md_get +#undef gcry_md_get_algo +#undef gcry_md_get_algo_dlen +#undef gcry_md_hash_buffer +#undef gcry_md_info +#undef gcry_md_is_enabled +#undef gcry_md_is_secure +#undef gcry_md_list +#undef gcry_md_map_name +#undef gcry_md_open +#undef gcry_md_read +/* gcry_md_register is not anymore a macro. */ +#undef gcry_md_unregister +#undef gcry_md_reset +#undef gcry_md_setkey +#undef gcry_md_write +#undef gcry_md_debug + +#undef gcry_cipher_algo_info +#undef gcry_cipher_algo_name +#undef gcry_cipher_close +#undef gcry_cipher_setkey +#undef gcry_cipher_setiv +#undef gcry_cipher_setctr +#undef gcry_cipher_ctl +#undef gcry_cipher_decrypt +#undef gcry_cipher_encrypt +#undef gcry_cipher_get_algo_blklen +#undef gcry_cipher_get_algo_keylen +#undef gcry_cipher_info +#undef gcry_cipher_list +#undef gcry_cipher_map_name +#undef gcry_cipher_mode_from_oid +#undef gcry_cipher_open +/* gcry_cipher_register is not anymore a macro. */ +#undef gcry_cipher_unregister + +#undef gcry_pk_algo_info +#undef gcry_pk_algo_name +#undef gcry_pk_ctl +#undef gcry_pk_decrypt +#undef gcry_pk_encrypt +#undef gcry_pk_genkey +#undef gcry_pk_get_keygrip +#undef gcry_pk_get_curve +#undef gcry_pk_get_param +#undef gcry_pk_get_nbits +#undef gcry_pk_list +#undef gcry_pk_map_name +/* gcry_pk_register is not anymore a macro. */ +#undef gcry_pk_unregister +#undef gcry_pk_sign +#undef gcry_pk_testkey +#undef gcry_pk_verify + +#undef gcry_ac_data_new +#undef gcry_ac_data_destroy +#undef gcry_ac_data_copy +#undef gcry_ac_data_length +#undef gcry_ac_data_clear +#undef gcry_ac_data_set +#undef gcry_ac_data_get_name +#undef gcry_ac_data_get_index +#undef gcry_ac_open +#undef gcry_ac_close +#undef gcry_ac_key_init +#undef gcry_ac_key_pair_generate +#undef gcry_ac_key_pair_extract +#undef gcry_ac_key_data_get +#undef gcry_ac_key_test +#undef gcry_ac_key_get_nbits +#undef gcry_ac_key_get_grip +#undef gcry_ac_key_destroy +#undef gcry_ac_key_pair_destroy +#undef gcry_ac_data_encrypt +#undef gcry_ac_data_decrypt +#undef gcry_ac_data_sign +#undef gcry_ac_data_verify +#undef gcry_ac_id_to_name +#undef gcry_ac_name_to_id +#undef gcry_ac_data_encode +#undef gcry_ac_data_decode +#undef gcry_ac_mpi_to_os +#undef gcry_ac_mpi_to_os_alloc +#undef gcry_ac_os_to_mpi +#undef gcry_ac_data_encrypt_scheme +#undef gcry_ac_data_decrypt_scheme +#undef gcry_ac_data_sign_scheme +#undef gcry_ac_data_verify_scheme +#undef gcry_ac_data_to_sexp +#undef gcry_ac_data_from_sexp +#undef gcry_ac_io_init +#undef gcry_ac_io_init_va + +#undef gcry_kdf_derive + +#undef gcry_prime_check +#undef gcry_prime_generate +#undef gcry_prime_group_generator +#undef gcry_prime_release_factors + +#undef gcry_random_add_bytes +#undef gcry_random_bytes +#undef gcry_random_bytes_secure +#undef gcry_randomize +#undef gcry_create_nonce + +#undef gcry_sexp_alist +#undef gcry_sexp_append +#undef gcry_sexp_build +#undef gcry_sexp_build_array +#undef gcry_sexp_cadr +#undef gcry_sexp_canon_len +#undef gcry_sexp_car +#undef gcry_sexp_cdr +#undef gcry_sexp_cons +#undef gcry_sexp_create +#undef gcry_sexp_dump +#undef gcry_sexp_find_token +#undef gcry_sexp_length +#undef gcry_sexp_new +#undef gcry_sexp_nth +#undef gcry_sexp_nth_data +#undef gcry_sexp_nth_mpi +#undef gcry_sexp_prepend +#undef gcry_sexp_release +#undef gcry_sexp_sprint +#undef gcry_sexp_sscan +#undef gcry_sexp_vlist +#undef gcry_sexp_nth_string + +#undef gcry_mpi_add +#undef gcry_mpi_add_ui +#undef gcry_mpi_addm +#undef gcry_mpi_aprint +#undef gcry_mpi_clear_bit +#undef gcry_mpi_clear_flag +#undef gcry_mpi_clear_highbit +#undef gcry_mpi_cmp +#undef gcry_mpi_cmp_ui +#undef gcry_mpi_copy +#undef gcry_mpi_div +#undef gcry_mpi_dump +#undef gcry_mpi_gcd +#undef gcry_mpi_get_flag +#undef gcry_mpi_get_nbits +#undef gcry_mpi_get_opaque +#undef gcry_mpi_invm +#undef gcry_mpi_mod +#undef gcry_mpi_mul +#undef gcry_mpi_mul_2exp +#undef gcry_mpi_mul_ui +#undef gcry_mpi_mulm +#undef gcry_mpi_new +#undef gcry_mpi_powm +#undef gcry_mpi_print +#undef gcry_mpi_randomize +#undef gcry_mpi_release +#undef gcry_mpi_rshift +#undef gcry_mpi_lshift +#undef gcry_mpi_scan +#undef gcry_mpi_set +#undef gcry_mpi_set_bit +#undef gcry_mpi_set_flag +#undef gcry_mpi_set_highbit +#undef gcry_mpi_set_opaque +#undef gcry_mpi_set_ui +#undef gcry_mpi_snew +#undef gcry_mpi_sub +#undef gcry_mpi_sub_ui +#undef gcry_mpi_subm +#undef gcry_mpi_swap +#undef gcry_mpi_test_bit + + +/* Now mark all symbols. */ + +MARK_VISIBLE (gcry_check_version) +MARK_VISIBLE (gcry_control) + +MARK_VISIBLE (gcry_set_allocation_handler) +MARK_VISIBLE (gcry_set_fatalerror_handler) +MARK_VISIBLE (gcry_set_gettext_handler) +MARK_VISIBLE (gcry_set_log_handler) +MARK_VISIBLE (gcry_set_outofcore_handler) +MARK_VISIBLE (gcry_set_progress_handler) +MARK_VISIBLE (gcry_err_code_from_errno) +MARK_VISIBLE (gcry_err_code_to_errno) +MARK_VISIBLE (gcry_err_make_from_errno) +MARK_VISIBLE (gcry_error_from_errno) +MARK_VISIBLE (gcry_strerror) +MARK_VISIBLE (gcry_strsource) + +MARK_VISIBLE (gcry_free) +MARK_VISIBLE (gcry_malloc) +MARK_VISIBLE (gcry_malloc_secure) +MARK_VISIBLE (gcry_calloc) +MARK_VISIBLE (gcry_calloc_secure) +MARK_VISIBLE (gcry_realloc) +MARK_VISIBLE (gcry_strdup) +MARK_VISIBLE (gcry_is_secure) +MARK_VISIBLE (gcry_xcalloc) +MARK_VISIBLE (gcry_xcalloc_secure) +MARK_VISIBLE (gcry_xmalloc) +MARK_VISIBLE (gcry_xmalloc_secure) +MARK_VISIBLE (gcry_xrealloc) +MARK_VISIBLE (gcry_xstrdup) + +MARK_VISIBLE (gcry_md_algo_info) +MARK_VISIBLE (gcry_md_algo_name) +MARK_VISIBLE (gcry_md_close) +MARK_VISIBLE (gcry_md_copy) +MARK_VISIBLE (gcry_md_ctl) +MARK_VISIBLE (gcry_md_enable) +MARK_VISIBLE (gcry_md_get) +MARK_VISIBLE (gcry_md_get_algo) +MARK_VISIBLE (gcry_md_get_algo_dlen) +MARK_VISIBLE (gcry_md_hash_buffer) +MARK_VISIBLE (gcry_md_info) +MARK_VISIBLE (gcry_md_is_enabled) +MARK_VISIBLE (gcry_md_is_secure) +MARK_VISIBLE (gcry_md_list) +MARK_VISIBLE (gcry_md_map_name) +MARK_VISIBLE (gcry_md_open) +MARK_VISIBLE (gcry_md_read) +MARK_VISIBLEX(gcry_md_register) +MARK_VISIBLE (gcry_md_reset) +MARK_VISIBLE (gcry_md_setkey) +MARK_VISIBLE (gcry_md_unregister) +MARK_VISIBLE (gcry_md_write) +MARK_VISIBLE (gcry_md_debug) + +MARK_VISIBLE (gcry_cipher_algo_info) +MARK_VISIBLE (gcry_cipher_algo_name) +MARK_VISIBLE (gcry_cipher_close) +MARK_VISIBLE (gcry_cipher_setkey) +MARK_VISIBLE (gcry_cipher_setiv) +MARK_VISIBLE (gcry_cipher_setctr) +MARK_VISIBLE (gcry_cipher_ctl) +MARK_VISIBLE (gcry_cipher_decrypt) +MARK_VISIBLE (gcry_cipher_encrypt) +MARK_VISIBLE (gcry_cipher_get_algo_blklen) +MARK_VISIBLE (gcry_cipher_get_algo_keylen) +MARK_VISIBLE (gcry_cipher_info) +MARK_VISIBLE (gcry_cipher_list) +MARK_VISIBLE (gcry_cipher_map_name) +MARK_VISIBLE (gcry_cipher_mode_from_oid) +MARK_VISIBLE (gcry_cipher_open) +MARK_VISIBLEX(gcry_cipher_register) +MARK_VISIBLE (gcry_cipher_unregister) + +MARK_VISIBLE (gcry_pk_algo_info) +MARK_VISIBLE (gcry_pk_algo_name) +MARK_VISIBLE (gcry_pk_ctl) +MARK_VISIBLE (gcry_pk_decrypt) +MARK_VISIBLE (gcry_pk_encrypt) +MARK_VISIBLE (gcry_pk_genkey) +MARK_VISIBLE (gcry_pk_get_keygrip) +MARK_VISIBLE (gcry_pk_get_curve) +MARK_VISIBLE (gcry_pk_get_param) +MARK_VISIBLE (gcry_pk_get_nbits) +MARK_VISIBLE (gcry_pk_list) +MARK_VISIBLE (gcry_pk_map_name) +MARK_VISIBLEX(gcry_pk_register) +MARK_VISIBLE (gcry_pk_sign) +MARK_VISIBLE (gcry_pk_testkey) +MARK_VISIBLE (gcry_pk_unregister) +MARK_VISIBLE (gcry_pk_verify) + +MARK_VISIBLE (gcry_ac_data_new) +MARK_VISIBLE (gcry_ac_data_destroy) +MARK_VISIBLE (gcry_ac_data_copy) +MARK_VISIBLE (gcry_ac_data_length) +MARK_VISIBLE (gcry_ac_data_clear) +MARK_VISIBLE (gcry_ac_data_set) +MARK_VISIBLE (gcry_ac_data_get_name) +MARK_VISIBLE (gcry_ac_data_get_index) +MARK_VISIBLE (gcry_ac_open) +MARK_VISIBLE (gcry_ac_close) +MARK_VISIBLE (gcry_ac_key_init) +MARK_VISIBLE (gcry_ac_key_pair_generate) +MARK_VISIBLE (gcry_ac_key_pair_extract) +MARK_VISIBLE (gcry_ac_key_data_get) +MARK_VISIBLE (gcry_ac_key_test) +MARK_VISIBLE (gcry_ac_key_get_nbits) +MARK_VISIBLE (gcry_ac_key_get_grip) +MARK_VISIBLE (gcry_ac_key_destroy) +MARK_VISIBLE (gcry_ac_key_pair_destroy) +MARK_VISIBLE (gcry_ac_data_encrypt) +MARK_VISIBLE (gcry_ac_data_decrypt) +MARK_VISIBLE (gcry_ac_data_sign) +MARK_VISIBLE (gcry_ac_data_verify) +MARK_VISIBLE (gcry_ac_id_to_name) +MARK_VISIBLE (gcry_ac_name_to_id) +/* MARK_VISIBLE (gcry_ac_list) Not defined although it is in + libgcrypt.vers. */ +MARK_VISIBLE (gcry_ac_data_encode) +MARK_VISIBLE (gcry_ac_data_decode) +MARK_VISIBLE (gcry_ac_mpi_to_os) +MARK_VISIBLE (gcry_ac_mpi_to_os_alloc) +MARK_VISIBLE (gcry_ac_os_to_mpi) +MARK_VISIBLE (gcry_ac_data_encrypt_scheme) +MARK_VISIBLE (gcry_ac_data_decrypt_scheme) +MARK_VISIBLE (gcry_ac_data_sign_scheme) +MARK_VISIBLE (gcry_ac_data_verify_scheme) +MARK_VISIBLE (gcry_ac_data_to_sexp) +MARK_VISIBLE (gcry_ac_data_from_sexp) +MARK_VISIBLE (gcry_ac_io_init) +MARK_VISIBLE (gcry_ac_io_init_va) + +MARK_VISIBLE (gcry_kdf_derive) + +MARK_VISIBLE (gcry_prime_check) +MARK_VISIBLE (gcry_prime_generate) +MARK_VISIBLE (gcry_prime_group_generator) +MARK_VISIBLE (gcry_prime_release_factors) + +MARK_VISIBLE (gcry_random_add_bytes) +MARK_VISIBLE (gcry_random_bytes) +MARK_VISIBLE (gcry_random_bytes_secure) +MARK_VISIBLE (gcry_randomize) +MARK_VISIBLE (gcry_create_nonce) + +MARK_VISIBLE (gcry_sexp_alist) +MARK_VISIBLE (gcry_sexp_append) +MARK_VISIBLE (gcry_sexp_build) +MARK_VISIBLE (gcry_sexp_build_array) +MARK_VISIBLE (gcry_sexp_cadr) +MARK_VISIBLE (gcry_sexp_canon_len) +MARK_VISIBLE (gcry_sexp_car) +MARK_VISIBLE (gcry_sexp_cdr) +MARK_VISIBLE (gcry_sexp_cons) +MARK_VISIBLE (gcry_sexp_create) +MARK_VISIBLE (gcry_sexp_dump) +MARK_VISIBLE (gcry_sexp_find_token) +MARK_VISIBLE (gcry_sexp_length) +MARK_VISIBLE (gcry_sexp_new) +MARK_VISIBLE (gcry_sexp_nth) +MARK_VISIBLE (gcry_sexp_nth_data) +MARK_VISIBLE (gcry_sexp_nth_mpi) +MARK_VISIBLE (gcry_sexp_prepend) +MARK_VISIBLE (gcry_sexp_release) +MARK_VISIBLE (gcry_sexp_sprint) +MARK_VISIBLE (gcry_sexp_sscan) +MARK_VISIBLE (gcry_sexp_vlist) +MARK_VISIBLE (gcry_sexp_nth_string) + +MARK_VISIBLE (gcry_mpi_add) +MARK_VISIBLE (gcry_mpi_add_ui) +MARK_VISIBLE (gcry_mpi_addm) +MARK_VISIBLE (gcry_mpi_aprint) +MARK_VISIBLE (gcry_mpi_clear_bit) +MARK_VISIBLE (gcry_mpi_clear_flag) +MARK_VISIBLE (gcry_mpi_clear_highbit) +MARK_VISIBLE (gcry_mpi_cmp) +MARK_VISIBLE (gcry_mpi_cmp_ui) +MARK_VISIBLE (gcry_mpi_copy) +MARK_VISIBLE (gcry_mpi_div) +MARK_VISIBLE (gcry_mpi_dump) +MARK_VISIBLE (gcry_mpi_gcd) +MARK_VISIBLE (gcry_mpi_get_flag) +MARK_VISIBLE (gcry_mpi_get_nbits) +MARK_VISIBLE (gcry_mpi_get_opaque) +MARK_VISIBLE (gcry_mpi_invm) +MARK_VISIBLE (gcry_mpi_mod) +MARK_VISIBLE (gcry_mpi_mul) +MARK_VISIBLE (gcry_mpi_mul_2exp) +MARK_VISIBLE (gcry_mpi_mul_ui) +MARK_VISIBLE (gcry_mpi_mulm) +MARK_VISIBLE (gcry_mpi_new) +MARK_VISIBLE (gcry_mpi_powm) +MARK_VISIBLE (gcry_mpi_print) +MARK_VISIBLE (gcry_mpi_randomize) +MARK_VISIBLE (gcry_mpi_release) +MARK_VISIBLE (gcry_mpi_rshift) +MARK_VISIBLE (gcry_mpi_lshift) +MARK_VISIBLE (gcry_mpi_scan) +MARK_VISIBLE (gcry_mpi_set) +MARK_VISIBLE (gcry_mpi_set_bit) +MARK_VISIBLE (gcry_mpi_set_flag) +MARK_VISIBLE (gcry_mpi_set_highbit) +MARK_VISIBLE (gcry_mpi_set_opaque) +MARK_VISIBLE (gcry_mpi_set_ui) +MARK_VISIBLE (gcry_mpi_snew) +MARK_VISIBLE (gcry_mpi_sub) +MARK_VISIBLE (gcry_mpi_sub_ui) +MARK_VISIBLE (gcry_mpi_subm) +MARK_VISIBLE (gcry_mpi_swap) +MARK_VISIBLE (gcry_mpi_test_bit) + + + +#undef MARK_VISIBLE +#endif /*_GCRY_INCLUDED_BY_VISIBILITY_C*/ + +#endif /*GCRY_VISIBILITY_H*/ diff --git a/grub-core/lib/libgcrypt_wrap/cipher_wrap.h b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h new file mode 100644 index 0000000..4283549 --- /dev/null +++ b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h @@ -0,0 +1,77 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_GCRY_WRAP_HEADER +#define GRUB_GCRY_WRAP_HEADER 1 + +#include <grub/types.h> +#include <grub/mm.h> +#include <grub/misc.h> +#include <grub/dl.h> +#include <grub/crypto.h> + +#include <sys/types.h> + +#define _gcry_mpi_invm gcry_mpi_invm +#define _gcry_mpi_set gcry_mpi_set +#define _gcry_mpi_set_ui gcry_mpi_set_ui +#define size_t grub_size_t + +#undef __GNU_LIBRARY__ +#define __GNU_LIBRARY__ 1 + +#define U64_C(c) (c ## ULL) + +#define PUBKEY_FLAG_NO_BLINDING (1 << 0) + +#define CIPHER_INFO_NO_WEAK_KEY 1 + +#define HAVE_U64_TYPEDEF 1 + +/* Selftests are in separate modules. */ +static inline char * +selftest (void) +{ + return NULL; +} + +static inline int +_gcry_fips_mode (void) +{ + return 0; +} + +#define assert gcry_assert + +#ifdef GRUB_UTIL + +#define memset grub_memset + +#endif + + +#define DBG_CIPHER 0 + +#include <string.h> +#pragma GCC diagnostic ignored "-Wredundant-decls" +#include <grub/gcrypt/g10lib.h> +#include <grub/gcrypt/gcrypt.h> + +#define gcry_mpi_mod _gcry_mpi_mod + +#endif diff --git a/grub-core/lib/libgcrypt_wrap/mem.c b/grub-core/lib/libgcrypt_wrap/mem.c new file mode 100644 index 0000000..74c6eaf --- /dev/null +++ b/grub-core/lib/libgcrypt_wrap/mem.c @@ -0,0 +1,140 @@ +#include <grub/gcrypt/g10lib.h> +#include <grub/gcrypt/gpg-error.h> +#include <grub/term.h> +#include <grub/crypto.h> +#include <grub/dl.h> +#include <grub/env.h> +#include <grub/safemath.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +void * +gcry_malloc (size_t n) +{ + return grub_malloc (n); +} + +void * +gcry_malloc_secure (size_t n) +{ + return grub_malloc (n); +} + +void +gcry_free (void *a) +{ + grub_free (a); +} + +int +gcry_is_secure (const void *a __attribute__ ((unused))) +{ + return 0; +} + +/* FIXME: implement "exit". */ +void * +gcry_xcalloc (size_t n, size_t m) +{ + void *ret; + size_t sz; + if (grub_mul (n, m, &sz)) + grub_fatal ("gcry_xcalloc would overflow"); + ret = grub_zalloc (sz); + if (!ret) + grub_fatal ("gcry_xcalloc failed"); + return ret; +} + +void * +gcry_xmalloc_secure (size_t n) +{ + void *ret; + ret = grub_malloc (n); + if (!ret) + grub_fatal ("gcry_xmalloc failed"); + return ret; +} + +void * +gcry_xcalloc_secure (size_t n, size_t m) +{ + void *ret; + size_t sz; + if (grub_mul (n, m, &sz)) + grub_fatal ("gcry_xcalloc would overflow"); + ret = grub_zalloc (sz); + if (!ret) + grub_fatal ("gcry_xcalloc failed"); + return ret; +} + +void * +gcry_xmalloc (size_t n) +{ + void *ret; + ret = grub_malloc (n); + if (!ret) + grub_fatal ("gcry_xmalloc failed"); + return ret; +} + +void * +gcry_xrealloc (void *a, size_t n) +{ + void *ret; + ret = grub_realloc (a, n); + if (!ret) + grub_fatal ("gcry_xrealloc failed"); + return ret; +} + +void +_gcry_check_heap (const void *a __attribute__ ((unused))) +{ + +} + +void _gcry_log_printf (const char *fmt, ...) +{ + va_list args; + const char *debug = grub_env_get ("debug"); + + if (! debug) + return; + + if (grub_strword (debug, "all") || grub_strword (debug, "gcrypt")) + { + grub_printf ("gcrypt: "); + va_start (args, fmt); + grub_vprintf (fmt, args); + va_end (args); + grub_refresh (); + } +} + +void _gcry_log_bug (const char *fmt, ...) +{ + va_list args; + + grub_printf ("gcrypt bug: "); + va_start (args, fmt); + grub_vprintf (fmt, args); + va_end (args); + grub_refresh (); + grub_fatal ("gcrypt bug"); +} + +gcry_err_code_t +gpg_error_from_syserror (void) +{ + switch (grub_errno) + { + case GRUB_ERR_NONE: + return GPG_ERR_NO_ERROR; + case GRUB_ERR_OUT_OF_MEMORY: + return GPG_ERR_OUT_OF_MEMORY; + default: + return GPG_ERR_GENERAL; + } +} diff --git a/grub-core/lib/minilzo/lzoconf.h b/grub-core/lib/minilzo/lzoconf.h new file mode 100644 index 0000000..61be29c --- /dev/null +++ b/grub-core/lib/minilzo/lzoconf.h @@ -0,0 +1,444 @@ +/* lzoconf.h -- configuration of the LZO data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + <markus@oberhumer.com> + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H_INCLUDED +#define __LZOCONF_H_INCLUDED 1 + +#define LZO_VERSION 0x2080 +#define LZO_VERSION_STRING "2.08" +#define LZO_VERSION_DATE "Jun 29 2014" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include <config.h> +#endif +#include <limits.h> +#include <stddef.h> + + +/*********************************************************************** +// LZO requires a conforming <limits.h> +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(USHRT_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* get OS and architecture defines */ +#ifndef __LZODEFS_H_INCLUDED +#include "lzodefs.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// some core defines +************************************************************************/ + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER 1 +# elif defined(__CHECKER__) +# define __LZO_CHECKER 1 +# elif defined(__INSURE__) +# define __LZO_CHECKER 1 +# elif defined(__PURIFY__) +# define __LZO_CHECKER 1 +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* lzo_uint must match size_t */ +#if !defined(LZO_UINT_MAX) +# if (LZO_ABI_LLP64) +# if (LZO_OS_WIN64) + typedef unsigned __int64 lzo_uint; + typedef __int64 lzo_int; +# else + typedef lzo_ullong_t lzo_uint; + typedef lzo_llong_t lzo_int; +# endif +# define LZO_SIZEOF_LZO_UINT 8 +# define LZO_UINT_MAX 0xffffffffffffffffull +# define LZO_INT_MAX 9223372036854775807LL +# define LZO_INT_MIN (-1LL - LZO_INT_MAX) +# elif (LZO_ABI_IP32L64) /* MIPS R5900 */ + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_INT +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LONG +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +/* The larger type of lzo_uint and lzo_uint32_t. */ +#if (LZO_SIZEOF_LZO_UINT >= 4) +# define lzo_xint lzo_uint +#else +# define lzo_xint lzo_uint32_t +#endif + +typedef int lzo_bool; + +/* sanity checks */ +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_UINT) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t)) + +#ifndef __LZO_MMODEL +#define __LZO_MMODEL /*empty*/ +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_xintp lzo_xint __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * + +#define lzo_int8_tp lzo_int8_t __LZO_MMODEL * +#define lzo_uint8_tp lzo_uint8_t __LZO_MMODEL * +#define lzo_int16_tp lzo_int16_t __LZO_MMODEL * +#define lzo_uint16_tp lzo_uint16_t __LZO_MMODEL * +#define lzo_int32_tp lzo_int32_t __LZO_MMODEL * +#define lzo_uint32_tp lzo_uint32_t __LZO_MMODEL * +#if defined(lzo_int64_t) +#define lzo_int64_tp lzo_int64_t __LZO_MMODEL * +#define lzo_uint64_tp lzo_uint64_t __LZO_MMODEL * +#endif + +/* Older LZO versions used to support ancient systems and memory models + * like 16-bit MSDOS with __huge pointers and Cray PVP, but these + * obsolete configurations are not supported any longer. + */ +#if defined(__LZO_MMODEL_HUGE) +#error "__LZO_MMODEL_HUGE is unsupported" +#endif +#if (LZO_MM_PVP) +#error "LZO_MM_PVP is unsupported" +#endif +#if (LZO_SIZEOF_INT < 4) +#error "LZO_SIZEOF_INT < 4 is unsupported" +#endif +#if (__LZO_UINTPTR_T_IS_POINTER) +#error "__LZO_UINTPTR_T_IS_POINTER is unsupported" +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) >= 4) +/* Strange configurations where sizeof(lzo_uint) != sizeof(size_t) should + * work but have not received much testing lately, so be strict here. + */ +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(size_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(ptrdiff_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_voidp)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_bytep)) + + +/*********************************************************************** +// function types +************************************************************************/ + +/* name mangling */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# define __LZO_CDECL __lzo_cdecl +#endif + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 /*empty*/ +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 /*empty*/ +#endif + +/* __cdecl calling convention for public C and assembly functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL +#endif + +/* function types */ +typedef int +(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + +typedef int +(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + + +/* Callback interface. Currently only the progress indicator ("nprogress") + * is used, but this may change in a future release. */ + +struct lzo_callback_t; +typedef struct lzo_callback_t lzo_callback_t; +#define lzo_callback_p lzo_callback_t __LZO_MMODEL * + +/* malloc & free function types */ +typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t) + (lzo_callback_p self, lzo_uint items, lzo_uint size); +typedef void (__LZO_CDECL *lzo_free_func_t) + (lzo_callback_p self, lzo_voidp ptr); + +/* a progress indicator callback function */ +typedef void (__LZO_CDECL *lzo_progress_func_t) + (lzo_callback_p, lzo_uint, lzo_uint, int); + +struct lzo_callback_t +{ + /* custom allocators (set to 0 to disable) */ + lzo_alloc_func_t nalloc; /* [not used right now] */ + lzo_free_func_t nfree; /* [not used right now] */ + + /* a progress indicator callback function (set to 0 to disable) */ + lzo_progress_func_t nprogress; + + /* INFO: the first parameter "self" of the nalloc/nfree/nprogress + * callbacks points back to this struct, so you are free to store + * some extra info in the following variables. */ + lzo_voidp user1; + lzo_xint user2; + lzo_xint user3; +}; + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) +#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ +#define LZO_E_INVALID_ARGUMENT (-10) +#define LZO_E_INVALID_ALIGNMENT (-11) /* pointer argument is not properly aligned */ +#define LZO_E_OUTPUT_NOT_CONSUMED (-12) +#define LZO_E_INTERNAL_ERROR (-99) + + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep)) +#endif + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32_t),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_callback_t)) +LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) + lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memset(lzo_voidp buf, int c, lzo_uint len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32_t) + lzo_adler32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); +LZO_EXTERN(lzo_uint32_t) + lzo_crc32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); +LZO_EXTERN(const lzo_uint32_tp) + lzo_get_crc32_table(void); + +/* misc. */ +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { + lzo_voidp a00; lzo_bytep a01; lzo_uint a02; lzo_xint a03; lzo_uintptr_t a04; + void *a05; unsigned char *a06; unsigned long a07; size_t a08; ptrdiff_t a09; +#if defined(lzo_int64_t) + lzo_uint64_t a10; +#endif +} lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of 'size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size); +#define LZO_PTR_ALIGN_UP(p,size) \ + ((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size))) + + +/*********************************************************************** +// deprecated macros - only for backward compatibility +************************************************************************/ + +/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */ +#define lzo_byte unsigned char +/* deprecated type names */ +#define lzo_int32 lzo_int32_t +#define lzo_uint32 lzo_uint32_t +#define lzo_int32p lzo_int32_t __LZO_MMODEL * +#define lzo_uint32p lzo_uint32_t __LZO_MMODEL * +#define LZO_INT32_MAX LZO_INT32_C(2147483647) +#define LZO_UINT32_MAX LZO_UINT32_C(4294967295) +#if defined(lzo_int64_t) +#define lzo_int64 lzo_int64_t +#define lzo_uint64 lzo_uint64_t +#define lzo_int64p lzo_int64_t __LZO_MMODEL * +#define lzo_uint64p lzo_uint64_t __LZO_MMODEL * +#define LZO_INT64_MAX LZO_INT64_C(9223372036854775807) +#define LZO_UINT64_MAX LZO_UINT64_C(18446744073709551615) +#endif +/* deprecated types */ +typedef union { lzo_bytep a; lzo_uint b; } __lzo_pu_u; +typedef union { lzo_bytep a; lzo_uint32_t b; } __lzo_pu32_u; + +#if defined(LZO_CFG_COMPAT) + +#define __LZOCONF_H 1 + +#if defined(LZO_ARCH_I086) +# define __LZO_i386 1 +#elif defined(LZO_ARCH_I386) +# define __LZO_i386 1 +#endif + +#if defined(LZO_OS_DOS16) +# define __LZO_DOS 1 +# define __LZO_DOS16 1 +#elif defined(LZO_OS_DOS32) +# define __LZO_DOS 1 +#elif defined(LZO_OS_WIN16) +# define __LZO_WIN 1 +# define __LZO_WIN16 1 +#elif defined(LZO_OS_WIN32) +# define __LZO_WIN 1 +#endif + +#define __LZO_CMODEL /*empty*/ +#define __LZO_DMODEL /*empty*/ +#define __LZO_ENTRY __LZO_CDECL +#define LZO_EXTERN_CDECL LZO_EXTERN +#define LZO_ALIGN LZO_PTR_ALIGN_UP + +#define lzo_compress_asm_t lzo_compress_t +#define lzo_decompress_asm_t lzo_decompress_t + +#endif /* LZO_CFG_COMPAT */ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + + +/* vim:set ts=4 sw=4 et: */ diff --git a/grub-core/lib/minilzo/lzodefs.h b/grub-core/lib/minilzo/lzodefs.h new file mode 100644 index 0000000..f4ae948 --- /dev/null +++ b/grub-core/lib/minilzo/lzodefs.h @@ -0,0 +1,2998 @@ +/* lzodefs.h -- architecture, OS and compiler specific defines + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + <markus@oberhumer.com> + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if !defined(LZO_CFG_NO_DISABLE_WUNDEF) +#if defined(__ARMCC_VERSION) +# pragma diag_suppress 193 +#elif defined(__clang__) && defined(__clang_minor__) +# pragma clang diagnostic ignored "-Wundef" +#elif defined(__INTEL_COMPILER) +# pragma warning(disable: 193) +#elif defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) +# if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) +# pragma GCC diagnostic ignored "-Wundef" +# endif +#elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if ((_MSC_VER-0) >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#endif +#if 0 && defined(__POCC__) && defined(_WIN32) +# if (__POCC__ >= 400) +# pragma warn(disable: 2216) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#ifndef _CRT_NONSTDC_NO_WARNINGS +#define _CRT_NONSTDC_NO_WARNINGS 1 +#endif +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif +#endif +#if 0 +#define LZO_0xffffUL 0xfffful +#define LZO_0xffffffffUL 0xfffffffful +#else +#define LZO_0xffffUL 65535ul +#define LZO_0xffffffffUL 4294967295ul +#endif +#define LZO_0xffffL LZO_0xffffUL +#define LZO_0xffffffffL LZO_0xffffffffUL +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if defined(__COUNTER__) +# ifndef LZO_CFG_USE_COUNTER +# define LZO_CFG_USE_COUNTER 1 +# endif +#else +# undef LZO_CFG_USE_COUNTER +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED 1 +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT0() /*empty*/ +#define LZO_PP_CONCAT1(a) a +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() +#define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) +#define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) +#define LZO_PP_EMPTY /*empty*/ +#define LZO_PP_EMPTY0() /*empty*/ +#define LZO_PP_EMPTY1(a) /*empty*/ +#define LZO_PP_EMPTY2(a,b) /*empty*/ +#define LZO_PP_EMPTY3(a,b,c) /*empty*/ +#define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ +#define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ +#define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ +#define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) +#define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-!!(b))) - (o)) << 1) + (o)*!!(b)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +# define LZO_EXTERN_C_BEGIN extern "C" { +# define LZO_EXTERN_C_END } +#else +# define LZO_EXTERN_C extern +# define LZO_EXTERN_C_BEGIN /*empty*/ +# define LZO_EXTERN_C_END /*empty*/ +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if (LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif (LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__ppc__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif defined(__mips__) && defined(__psp__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) && defined(__MACH__) +# if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) +# define LZO_OS_POSIX_DARWIN 1040 +# define LZO_INFO_OS_POSIX "darwin_iphone" +# elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) +# define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +# define LZO_INFO_OS_POSIX "darwin" +# else +# define LZO_OS_POSIX_DARWIN 1 +# define LZO_INFO_OS_POSIX "darwin" +# endif +# define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) +# define LZO_CC_INTELC __INTEL_COMPILER +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_INTELC_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) +# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) +# else +# define LZO_CC_CLANG 0x010000L +# endif +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_CLANG_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +# define LZO_INFO_CC "clang" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_LLVM LZO_CC_LLVM_GNUC +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__ARMCC_VERSION) && !defined(__GNUC__) +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__CODEGEARC__) +# define LZO_CC_CODEGEARC 1 +# define LZO_INFO_CC "CodeGear C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) +# define LZO_CC_GHS 1 +# define LZO_INFO_CC "Green Hills C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_GHS_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) +# define LZO_CC_HPACC __HP_aCC +# define LZO_INFO_CC "HP aCC" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) && ((__IBMC__-0) > 0) +# define LZO_CC_IBMC __IBMC__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) +# define LZO_CC_IBMC __IBMCPP__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) +# define LZO_CC_MWERKS __MWERKS__ +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) +# else +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" +# endif +# define LZO_INFO_CC "Portland Group PGI C" +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if ((__ZTC__-0) == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_MSC _MSC_VER +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if (LZO_CC_GNUC) && defined(__OPEN64__) +# if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) +# define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) +# define LZO_CC_OPEN64_GNUC LZO_CC_GNUC +# endif +#endif +#if (LZO_CC_GNUC) && defined(__PCC__) +# if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) +# define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) +# define LZO_CC_PCC_GNUC LZO_CC_GNUC +# endif +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if (LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__aarch64__) +# define LZO_ARCH_ARM64 1 +# define LZO_INFO_ARCH "arm64" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) +# define LZO_ARCH_ARM 1 +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# if defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 1) +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +# elif defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 2) +# define LZO_INFO_ARCH "arm" +# else +# define LZO_INFO_ARCH "arm" +# endif +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__avr32__) || defined(__AVR32__) +# define LZO_ARCH_AVR32 1 +# define LZO_INFO_ARCH "avr32" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) +# define LZO_ARCH_X64 1 +#elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_AMD64 1 +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) +# define LZO_ARCH_AARCH64 1 +#elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_ARM64 1 +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) +# define LZO_ARCH_X86 1 +#elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_I386 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM_THUMB) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM_THUMB) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086PM && !LZO_ARCH_I086) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# if !defined(LZO_TARGET_FEATURE_SSE2) +# if defined(__SSE2__) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif defined(_MSC_VER) && ((defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) || defined(_M_AMD64)) +# define LZO_TARGET_FEATURE_SSE2 1 +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSSE3) +# if (LZO_TARGET_FEATURE_SSE2) +# if defined(__SSSE3__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# elif defined(_MSC_VER) && defined(__AVX__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSE4_2) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__SSE4_2__) +# define LZO_TARGET_FEATURE_SSE4_2 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__AVX__) +# define LZO_TARGET_FEATURE_AVX 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX2) +# if (LZO_TARGET_FEATURE_AVX) +# if defined(__AVX2__) +# define LZO_TARGET_FEATURE_AVX2 1 +# endif +# endif +# endif +#endif +#if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if defined(__ARM_NEON__) +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if 1 +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#endif +#if 0 +#elif !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown LZO_ARCH_I086 memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "unexpected configuration - check your compiler defines" +# elif (LZO_CC_ZORTECHC) +# else +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_gnuc_extension__ __extension__ +#else +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# else +# define LZO_CFG_USE_NEW_STYLE_CASTS 1 +# endif +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(__cplusplus) +# if defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# undef LZO_CFG_USE_NEW_STYLE_CASTS +# endif +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(LZO_REINTERPRET_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast<t> (e)) +# endif +#endif +#if !defined(LZO_REINTERPRET_CAST) +# define LZO_REINTERPRET_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_STATIC_CAST(t,e) (static_cast<t> (e)) +# endif +#endif +#if !defined(LZO_STATIC_CAST) +# define LZO_STATIC_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST2) +# define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) +#endif +#if !defined(LZO_UNCONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_PCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_PCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_PCAST) +# define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) +#endif +#if !defined(LZO_CCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_CCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_CCAST) +# define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) +#endif +#if !defined(LZO_ICONV) +# define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ICAST) +# define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ITRUNC) +# define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(__lzo_cte) +# if (LZO_CC_MSC || LZO_CC_WATCOMC) +# define __lzo_cte(e) ((void)0,(e)) +# elif 1 +# define __lzo_cte(e) ((void)0,(e)) +# endif +#endif +#if !defined(__lzo_cte) +# define __lzo_cte(e) (e) +#endif +#if !defined(LZO_BLOCK_BEGIN) +# define LZO_BLOCK_BEGIN do { +# define LZO_BLOCK_END } while __lzo_cte(0) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {LZO_EXTERN_C int lzo_unused__[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {LZO_EXTERN_C int lzo_unused_func__[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_CLANG >= 0x020800ul) +# define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) +# elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_GHS) +# define __lzo_inline __inline__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_inline __inline__ +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_inline __inline__ +#endif +#endif +#if defined(__lzo_inline) +# ifndef __lzo_HAVE_inline +# define __lzo_HAVE_inline 1 +# endif +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# ifndef __lzo_HAVE_forceinline +# define __lzo_HAVE_forceinline 1 +# endif +#else +# define __lzo_forceinline __lzo_inline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# ifndef __lzo_HAVE_noinline +# define __lzo_HAVE_noinline 1 +# endif +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_static_inline) +#if (LZO_CC_IBMC) +# define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline +#endif +#endif +#if !defined(__lzo_static_inline) +# define __lzo_static_inline static __lzo_inline +#endif +#if !defined(__lzo_static_forceinline) +#if (LZO_CC_IBMC) +# define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline +#endif +#endif +#if !defined(__lzo_static_forceinline) +# define __lzo_static_forceinline static __lzo_forceinline +#endif +#if !defined(__lzo_static_noinline) +#if (LZO_CC_IBMC) +# define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline +#endif +#endif +#if !defined(__lzo_static_noinline) +# define __lzo_static_noinline static __lzo_noinline +#endif +#if !defined(__lzo_c99_extern_inline) +#if defined(__GNUC_GNU_INLINE__) +# define __lzo_c99_extern_inline __lzo_inline +#elif defined(__GNUC_STDC_INLINE__) +# define __lzo_c99_extern_inline extern __lzo_inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_c99_extern_inline extern __lzo_inline +#endif +#if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) +# define __lzo_c99_extern_inline __lzo_inline +#endif +#endif +#if defined(__lzo_c99_extern_inline) +# ifndef __lzo_HAVE_c99_extern_inline +# define __lzo_HAVE_c99_extern_inline 1 +# endif +#else +# define __lzo_c99_extern_inline /*empty*/ +#endif +#if !defined(__lzo_may_alias) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_CLANG >= 0x020900ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#endif +#endif +#if defined(__lzo_may_alias) +# ifndef __lzo_HAVE_may_alias +# define __lzo_HAVE_may_alias 1 +# endif +#else +# define __lzo_may_alias /*empty*/ +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#endif +#endif +#if defined(__lzo_noreturn) +# ifndef __lzo_HAVE_noreturn +# define __lzo_HAVE_noreturn 1 +# endif +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# ifndef __lzo_HAVE_nothrow +# define __lzo_HAVE_nothrow 1 +# endif +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 1210) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_restrict __restrict__ +#endif +#endif +#if defined(__lzo_restrict) +# ifndef __lzo_HAVE_restrict +# define __lzo_HAVE_restrict 1 +# endif +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_GHS) && !defined(__cplusplus) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_IBMC >= 600) +# define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# ifndef __lzo_HAVE_alignof +# define __lzo_HAVE_alignof 1 +# endif +#endif +#if !defined(__lzo_struct_packed) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { +# define __lzo_struct_packed_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_struct_packed(s) _Packed struct s { +# define __lzo_struct_packed_end() }; +#endif +#endif +#if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) +# define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) +#endif +#if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) +# define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() +#endif +#if !defined(__lzo_byte_struct) +#if defined(__lzo_struct_packed) +# define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() +# define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); +# define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); +#endif +#endif +#if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) +# define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) +#endif +#if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) +#if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) +#elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_CILLY || LZO_CC_PCC) +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_align16(s) struct __declspec(align(16)) s { +# define __lzo_struct_align16_end() }; +# define __lzo_struct_align32(s) struct __declspec(align(32)) s { +# define __lzo_struct_align32_end() }; +# define __lzo_struct_align64(s) struct __declspec(align(64)) s { +# define __lzo_struct_align64_end() }; +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_struct_align16(s) struct s { +# define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); +# define __lzo_struct_align32(s) struct s { +# define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); +# define __lzo_struct_align64(s) struct s { +# define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); +#endif +#endif +#if !defined(__lzo_union_um) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_union_am(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_union_um(s) __pragma(pack(push,1)) union s { +# define __lzo_union_um_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_union_um(s) _Packed union s { +# define __lzo_union_um_end() }; +#endif +#endif +#if !defined(__lzo_union_am) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() }; +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# ifndef __lzo_HAVE_constructor +# define __lzo_HAVE_constructor 1 +# endif +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# ifndef __lzo_HAVE_destructor +# define __lzo_HAVE_destructor 1 +# endif +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_IBMC >= 1010) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# ifndef __lzo_HAVE_likely +# define __lzo_HAVE_likely 1 +# endif +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# ifndef __lzo_HAVE_unlikely +# define __lzo_HAVE_unlikely 1 +# endif +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(__lzo_static_unused_void_func) +# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_static_unused_void_func(f) static void __attribute__((__unused__)) f(void) +# else +# define __lzo_static_unused_void_func(f) static __lzo_inline void f(void) +# endif +#endif +#if !defined(__lzo_loop_forever) +# if (LZO_CC_IBMC) +# define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END +# else +# define __lzo_loop_forever() do { ; } while __lzo_cte(1) +# endif +#endif +#if !defined(__lzo_unreachable) +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_GNUC >= 0x040500ul) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 +# define __lzo_unreachable() __builtin_unreachable(); +#endif +#endif +#if defined(__lzo_unreachable) +# ifndef __lzo_HAVE_unreachable +# define __lzo_HAVE_unreachable 1 +# endif +#else +# if 0 +# define __lzo_unreachable() ((void)0); +# else +# define __lzo_unreachable() __lzo_loop_forever(); +# endif +#endif +#ifndef __LZO_CTA_NAME +#if (LZO_CFG_USE_COUNTER) +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) +#else +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) +#endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} +# elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} +# elif (LZO_CC_GNUC >= 0x040700ul) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) +#if defined(__cplusplus) +extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if !defined(LZO_HAVE_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#endif +#ifndef LZO_SIZEOF_SHORT +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#elif defined(__SIZEOF_SHORT__) +# define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) +#endif +#endif +#ifndef LZO_SIZEOF_INT +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#elif defined(__SIZEOF_INT__) +# define LZO_SIZEOF_INT (__SIZEOF_INT__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#elif defined(__SIZEOF_LONG__) +# define LZO_SIZEOF_LONG (__SIZEOF_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG_LONG +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#elif defined(__SIZEOF_LONG_LONG__) +# define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF___INT16 +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#endif +#ifndef LZO_SIZEOF___INT32 +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#endif +#ifndef LZO_SIZEOF___INT64 +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#endif +#ifndef LZO_SIZEOF_VOID_P +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#elif defined(__SIZEOF_POINTER__) +# define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) +#endif +#endif +#ifndef LZO_SIZEOF_SIZE_T +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#elif defined(__SIZEOF_SIZE_T__) +# define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) +#endif +#endif +#ifndef LZO_SIZEOF_PTRDIFF_T +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#elif defined(__SIZEOF_PTRDIFF_T__) +# define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) +#endif +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,39) == 1) +# define LZO_SIZEOF_LONG 5 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && (LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if (LZO_CFG_NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(_NO_LONGLONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_WORDSIZE) +#if (LZO_ARCH_ALPHA) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AMD64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AVR) +# define LZO_WORDSIZE 1 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define LZO_WORDSIZE 4 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_WORDSIZE 4 +# else +# define LZO_WORDSIZE 2 +# endif +#elif (LZO_ARCH_I086) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_IA64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_M16C) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_SPU) +# define LZO_WORDSIZE 4 +#elif (LZO_ARCH_Z80) +# define LZO_WORDSIZE 1 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_WORDSIZE 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define LZO_WORDSIZE 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_WORDSIZE 8 +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LP64__) || defined(__LP64) || defined(_LP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_ARCH_AVR) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#elif (LZO_ARCH_M16C) +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_ARCH_SPU) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_ARCH_Z80) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# if defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# else +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# endif +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) +#endif +#if !defined(LZO_WORDSIZE) +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) +# if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +# elif defined(__BIG_ENDIAN) +# define LZO_ABI_BIG_ENDIAN 1 +# else +# define LZO_ABI_LITTLE_ENDIAN 1 +# endif +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif (LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif (LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_LP32 1 +# define LZO_INFO_ABI_PM "lp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if 0 +#elif !defined(__LZO_LIBC_OVERRIDE) +#if (LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif (LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif (LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif (LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif (LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uc" "libc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_CC_GNUC) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) +# define __LZO_ASM_CLOBBER "memory" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_CC : "cc" +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_ARM) +# if defined(__ARM_FEATURE_UNALIGNED) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 6) && !defined(__TARGET_PROFILE_M) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_CRIS) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_I386) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if (LZO_ABI_BIG_ENDIAN) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +# endif +#elif (LZO_ARCH_S390) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#ifndef LZO_CFG_NO_INLINE_ASM +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_INLINE_ASM 1 +#elif (LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#if (LZO_CFG_NO_INLINE_ASM) +# undef LZO_ASM_SYNTAX_MSC +# undef LZO_ASM_SYNTAX_GNUC +# undef __LZO_ASM_CLOBBER +# undef __LZO_ASM_CLOBBER_LIST_CC +# undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY +# undef __LZO_ASM_CLOBBER_LIST_EMPTY +#endif +#ifndef LZO_CFG_NO_UNALIGNED +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER +#if !(LZO_CFG_SKIP_LZO_TYPES) +#if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) +# error "missing defines for sizes" +#endif +#if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) +# error "missing defines for sizes" +#endif +#if !defined(lzo_llong_t) +#if (LZO_SIZEOF_LONG_LONG+0 > 0) +__lzo_gnuc_extension__ typedef long long lzo_llong_t__; +__lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; +# define lzo_llong_t lzo_llong_t__ +# define lzo_ullong_t lzo_ullong_t__ +#endif +#endif +#if !defined(lzo_int16e_t) +#if (LZO_SIZEOF_LONG == 2) +# define lzo_int16e_t long +# define lzo_uint16e_t unsigned long +#elif (LZO_SIZEOF_INT == 2) +# define lzo_int16e_t int +# define lzo_uint16e_t unsigned int +#elif (LZO_SIZEOF_SHORT == 2) +# define lzo_int16e_t short int +# define lzo_uint16e_t unsigned short int +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) + typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); + typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); +# define lzo_int16e_t lzo_int16e_hi_t__ +# define lzo_uint16e_t lzo_uint16e_hi_t__ +#elif (LZO_SIZEOF___INT16 == 2) +# define lzo_int16e_t __int16 +# define lzo_uint16e_t unsigned __int16 +#else +#endif +#endif +#if defined(lzo_int16e_t) +# define LZO_SIZEOF_LZO_INT16E_T 2 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) +#endif +#if !defined(lzo_int32e_t) +#if (LZO_SIZEOF_LONG == 4) +# define lzo_int32e_t long int +# define lzo_uint32e_t unsigned long int +#elif (LZO_SIZEOF_INT == 4) +# define lzo_int32e_t int +# define lzo_uint32e_t unsigned int +#elif (LZO_SIZEOF_SHORT == 4) +# define lzo_int32e_t short int +# define lzo_uint32e_t unsigned short int +#elif (LZO_SIZEOF_LONG_LONG == 4) +# define lzo_int32e_t lzo_llong_t +# define lzo_uint32e_t lzo_ullong_t +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +#elif (LZO_SIZEOF___INT32 == 4) +# define lzo_int32e_t __int32 +# define lzo_uint32e_t unsigned __int32 +#else +#endif +#endif +#if defined(lzo_int32e_t) +# define LZO_SIZEOF_LZO_INT32E_T 4 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) +#endif +#if !defined(lzo_int64e_t) +#if (LZO_SIZEOF___INT64 == 8) +# if (LZO_CC_BORLANDC) && !(LZO_CFG_TYPE_PREFER___INT64) +# define LZO_CFG_TYPE_PREFER___INT64 1 +# endif +#endif +#if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int64e_t int +# define lzo_uint64e_t unsigned int +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG == 8) +# define lzo_int64e_t long int +# define lzo_uint64e_t unsigned long int +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG +#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_TYPE_PREFER___INT64) +# define lzo_int64e_t lzo_llong_t +# define lzo_uint64e_t lzo_ullong_t +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0ll) +# define LZO_UINT64_C(c) ((c) + 0ull) +# elif 0 +# define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) +# define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) +# else +# define LZO_INT64_C(c) (c##LL) +# define LZO_UINT64_C(c) (c##ULL) +# endif +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG_LONG +#elif (LZO_SIZEOF___INT64 == 8) +# define lzo_int64e_t __int64 +# define lzo_uint64e_t unsigned __int64 +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0i64) +# define LZO_UINT64_C(c) ((c) + 0ui64) +# else +# define LZO_INT64_C(c) (c##i64) +# define LZO_UINT64_C(c) (c##ui64) +# endif +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF___INT64 +#else +#endif +#endif +#if defined(lzo_int64e_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) +#endif +#if !defined(lzo_int32l_t) +#if defined(lzo_int32e_t) +# define lzo_int32l_t lzo_int32e_t +# define lzo_uint32l_t lzo_uint32e_t +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T +#elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int32l_t int +# define lzo_uint32l_t unsigned int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= 4) +# define lzo_int32l_t long int +# define lzo_uint32l_t unsigned long int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG +#else +# error "lzo_int32l_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) +#endif +#if !defined(lzo_int64l_t) +#if defined(lzo_int64e_t) +# define lzo_int64l_t lzo_int64e_t +# define lzo_uint64l_t lzo_uint64e_t +# define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T +#else +#endif +#endif +#if defined(lzo_int64l_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) +#endif +#if !defined(lzo_int32f_t) +#if (LZO_SIZEOF_SIZE_T >= 8) +# define lzo_int32f_t lzo_int64l_t +# define lzo_uint32f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T +#else +# define lzo_int32f_t lzo_int32l_t +# define lzo_uint32f_t lzo_uint32l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) +#endif +#if !defined(lzo_int64f_t) +#if defined(lzo_int64l_t) +# define lzo_int64f_t lzo_int64l_t +# define lzo_uint64f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T +#else +#endif +#endif +#if defined(lzo_int64f_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) +#endif +#if !defined(lzo_intptr_t) +#if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) +# define __LZO_INTPTR_T_IS_POINTER 1 + typedef char* lzo_intptr_t; + typedef char* lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P +#elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) + typedef __w64 int lzo_intptr_t; + typedef __w64 unsigned int lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) +# define lzo_intptr_t short +# define lzo_uintptr_t unsigned short +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT +#elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_intptr_t int +# define lzo_uintptr_t unsigned int +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t long +# define lzo_uintptr_t unsigned long +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG +#elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t lzo_int64l_t +# define lzo_uintptr_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T +#else +# error "lzo_intptr_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) +#endif +#if !defined(lzo_word_t) +#if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) +#if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) +# define lzo_word_t lzo_uintptr_t +# define lzo_sword_t lzo_intptr_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T +#elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) +# define lzo_word_t unsigned long +# define lzo_sword_t long +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG +#elif (LZO_WORDSIZE == LZO_SIZEOF_INT) +# define lzo_word_t unsigned int +# define lzo_sword_t int +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT +#elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) +# define lzo_word_t unsigned short +# define lzo_sword_t short +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT +#elif (LZO_WORDSIZE == 1) +# define lzo_word_t unsigned char +# define lzo_sword_t signed char +# define LZO_SIZEOF_LZO_WORD_T 1 +#elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) +# define lzo_word_t lzo_uint64l_t +# define lzo_sword_t lzo_int64l_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +#elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) +#if 0 + typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); + typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); +# define lzo_word_t lzo_word_t +# define lzo_sword_t lzo_sword_t +# define LZO_SIZEOF_LZO_WORD_T 16 +#endif +#else +# error "lzo_word_t" +#endif +#endif +#endif +#if 1 && defined(lzo_word_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) +#endif +#if 1 +#define lzo_int8_t signed char +#define lzo_uint8_t unsigned char +#define LZO_SIZEOF_LZO_INT8_T 1 +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) +#endif +#if defined(lzo_int16e_t) +#define lzo_int16_t lzo_int16e_t +#define lzo_uint16_t lzo_uint16e_t +#define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) +#endif +#if defined(lzo_int32e_t) +#define lzo_int32_t lzo_int32e_t +#define lzo_uint32_t lzo_uint32e_t +#define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) +#endif +#if defined(lzo_int64e_t) +#define lzo_int64_t lzo_int64e_t +#define lzo_uint64_t lzo_uint64e_t +#define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) +#endif +#if 1 +#define lzo_int_least32_t lzo_int32l_t +#define lzo_uint_least32_t lzo_uint32l_t +#define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) +#endif +#if defined(lzo_int64l_t) +#define lzo_int_least64_t lzo_int64l_t +#define lzo_uint_least64_t lzo_uint64l_t +#define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) +#endif +#if 1 +#define lzo_int_fast32_t lzo_int32f_t +#define lzo_uint_fast32_t lzo_uint32f_t +#define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) +#endif +#if defined(lzo_int64f_t) +#define lzo_int_fast64_t lzo_int64f_t +#define lzo_uint_fast64_t lzo_uint64f_t +#define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) +#endif +#if !defined(LZO_INT16_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) ((c) + 0) +# define LZO_UINT16_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) ((c) + 0L) +# define LZO_UINT16_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) (c) +# define LZO_UINT16_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) (c##L) +# define LZO_UINT16_C(c) (c##UL) +# else +# error "LZO_INT16_C" +# endif +#endif +#if !defined(LZO_INT32_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) ((c) + 0) +# define LZO_UINT32_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) ((c) + 0L) +# define LZO_UINT32_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) (c) +# define LZO_UINT32_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) (c##L) +# define LZO_UINT32_C(c) (c##UL) +# elif (LZO_SIZEOF_LONG_LONG >= 4) +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# else +# error "LZO_INT32_C" +# endif +#endif +#if !defined(LZO_INT64_C) && defined(lzo_int64l_t) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) ((c) + 0) +# define LZO_UINT64_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) ((c) + 0L) +# define LZO_UINT64_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) (c) +# define LZO_UINT64_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) (c##L) +# define LZO_UINT64_C(c) (c##UL) +# else +# error "LZO_INT64_C" +# endif +#endif +#endif + +#endif /* already included */ + +/* vim:set ts=4 sw=4 et: */ diff --git a/grub-core/lib/minilzo/minilzo.c b/grub-core/lib/minilzo/minilzo.c new file mode 100644 index 0000000..ab2be5f --- /dev/null +++ b/grub-core/lib/minilzo/minilzo.c @@ -0,0 +1,6053 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + <markus@oberhumer.com> + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO 1 + +#if defined(LZO_CFG_FREESTANDING) +# undef MINILZO_HAVE_CONFIG_H +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# include <config.h> +#endif +#include <limits.h> +#include <stddef.h> +#if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS) + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if !defined(LZO_CFG_NO_DISABLE_WUNDEF) +#if defined(__ARMCC_VERSION) +# pragma diag_suppress 193 +#elif defined(__clang__) && defined(__clang_minor__) +# pragma clang diagnostic ignored "-Wundef" +#elif defined(__INTEL_COMPILER) +# pragma warning(disable: 193) +#elif defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) +# if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) +# pragma GCC diagnostic ignored "-Wundef" +# endif +#elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if ((_MSC_VER-0) >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#endif +#if 0 && defined(__POCC__) && defined(_WIN32) +# if (__POCC__ >= 400) +# pragma warn(disable: 2216) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#ifndef _CRT_NONSTDC_NO_WARNINGS +#define _CRT_NONSTDC_NO_WARNINGS 1 +#endif +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif +#endif +#if 0 +#define LZO_0xffffUL 0xfffful +#define LZO_0xffffffffUL 0xfffffffful +#else +#define LZO_0xffffUL 65535ul +#define LZO_0xffffffffUL 4294967295ul +#endif +#define LZO_0xffffL LZO_0xffffUL +#define LZO_0xffffffffL LZO_0xffffffffUL +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if defined(__COUNTER__) +# ifndef LZO_CFG_USE_COUNTER +# define LZO_CFG_USE_COUNTER 1 +# endif +#else +# undef LZO_CFG_USE_COUNTER +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED 1 +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT0() /*empty*/ +#define LZO_PP_CONCAT1(a) a +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() +#define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) +#define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) +#define LZO_PP_EMPTY /*empty*/ +#define LZO_PP_EMPTY0() /*empty*/ +#define LZO_PP_EMPTY1(a) /*empty*/ +#define LZO_PP_EMPTY2(a,b) /*empty*/ +#define LZO_PP_EMPTY3(a,b,c) /*empty*/ +#define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ +#define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ +#define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ +#define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) +#define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-!!(b))) - (o)) << 1) + (o)*!!(b)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +# define LZO_EXTERN_C_BEGIN extern "C" { +# define LZO_EXTERN_C_END } +#else +# define LZO_EXTERN_C extern +# define LZO_EXTERN_C_BEGIN /*empty*/ +# define LZO_EXTERN_C_END /*empty*/ +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if (LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif (LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__ppc__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif defined(__mips__) && defined(__psp__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) && defined(__MACH__) +# if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) +# define LZO_OS_POSIX_DARWIN 1040 +# define LZO_INFO_OS_POSIX "darwin_iphone" +# elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) +# define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +# define LZO_INFO_OS_POSIX "darwin" +# else +# define LZO_OS_POSIX_DARWIN 1 +# define LZO_INFO_OS_POSIX "darwin" +# endif +# define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) +# define LZO_CC_INTELC __INTEL_COMPILER +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_INTELC_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) +# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) +# else +# define LZO_CC_CLANG 0x010000L +# endif +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_CLANG_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +# define LZO_INFO_CC "clang" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_LLVM LZO_CC_LLVM_GNUC +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__ARMCC_VERSION) && !defined(__GNUC__) +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__CODEGEARC__) +# define LZO_CC_CODEGEARC 1 +# define LZO_INFO_CC "CodeGear C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) +# define LZO_CC_GHS 1 +# define LZO_INFO_CC "Green Hills C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_GHS_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) +# define LZO_CC_HPACC __HP_aCC +# define LZO_INFO_CC "HP aCC" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) && ((__IBMC__-0) > 0) +# define LZO_CC_IBMC __IBMC__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) +# define LZO_CC_IBMC __IBMCPP__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) +# define LZO_CC_MWERKS __MWERKS__ +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) +# else +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" +# endif +# define LZO_INFO_CC "Portland Group PGI C" +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if ((__ZTC__-0) == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_MSC _MSC_VER +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if (LZO_CC_GNUC) && defined(__OPEN64__) +# if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) +# define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) +# define LZO_CC_OPEN64_GNUC LZO_CC_GNUC +# endif +#endif +#if (LZO_CC_GNUC) && defined(__PCC__) +# if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) +# define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) +# define LZO_CC_PCC_GNUC LZO_CC_GNUC +# endif +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if (LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__aarch64__) +# define LZO_ARCH_ARM64 1 +# define LZO_INFO_ARCH "arm64" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) +# define LZO_ARCH_ARM 1 +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# if defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 1) +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +# elif defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 2) +# define LZO_INFO_ARCH "arm" +# else +# define LZO_INFO_ARCH "arm" +# endif +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__avr32__) || defined(__AVR32__) +# define LZO_ARCH_AVR32 1 +# define LZO_INFO_ARCH "avr32" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) +# define LZO_ARCH_X64 1 +#elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_AMD64 1 +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) +# define LZO_ARCH_AARCH64 1 +#elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_ARM64 1 +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) +# define LZO_ARCH_X86 1 +#elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_I386 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM_THUMB) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM_THUMB) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086PM && !LZO_ARCH_I086) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# if !defined(LZO_TARGET_FEATURE_SSE2) +# if defined(__SSE2__) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif defined(_MSC_VER) && ((defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) || defined(_M_AMD64)) +# define LZO_TARGET_FEATURE_SSE2 1 +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSSE3) +# if (LZO_TARGET_FEATURE_SSE2) +# if defined(__SSSE3__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# elif defined(_MSC_VER) && defined(__AVX__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSE4_2) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__SSE4_2__) +# define LZO_TARGET_FEATURE_SSE4_2 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__AVX__) +# define LZO_TARGET_FEATURE_AVX 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX2) +# if (LZO_TARGET_FEATURE_AVX) +# if defined(__AVX2__) +# define LZO_TARGET_FEATURE_AVX2 1 +# endif +# endif +# endif +#endif +#if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if defined(__ARM_NEON__) +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if 1 +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#endif +#if 0 +#elif !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown LZO_ARCH_I086 memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "unexpected configuration - check your compiler defines" +# elif (LZO_CC_ZORTECHC) +# else +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_gnuc_extension__ __extension__ +#else +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# else +# define LZO_CFG_USE_NEW_STYLE_CASTS 1 +# endif +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(__cplusplus) +# if defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# undef LZO_CFG_USE_NEW_STYLE_CASTS +# endif +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(LZO_REINTERPRET_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast<t> (e)) +# endif +#endif +#if !defined(LZO_REINTERPRET_CAST) +# define LZO_REINTERPRET_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_STATIC_CAST(t,e) (static_cast<t> (e)) +# endif +#endif +#if !defined(LZO_STATIC_CAST) +# define LZO_STATIC_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST2) +# define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) +#endif +#if !defined(LZO_UNCONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_PCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_PCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_PCAST) +# define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) +#endif +#if !defined(LZO_CCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_CCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_CCAST) +# define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) +#endif +#if !defined(LZO_ICONV) +# define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ICAST) +# define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ITRUNC) +# define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(__lzo_cte) +# if (LZO_CC_MSC || LZO_CC_WATCOMC) +# define __lzo_cte(e) ((void)0,(e)) +# elif 1 +# define __lzo_cte(e) ((void)0,(e)) +# endif +#endif +#if !defined(__lzo_cte) +# define __lzo_cte(e) (e) +#endif +#if !defined(LZO_BLOCK_BEGIN) +# define LZO_BLOCK_BEGIN do { +# define LZO_BLOCK_END } while __lzo_cte(0) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {LZO_EXTERN_C int lzo_unused__[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {LZO_EXTERN_C int lzo_unused_func__[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_CLANG >= 0x020800ul) +# define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) +# elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_GHS) +# define __lzo_inline __inline__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_inline __inline__ +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_inline __inline__ +#endif +#endif +#if defined(__lzo_inline) +# ifndef __lzo_HAVE_inline +# define __lzo_HAVE_inline 1 +# endif +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# ifndef __lzo_HAVE_forceinline +# define __lzo_HAVE_forceinline 1 +# endif +#else +# define __lzo_forceinline __lzo_inline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# ifndef __lzo_HAVE_noinline +# define __lzo_HAVE_noinline 1 +# endif +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_static_inline) +#if (LZO_CC_IBMC) +# define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline +#endif +#endif +#if !defined(__lzo_static_inline) +# define __lzo_static_inline static __lzo_inline +#endif +#if !defined(__lzo_static_forceinline) +#if (LZO_CC_IBMC) +# define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline +#endif +#endif +#if !defined(__lzo_static_forceinline) +# define __lzo_static_forceinline static __lzo_forceinline +#endif +#if !defined(__lzo_static_noinline) +#if (LZO_CC_IBMC) +# define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline +#endif +#endif +#if !defined(__lzo_static_noinline) +# define __lzo_static_noinline static __lzo_noinline +#endif +#if !defined(__lzo_c99_extern_inline) +#if defined(__GNUC_GNU_INLINE__) +# define __lzo_c99_extern_inline __lzo_inline +#elif defined(__GNUC_STDC_INLINE__) +# define __lzo_c99_extern_inline extern __lzo_inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_c99_extern_inline extern __lzo_inline +#endif +#if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) +# define __lzo_c99_extern_inline __lzo_inline +#endif +#endif +#if defined(__lzo_c99_extern_inline) +# ifndef __lzo_HAVE_c99_extern_inline +# define __lzo_HAVE_c99_extern_inline 1 +# endif +#else +# define __lzo_c99_extern_inline /*empty*/ +#endif +#if !defined(__lzo_may_alias) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_CLANG >= 0x020900ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#endif +#endif +#if defined(__lzo_may_alias) +# ifndef __lzo_HAVE_may_alias +# define __lzo_HAVE_may_alias 1 +# endif +#else +# define __lzo_may_alias /*empty*/ +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#endif +#endif +#if defined(__lzo_noreturn) +# ifndef __lzo_HAVE_noreturn +# define __lzo_HAVE_noreturn 1 +# endif +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# ifndef __lzo_HAVE_nothrow +# define __lzo_HAVE_nothrow 1 +# endif +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 1210) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_restrict __restrict__ +#endif +#endif +#if defined(__lzo_restrict) +# ifndef __lzo_HAVE_restrict +# define __lzo_HAVE_restrict 1 +# endif +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_GHS) && !defined(__cplusplus) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_IBMC >= 600) +# define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# ifndef __lzo_HAVE_alignof +# define __lzo_HAVE_alignof 1 +# endif +#endif +#if !defined(__lzo_struct_packed) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { +# define __lzo_struct_packed_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_struct_packed(s) _Packed struct s { +# define __lzo_struct_packed_end() }; +#endif +#endif +#if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) +# define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) +#endif +#if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) +# define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() +#endif +#if !defined(__lzo_byte_struct) +#if defined(__lzo_struct_packed) +# define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() +# define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); +# define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); +#endif +#endif +#if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) +# define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) +#endif +#if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) +#if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) +#elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_CILLY || LZO_CC_PCC) +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_align16(s) struct __declspec(align(16)) s { +# define __lzo_struct_align16_end() }; +# define __lzo_struct_align32(s) struct __declspec(align(32)) s { +# define __lzo_struct_align32_end() }; +# define __lzo_struct_align64(s) struct __declspec(align(64)) s { +# define __lzo_struct_align64_end() }; +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_struct_align16(s) struct s { +# define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); +# define __lzo_struct_align32(s) struct s { +# define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); +# define __lzo_struct_align64(s) struct s { +# define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); +#endif +#endif +#if !defined(__lzo_union_um) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_union_am(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_union_um(s) __pragma(pack(push,1)) union s { +# define __lzo_union_um_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_union_um(s) _Packed union s { +# define __lzo_union_um_end() }; +#endif +#endif +#if !defined(__lzo_union_am) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() }; +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# ifndef __lzo_HAVE_constructor +# define __lzo_HAVE_constructor 1 +# endif +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# ifndef __lzo_HAVE_destructor +# define __lzo_HAVE_destructor 1 +# endif +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_IBMC >= 1010) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# ifndef __lzo_HAVE_likely +# define __lzo_HAVE_likely 1 +# endif +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# ifndef __lzo_HAVE_unlikely +# define __lzo_HAVE_unlikely 1 +# endif +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(__lzo_static_unused_void_func) +# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_static_unused_void_func(f) static void __attribute__((__unused__)) f(void) +# else +# define __lzo_static_unused_void_func(f) static __lzo_inline void f(void) +# endif +#endif +#if !defined(__lzo_loop_forever) +# if (LZO_CC_IBMC) +# define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END +# else +# define __lzo_loop_forever() do { ; } while __lzo_cte(1) +# endif +#endif +#if !defined(__lzo_unreachable) +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_GNUC >= 0x040500ul) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 +# define __lzo_unreachable() __builtin_unreachable(); +#endif +#endif +#if defined(__lzo_unreachable) +# ifndef __lzo_HAVE_unreachable +# define __lzo_HAVE_unreachable 1 +# endif +#else +# if 0 +# define __lzo_unreachable() ((void)0); +# else +# define __lzo_unreachable() __lzo_loop_forever(); +# endif +#endif +#ifndef __LZO_CTA_NAME +#if (LZO_CFG_USE_COUNTER) +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) +#else +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) +#endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} +# elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} +# elif (LZO_CC_GNUC >= 0x040700ul) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) +#if defined(__cplusplus) +extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if !defined(LZO_HAVE_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#endif +#ifndef LZO_SIZEOF_SHORT +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#elif defined(__SIZEOF_SHORT__) +# define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) +#endif +#endif +#ifndef LZO_SIZEOF_INT +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#elif defined(__SIZEOF_INT__) +# define LZO_SIZEOF_INT (__SIZEOF_INT__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#elif defined(__SIZEOF_LONG__) +# define LZO_SIZEOF_LONG (__SIZEOF_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG_LONG +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#elif defined(__SIZEOF_LONG_LONG__) +# define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF___INT16 +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#endif +#ifndef LZO_SIZEOF___INT32 +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#endif +#ifndef LZO_SIZEOF___INT64 +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#endif +#ifndef LZO_SIZEOF_VOID_P +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#elif defined(__SIZEOF_POINTER__) +# define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) +#endif +#endif +#ifndef LZO_SIZEOF_SIZE_T +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#elif defined(__SIZEOF_SIZE_T__) +# define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) +#endif +#endif +#ifndef LZO_SIZEOF_PTRDIFF_T +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#elif defined(__SIZEOF_PTRDIFF_T__) +# define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) +#endif +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,39) == 1) +# define LZO_SIZEOF_LONG 5 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && (LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if (LZO_CFG_NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(_NO_LONGLONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_WORDSIZE) +#if (LZO_ARCH_ALPHA) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AMD64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AVR) +# define LZO_WORDSIZE 1 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define LZO_WORDSIZE 4 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_WORDSIZE 4 +# else +# define LZO_WORDSIZE 2 +# endif +#elif (LZO_ARCH_I086) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_IA64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_M16C) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_SPU) +# define LZO_WORDSIZE 4 +#elif (LZO_ARCH_Z80) +# define LZO_WORDSIZE 1 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_WORDSIZE 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define LZO_WORDSIZE 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_WORDSIZE 8 +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LP64__) || defined(__LP64) || defined(_LP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_ARCH_AVR) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#elif (LZO_ARCH_M16C) +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_ARCH_SPU) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_ARCH_Z80) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# if defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# else +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# endif +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) +#endif +#if !defined(LZO_WORDSIZE) +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) +# if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +# elif defined(__BIG_ENDIAN) +# define LZO_ABI_BIG_ENDIAN 1 +# else +# define LZO_ABI_LITTLE_ENDIAN 1 +# endif +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif (LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif (LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_LP32 1 +# define LZO_INFO_ABI_PM "lp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if 0 +#elif !defined(__LZO_LIBC_OVERRIDE) +#if (LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif (LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif (LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif (LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif (LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uc" "libc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_CC_GNUC) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) +# define __LZO_ASM_CLOBBER "memory" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_CC : "cc" +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_ARM) +# if defined(__ARM_FEATURE_UNALIGNED) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 6) && !defined(__TARGET_PROFILE_M) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_CRIS) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_I386) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if (LZO_ABI_BIG_ENDIAN) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +# endif +#elif (LZO_ARCH_S390) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#ifndef LZO_CFG_NO_INLINE_ASM +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_INLINE_ASM 1 +#elif (LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#if (LZO_CFG_NO_INLINE_ASM) +# undef LZO_ASM_SYNTAX_MSC +# undef LZO_ASM_SYNTAX_GNUC +# undef __LZO_ASM_CLOBBER +# undef __LZO_ASM_CLOBBER_LIST_CC +# undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY +# undef __LZO_ASM_CLOBBER_LIST_EMPTY +#endif +#ifndef LZO_CFG_NO_UNALIGNED +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER +#if !(LZO_CFG_SKIP_LZO_TYPES) +#if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) +# error "missing defines for sizes" +#endif +#if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) +# error "missing defines for sizes" +#endif +#if !defined(lzo_llong_t) +#if (LZO_SIZEOF_LONG_LONG+0 > 0) +__lzo_gnuc_extension__ typedef long long lzo_llong_t__; +__lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; +# define lzo_llong_t lzo_llong_t__ +# define lzo_ullong_t lzo_ullong_t__ +#endif +#endif +#if !defined(lzo_int16e_t) +#if (LZO_SIZEOF_LONG == 2) +# define lzo_int16e_t long +# define lzo_uint16e_t unsigned long +#elif (LZO_SIZEOF_INT == 2) +# define lzo_int16e_t int +# define lzo_uint16e_t unsigned int +#elif (LZO_SIZEOF_SHORT == 2) +# define lzo_int16e_t short int +# define lzo_uint16e_t unsigned short int +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) + typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); + typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); +# define lzo_int16e_t lzo_int16e_hi_t__ +# define lzo_uint16e_t lzo_uint16e_hi_t__ +#elif (LZO_SIZEOF___INT16 == 2) +# define lzo_int16e_t __int16 +# define lzo_uint16e_t unsigned __int16 +#else +#endif +#endif +#if defined(lzo_int16e_t) +# define LZO_SIZEOF_LZO_INT16E_T 2 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) +#endif +#if !defined(lzo_int32e_t) +#if (LZO_SIZEOF_LONG == 4) +# define lzo_int32e_t long int +# define lzo_uint32e_t unsigned long int +#elif (LZO_SIZEOF_INT == 4) +# define lzo_int32e_t int +# define lzo_uint32e_t unsigned int +#elif (LZO_SIZEOF_SHORT == 4) +# define lzo_int32e_t short int +# define lzo_uint32e_t unsigned short int +#elif (LZO_SIZEOF_LONG_LONG == 4) +# define lzo_int32e_t lzo_llong_t +# define lzo_uint32e_t lzo_ullong_t +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +#elif (LZO_SIZEOF___INT32 == 4) +# define lzo_int32e_t __int32 +# define lzo_uint32e_t unsigned __int32 +#else +#endif +#endif +#if defined(lzo_int32e_t) +# define LZO_SIZEOF_LZO_INT32E_T 4 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) +#endif +#if !defined(lzo_int64e_t) +#if (LZO_SIZEOF___INT64 == 8) +# if (LZO_CC_BORLANDC) && !(LZO_CFG_TYPE_PREFER___INT64) +# define LZO_CFG_TYPE_PREFER___INT64 1 +# endif +#endif +#if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int64e_t int +# define lzo_uint64e_t unsigned int +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG == 8) +# define lzo_int64e_t long int +# define lzo_uint64e_t unsigned long int +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG +#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_TYPE_PREFER___INT64) +# define lzo_int64e_t lzo_llong_t +# define lzo_uint64e_t lzo_ullong_t +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0ll) +# define LZO_UINT64_C(c) ((c) + 0ull) +# elif 0 +# define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) +# define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) +# else +# define LZO_INT64_C(c) (c##LL) +# define LZO_UINT64_C(c) (c##ULL) +# endif +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG_LONG +#elif (LZO_SIZEOF___INT64 == 8) +# define lzo_int64e_t __int64 +# define lzo_uint64e_t unsigned __int64 +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0i64) +# define LZO_UINT64_C(c) ((c) + 0ui64) +# else +# define LZO_INT64_C(c) (c##i64) +# define LZO_UINT64_C(c) (c##ui64) +# endif +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF___INT64 +#else +#endif +#endif +#if defined(lzo_int64e_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) +#endif +#if !defined(lzo_int32l_t) +#if defined(lzo_int32e_t) +# define lzo_int32l_t lzo_int32e_t +# define lzo_uint32l_t lzo_uint32e_t +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T +#elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int32l_t int +# define lzo_uint32l_t unsigned int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= 4) +# define lzo_int32l_t long int +# define lzo_uint32l_t unsigned long int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG +#else +# error "lzo_int32l_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) +#endif +#if !defined(lzo_int64l_t) +#if defined(lzo_int64e_t) +# define lzo_int64l_t lzo_int64e_t +# define lzo_uint64l_t lzo_uint64e_t +# define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T +#else +#endif +#endif +#if defined(lzo_int64l_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) +#endif +#if !defined(lzo_int32f_t) +#if (LZO_SIZEOF_SIZE_T >= 8) +# define lzo_int32f_t lzo_int64l_t +# define lzo_uint32f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T +#else +# define lzo_int32f_t lzo_int32l_t +# define lzo_uint32f_t lzo_uint32l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) +#endif +#if !defined(lzo_int64f_t) +#if defined(lzo_int64l_t) +# define lzo_int64f_t lzo_int64l_t +# define lzo_uint64f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T +#else +#endif +#endif +#if defined(lzo_int64f_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) +#endif +#if !defined(lzo_intptr_t) +#if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) +# define __LZO_INTPTR_T_IS_POINTER 1 + typedef char* lzo_intptr_t; + typedef char* lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P +#elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) + typedef __w64 int lzo_intptr_t; + typedef __w64 unsigned int lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) +# define lzo_intptr_t short +# define lzo_uintptr_t unsigned short +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT +#elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_intptr_t int +# define lzo_uintptr_t unsigned int +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t long +# define lzo_uintptr_t unsigned long +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG +#elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t lzo_int64l_t +# define lzo_uintptr_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T +#else +# error "lzo_intptr_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) +#endif +#if !defined(lzo_word_t) +#if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) +#if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) +# define lzo_word_t lzo_uintptr_t +# define lzo_sword_t lzo_intptr_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T +#elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) +# define lzo_word_t unsigned long +# define lzo_sword_t long +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG +#elif (LZO_WORDSIZE == LZO_SIZEOF_INT) +# define lzo_word_t unsigned int +# define lzo_sword_t int +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT +#elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) +# define lzo_word_t unsigned short +# define lzo_sword_t short +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT +#elif (LZO_WORDSIZE == 1) +# define lzo_word_t unsigned char +# define lzo_sword_t signed char +# define LZO_SIZEOF_LZO_WORD_T 1 +#elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) +# define lzo_word_t lzo_uint64l_t +# define lzo_sword_t lzo_int64l_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +#elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) +#if 0 + typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); + typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); +# define lzo_word_t lzo_word_t +# define lzo_sword_t lzo_sword_t +# define LZO_SIZEOF_LZO_WORD_T 16 +#endif +#else +# error "lzo_word_t" +#endif +#endif +#endif +#if 1 && defined(lzo_word_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) +#endif +#if 1 +#define lzo_int8_t signed char +#define lzo_uint8_t unsigned char +#define LZO_SIZEOF_LZO_INT8_T 1 +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) +#endif +#if defined(lzo_int16e_t) +#define lzo_int16_t lzo_int16e_t +#define lzo_uint16_t lzo_uint16e_t +#define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) +#endif +#if defined(lzo_int32e_t) +#define lzo_int32_t lzo_int32e_t +#define lzo_uint32_t lzo_uint32e_t +#define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) +#endif +#if defined(lzo_int64e_t) +#define lzo_int64_t lzo_int64e_t +#define lzo_uint64_t lzo_uint64e_t +#define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) +#endif +#if 1 +#define lzo_int_least32_t lzo_int32l_t +#define lzo_uint_least32_t lzo_uint32l_t +#define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) +#endif +#if defined(lzo_int64l_t) +#define lzo_int_least64_t lzo_int64l_t +#define lzo_uint_least64_t lzo_uint64l_t +#define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) +#endif +#if 1 +#define lzo_int_fast32_t lzo_int32f_t +#define lzo_uint_fast32_t lzo_uint32f_t +#define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) +#endif +#if defined(lzo_int64f_t) +#define lzo_int_fast64_t lzo_int64f_t +#define lzo_uint_fast64_t lzo_uint64f_t +#define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) +#endif +#if !defined(LZO_INT16_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) ((c) + 0) +# define LZO_UINT16_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) ((c) + 0L) +# define LZO_UINT16_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) (c) +# define LZO_UINT16_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) (c##L) +# define LZO_UINT16_C(c) (c##UL) +# else +# error "LZO_INT16_C" +# endif +#endif +#if !defined(LZO_INT32_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) ((c) + 0) +# define LZO_UINT32_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) ((c) + 0L) +# define LZO_UINT32_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) (c) +# define LZO_UINT32_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) (c##L) +# define LZO_UINT32_C(c) (c##UL) +# elif (LZO_SIZEOF_LONG_LONG >= 4) +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# else +# error "LZO_INT32_C" +# endif +#endif +#if !defined(LZO_INT64_C) && defined(lzo_int64l_t) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) ((c) + 0) +# define LZO_UINT64_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) ((c) + 0L) +# define LZO_UINT64_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) (c) +# define LZO_UINT64_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) (c##L) +# define LZO_UINT64_C(c) (c##UL) +# else +# error "LZO_INT64_C" +# endif +#endif +#endif + +#endif + +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2080) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H 1 +#endif + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H 1 + +#if !defined(__LZO_IN_MINILZO) +#if defined(LZO_CFG_FREESTANDING) && (LZO_CFG_FREESTANDING) +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +#endif +#if defined(LZO_CFG_EXTRA_CONFIG_HEADER) +# include LZO_CFG_EXTRA_CONFIG_HEADER +#endif +#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED) +# error "include this file first" +#endif +#include "lzo/lzoconf.h" +#if defined(LZO_CFG_EXTRA_CONFIG_HEADER2) +# include LZO_CFG_EXTRA_CONFIG_HEADER2 +#endif +#endif + +#if (LZO_VERSION < 0x2080) || !defined(__LZOCONF_H_INCLUDED) +# error "version mismatch" +#endif + +#if (LZO_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1100)) +# pragma warning(disable: 4702) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1000)) +# pragma warning(disable: 4127 4701) +# pragma warning(disable: 4514 4710 4711) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1300)) +# pragma warning(disable: 4820) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1800)) +# pragma warning(disable: 4746) +#endif + +#if (LZO_CC_SUNPROC) +#if !defined(__cplusplus) +# pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED) +# pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP) +# pragma error_messages(off,E_STATEMENT_NOT_REACHED) +#endif +#endif + +#if defined(__LZO_IN_MINILZO) || (LZO_CFG_FREESTANDING) +#elif 1 +# include <string.h> +#else +# define LZO_WANT_ACC_INCD_H 1 +#endif +#if defined(LZO_HAVE_CONFIG_H) +# define LZO_CFG_NO_CONFIG_HEADER 1 +#endif + +#if 1 && !defined(LZO_CFG_FREESTANDING) +#if 1 && !defined(HAVE_STRING_H) +#define HAVE_STRING_H 1 +#endif +#if 1 && !defined(HAVE_MEMCMP) +#define HAVE_MEMCMP 1 +#endif +#if 1 && !defined(HAVE_MEMCPY) +#define HAVE_MEMCPY 1 +#endif +#if 1 && !defined(HAVE_MEMMOVE) +#define HAVE_MEMMOVE 1 +#endif +#if 1 && !defined(HAVE_MEMSET) +#define HAVE_MEMSET 1 +#endif +#endif + +#if 1 && defined(HAVE_STRING_H) +#include <string.h> +#endif + +#if 1 || defined(lzo_int8_t) || defined(lzo_uint8_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint8_t) == 1) +#endif +#if 1 || defined(lzo_int16_t) || defined(lzo_uint16_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint16_t) == 2) +#endif +#if 1 || defined(lzo_int32_t) || defined(lzo_uint32_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32_t) == 4) +#endif +#if defined(lzo_int64_t) || defined(lzo_uint64_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64_t) == 8) +#endif + +#if (LZO_CFG_FREESTANDING) +# undef HAVE_MEMCMP +# undef HAVE_MEMCPY +# undef HAVE_MEMMOVE +# undef HAVE_MEMSET +#endif + +#if !(HAVE_MEMCMP) +# undef memcmp +# define memcmp(a,b,c) lzo_memcmp(a,b,c) +#else +# undef lzo_memcmp +# define lzo_memcmp(a,b,c) memcmp(a,b,c) +#endif +#if !(HAVE_MEMCPY) +# undef memcpy +# define memcpy(a,b,c) lzo_memcpy(a,b,c) +#else +# undef lzo_memcpy +# define lzo_memcpy(a,b,c) memcpy(a,b,c) +#endif +#if !(HAVE_MEMMOVE) +# undef memmove +# define memmove(a,b,c) lzo_memmove(a,b,c) +#else +# undef lzo_memmove +# define lzo_memmove(a,b,c) memmove(a,b,c) +#endif +#if !(HAVE_MEMSET) +# undef memset +# define memset(a,b,c) lzo_memset(a,b,c) +#else +# undef lzo_memset +# define lzo_memset(a,b,c) memset(a,b,c) +#endif + +#undef NDEBUG +#if (LZO_CFG_FREESTANDING) +# undef LZO_DEBUG +# define NDEBUG 1 +# undef assert +# define assert(e) ((void)0) +#else +# if !defined(LZO_DEBUG) +# define NDEBUG 1 +# endif +# include <assert.h> +#endif + +#if 0 && defined(__BOUNDS_CHECKING_ON) +# include <unchecked.h> +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if (LZO_CFG_PGO) +# undef __lzo_likely +# undef __lzo_unlikely +# define __lzo_likely(e) (e) +# define __lzo_unlikely(e) (e) +#endif + +#undef _ +#undef __ +#undef ___ +#undef ____ +#undef _p0 +#undef _p1 +#undef _p2 +#undef _p3 +#undef _p4 +#undef _s0 +#undef _s1 +#undef _s2 +#undef _s3 +#undef _s4 +#undef _ww + +#if 1 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#if !defined(DMUL) +#if 0 + +# define DMUL(a,b) ((lzo_xint) ((lzo_uint32_t)(a) * (lzo_uint32_t)(b))) +#else +# define DMUL(a,b) ((lzo_xint) ((a) * (b))) +#endif +#endif + +#ifndef __LZO_FUNC_H +#define __LZO_FUNC_H 1 + +#if !defined(LZO_BITOPS_USE_ASM_BITSCAN) && !defined(LZO_BITOPS_USE_GNUC_BITSCAN) && !defined(LZO_BITOPS_USE_MSC_BITSCAN) +#if 1 && (LZO_ARCH_AMD64) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_ASM_SYNTAX_GNUC) +#define LZO_BITOPS_USE_ASM_BITSCAN 1 +#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul)))) +#define LZO_BITOPS_USE_GNUC_BITSCAN 1 +#elif (LZO_OS_WIN32 || LZO_OS_WIN64) && ((LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 1010)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) +#define LZO_BITOPS_USE_MSC_BITSCAN 1 +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +#include <intrin.h> +#endif +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +#pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) +#endif +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64) +#pragma intrinsic(_BitScanReverse64) +#pragma intrinsic(_BitScanForward64) +#endif +#endif +#endif + +__lzo_static_forceinline unsigned lzo_bitops_ctlz32_func(lzo_uint32_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) + unsigned long r; (void) _BitScanReverse(&r, v); return (unsigned) r ^ 31; +#define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint32_t r; + __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r ^ 31; +#define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT == 4) + unsigned r; r = (unsigned) __builtin_clz(v); return r; +#define lzo_bitops_ctlz32(v) ((unsigned) __builtin_clz(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} + +#if defined(lzo_uint64_t) +__lzo_static_forceinline unsigned lzo_bitops_ctlz64_func(lzo_uint64_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) + unsigned long r; (void) _BitScanReverse64(&r, v); return (unsigned) r ^ 63; +#define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint64_t r; + __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r ^ 63; +#define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_clzl(v); return r; +#define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzl(v)) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG == 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_clzll(v); return r; +#define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzll(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} +#endif + +__lzo_static_forceinline unsigned lzo_bitops_cttz32_func(lzo_uint32_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) + unsigned long r; (void) _BitScanForward(&r, v); return (unsigned) r; +#define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint32_t r; + __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r; +#define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT >= 4) + unsigned r; r = (unsigned) __builtin_ctz(v); return r; +#define lzo_bitops_cttz32(v) ((unsigned) __builtin_ctz(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} + +#if defined(lzo_uint64_t) +__lzo_static_forceinline unsigned lzo_bitops_cttz64_func(lzo_uint64_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) + unsigned long r; (void) _BitScanForward64(&r, v); return (unsigned) r; +#define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint64_t r; + __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r; +#define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG >= 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_ctzl(v); return r; +#define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzl(v)) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG >= 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_ctzll(v); return r; +#define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzll(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} +#endif + +#if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +static void __attribute__((__unused__)) +#else +__lzo_static_forceinline void +#endif +lzo_bitops_unused_funcs(void) +{ + LZO_UNUSED_FUNC(lzo_bitops_ctlz32_func); + LZO_UNUSED_FUNC(lzo_bitops_cttz32_func); +#if defined(lzo_uint64_t) + LZO_UNUSED_FUNC(lzo_bitops_ctlz64_func); + LZO_UNUSED_FUNC(lzo_bitops_cttz64_func); +#endif + LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); +} + +#if defined(__lzo_alignof) && !(LZO_CFG_NO_UNALIGNED) +#ifndef __lzo_memops_tcheck +#define __lzo_memops_tcheck(t,a,b) ((void)0, sizeof(t) == (a) && __lzo_alignof(t) == (b)) +#endif +#endif +#ifndef lzo_memops_TU0p +#define lzo_memops_TU0p void __LZO_MMODEL * +#endif +#ifndef lzo_memops_TU1p +#define lzo_memops_TU1p unsigned char __LZO_MMODEL * +#endif +#ifndef lzo_memops_TU2p +#if (LZO_OPT_UNALIGNED16) +typedef lzo_uint16_t __lzo_may_alias lzo_memops_TU2; +#define lzo_memops_TU2p volatile lzo_memops_TU2 * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU2_struct,2) +typedef struct lzo_memops_TU2_struct lzo_memops_TU2; +#else +struct lzo_memops_TU2_struct { unsigned char a[2]; } __lzo_may_alias; +typedef struct lzo_memops_TU2_struct lzo_memops_TU2; +#endif +#ifndef lzo_memops_TU2p +#define lzo_memops_TU2p lzo_memops_TU2 * +#endif +#endif +#ifndef lzo_memops_TU4p +#if (LZO_OPT_UNALIGNED32) +typedef lzo_uint32_t __lzo_may_alias lzo_memops_TU4; +#define lzo_memops_TU4p volatile lzo_memops_TU4 __LZO_MMODEL * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU4_struct,4) +typedef struct lzo_memops_TU4_struct lzo_memops_TU4; +#else +struct lzo_memops_TU4_struct { unsigned char a[4]; } __lzo_may_alias; +typedef struct lzo_memops_TU4_struct lzo_memops_TU4; +#endif +#ifndef lzo_memops_TU4p +#define lzo_memops_TU4p lzo_memops_TU4 __LZO_MMODEL * +#endif +#endif +#ifndef lzo_memops_TU8p +#if (LZO_OPT_UNALIGNED64) +typedef lzo_uint64_t __lzo_may_alias lzo_memops_TU8; +#define lzo_memops_TU8p volatile lzo_memops_TU8 __LZO_MMODEL * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU8_struct,8) +typedef struct lzo_memops_TU8_struct lzo_memops_TU8; +#else +struct lzo_memops_TU8_struct { unsigned char a[8]; } __lzo_may_alias; +typedef struct lzo_memops_TU8_struct lzo_memops_TU8; +#endif +#ifndef lzo_memops_TU8p +#define lzo_memops_TU8p lzo_memops_TU8 __LZO_MMODEL * +#endif +#endif +#ifndef lzo_memops_set_TU1p +#define lzo_memops_set_TU1p volatile lzo_memops_TU1p +#endif +#ifndef lzo_memops_move_TU1p +#define lzo_memops_move_TU1p lzo_memops_TU1p +#endif +#define LZO_MEMOPS_SET1(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__1 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__1[0] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET2(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__2 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__2[0] = LZO_BYTE(cc); d__2[1] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET3(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__3 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__3[0] = LZO_BYTE(cc); d__3[1] = LZO_BYTE(cc); d__3[2] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET4(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__4 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__4[0] = LZO_BYTE(cc); d__4[1] = LZO_BYTE(cc); d__4[2] = LZO_BYTE(cc); d__4[3] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE1(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__1 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__1 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__1[0] = s__1[0]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE2(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__2 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__2 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__2[0] = s__2[0]; d__2[1] = s__2[1]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE3(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__3 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__3 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__3[0] = s__3[0]; d__3[1] = s__3[1]; d__3[2] = s__3[2]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE4(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__4 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__4 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__4[0] = s__4[0]; d__4[1] = s__4[1]; d__4[2] = s__4[2]; d__4[3] = s__4[3]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE8(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__8 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__8 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__8[0] = s__8[0]; d__8[1] = s__8[1]; d__8[2] = s__8[2]; d__8[3] = s__8[3]; \ + d__8[4] = s__8[4]; d__8[5] = s__8[5]; d__8[6] = s__8[6]; d__8[7] = s__8[7]; \ + LZO_BLOCK_END +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU1p)0)==1) +#define LZO_MEMOPS_COPY1(dd,ss) LZO_MEMOPS_MOVE1(dd,ss) +#if (LZO_OPT_UNALIGNED16) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2) +#define LZO_MEMOPS_COPY2(dd,ss) \ + * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss) +#elif defined(__lzo_memops_tcheck) +#define LZO_MEMOPS_COPY2(dd,ss) \ + LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU2,2,1)) { \ + * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE2(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY2(dd,ss) LZO_MEMOPS_MOVE2(dd,ss) +#endif +#if (LZO_OPT_UNALIGNED32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4) +#define LZO_MEMOPS_COPY4(dd,ss) \ + * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss) +#elif defined(__lzo_memops_tcheck) +#define LZO_MEMOPS_COPY4(dd,ss) \ + LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU4,4,1)) { \ + * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE4(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY4(dd,ss) LZO_MEMOPS_MOVE4(dd,ss) +#endif +#if (LZO_WORDSIZE != 8) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END +#else +#if (LZO_OPT_UNALIGNED64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8) +#define LZO_MEMOPS_COPY8(dd,ss) \ + * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss) +#elif (LZO_OPT_UNALIGNED32) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END +#elif defined(__lzo_memops_tcheck) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU8,8,1)) { \ + * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE8(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY8(dd,ss) LZO_MEMOPS_MOVE8(dd,ss) +#endif +#endif +#define LZO_MEMOPS_COPYN(dd,ss,nn) \ + LZO_BLOCK_BEGIN \ + lzo_memops_TU1p d__n = (lzo_memops_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_TU1p s__n = (const lzo_memops_TU1p) (const lzo_memops_TU0p) (ss); \ + lzo_uint n__n = (nn); \ + while ((void)0, n__n >= 8) { LZO_MEMOPS_COPY8(d__n, s__n); d__n += 8; s__n += 8; n__n -= 8; } \ + if ((void)0, n__n >= 4) { LZO_MEMOPS_COPY4(d__n, s__n); d__n += 4; s__n += 4; n__n -= 4; } \ + if ((void)0, n__n > 0) do { *d__n++ = *s__n++; } while (--n__n > 0); \ + LZO_BLOCK_END + +__lzo_static_forceinline lzo_uint16_t lzo_memops_get_le16(const lzo_voidp ss) +{ + lzo_uint16_t v; +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY2(&v, ss); +#elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + const lzo_memops_TU2p s = (const lzo_memops_TU2p) ss; + unsigned long vv; + __asm__("lhbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); + v = (lzo_uint16_t) vv; +#else + const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; + v = (lzo_uint16_t) (((lzo_uint16_t)s[0]) | ((lzo_uint16_t)s[1] << 8)); +#endif + return v; +} +#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE16(ss) * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss) +#else +#define LZO_MEMOPS_GET_LE16(ss) lzo_memops_get_le16(ss) +#endif + +__lzo_static_forceinline lzo_uint32_t lzo_memops_get_le32(const lzo_voidp ss) +{ + lzo_uint32_t v; +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY4(&v, ss); +#elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + const lzo_memops_TU4p s = (const lzo_memops_TU4p) ss; + unsigned long vv; + __asm__("lwbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); + v = (lzo_uint32_t) vv; +#else + const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; + v = (lzo_uint32_t) (((lzo_uint32_t)s[0]) | ((lzo_uint32_t)s[1] << 8) | ((lzo_uint32_t)s[2] << 16) | ((lzo_uint32_t)s[3] << 24)); +#endif + return v; +} +#if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE32(ss) * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss) +#else +#define LZO_MEMOPS_GET_LE32(ss) lzo_memops_get_le32(ss) +#endif + +#if (LZO_OPT_UNALIGNED64) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE64(ss) * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss) +#endif + +__lzo_static_forceinline lzo_uint16_t lzo_memops_get_ne16(const lzo_voidp ss) +{ + lzo_uint16_t v; + LZO_MEMOPS_COPY2(&v, ss); + return v; +} +#if (LZO_OPT_UNALIGNED16) +#define LZO_MEMOPS_GET_NE16(ss) * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss) +#else +#define LZO_MEMOPS_GET_NE16(ss) lzo_memops_get_ne16(ss) +#endif + +__lzo_static_forceinline lzo_uint32_t lzo_memops_get_ne32(const lzo_voidp ss) +{ + lzo_uint32_t v; + LZO_MEMOPS_COPY4(&v, ss); + return v; +} +#if (LZO_OPT_UNALIGNED32) +#define LZO_MEMOPS_GET_NE32(ss) * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss) +#else +#define LZO_MEMOPS_GET_NE32(ss) lzo_memops_get_ne32(ss) +#endif + +#if (LZO_OPT_UNALIGNED64) +#define LZO_MEMOPS_GET_NE64(ss) * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss) +#endif + +__lzo_static_forceinline void lzo_memops_put_le16(lzo_voidp dd, lzo_uint16_t vv) +{ +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY2(dd, &vv); +#elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + lzo_memops_TU2p d = (lzo_memops_TU2p) dd; + unsigned long v = vv; + __asm__("sthbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); +#else + lzo_memops_TU1p d = (lzo_memops_TU1p) dd; + d[0] = LZO_BYTE((vv ) & 0xff); + d[1] = LZO_BYTE((vv >> 8) & 0xff); +#endif +} +#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_PUT_LE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_LE16(dd,vv) lzo_memops_put_le16(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_le32(lzo_voidp dd, lzo_uint32_t vv) +{ +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY4(dd, &vv); +#elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + lzo_memops_TU4p d = (lzo_memops_TU4p) dd; + unsigned long v = vv; + __asm__("stwbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); +#else + lzo_memops_TU1p d = (lzo_memops_TU1p) dd; + d[0] = LZO_BYTE((vv ) & 0xff); + d[1] = LZO_BYTE((vv >> 8) & 0xff); + d[2] = LZO_BYTE((vv >> 16) & 0xff); + d[3] = LZO_BYTE((vv >> 24) & 0xff); +#endif +} +#if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_PUT_LE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_LE32(dd,vv) lzo_memops_put_le32(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_ne16(lzo_voidp dd, lzo_uint16_t vv) +{ + LZO_MEMOPS_COPY2(dd, &vv); +} +#if (LZO_OPT_UNALIGNED16) +#define LZO_MEMOPS_PUT_NE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_NE16(dd,vv) lzo_memops_put_ne16(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_ne32(lzo_voidp dd, lzo_uint32_t vv) +{ + LZO_MEMOPS_COPY4(dd, &vv); +} +#if (LZO_OPT_UNALIGNED32) +#define LZO_MEMOPS_PUT_NE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_NE32(dd,vv) lzo_memops_put_ne32(dd,vv) +#endif + +#if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +static void __attribute__((__unused__)) +#else +__lzo_static_forceinline void +#endif +lzo_memops_unused_funcs(void) +{ + LZO_UNUSED_FUNC(lzo_memops_get_le16); + LZO_UNUSED_FUNC(lzo_memops_get_le32); + LZO_UNUSED_FUNC(lzo_memops_get_ne16); + LZO_UNUSED_FUNC(lzo_memops_get_ne32); + LZO_UNUSED_FUNC(lzo_memops_put_le16); + LZO_UNUSED_FUNC(lzo_memops_put_le32); + LZO_UNUSED_FUNC(lzo_memops_put_ne16); + LZO_UNUSED_FUNC(lzo_memops_put_ne32); + LZO_UNUSED_FUNC(lzo_memops_unused_funcs); +} + +#endif + +#ifndef UA_SET1 +#define UA_SET1 LZO_MEMOPS_SET1 +#endif +#ifndef UA_SET2 +#define UA_SET2 LZO_MEMOPS_SET2 +#endif +#ifndef UA_SET3 +#define UA_SET3 LZO_MEMOPS_SET3 +#endif +#ifndef UA_SET4 +#define UA_SET4 LZO_MEMOPS_SET4 +#endif +#ifndef UA_MOVE1 +#define UA_MOVE1 LZO_MEMOPS_MOVE1 +#endif +#ifndef UA_MOVE2 +#define UA_MOVE2 LZO_MEMOPS_MOVE2 +#endif +#ifndef UA_MOVE3 +#define UA_MOVE3 LZO_MEMOPS_MOVE3 +#endif +#ifndef UA_MOVE4 +#define UA_MOVE4 LZO_MEMOPS_MOVE4 +#endif +#ifndef UA_MOVE8 +#define UA_MOVE8 LZO_MEMOPS_MOVE8 +#endif +#ifndef UA_COPY1 +#define UA_COPY1 LZO_MEMOPS_COPY1 +#endif +#ifndef UA_COPY2 +#define UA_COPY2 LZO_MEMOPS_COPY2 +#endif +#ifndef UA_COPY3 +#define UA_COPY3 LZO_MEMOPS_COPY3 +#endif +#ifndef UA_COPY4 +#define UA_COPY4 LZO_MEMOPS_COPY4 +#endif +#ifndef UA_COPY8 +#define UA_COPY8 LZO_MEMOPS_COPY8 +#endif +#ifndef UA_COPYN +#define UA_COPYN LZO_MEMOPS_COPYN +#endif +#ifndef UA_COPYN_X +#define UA_COPYN_X LZO_MEMOPS_COPYN +#endif +#ifndef UA_GET_LE16 +#define UA_GET_LE16 LZO_MEMOPS_GET_LE16 +#endif +#ifndef UA_GET_LE32 +#define UA_GET_LE32 LZO_MEMOPS_GET_LE32 +#endif +#ifdef LZO_MEMOPS_GET_LE64 +#ifndef UA_GET_LE64 +#define UA_GET_LE64 LZO_MEMOPS_GET_LE64 +#endif +#endif +#ifndef UA_GET_NE16 +#define UA_GET_NE16 LZO_MEMOPS_GET_NE16 +#endif +#ifndef UA_GET_NE32 +#define UA_GET_NE32 LZO_MEMOPS_GET_NE32 +#endif +#ifdef LZO_MEMOPS_GET_NE64 +#ifndef UA_GET_NE64 +#define UA_GET_NE64 LZO_MEMOPS_GET_NE64 +#endif +#endif +#ifndef UA_PUT_LE16 +#define UA_PUT_LE16 LZO_MEMOPS_PUT_LE16 +#endif +#ifndef UA_PUT_LE32 +#define UA_PUT_LE32 LZO_MEMOPS_PUT_LE32 +#endif +#ifndef UA_PUT_NE16 +#define UA_PUT_NE16 LZO_MEMOPS_PUT_NE16 +#endif +#ifndef UA_PUT_NE32 +#define UA_PUT_NE32 LZO_MEMOPS_PUT_NE32 +#endif + +#define MEMCPY8_DS(dest,src,len) \ + lzo_memcpy(dest,src,len); dest += len; src += len + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; while (--len > 0) + +LZO_EXTERN(const lzo_bytep) lzo_copyright(void); + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if (LZO_ARCH_I086) +#error "LZO_ARCH_I086 is unsupported" +#elif (LZO_MM_PVP) +#error "LZO_MM_PVP is unsupported" +#else +#define PTR(a) ((lzo_uintptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) (PTR(a) - PTR(b)) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_xint a_lzo_xint; + lzo_int16_t a_lzo_int16_t; + lzo_uint16_t a_lzo_uint16_t; + lzo_int32_t a_lzo_int32_t; + lzo_uint32_t a_lzo_uint32_t; +#if defined(lzo_uint64_t) + lzo_int64_t a_lzo_int64_t; + lzo_uint64_t a_lzo_uint64_t; +#endif + size_t a_size_t; + ptrdiff_t a_ptrdiff_t; + lzo_uintptr_t a_lzo_uintptr_t; + void * a_void_p; + char * a_char_p; + unsigned char * a_uchar_p; + const void * a_c_void_p; + const char * a_c_char_p; + const unsigned char * a_c_uchar_p; + lzo_voidp a_lzo_voidp; + lzo_bytep a_lzo_bytep; + const lzo_voidp a_c_lzo_voidp; + const lzo_bytep a_c_lzo_bytep; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#ifndef LZO_DETERMINISTIC +#define LZO_DETERMINISTIC 1 +#endif + +#ifndef LZO_DICT_USE_PTR +#define LZO_DICT_USE_PTR 1 +#endif + +#if (LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t * +#endif + +#endif + +#if !defined(MINILZO_CFG_SKIP_LZO_PTR) + +LZO_PUBLIC(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_uintptr_t p; + +#if (LZO_ARCH_I086) +#error "LZO_ARCH_I086 is unsupported" +#elif (LZO_MM_PVP) +#error "LZO_MM_PVP is unsupported" +#else + p = (lzo_uintptr_t) PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ +#if (__LZO_UINTPTR_T_IS_POINTER) +#error "__LZO_UINTPTR_T_IS_POINTER is unsupported" +#else + lzo_uintptr_t p, n; + p = __lzo_ptr_linear(ptr); + n = (((p + size - 1) / size) * size) - p; +#endif + + assert(size > 0); + assert((long)n >= 0); + assert(n <= size); + return (unsigned)n; +} + +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_UTIL) + +/* If you use the LZO library in a product, I would appreciate that you + * keep this copyright string in the executable of your product. + */ + +static const char __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\r\n\n" + "LZO data compression library.\n" + "$Copyright: LZO Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer\n" + "<markus@oberhumer.com>\n" + "http://www.oberhumer.com $\n\n" + "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" + "$Info: " LZO_INFO_STRING " $\n"; +#endif + +LZO_PUBLIC(const lzo_bytep) +lzo_copyright(void) +{ + return (const lzo_bytep) __lzo_copyright; +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1) +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2) +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4) +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8) + +LZO_PUBLIC(lzo_uint32_t) +lzo_adler32(lzo_uint32_t adler, const lzo_bytep buf, lzo_uint len) +{ + lzo_uint32_t s1 = adler & 0xffff; + lzo_uint32_t s2 = (adler >> 16) & 0xffff; + unsigned k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +#undef LZO_DO1 +#undef LZO_DO2 +#undef LZO_DO4 +#undef LZO_DO8 +#undef LZO_DO16 + +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_STRING) +#undef lzo_memcmp +#undef lzo_memcpy +#undef lzo_memmove +#undef lzo_memset +#if !defined(__LZO_MMODEL_HUGE) +# undef LZO_HAVE_MM_HUGE_PTR +#endif +#define lzo_hsize_t lzo_uint +#define lzo_hvoid_p lzo_voidp +#define lzo_hbyte_p lzo_bytep +#define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f +#define lzo_hmemcmp lzo_memcmp +#define lzo_hmemcpy lzo_memcpy +#define lzo_hmemmove lzo_memmove +#define lzo_hmemset lzo_memset +#define __LZOLIB_HMEMCPY_CH_INCLUDED 1 +#if !defined(LZOLIB_PUBLIC) +# define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f) +#endif +LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCMP) + const lzo_hbyte_p p1 = LZO_STATIC_CAST(const lzo_hbyte_p, s1); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, s2); + if __lzo_likely(len > 0) do + { + int d = *p1 - *p2; + if (d != 0) + return d; + p1++; p2++; + } while __lzo_likely(--len > 0); + return 0; +#else + return memcmp(s1, s2, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCPY) + lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); + if (!(len > 0) || p1 == p2) + return dest; + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + return dest; +#else + return memcpy(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMMOVE) + lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); + if (!(len > 0) || p1 == p2) + return dest; + if (p1 < p2) + { + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while __lzo_likely(--len > 0); + } + return dest; +#else + return memmove(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int cc, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET) + lzo_hbyte_p p = LZO_STATIC_CAST(lzo_hbyte_p, s); + unsigned char c = LZO_ITRUNC(unsigned char, cc); + if __lzo_likely(len > 0) do + *p++ = c; + while __lzo_likely(--len > 0); + return s; +#else + return memset(s, cc, len); +#endif +} +#undef LZOLIB_PUBLIC +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_INIT) + +#if !defined(__LZO_IN_MINILZO) + +#define LZO_WANT_ACC_CHK_CH 1 +#undef LZOCHK_ASSERT + + LZOCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) + LZOCHK_ASSERT_IS_SIGNED_T(lzo_int) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) +#if !(__LZO_UINTPTR_T_IS_POINTER) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) +#endif + LZOCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) + +#endif +#undef LZOCHK_ASSERT + +union lzo_config_check_union { + lzo_uint a[2]; + unsigned char b[2*LZO_MAX(8,sizeof(lzo_uint))]; +#if defined(lzo_uint64_t) + lzo_uint64_t c[2]; +#endif +}; + +#if 0 +#define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off))) +#else +static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off) +{ + return (lzo_voidp) ((lzo_bytep) ptr + off); +} +#endif + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030100ul && LZO_CC_CLANG < 0x030300ul)) +# if 0 + volatile +# endif +#endif + union lzo_config_check_union u; + lzo_voidp p; + unsigned r = 1; + + u.a[0] = u.a[1] = 0; + p = u2p(&u, 0); + r &= ((* (lzo_bytep) p) == 0); +#if !(LZO_CFG_NO_CONFIG_CHECK) +#if (LZO_ABI_BIG_ENDIAN) + u.a[0] = u.a[1] = 0; u.b[sizeof(lzo_uint) - 1] = 128; + p = u2p(&u, 0); + r &= ((* (lzo_uintp) p) == 128); +#endif +#if (LZO_ABI_LITTLE_ENDIAN) + u.a[0] = u.a[1] = 0; u.b[0] = 128; + p = u2p(&u, 0); + r &= ((* (lzo_uintp) p) == 128); +#endif + u.a[0] = u.a[1] = 0; + u.b[0] = 1; u.b[3] = 2; + p = u2p(&u, 1); + r &= UA_GET_NE16(p) == 0; + r &= UA_GET_LE16(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE16(p) == 128; + u.b[2] = 129; + r &= UA_GET_LE16(p) == LZO_UINT16_C(0x8180); +#if (LZO_ABI_BIG_ENDIAN) + r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8081); +#endif +#if (LZO_ABI_LITTLE_ENDIAN) + r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8180); +#endif + u.a[0] = u.a[1] = 0; + u.b[0] = 3; u.b[5] = 4; + p = u2p(&u, 1); + r &= UA_GET_NE32(p) == 0; + r &= UA_GET_LE32(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE32(p) == 128; + u.b[2] = 129; u.b[3] = 130; u.b[4] = 131; + r &= UA_GET_LE32(p) == LZO_UINT32_C(0x83828180); +#if (LZO_ABI_BIG_ENDIAN) + r &= UA_GET_NE32(p) == LZO_UINT32_C(0x80818283); +#endif +#if (LZO_ABI_LITTLE_ENDIAN) + r &= UA_GET_NE32(p) == LZO_UINT32_C(0x83828180); +#endif +#if defined(UA_GET_NE64) + u.c[0] = u.c[1] = 0; + u.b[0] = 5; u.b[9] = 6; + p = u2p(&u, 1); + u.c[0] = u.c[1] = 0; + r &= UA_GET_NE64(p) == 0; +#if defined(UA_GET_LE64) + r &= UA_GET_LE64(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE64(p) == 128; +#endif +#endif +#if defined(lzo_bitops_ctlz32) + { unsigned i = 0; lzo_uint32_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_ctlz32(v) == 31 - i; + r &= lzo_bitops_ctlz32_func(v) == 31 - i; + }} +#endif +#if defined(lzo_bitops_ctlz64) + { unsigned i = 0; lzo_uint64_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_ctlz64(v) == 63 - i; + r &= lzo_bitops_ctlz64_func(v) == 63 - i; + }} +#endif +#if defined(lzo_bitops_cttz32) + { unsigned i = 0; lzo_uint32_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_cttz32(v) == i; + r &= lzo_bitops_cttz32_func(v) == i; + }} +#endif +#if defined(lzo_bitops_cttz64) + { unsigned i = 0; lzo_uint64_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_cttz64(v) == i; + r &= lzo_bitops_cttz64_func(v) == i; + }} +#endif +#endif + LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); + + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +LZO_PUBLIC(int) +__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + +#if defined(__LZO_IN_MINILZO) +#elif (LZO_CC_MSC && ((_MSC_VER) < 700)) +#else +#define LZO_WANT_ACC_CHK_CH 1 +#undef LZOCHK_ASSERT +#define LZOCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif +#undef LZOCHK_ASSERT + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32_t)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_callback_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD) + +#if 0 +BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment, + WORD wHeapSize, LPSTR lpszCmdLine ) +#else +int __far __pascal LibMain ( int a, short b, short c, long d ) +#endif +{ + LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d); + return 1; +} + +#endif + +#endif + +#endif + +#define LZO1X 1 +#define LZO_EOF_CODE 1 +#define M2_MAX_OFFSET 0x0800 + +#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) + +#if 1 && defined(UA_GET_LE32) +#undef LZO_DICT_USE_PTR +#define LZO_DICT_USE_PTR 0 +#undef lzo_dict_t +#define lzo_dict_t lzo_uint16_t +#endif + +#define LZO_NEED_DICT_H 1 +#ifndef D_BITS +#define D_BITS 14 +#endif +#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) +#if 1 +#define DINDEX(dv,p) DM(((DMUL(0x1824429d,dv)) >> (32-D_BITS))) +#else +#define DINDEX(dv,p) DM((dv) + ((dv) >> (32-D_BITS))) +#endif + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H 1 + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X 1 +#endif + +#if !defined(__LZO_IN_MINILZO) +#include "lzo/lzo1x.h" +#endif + +#ifndef LZO_EOF_CODE +#define LZO_EOF_CODE 1 +#endif +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 6 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 6 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#undef DM +#undef DX + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_xint)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_xint)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +#if (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_LLVM) +static void __attribute__((__unused__)) +#else +static void +#endif +DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) +{ + lzo_xint df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if (LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_dict_t) pd(p, in)) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if (LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR(( \ + m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \ + PTR_LT(m_pos,in) || \ + (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) == 0 || \ + m_off > max_offset ))) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (pd(ip, in) <= m_off || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if (LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define LZO_DETERMINISTIC !(LZO_DICT_USE_PTR) + +#ifndef DO_COMPRESS +#define DO_COMPRESS lzo1x_1_compress +#endif + +#if 1 && defined(DO_COMPRESS) && !defined(do_compress) +# define do_compress LZO_PP_ECONCAT2(DO_COMPRESS,_core) +#endif + +static __lzo_noinline lzo_uint +do_compress ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_uint ti, lzo_voidp wrkmem) +{ + const lzo_bytep ip; + lzo_bytep op; + const lzo_bytep const in_end = in + in_len; + const lzo_bytep const ip_end = in + in_len - 20; + const lzo_bytep ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += ti < 4 ? 4 - ti : 0; + for (;;) + { + const lzo_bytep m_pos; +#if !(LZO_DETERMINISTIC) + LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0); + lzo_uint m_len; + lzo_uint dindex; +next: + if __lzo_unlikely(ip >= ip_end) + break; + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if (LZO_OPT_UNALIGNED32) + if (UA_GET_NE32(m_pos) != UA_GET_NE32(ip)) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3]) +#endif + { +literal: + UPDATE_I(dict,0,dindex,ip,in); + ip += 1 + ((ip - ii) >> 5); + continue; + } + UPDATE_I(dict,0,dindex,ip,in); +#else + lzo_uint m_off; + lzo_uint m_len; + { + lzo_uint32_t dv; + lzo_uint dindex; +literal: + ip += 1 + ((ip - ii) >> 5); +next: + if __lzo_unlikely(ip >= ip_end) + break; + dv = UA_GET_LE32(ip); + dindex = DINDEX(dv,ip); + GINDEX(m_off,m_pos,in+dict,dindex,in); + UPDATE_I(dict,0,dindex,ip,in); + if __lzo_unlikely(dv != UA_GET_LE32(m_pos)) + goto literal; + } +#endif + + ii -= ti; ti = 0; + { + lzo_uint t = pd(ip,ii); + if (t != 0) + { + if (t <= 3) + { + op[-2] = LZO_BYTE(op[-2] | t); +#if (LZO_OPT_UNALIGNED32) + UA_COPY4(op, ii); + op += t; +#else + { do *op++ = *ii++; while (--t > 0); } +#endif + } +#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) + else if (t <= 16) + { + *op++ = LZO_BYTE(t - 3); + UA_COPY8(op, ii); + UA_COPY8(op+8, ii+8); + op += t; + } +#endif + else + { + if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + *op++ = 0; + while __lzo_unlikely(tt > 255) + { + tt -= 255; + UA_SET1(op, 0); + op++; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } +#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) + do { + UA_COPY8(op, ii); + UA_COPY8(op+8, ii+8); + op += 16; ii += 16; t -= 16; + } while (t >= 16); if (t > 0) +#endif + { do *op++ = *ii++; while (--t > 0); } + } + } + } + m_len = 4; + { +#if (LZO_OPT_UNALIGNED64) + lzo_uint64_t v; + v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); + if __lzo_unlikely(v == 0) { + do { + m_len += 8; + v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (v == 0); + } +#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz64) + m_len += lzo_bitops_ctlz64(v) / CHAR_BIT; +#elif (LZO_ABI_BIG_ENDIAN) + if ((v >> (64 - CHAR_BIT)) == 0) do { + v <<= CHAR_BIT; + m_len += 1; + } while ((v >> (64 - CHAR_BIT)) == 0); +#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz64) + m_len += lzo_bitops_cttz64(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) + if ((v & UCHAR_MAX) == 0) do { + v >>= CHAR_BIT; + m_len += 1; + } while ((v & UCHAR_MAX) == 0); +#else + if (ip[m_len] == m_pos[m_len]) do { + m_len += 1; + } while (ip[m_len] == m_pos[m_len]); +#endif +#elif (LZO_OPT_UNALIGNED32) + lzo_uint32_t v; + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); + if __lzo_unlikely(v == 0) { + do { + m_len += 4; + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); + if (v != 0) + break; + m_len += 4; + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (v == 0); + } +#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz32) + m_len += lzo_bitops_ctlz32(v) / CHAR_BIT; +#elif (LZO_ABI_BIG_ENDIAN) + if ((v >> (32 - CHAR_BIT)) == 0) do { + v <<= CHAR_BIT; + m_len += 1; + } while ((v >> (32 - CHAR_BIT)) == 0); +#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz32) + m_len += lzo_bitops_cttz32(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) + if ((v & UCHAR_MAX) == 0) do { + v >>= CHAR_BIT; + m_len += 1; + } while ((v & UCHAR_MAX) == 0); +#else + if (ip[m_len] == m_pos[m_len]) do { + m_len += 1; + } while (ip[m_len] == m_pos[m_len]); +#endif +#else + if __lzo_unlikely(ip[m_len] == m_pos[m_len]) { + do { + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (ip[m_len] == m_pos[m_len]); + } +#endif + } +m_len_done: + m_off = pd(ip,m_pos); + ip += m_len; + ii = ip; + if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= M3_MAX_LEN) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= M3_MAX_LEN; + *op++ = M3_MARKER | 0; + while __lzo_unlikely(m_len > 255) + { + m_len -= 255; + UA_SET1(op, 0); + op++; + } + *op++ = LZO_BYTE(m_len); + } + *op++ = LZO_BYTE(m_off << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + else + { + m_off -= 0x4000; + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8)); + while __lzo_unlikely(m_len > 255) + { + m_len -= 255; + UA_SET1(op, 0); + op++; + } + *op++ = LZO_BYTE(m_len); + } + *op++ = LZO_BYTE(m_off << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + goto next; + } + + *out_len = pd(op, out); + return pd(in_end,ii-ti); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + const lzo_bytep ip = in; + lzo_bytep op = out; + lzo_uint l = in_len; + lzo_uint t = 0; + + while (l > 20) + { + lzo_uint ll = l; + lzo_uintptr_t ll_end; +#if 0 || (LZO_DETERMINISTIC) + ll = LZO_MIN(ll, 49152); +#endif + ll_end = (lzo_uintptr_t)ip + ll; + if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll) + break; +#if (LZO_DETERMINISTIC) + lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t)); +#endif + t = do_compress(ip,ll,op,out_len,t,wrkmem); + ip += ll; + op += *out_len; + l -= ll; + } + t += l; + + if (t > 0) + { + const lzo_bytep ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] = LZO_BYTE(op[-2] | t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + UA_SET1(op, 0); + op++; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + UA_COPYN(op, ii, t); + op += t; + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = pd(op, out); + return LZO_E_OK; +} + +#endif + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND 1 +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_IP_AND_TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef TEST_IV +#undef TEST_OV +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP 1 +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP 1 +#else +# define TEST_OP 1 +#endif + +#if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) +#elif defined(HAVE_TEST_IP) +# define TEST_IP_AND_TEST_OP TEST_IP +#elif defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP TEST_OP +#else +# define TEST_IP_AND_TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP 1 +#else +# define NEED_IP(x) ((void) 0) +# define TEST_IV(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP 1 +#else +# define NEED_OP(x) ((void) 0) +# define TEST_OV(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP 1 +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP 1 +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + lzo_bytep op; + const lzo_bytep ip; + lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + NEED_IP(1); + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+3); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + for (;;) + { + NEED_IP(3); + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_IV(t); + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + t += 3; + if (t >= 8) do + { + UA_COPY8(op,ip); + op += 8; ip += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } + if (t > 0) + { + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + } +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + UA_COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !(LZO_OPT_UNALIGNED32) + } + else +#endif +#endif +#if !(LZO_OPT_UNALIGNED32) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + for (;;) { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 31 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 7 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + if (op - m_pos >= 8) + { + t += (3 - 1); + if (t >= 8) do + { + UA_COPY8(op,m_pos); + op += 8; m_pos += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } + if (t > 0) + { + *op++ = m_pos[0]; + if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } + } + } + else +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } + } + +eof_found: + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +#define LZO_TEST_OVERRUN 1 +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND 1 +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_IP_AND_TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef TEST_IV +#undef TEST_OV +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP 1 +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP 1 +#else +# define TEST_OP 1 +#endif + +#if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) +#elif defined(HAVE_TEST_IP) +# define TEST_IP_AND_TEST_OP TEST_IP +#elif defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP TEST_OP +#else +# define TEST_IP_AND_TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP 1 +#else +# define NEED_IP(x) ((void) 0) +# define TEST_IV(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP 1 +#else +# define NEED_OP(x) ((void) 0) +# define TEST_OV(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP 1 +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP 1 +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + lzo_bytep op; + const lzo_bytep ip; + lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + NEED_IP(1); + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+3); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + for (;;) + { + NEED_IP(3); + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_IV(t); + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + t += 3; + if (t >= 8) do + { + UA_COPY8(op,ip); + op += 8; ip += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } + if (t > 0) + { + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + } +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + UA_COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !(LZO_OPT_UNALIGNED32) + } + else +#endif +#endif +#if !(LZO_OPT_UNALIGNED32) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + for (;;) { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 31 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 7 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + if (op - m_pos >= 8) + { + t += (3 - 1); + if (t >= 8) do + { + UA_COPY8(op,m_pos); + op += 8; m_pos += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } + if (t > 0) + { + *op++ = m_pos[0]; + if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } + } + } + else +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } + } + +eof_found: + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +/***** End of minilzo.c *****/ diff --git a/grub-core/lib/minilzo/minilzo.h b/grub-core/lib/minilzo/minilzo.h new file mode 100644 index 0000000..7937454 --- /dev/null +++ b/grub-core/lib/minilzo/minilzo.h @@ -0,0 +1,94 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + <markus@oberhumer.com> + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H +#define __MINILZO_H 1 + +#define MINILZO_VERSION 0x2080 + +#ifdef __LZOCONF_H +# error "you cannot use both LZO and miniLZO" +#endif + +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32_t) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/grub-core/lib/mips/arc/reboot.c b/grub-core/lib/mips/arc/reboot.c new file mode 100644 index 0000000..ecf12a7 --- /dev/null +++ b/grub-core/lib/mips/arc/reboot.c @@ -0,0 +1,35 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/arc/arc.h> +#include <grub/misc.h> +#include <grub/time.h> +#include <grub/term.h> +#include <grub/i18n.h> + +void +grub_reboot (void) +{ + GRUB_ARC_FIRMWARE_VECTOR->restart (); + + grub_millisleep (1500); + + grub_puts_ (N_("Reboot failed")); + grub_refresh (); + while (1); +} diff --git a/grub-core/lib/mips/loongson/reboot.c b/grub-core/lib/mips/loongson/reboot.c new file mode 100644 index 0000000..a20e574 --- /dev/null +++ b/grub-core/lib/mips/loongson/reboot.c @@ -0,0 +1,64 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/machine/ec.h> +#include <grub/machine/kernel.h> +#include <grub/machine/memory.h> +#include <grub/misc.h> +#include <grub/pci.h> +#include <grub/cs5536.h> +#include <grub/time.h> +#include <grub/term.h> +#include <grub/i18n.h> + +void +grub_reboot (void) +{ + switch (grub_arch_machine) + { + case GRUB_ARCH_MACHINE_FULOONG2E: + grub_outl (grub_inl (0xbfe00104) & ~4, 0xbfe00104); + grub_outl (grub_inl (0xbfe00104) | 4, 0xbfe00104); + break; + case GRUB_ARCH_MACHINE_FULOONG2F: + { + grub_pci_device_t dev; + if (!grub_cs5536_find (&dev)) + break; + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_RESET, + grub_cs5536_read_msr (dev, + GRUB_CS5536_MSR_DIVIL_RESET) + | 1); + break; + } + case GRUB_ARCH_MACHINE_YEELOONG: + grub_write_ec (GRUB_MACHINE_EC_COMMAND_REBOOT); + break; + case GRUB_ARCH_MACHINE_YEELOONG_3A: + grub_millisleep (1); + grub_outb (0x4e, GRUB_MACHINE_PCI_IO_BASE_3A | 0x66); + grub_millisleep (1); + grub_outb (1, GRUB_MACHINE_PCI_IO_BASE_3A | 0x62); + grub_millisleep (5000); + } + grub_millisleep (1500); + + grub_puts_ (N_("Reboot failed")); + grub_refresh (); + while (1); +} diff --git a/grub-core/lib/mips/qemu_mips/reboot.c b/grub-core/lib/mips/qemu_mips/reboot.c new file mode 100644 index 0000000..ba0f6ac --- /dev/null +++ b/grub-core/lib/mips/qemu_mips/reboot.c @@ -0,0 +1,27 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/misc.h> +#include <grub/cpu/io.h> + +void +grub_reboot (void) +{ + grub_outl (42, 0xbfbf0000); + while (1); +} diff --git a/grub-core/lib/mips/relocator.c b/grub-core/lib/mips/relocator.c new file mode 100644 index 0000000..743b213 --- /dev/null +++ b/grub-core/lib/mips/relocator.c @@ -0,0 +1,147 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/mm.h> +#include <grub/misc.h> + +#include <grub/types.h> +#include <grub/types.h> +#include <grub/err.h> +#include <grub/cache.h> + +#include <grub/mips/relocator.h> +#include <grub/relocator_private.h> + +/* Do we need mips64? */ + +extern grub_uint8_t grub_relocator_forward_start; +extern grub_uint8_t grub_relocator_forward_end; +extern grub_uint8_t grub_relocator_backward_start; +extern grub_uint8_t grub_relocator_backward_end; + +#define REGW_SIZEOF (2 * sizeof (grub_uint32_t)) +#define JUMP_SIZEOF (2 * sizeof (grub_uint32_t)) + +#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator_##x##_end \ + - &grub_relocator_##x##_start) +#define RELOCATOR_SIZEOF(x) (RELOCATOR_SRC_SIZEOF(x) \ + + REGW_SIZEOF * 3) +grub_size_t grub_relocator_align = sizeof (grub_uint32_t); +grub_size_t grub_relocator_forward_size; +grub_size_t grub_relocator_backward_size; +grub_size_t grub_relocator_jumper_size = JUMP_SIZEOF + REGW_SIZEOF; + +void +grub_cpu_relocator_init (void) +{ + grub_relocator_forward_size = RELOCATOR_SIZEOF(forward); + grub_relocator_backward_size = RELOCATOR_SIZEOF(backward); +} + +static void +write_reg (int regn, grub_uint32_t val, void **target) +{ + /* lui $r, (val+0x8000). */ + *(grub_uint32_t *) *target = ((0x3c00 | regn) << 16) | ((val + 0x8000) >> 16); + *target = ((grub_uint32_t *) *target) + 1; + /* addiu $r, $r, val. */ + *(grub_uint32_t *) *target = (((0x2400 | regn << 5 | regn) << 16) + | (val & 0xffff)); + *target = ((grub_uint32_t *) *target) + 1; +} + +static void +write_jump (int regn, void **target) +{ + /* j $r. */ + *(grub_uint32_t *) *target = (regn<<21) | 0x8; + *target = ((grub_uint32_t *) *target) + 1; + /* nop. */ + *(grub_uint32_t *) *target = 0; + *target = ((grub_uint32_t *) *target) + 1; +} + +void +grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) +{ + write_reg (1, addr, &rels); + write_jump (1, &rels); +} + +void +grub_cpu_relocator_backward (void *ptr0, void *src, void *dest, + grub_size_t size) +{ + void *ptr = ptr0; + write_reg (8, (grub_uint32_t) src, &ptr); + write_reg (9, (grub_uint32_t) dest, &ptr); + write_reg (10, (grub_uint32_t) size, &ptr); + grub_memcpy (ptr, &grub_relocator_backward_start, + RELOCATOR_SRC_SIZEOF (backward)); +} + +void +grub_cpu_relocator_forward (void *ptr0, void *src, void *dest, + grub_size_t size) +{ + void *ptr = ptr0; + write_reg (8, (grub_uint32_t) src, &ptr); + write_reg (9, (grub_uint32_t) dest, &ptr); + write_reg (10, (grub_uint32_t) size, &ptr); + grub_memcpy (ptr, &grub_relocator_forward_start, + RELOCATOR_SRC_SIZEOF (forward)); +} + +grub_err_t +grub_relocator32_boot (struct grub_relocator *rel, + struct grub_relocator32_state state) +{ + grub_relocator_chunk_t ch; + void *ptr; + grub_err_t err; + void *relst; + grub_size_t relsize; + grub_size_t stateset_size = 31 * REGW_SIZEOF + JUMP_SIZEOF; + unsigned i; + grub_addr_t vtarget; + + err = grub_relocator_alloc_chunk_align (rel, &ch, 0, UP_TO_TOP32 (stateset_size), + stateset_size, sizeof (grub_uint32_t), + GRUB_RELOCATOR_PREFERENCE_NONE, 0); + if (err) + return err; + + ptr = get_virtual_current_address (ch); + for (i = 1; i < 32; i++) + write_reg (i, state.gpr[i], &ptr); + write_jump (state.jumpreg, &ptr); + + vtarget = (grub_addr_t) grub_map_memory (get_physical_target_address (ch), + stateset_size); + + err = grub_relocator_prepare_relocs (rel, vtarget, &relst, &relsize); + if (err) + return err; + + grub_arch_sync_caches ((void *) relst, relsize); + + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/mips/relocator_asm.S b/grub-core/lib/mips/relocator_asm.S new file mode 100644 index 0000000..1d142a4 --- /dev/null +++ b/grub-core/lib/mips/relocator_asm.S @@ -0,0 +1,61 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> + + .p2align 4 /* force 16-byte alignment */ + + .set noreorder + .set nomacro + +VARIABLE (grub_relocator_forward_start) + move $a0, $9 + move $a1, $10 + +copycont1: + lb $11,0($8) + sb $11,0($9) + addiu $8, $8, 1 + addiu $10, $10, -1 + bne $10, $0, copycont1 + addiu $9, $9, 1 + +#include "../../kern/mips/cache_flush.S" + +VARIABLE (grub_relocator_forward_end) + +VARIABLE (grub_relocator_backward_start) + move $a0, $9 + move $a1, $10 + + addu $9, $9, $10 + addu $8, $8, $10 + /* Backward movsl is implicitly off-by-one. compensate that. */ + addiu $9, $9, -1 + addiu $8, $8, -1 +copycont2: + lb $11,0($8) + sb $11,0($9) + addiu $8, $8, -1 + addiu $10, $10, -1 + bne $10, $0, copycont2 + addiu $9, $9, -1 + +#include "../../kern/mips/cache_flush.S" + +VARIABLE (grub_relocator_backward_end) diff --git a/grub-core/lib/mips/setjmp.S b/grub-core/lib/mips/setjmp.S new file mode 100644 index 0000000..895235b --- /dev/null +++ b/grub-core/lib/mips/setjmp.S @@ -0,0 +1,71 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2007,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> +#include <grub/dl.h> +#include <grub/mips/asm.h> + + .file "setjmp.S" + +GRUB_MOD_LICENSE "GPLv3+" + + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + GRUB_ASM_REG_S $s0, 0($a0) + GRUB_ASM_REG_S $s1, 8($a0) + GRUB_ASM_REG_S $s2, 16($a0) + GRUB_ASM_REG_S $s3, 24($a0) + GRUB_ASM_REG_S $s4, 32($a0) + GRUB_ASM_REG_S $s5, 40($a0) + GRUB_ASM_REG_S $s6, 48($a0) + GRUB_ASM_REG_S $s7, 56($a0) + GRUB_ASM_REG_S $s8, 64($a0) + GRUB_ASM_REG_S $gp, 72($a0) + GRUB_ASM_REG_S $sp, 80($a0) + GRUB_ASM_REG_S $ra, 88($a0) + move $v0, $zero + move $v1, $zero + jr $ra + nop +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + GRUB_ASM_REG_L $s0, 0($a0) + GRUB_ASM_REG_L $s1, 8($a0) + GRUB_ASM_REG_L $s2, 16($a0) + GRUB_ASM_REG_L $s3, 24($a0) + GRUB_ASM_REG_L $s4, 32($a0) + GRUB_ASM_REG_L $s5, 40($a0) + GRUB_ASM_REG_L $s6, 48($a0) + GRUB_ASM_REG_L $s7, 56($a0) + GRUB_ASM_REG_L $s8, 64($a0) + GRUB_ASM_REG_L $gp, 72($a0) + GRUB_ASM_REG_L $sp, 80($a0) + GRUB_ASM_REG_L $ra, 88($a0) + move $v0, $a1 + bne $v0, $zero, 1f + addiu $v0, $v0, 1 +1: + move $v1, $zero + jr $ra + nop diff --git a/grub-core/lib/pbkdf2.c b/grub-core/lib/pbkdf2.c new file mode 100644 index 0000000..28aa96c --- /dev/null +++ b/grub-core/lib/pbkdf2.c @@ -0,0 +1,109 @@ +/* gc-pbkdf2-sha1.c --- Password-Based Key Derivation Function a'la PKCS#5 + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Simon Josefsson. */ +/* Imported from gnulib. */ + +#include <grub/crypto.h> +#include <grub/mm.h> +#include <grub/misc.h> +#include <grub/dl.h> + +GRUB_MOD_LICENSE ("GPLv2+"); + +/* Implement PKCS#5 PBKDF2 as per RFC 2898. The PRF to use is HMAC variant + of digest supplied by MD. Inputs are the password P of length PLEN, + the salt S of length SLEN, the iteration counter C (> 0), and the + desired derived output length DKLEN. Output buffer is DK which + must have room for at least DKLEN octets. The output buffer will + be filled with the derived data. */ + +gcry_err_code_t +grub_crypto_pbkdf2 (const struct gcry_md_spec *md, + const grub_uint8_t *P, grub_size_t Plen, + const grub_uint8_t *S, grub_size_t Slen, + unsigned int c, + grub_uint8_t *DK, grub_size_t dkLen) +{ + unsigned int hLen = md->mdlen; + grub_uint8_t U[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t T[GRUB_CRYPTO_MAX_MDLEN]; + unsigned int u; + unsigned int l; + unsigned int r; + unsigned int i; + unsigned int k; + gcry_err_code_t rc; + grub_uint8_t *tmp; + grub_size_t tmplen = Slen + 4; + + if (md->mdlen > GRUB_CRYPTO_MAX_MDLEN || md->mdlen == 0) + return GPG_ERR_INV_ARG; + + if (c == 0) + return GPG_ERR_INV_ARG; + + if (dkLen == 0) + return GPG_ERR_INV_ARG; + + if (dkLen > 4294967295U) + return GPG_ERR_INV_ARG; + + l = ((dkLen - 1) / hLen) + 1; + r = dkLen - (l - 1) * hLen; + + tmp = grub_malloc (tmplen); + if (tmp == NULL) + return GPG_ERR_OUT_OF_MEMORY; + + grub_memcpy (tmp, S, Slen); + + for (i = 1; i - 1 < l; i++) + { + grub_memset (T, 0, hLen); + + for (u = 0; u < c; u++) + { + if (u == 0) + { + tmp[Slen + 0] = (i & 0xff000000) >> 24; + tmp[Slen + 1] = (i & 0x00ff0000) >> 16; + tmp[Slen + 2] = (i & 0x0000ff00) >> 8; + tmp[Slen + 3] = (i & 0x000000ff) >> 0; + + rc = grub_crypto_hmac_buffer (md, P, Plen, tmp, tmplen, U); + } + else + rc = grub_crypto_hmac_buffer (md, P, Plen, U, hLen, U); + + if (rc != GPG_ERR_NO_ERROR) + { + grub_free (tmp); + return rc; + } + + for (k = 0; k < hLen; k++) + T[k] ^= U[k]; + } + + grub_memcpy (DK + (i - 1) * hLen, T, i == l ? r : hLen); + } + + grub_free (tmp); + + return GPG_ERR_NO_ERROR; +} diff --git a/grub-core/lib/posix_wrap/assert.h b/grub-core/lib/posix_wrap/assert.h new file mode 100644 index 0000000..6b00a0b --- /dev/null +++ b/grub-core/lib/posix_wrap/assert.h @@ -0,0 +1,33 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_ASSERT_H +#define GRUB_POSIX_ASSERT_H 1 + +#include <grub/misc.h> + +#define assert(x) assert_real(__FILE__, __LINE__, x) + +static inline void +assert_real (const char *file, int line, int cond) +{ + if (!cond) + grub_printf ("Assertion failed at %s:%d\n", file, line); +} + +#endif diff --git a/grub-core/lib/posix_wrap/ctype.h b/grub-core/lib/posix_wrap/ctype.h new file mode 100644 index 0000000..38b5727 --- /dev/null +++ b/grub-core/lib/posix_wrap/ctype.h @@ -0,0 +1,108 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_CTYPE_H +#define GRUB_POSIX_CTYPE_H 1 + +#include <grub/misc.h> + +static inline int +toupper (int c) +{ + return grub_toupper (c); +} + +static inline int +isspace (int c) +{ + return grub_isspace (c); +} + +static inline int +isdigit (int c) +{ + return grub_isdigit (c); +} + +static inline int +islower (int c) +{ + return grub_islower (c); +} + +static inline int +isascii (int c) +{ + return !(c & ~0x7f); +} + +static inline int +isupper (int c) +{ + return grub_isupper (c); +} + +static inline int +isxdigit (int c) +{ + return grub_isxdigit (c); +} + +static inline int +isprint (int c) +{ + return grub_isprint (c); +} + +static inline int +iscntrl (int c) +{ + return !grub_isprint (c); +} + +static inline int +isgraph (int c) +{ + return grub_isprint (c) && !grub_isspace (c); +} + +static inline int +isalnum (int c) +{ + return grub_isalpha (c) || grub_isdigit (c); +} + +static inline int +ispunct (int c) +{ + return grub_isprint (c) && !grub_isspace (c) && !isalnum (c); +} + +static inline int +isalpha (int c) +{ + return grub_isalpha (c); +} + +static inline int +tolower (int c) +{ + return grub_tolower (c); +} + +#endif diff --git a/grub-core/lib/posix_wrap/errno.h b/grub-core/lib/posix_wrap/errno.h new file mode 100644 index 0000000..ba63b23 --- /dev/null +++ b/grub-core/lib/posix_wrap/errno.h @@ -0,0 +1,29 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_ERRNO_H +#define GRUB_POSIX_ERRNO_H 1 + +#include <grub/err.h> + +#undef errno +#define errno grub_errno +#define EINVAL GRUB_ERR_BAD_NUMBER +#define ENOMEM GRUB_ERR_OUT_OF_MEMORY + +#endif diff --git a/grub-core/lib/posix_wrap/inttypes.h b/grub-core/lib/posix_wrap/inttypes.h new file mode 100644 index 0000000..a12c43b --- /dev/null +++ b/grub-core/lib/posix_wrap/inttypes.h @@ -0,0 +1 @@ +#include <sys/types.h> diff --git a/grub-core/lib/posix_wrap/langinfo.h b/grub-core/lib/posix_wrap/langinfo.h new file mode 100644 index 0000000..ab75af1 --- /dev/null +++ b/grub-core/lib/posix_wrap/langinfo.h @@ -0,0 +1,38 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_LANGINFO_H +#define GRUB_POSIX_LANGINFO_H 1 + +#include <localcharset.h> + +typedef enum { CODESET } nl_item; + +static inline const char * +nl_langinfo (nl_item item) +{ + switch (item) + { + case CODESET: + return "UTF-8"; + default: + return ""; + } +} + +#endif diff --git a/grub-core/lib/posix_wrap/limits.h b/grub-core/lib/posix_wrap/limits.h new file mode 100644 index 0000000..7217138 --- /dev/null +++ b/grub-core/lib/posix_wrap/limits.h @@ -0,0 +1,41 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_LIMITS_H +#define GRUB_POSIX_LIMITS_H + +#include <grub/types.h> + +#define UCHAR_MAX GRUB_UCHAR_MAX +#define USHRT_MAX GRUB_USHRT_MAX +#define UINT_MAX GRUB_UINT_MAX +#define ULONG_MAX GRUB_ULONG_MAX +#define SIZE_MAX GRUB_SIZE_MAX + +#define SCHAR_MIN GRUB_SCHAR_MIN +#define SCHAR_MAX GRUB_SCHAR_MAX +#define SHRT_MIN GRUB_SHRT_MIN +#define SHRT_MAX GRUB_SHRT_MAX +#define INT_MIN GRUB_INT_MIN +#define INT_MAX GRUB_INT_MAX +#define LONG_MIN GRUB_LONG_MIN +#define LONG_MAX GRUB_LONG_MAX + +#define CHAR_BIT 8 + +#endif diff --git a/grub-core/lib/posix_wrap/localcharset.h b/grub-core/lib/posix_wrap/localcharset.h new file mode 100644 index 0000000..502d860 --- /dev/null +++ b/grub-core/lib/posix_wrap/localcharset.h @@ -0,0 +1,28 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_LOCALCHARSET_H +#define GRUB_POSIX_LOCALCHARSET_H 1 + +static inline const char * +locale_charset (void) +{ + return "UTF-8"; +} + +#endif diff --git a/grub-core/lib/posix_wrap/locale.h b/grub-core/lib/posix_wrap/locale.h new file mode 100644 index 0000000..569a765 --- /dev/null +++ b/grub-core/lib/posix_wrap/locale.h @@ -0,0 +1,3 @@ +#ifdef GRUB_UTIL +#include_next <locale.h> +#endif diff --git a/grub-core/lib/posix_wrap/stdint.h b/grub-core/lib/posix_wrap/stdint.h new file mode 100644 index 0000000..a12c43b --- /dev/null +++ b/grub-core/lib/posix_wrap/stdint.h @@ -0,0 +1 @@ +#include <sys/types.h> diff --git a/grub-core/lib/posix_wrap/stdio.h b/grub-core/lib/posix_wrap/stdio.h new file mode 100644 index 0000000..d5a8b75 --- /dev/null +++ b/grub-core/lib/posix_wrap/stdio.h @@ -0,0 +1,43 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_STDIO_H +#define GRUB_POSIX_STDIO_H 1 + +#include <grub/misc.h> +#include <grub/file.h> +#include <sys/types.h> + +typedef struct grub_file FILE; + +#define EOF -1 + +static inline int +snprintf (char *str, grub_size_t n, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start (ap, fmt); + ret = grub_vsnprintf (str, n, fmt, ap); + va_end (ap); + + return ret; +} + +#endif diff --git a/grub-core/lib/posix_wrap/stdlib.h b/grub-core/lib/posix_wrap/stdlib.h new file mode 100644 index 0000000..7a8d385 --- /dev/null +++ b/grub-core/lib/posix_wrap/stdlib.h @@ -0,0 +1,61 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_STDLIB_H +#define GRUB_POSIX_STDLIB_H 1 + +#include <grub/mm.h> +#include <grub/misc.h> +#include <grub/safemath.h> + +static inline void +free (void *ptr) +{ + grub_free (ptr); +} + +static inline void * +malloc (grub_size_t size) +{ + return grub_malloc (size); +} + +static inline void * +calloc (grub_size_t size, grub_size_t nelem) +{ + grub_size_t sz; + + if (grub_mul (size, nelem, &sz)) + return NULL; + + return grub_zalloc (sz); +} + +static inline void * +realloc (void *ptr, grub_size_t size) +{ + return grub_realloc (ptr, size); +} + +static inline int +abs (int c) +{ + return (c >= 0) ? c : -c; +} + +#endif diff --git a/grub-core/lib/posix_wrap/string.h b/grub-core/lib/posix_wrap/string.h new file mode 100644 index 0000000..7ae6eee --- /dev/null +++ b/grub-core/lib/posix_wrap/string.h @@ -0,0 +1,92 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_STRING_H +#define GRUB_POSIX_STRING_H 1 + +#include <grub/misc.h> +#include <sys/types.h> + +#define HAVE_STRCASECMP 1 + +static inline grub_size_t +strlen (const char *s) +{ + return grub_strlen (s); +} + +static inline int +strcmp (const char *s1, const char *s2) +{ + return grub_strcmp (s1, s2); +} + +static inline int +strcasecmp (const char *s1, const char *s2) +{ + return grub_strcasecmp (s1, s2); +} + +static inline void +bcopy (const void *src, void *dest, grub_size_t n) +{ + grub_memcpy (dest, src, n); +} + +static inline char * +strcpy (char *dest, const char *src) +{ + return grub_strcpy (dest, src); +} + +static inline char * +strstr (const char *haystack, const char *needle) +{ + return grub_strstr (haystack, needle); +} + +static inline char * +strchr (const char *s, int c) +{ + return grub_strchr (s, c); +} + +static inline char * +strncpy (char *dest, const char *src, grub_size_t n) +{ + return grub_strncpy (dest, src, n); +} + +static inline int +strcoll (const char *s1, const char *s2) +{ + return grub_strcmp (s1, s2); +} + +static inline void * +memchr (const void *s, int c, grub_size_t n) +{ + return grub_memchr (s, c, n); +} + +#define memcmp grub_memcmp +#define memcpy grub_memcpy +#define memmove grub_memmove +#define memset grub_memset + +#endif diff --git a/grub-core/lib/posix_wrap/sys/types.h b/grub-core/lib/posix_wrap/sys/types.h new file mode 100644 index 0000000..854eb01 --- /dev/null +++ b/grub-core/lib/posix_wrap/sys/types.h @@ -0,0 +1,65 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_SYS_TYPES_H +#define GRUB_POSIX_SYS_TYPES_H 1 + +#include <grub/misc.h> + +#include <stddef.h> + +typedef grub_ssize_t ssize_t; +#ifndef GRUB_POSIX_BOOL_DEFINED +typedef enum { false = 0, true = 1 } bool; +#define GRUB_POSIX_BOOL_DEFINED 1 +#endif + +typedef grub_uint8_t uint8_t; +typedef grub_uint16_t uint16_t; +typedef grub_uint32_t uint32_t; +typedef grub_uint64_t uint64_t; + +typedef grub_int8_t int8_t; +typedef grub_int16_t int16_t; +typedef grub_int32_t int32_t; +typedef grub_int64_t int64_t; + +#define HAVE_U64_TYPEDEF 1 +typedef grub_uint64_t u64; +#define HAVE_U32_TYPEDEF 1 +typedef grub_uint32_t u32; +#define HAVE_U16_TYPEDEF 1 +typedef grub_uint16_t u16; +#define HAVE_BYTE_TYPEDEF 1 +typedef grub_uint8_t byte; + +typedef grub_addr_t uintptr_t; + +#define SIZEOF_UNSIGNED_LONG GRUB_CPU_SIZEOF_LONG +#define SIZEOF_UNSIGNED_INT 4 +#define SIZEOF_UNSIGNED_LONG_LONG 8 +#define SIZEOF_UNSIGNED_SHORT 2 +#define SIZEOF_UINT64_T 8 + +#ifdef GRUB_CPU_WORDS_BIGENDIAN +#define WORDS_BIGENDIAN 1 +#else +#undef WORDS_BIGENDIAN +#endif + +#endif diff --git a/grub-core/lib/posix_wrap/unistd.h b/grub-core/lib/posix_wrap/unistd.h new file mode 100644 index 0000000..a12c43b --- /dev/null +++ b/grub-core/lib/posix_wrap/unistd.h @@ -0,0 +1 @@ +#include <sys/types.h> diff --git a/grub-core/lib/posix_wrap/wchar.h b/grub-core/lib/posix_wrap/wchar.h new file mode 100644 index 0000000..e0e04a6 --- /dev/null +++ b/grub-core/lib/posix_wrap/wchar.h @@ -0,0 +1,119 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_WCHAR_H +#define GRUB_POSIX_WCHAR_H 1 + +#include <grub/charset.h> + +#define wint_t grub_posix_wint_t +#define wchar_t grub_posix_wchar_t +#define mbstate_t grub_posix_mbstate_t + +/* UCS-4. */ +typedef grub_int32_t wint_t; +enum + { + WEOF = -1 + }; + +/* UCS-4. */ +typedef grub_int32_t wchar_t; + +typedef struct mbstate { + grub_uint32_t code; + int count; +} mbstate_t; + +/* UTF-8. */ +#define MB_CUR_MAX 4 +#define MB_LEN_MAX 4 + +static inline size_t +mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) +{ + const char *ptr; + if (!s) + { + pwc = 0; + s = ""; + n = 1; + } + + if (pwc) + *pwc = 0; + + for (ptr = s; ptr < s + n; ptr++) + { + if (!grub_utf8_process (*ptr, &ps->code, &ps->count)) + return -1; + if (ps->count) + continue; + if (pwc) + *pwc = ps->code; + if (ps->code == 0) + return 0; + return ptr - s + 1; + } + return -2; +} + +static inline int +mbsinit(const mbstate_t *ps) +{ + return ps->count == 0; +} + +static inline size_t +wcrtomb (char *s, wchar_t wc, mbstate_t *ps __attribute__ ((unused))) +{ + if (s == 0) + return 1; + return grub_encode_utf8_character ((grub_uint8_t *) s, + (grub_uint8_t *) s + MB_LEN_MAX, + wc); +} + +static inline wint_t btowc (int c) +{ + if (c & ~0x7f) + return WEOF; + return c; +} + + +static inline int +wcscoll (const wchar_t *s1, const wchar_t *s2) +{ + while (*s1 && *s2) + { + if (*s1 != *s2) + break; + + s1++; + s2++; + } + + if (*s1 < *s2) + return -1; + if (*s1 > *s2) + return +1; + return 0; +} + +#endif diff --git a/grub-core/lib/posix_wrap/wctype.h b/grub-core/lib/posix_wrap/wctype.h new file mode 100644 index 0000000..3771dc5 --- /dev/null +++ b/grub-core/lib/posix_wrap/wctype.h @@ -0,0 +1,110 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_POSIX_WCTYPE_H +#define GRUB_POSIX_WCTYPE_H 1 + +#include <grub/misc.h> +#include <wchar.h> + +#define wctype_t grub_posix_wctype_t + +typedef enum { GRUB_CTYPE_INVALID, + GRUB_CTYPE_ALNUM, GRUB_CTYPE_CNTRL, GRUB_CTYPE_LOWER, + GRUB_CTYPE_SPACE, GRUB_CTYPE_ALPHA, GRUB_CTYPE_DIGIT, + GRUB_CTYPE_PRINT, GRUB_CTYPE_UPPER, GRUB_CTYPE_BLANK, + GRUB_CTYPE_GRAPH, GRUB_CTYPE_PUNCT, GRUB_CTYPE_XDIGIT, + GRUB_CTYPE_MAX} wctype_t; + +#define CHARCLASS_NAME_MAX (sizeof ("xdigit") - 1) + +static inline wctype_t +wctype (const char *name) +{ + wctype_t i; + static const char names[][10] = { "", + "alnum", "cntrl", "lower", + "space", "alpha", "digit", + "print", "upper", "blank", + "graph", "punct", "xdigit" }; + for (i = GRUB_CTYPE_INVALID; i < GRUB_CTYPE_MAX; i++) + if (grub_strcmp (names[i], name) == 0) + return i; + return GRUB_CTYPE_INVALID; +} + +/* FIXME: take into account international lowercase characters. */ +static inline int +iswlower (wint_t wc) +{ + return grub_islower (wc); +} + +static inline wint_t +towlower (wint_t c) +{ + return grub_tolower (c); +} + +static inline wint_t +towupper (wint_t c) +{ + return grub_toupper (c); +} + +static inline int +iswalnum (wint_t c) +{ + return grub_isalpha (c) || grub_isdigit (c); +} + +static inline int +iswctype (wint_t wc, wctype_t desc) +{ + switch (desc) + { + case GRUB_CTYPE_ALNUM: + return iswalnum (wc); + case GRUB_CTYPE_CNTRL: + return grub_iscntrl (wc); + case GRUB_CTYPE_LOWER: + return iswlower (wc); + case GRUB_CTYPE_SPACE: + return grub_isspace (wc); + case GRUB_CTYPE_ALPHA: + return grub_isalpha (wc); + case GRUB_CTYPE_DIGIT: + return grub_isdigit (wc); + case GRUB_CTYPE_PRINT: + return grub_isprint (wc); + case GRUB_CTYPE_UPPER: + return grub_isupper (wc); + case GRUB_CTYPE_BLANK: + return wc == ' ' || wc == '\t'; + case GRUB_CTYPE_GRAPH: + return grub_isgraph (wc); + case GRUB_CTYPE_PUNCT: + return grub_isprint (wc) && !grub_isspace (wc) && !iswalnum (wc); + case GRUB_CTYPE_XDIGIT: + return grub_isxdigit (wc); + default: + return 0; + } +} + +#endif diff --git a/grub-core/lib/powerpc/relocator.c b/grub-core/lib/powerpc/relocator.c new file mode 100644 index 0000000..8ffb8b6 --- /dev/null +++ b/grub-core/lib/powerpc/relocator.c @@ -0,0 +1,140 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/mm.h> +#include <grub/misc.h> + +#include <grub/types.h> +#include <grub/types.h> +#include <grub/err.h> +#include <grub/cache.h> + +#include <grub/powerpc/relocator.h> +#include <grub/relocator_private.h> + +extern grub_uint8_t grub_relocator_forward_start; +extern grub_uint8_t grub_relocator_forward_end; +extern grub_uint8_t grub_relocator_backward_start; +extern grub_uint8_t grub_relocator_backward_end; + +#define REGW_SIZEOF (2 * sizeof (grub_uint32_t)) +#define JUMP_SIZEOF (sizeof (grub_uint32_t)) + +#define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator_##x##_end \ + - &grub_relocator_##x##_start) +#define RELOCATOR_SIZEOF(x) (RELOCATOR_SRC_SIZEOF(x) \ + + REGW_SIZEOF * 3) +grub_size_t grub_relocator_align = sizeof (grub_uint32_t); +grub_size_t grub_relocator_forward_size; +grub_size_t grub_relocator_backward_size; +grub_size_t grub_relocator_jumper_size = JUMP_SIZEOF + REGW_SIZEOF; + +void +grub_cpu_relocator_init (void) +{ + grub_relocator_forward_size = RELOCATOR_SIZEOF(forward); + grub_relocator_backward_size = RELOCATOR_SIZEOF(backward); +} + +static void +write_reg (int regn, grub_uint32_t val, void **target) +{ + /* lis r, val >> 16 */ + *(grub_uint32_t *) *target = + ((0x3c00 | (regn << 5)) << 16) | (val >> 16); + *target = ((grub_uint32_t *) *target) + 1; + /* ori r, r, val & 0xffff. */ + *(grub_uint32_t *) *target = (((0x6000 | regn << 5 | regn) << 16) + | (val & 0xffff)); + *target = ((grub_uint32_t *) *target) + 1; +} + +static void +write_jump (void **target) +{ + /* blr. */ + *(grub_uint32_t *) *target = 0x4e800020; + *target = ((grub_uint32_t *) *target) + 1; +} + +void +grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) +{ + write_reg (GRUB_PPC_JUMP_REGISTER, addr, &rels); + write_jump (&rels); +} + +void +grub_cpu_relocator_backward (void *ptr0, void *src, void *dest, + grub_size_t size) +{ + void *ptr = ptr0; + write_reg (8, (grub_uint32_t) src, &ptr); + write_reg (9, (grub_uint32_t) dest, &ptr); + write_reg (10, (grub_uint32_t) size, &ptr); + grub_memcpy (ptr, &grub_relocator_backward_start, + RELOCATOR_SRC_SIZEOF (backward)); +} + +void +grub_cpu_relocator_forward (void *ptr0, void *src, void *dest, + grub_size_t size) +{ + void *ptr = ptr0; + write_reg (8, (grub_uint32_t) src, &ptr); + write_reg (9, (grub_uint32_t) dest, &ptr); + write_reg (10, (grub_uint32_t) size, &ptr); + grub_memcpy (ptr, &grub_relocator_forward_start, + RELOCATOR_SRC_SIZEOF (forward)); +} + +grub_err_t +grub_relocator32_boot (struct grub_relocator *rel, + struct grub_relocator32_state state) +{ + void *ptr; + grub_err_t err; + void *relst; + grub_size_t relsize; + grub_size_t stateset_size = 32 * REGW_SIZEOF + JUMP_SIZEOF; + unsigned i; + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_align (rel, &ch, 0, UP_TO_TOP32 (stateset_size), + stateset_size, sizeof (grub_uint32_t), + GRUB_RELOCATOR_PREFERENCE_NONE, 0); + if (err) + return err; + + ptr = get_virtual_current_address (ch); + for (i = 0; i < 32; i++) + write_reg (i, state.gpr[i], &ptr); + write_jump (&ptr); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, &relsize); + if (err) + return err; + + grub_arch_sync_caches ((void *) relst, relsize); + + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/powerpc/relocator_asm.S b/grub-core/lib/powerpc/relocator_asm.S new file mode 100644 index 0000000..355e9c8 --- /dev/null +++ b/grub-core/lib/powerpc/relocator_asm.S @@ -0,0 +1,60 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE (grub_relocator_forward_start) + mr 3, 9 + mr 4, 10 + +copycont1: + lbz 11,0(8) + stb 11,0(9) + addi 8, 8, 0x1 + addi 9, 9, 0x1 + addi 10, 10, -1 + cmpwi 10, 0 + bne copycont1 + +#include "../../kern/powerpc/cache_flush.S" + +VARIABLE (grub_relocator_forward_end) + +VARIABLE (grub_relocator_backward_start) + mr 3, 9 + mr 4, 10 + + add 9, 9, 10 + add 8, 8, 10 + /* Backward movsl is implicitly off-by-one. compensate that. */ + addi 9, 9, -1 + addi 8, 8, -1 +copycont2: + lbz 11,0(8) + stb 11,0(9) + addi 8, 8, -1 + addi 9, 9, -1 + addi 10, 10, -1 + cmpwi 10, 0 + bne copycont2 + +#include "../../kern/powerpc/cache_flush.S" + +VARIABLE (grub_relocator_backward_end) diff --git a/grub-core/lib/powerpc/setjmp.S b/grub-core/lib/powerpc/setjmp.S new file mode 100644 index 0000000..716b563 --- /dev/null +++ b/grub-core/lib/powerpc/setjmp.S @@ -0,0 +1,89 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2004,2007 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> +#include <grub/dl.h> + + .file "setjmp.S" + +GRUB_MOD_LICENSE "GPLv3+" + + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + stw 1, 0(3) + stw 14, 4(3) + stw 15, 8(3) + stw 16, 12(3) + stw 17, 16(3) + stw 18, 20(3) + stw 19, 24(3) + stw 20, 28(3) + stw 21, 32(3) + stw 22, 36(3) + stw 23, 40(3) + stw 24, 44(3) + stw 25, 48(3) + stw 26, 52(3) + stw 27, 56(3) + stw 28, 60(3) + stw 29, 64(3) + stw 30, 68(3) + stw 31, 72(3) + mflr 4 + stw 4, 76(3) + mfcr 4 + stw 4, 80(3) + li 3, 0 + blr + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + lwz 1, 0(3) + lwz 14, 4(3) + lwz 15, 8(3) + lwz 16, 12(3) + lwz 17, 16(3) + lwz 18, 20(3) + lwz 19, 24(3) + lwz 20, 28(3) + lwz 21, 32(3) + lwz 22, 36(3) + lwz 23, 40(3) + lwz 24, 44(3) + lwz 25, 48(3) + lwz 26, 52(3) + lwz 27, 56(3) + lwz 28, 60(3) + lwz 29, 64(3) + lwz 30, 68(3) + lwz 31, 72(3) + lwz 5, 76(3) + mtlr 5 + lwz 5, 80(3) + mtcr 5 + mr. 3, 4 + bne 1f + li 3, 1 +1: blr + diff --git a/grub-core/lib/priority_queue.c b/grub-core/lib/priority_queue.c new file mode 100644 index 0000000..7d5e7c0 --- /dev/null +++ b/grub-core/lib/priority_queue.c @@ -0,0 +1,163 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/priority_queue.h> +#include <grub/mm.h> +#include <grub/dl.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_priority_queue +{ + grub_size_t elsize; + grub_size_t allocated; + grub_size_t used; + grub_comparator_t cmp; + void *els; +}; + +static inline void * +element (struct grub_priority_queue *pq, grub_size_t k) +{ + return ((grub_uint8_t *) pq->els) + k * pq->elsize; +} + +static inline void +swap (struct grub_priority_queue *pq, grub_size_t m, grub_size_t n) +{ + grub_uint8_t *p1, *p2; + grub_size_t l; + p1 = (grub_uint8_t *) element (pq, m); + p2 = (grub_uint8_t *) element (pq, n); + for (l = pq->elsize; l; l--, p1++, p2++) + { + grub_uint8_t t; + t = *p1; + *p1 = *p2; + *p2 = t; + } +} + +static inline grub_size_t +parent (grub_size_t v) +{ + return (v - 1) / 2; +} + +static inline grub_size_t +left_child (grub_size_t v) +{ + return 2 * v + 1; +} + +static inline grub_size_t +right_child (grub_size_t v) +{ + return 2 * v + 2; +} + +void * +grub_priority_queue_top (grub_priority_queue_t pq) +{ + if (!pq->used) + return 0; + return element (pq, 0); +} + +void +grub_priority_queue_destroy (grub_priority_queue_t pq) +{ + grub_free (pq->els); + grub_free (pq); +} + +grub_priority_queue_t +grub_priority_queue_new (grub_size_t elsize, + grub_comparator_t cmp) +{ + struct grub_priority_queue *ret; + void *els; + els = grub_calloc (8, elsize); + if (!els) + return 0; + ret = (struct grub_priority_queue *) grub_malloc (sizeof (*ret)); + if (!ret) + { + grub_free (els); + return 0; + } + ret->elsize = elsize; + ret->allocated = 8; + ret->used = 0; + ret->cmp = cmp; + ret->els = els; + return ret; +} + +/* Heap property: pq->cmp (element (pq, p), element (pq, parent (p))) <= 0. */ +grub_err_t +grub_priority_queue_push (grub_priority_queue_t pq, const void *el) +{ + grub_size_t p; + if (pq->used == pq->allocated) + { + void *els; + els = grub_realloc (pq->els, pq->elsize * 2 * pq->allocated); + if (!els) + return grub_errno; + pq->allocated *= 2; + pq->els = els; + } + pq->used++; + grub_memcpy (element (pq, pq->used - 1), el, pq->elsize); + for (p = pq->used - 1; p; p = parent (p)) + { + if (pq->cmp (element (pq, p), element (pq, parent (p))) <= 0) + break; + swap (pq, p, parent (p)); + } + + return GRUB_ERR_NONE; +} + +void +grub_priority_queue_pop (grub_priority_queue_t pq) +{ + grub_size_t p; + + swap (pq, 0, pq->used - 1); + pq->used--; + for (p = 0; left_child (p) < pq->used; ) + { + grub_size_t c; + if (pq->cmp (element (pq, left_child (p)), element (pq, p)) <= 0 + && (right_child (p) >= pq->used + || pq->cmp (element (pq, right_child (p)), element (pq, p)) <= 0)) + break; + if (right_child (p) >= pq->used + || pq->cmp (element (pq, left_child (p)), + element (pq, right_child (p))) > 0) + c = left_child (p); + else + c = right_child (p); + swap (pq, p, c); + p = c; + } +} + + diff --git a/grub-core/lib/progress.c b/grub-core/lib/progress.c new file mode 100644 index 0000000..4b7cbbc --- /dev/null +++ b/grub-core/lib/progress.c @@ -0,0 +1,145 @@ +/* progress.c - show loading progress */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/types.h> +#include <grub/time.h> +#include <grub/term.h> +#include <grub/dl.h> +#include <grub/misc.h> +#include <grub/normal.h> +#include <grub/net.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define UPDATE_INTERVAL 800 + +static void +grub_file_progress_hook_real (grub_disk_addr_t sector __attribute__ ((unused)), + unsigned offset __attribute__ ((unused)), + unsigned length, void *data) +{ + static int call_depth = 0; + grub_uint64_t now; + static grub_uint64_t last_progress_update_time; + grub_file_t file = data; + const char *e; + file->progress_offset += length; + + if (call_depth) + return; + + e = grub_env_get ("enable_progress_indicator"); + if (e && e[0] == '0') { + return; + } + + call_depth = 1; + now = grub_get_time_ms (); + + if (((now - last_progress_update_time > UPDATE_INTERVAL) && + (file->progress_offset - file->offset > 0)) || + (file->progress_offset == file->size)) + { + static char buffer[80]; + struct grub_term_output *term; + const char *partial_file_name; + + unsigned long long percent; + grub_uint64_t current_speed; + + if (now - file->last_progress_time < 10) + current_speed = 0; + else + current_speed = grub_divmod64 ((file->progress_offset + - file->last_progress_offset) + * 100ULL * 1000ULL, + now - file->last_progress_time, 0); + + if (file->size == 0) + percent = 100; + else + percent = grub_divmod64 (100 * file->progress_offset, + file->size, 0); + + /* grub_net_fs_open() saves off partial file structure before name is initialized. + It already saves passed file name in net structure so just use it in this case. + */ + if (file->device->net) + partial_file_name = grub_strrchr (file->device->net->name, '/'); + else if (file->name) /* grub_file_open() may leave it as NULL */ + partial_file_name = grub_strrchr (file->name, '/'); + else + partial_file_name = NULL; + if (partial_file_name) + partial_file_name++; + else + partial_file_name = ""; + + file->estimated_speed = (file->estimated_speed + current_speed) >> 1; + + grub_snprintf (buffer, sizeof (buffer), " [ %.20s %s %llu%% ", + partial_file_name, + grub_get_human_size (file->progress_offset, + GRUB_HUMAN_SIZE_NORMAL), + (unsigned long long) percent); + + char *ptr = buffer + grub_strlen (buffer); + grub_snprintf (ptr, sizeof (buffer) - (ptr - buffer), "%s ]", + grub_get_human_size (file->estimated_speed, + GRUB_HUMAN_SIZE_SPEED)); + + grub_size_t len = grub_strlen (buffer); + FOR_ACTIVE_TERM_OUTPUTS (term) + { + if (term->progress_update_counter++ > term->progress_update_divisor + || (file->progress_offset == file->size + && term->progress_update_divisor + != (unsigned) GRUB_PROGRESS_NO_UPDATE)) + { + struct grub_term_coordinate old_pos = grub_term_getxy (term); + struct grub_term_coordinate new_pos = old_pos; + new_pos.x = grub_term_width (term) - len - 1; + + grub_term_gotoxy (term, new_pos); + grub_puts_terminal (buffer, term); + grub_term_gotoxy (term, old_pos); + + term->progress_update_counter = 0; + + if (term->refresh) + term->refresh (term); + } + } + + file->last_progress_offset = file->progress_offset; + file->last_progress_time = now; + last_progress_update_time = now; + } + call_depth = 0; +} + +GRUB_MOD_INIT(progress) +{ + grub_file_progress_hook = grub_file_progress_hook_real; +} + +GRUB_MOD_FINI(progress) +{ + grub_file_progress_hook = 0; +} diff --git a/grub-core/lib/random.c b/grub-core/lib/random.c new file mode 100644 index 0000000..43b9664 --- /dev/null +++ b/grub-core/lib/random.c @@ -0,0 +1,120 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2016 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/random.h> +#include <grub/dl.h> +#include <grub/lib/hexdump.h> +#include <grub/command.h> +#include <grub/mm.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +grub_err_t +grub_crypto_get_random (void *buffer, grub_size_t sz) +{ + /* This is an arbitrer between different methods. + TODO: Add more methods in the future. */ + /* TODO: Add some PRNG smartness to reduce damage from bad entropy. */ + if (grub_crypto_arch_get_random (buffer, sz)) + return GRUB_ERR_NONE; + return grub_error (GRUB_ERR_IO, "no random sources found"); +} + +static int +get_num_digits (int val) +{ + int ret = 0; + while (val != 0) + { + ret++; + val /= 10; + } + if (ret == 0) + return 1; + return ret; +} + +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + +static grub_err_t +grub_cmd_hexdump_random (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) +{ + grub_size_t length = 64; + grub_err_t err; + void *buffer; + grub_uint8_t *ptr; + int stats[256]; + int i, digits = 2; + char template[10]; + + if (argc >= 1) + length = grub_strtoull (args[0], 0, 0); + + if (length == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "length pust be positive"); + + buffer = grub_malloc (length); + if (!buffer) + return grub_errno; + + err = grub_crypto_get_random (buffer, length); + if (err) + { + grub_free (buffer); + return err; + } + + hexdump (0, buffer, length); + grub_memset(stats, 0, sizeof(stats)); + for (ptr = buffer; ptr < (grub_uint8_t *) buffer + length; ptr++) + stats[*ptr]++; + grub_printf ("Statistics:\n"); + for (i = 0; i < 256; i++) + { + int z = get_num_digits (stats[i]); + if (z > digits) + digits = z; + } + + grub_snprintf (template, sizeof (template), "%%0%dd ", digits); + + for (i = 0; i < 256; i++) + { + grub_printf ("%s", template);//, stats[i]); + if ((i & 0xf) == 0xf) + grub_printf ("\n"); + } + + grub_free (buffer); + + return 0; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT (random) +{ + cmd = grub_register_command ("hexdump_random", grub_cmd_hexdump_random, + N_("[LENGTH]"), + N_("Hexdump random data.")); +} + +GRUB_MOD_FINI (random) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c new file mode 100644 index 0000000..467305b --- /dev/null +++ b/grub-core/lib/reed_solomon.c @@ -0,0 +1,493 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef TEST +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#define xcalloc calloc +#define xmalloc malloc +#define grub_memset memset +#define grub_memcpy memcpy +#endif + +#ifndef STANDALONE +#include <assert.h> +#endif + +#ifndef STANDALONE +#ifdef TEST +typedef unsigned int grub_size_t; +typedef unsigned char grub_uint8_t; +#else +#include <grub/types.h> +#include <grub/reed_solomon.h> +#include <grub/util/misc.h> +#include <grub/misc.h> +#endif +#endif + +#define SECTOR_SIZE 512 +#define MAX_BLOCK_SIZE (200 * SECTOR_SIZE) + +#ifdef STANDALONE +#ifdef TEST +typedef unsigned int grub_size_t; +typedef unsigned char grub_uint8_t; +#else +#include <grub/types.h> +#include <grub/misc.h> +#endif +#ifdef __i386__ +#define REED_SOLOMON_ATTRIBUTE __attribute__ ((regparm(3))) +#else +#define REED_SOLOMON_ATTRIBUTE +#endif +void +grub_reed_solomon_recover (void *ptr_, grub_size_t s, grub_size_t rs) + REED_SOLOMON_ATTRIBUTE; +#else +#define REED_SOLOMON_ATTRIBUTE +#endif + +#define GF_SIZE 8 +typedef grub_uint8_t gf_single_t; +#define GF_POLYNOMIAL 0x1d +#define GF_INVERT2 0x8e +#if defined (STANDALONE) && !defined (TEST) + +#ifdef __APPLE__ +#define ATTRIBUTE_TEXT __attribute__ ((section("_text,_text"))) +#else +#define ATTRIBUTE_TEXT __attribute__ ((section(".text"))) +#endif + +static gf_single_t * const gf_powx ATTRIBUTE_TEXT = (void *) 0x100000; +static gf_single_t * const gf_powx_inv ATTRIBUTE_TEXT = (void *) 0x100200; +static int *const chosenstat ATTRIBUTE_TEXT = (void *) 0x100300; +static gf_single_t *const sigma ATTRIBUTE_TEXT = (void *) 0x100700; +static gf_single_t *const errpot ATTRIBUTE_TEXT = (void *) 0x100800; +static int *const errpos ATTRIBUTE_TEXT = (void *) 0x100900; +static gf_single_t *const sy ATTRIBUTE_TEXT = (void *) 0x100d00; +static gf_single_t *const mstat ATTRIBUTE_TEXT = (void *) 0x100e00; +static gf_single_t *const errvals ATTRIBUTE_TEXT = (void *) 0x100f00; +static gf_single_t *const eqstat ATTRIBUTE_TEXT = (void *) 0x101000; +/* Next available address: (void *) 0x112000. */ +#else + +static gf_single_t gf_powx[255 * 2]; +static gf_single_t gf_powx_inv[256]; +static int chosenstat[256]; +static gf_single_t sigma[256]; +static gf_single_t errpot[256]; +static int errpos[256]; +static gf_single_t sy[256]; +static gf_single_t mstat[256]; +static gf_single_t errvals[256]; +static gf_single_t eqstat[65536 + 256]; +#endif + +static gf_single_t +gf_mul (gf_single_t a, gf_single_t b) +{ + if (a == 0 || b == 0) + return 0; + return gf_powx[(int) gf_powx_inv[a] + (int) gf_powx_inv[b]]; +} + +static inline gf_single_t +gf_invert (gf_single_t a) +{ + return gf_powx[255 - (int) gf_powx_inv[a]]; +} + +static void +init_powx (void) +{ + int i; + grub_uint8_t cur = 1; + + gf_powx_inv[0] = 0; + for (i = 0; i < 255; i++) + { + gf_powx[i] = cur; + gf_powx[i + 255] = cur; + gf_powx_inv[cur] = i; + if (cur & (1ULL << (GF_SIZE - 1))) + cur = (cur << 1) ^ GF_POLYNOMIAL; + else + cur <<= 1; + } +} + +static gf_single_t +pol_evaluate (gf_single_t *pol, grub_size_t degree, int log_x) +{ + int i; + gf_single_t s = 0; + int log_xn = 0; + for (i = degree; i >= 0; i--) + { + if (pol[i]) + s ^= gf_powx[(int) gf_powx_inv[pol[i]] + log_xn]; + log_xn += log_x; + if (log_xn >= ((1 << GF_SIZE) - 1)) + log_xn -= ((1 << GF_SIZE) - 1); + } + return s; +} + +#if !defined (STANDALONE) +static void +rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs) +{ + gf_single_t *rs_polynomial; + int i, j; + gf_single_t *m; + m = xcalloc (s + rs, sizeof (gf_single_t)); + grub_memcpy (m, data, s * sizeof (gf_single_t)); + rs_polynomial = xcalloc (rs + 1, sizeof (gf_single_t)); + rs_polynomial[rs] = 1; + /* Multiply with X - a^r */ + for (j = 0; j < rs; j++) + { + for (i = 0; i < rs; i++) + if (rs_polynomial[i]) + rs_polynomial[i] = (rs_polynomial[i + 1] + ^ gf_powx[j + (int) gf_powx_inv[rs_polynomial[i]]]); + else + rs_polynomial[i] = rs_polynomial[i + 1]; + if (rs_polynomial[rs]) + rs_polynomial[rs] = gf_powx[j + (int) gf_powx_inv[rs_polynomial[rs]]]; + } + for (j = 0; j < s; j++) + if (m[j]) + { + gf_single_t f = m[j]; + for (i = 0; i <= rs; i++) + m[i+j] ^= gf_mul (rs_polynomial[i], f); + } + free (rs_polynomial); + grub_memcpy (data + s, m + s, rs * sizeof (gf_single_t)); + free (m); +} +#endif + +static void +gauss_eliminate (gf_single_t *eq, int n, int m, int *chosen) +{ + int i, j; + + for (i = 0 ; i < n; i++) + { + int nzidx; + int k; + gf_single_t r; + for (nzidx = 0; nzidx < m && (eq[i * (m + 1) + nzidx] == 0); + nzidx++); + if (nzidx == m) + continue; + chosen[i] = nzidx; + r = gf_invert (eq[i * (m + 1) + nzidx]); + for (j = 0; j < m + 1; j++) + eq[i * (m + 1) + j] = gf_mul (eq[i * (m + 1) + j], r); + for (j = i + 1; j < n; j++) + { + gf_single_t rr = eq[j * (m + 1) + nzidx]; + for (k = 0; k < m + 1; k++) + eq[j * (m + 1) + k] ^= gf_mul (eq[i * (m + 1) + k], rr); + } + } +} + +static void +gauss_solve (gf_single_t *eq, int n, int m, gf_single_t *sol) +{ + int i, j; + + for (i = 0; i < n; i++) + chosenstat[i] = -1; + for (i = 0; i < m; i++) + sol[i] = 0; + gauss_eliminate (eq, n, m, chosenstat); + for (i = n - 1; i >= 0; i--) + { + gf_single_t s = 0; + if (chosenstat[i] == -1) + continue; + for (j = 0; j < m; j++) + s ^= gf_mul (eq[i * (m + 1) + j], sol[j]); + s ^= eq[i * (m + 1) + m]; + sol[chosenstat[i]] = s; + } +} + +static void +rs_recover (gf_single_t *mm, grub_size_t s, grub_size_t rs) +{ + grub_size_t rs2 = rs / 2; + int errnum = 0; + int i, j; + + for (i = 0; i < (int) rs; i++) + sy[i] = pol_evaluate (mm, s + rs - 1, i); + + for (i = 0; i < (int) rs; i++) + if (sy[i] != 0) + break; + + /* No error detected. */ + if (i == (int) rs) + return; + + { + + for (i = 0; i < (int) rs2; i++) + for (j = 0; j < (int) rs2 + 1; j++) + eqstat[i * (rs2 + 1) + j] = sy[i+j]; + + for (i = 0; i < (int) rs2; i++) + sigma[i] = 0; + + gauss_solve (eqstat, rs2, rs2, sigma); + } + + for (i = 0; i < (int) (rs + s); i++) + if (pol_evaluate (sigma, rs2 - 1, 255 - i) == gf_powx[i]) + { + errpot[errnum] = gf_powx[i]; + errpos[errnum++] = s + rs - i - 1; + } + { + for (j = 0; j < errnum; j++) + eqstat[j] = 1; + eqstat[errnum] = sy[0]; + for (i = 1; i < (int) rs; i++) + { + for (j = 0; j < (int) errnum; j++) + eqstat[(errnum + 1) * i + j] = gf_mul (errpot[j], + eqstat[(errnum + 1) * (i - 1) + + j]); + eqstat[(errnum + 1) * i + errnum] = sy[i]; + } + + gauss_solve (eqstat, rs, errnum, errvals); + + for (i = 0; i < (int) errnum; i++) + mm[errpos[i]] ^= errvals[i]; + } +} + +static void +decode_block (gf_single_t *ptr, grub_size_t s, + gf_single_t *rptr, grub_size_t rs) +{ + int i, j; + for (i = 0; i < SECTOR_SIZE; i++) + { + grub_size_t ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; + grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; + + /* Nothing to do. */ + if (!ds || !rr) + continue; + + for (j = 0; j < (int) ds; j++) + mstat[j] = ptr[SECTOR_SIZE * j + i]; + for (j = 0; j < (int) rr; j++) + mstat[j + ds] = rptr[SECTOR_SIZE * j + i]; + + rs_recover (mstat, ds, rr); + + for (j = 0; j < (int) ds; j++) + ptr[SECTOR_SIZE * j + i] = mstat[j]; + } +} + +#if !defined (STANDALONE) +static void +encode_block (gf_single_t *ptr, grub_size_t s, + gf_single_t *rptr, grub_size_t rs) +{ + int i, j; + for (i = 0; i < SECTOR_SIZE; i++) + { + grub_size_t ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; + grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; + gf_single_t *m; + + if (!ds || !rr) + continue; + + m = xmalloc (ds + rr); + for (j = 0; j < ds; j++) + m[j] = ptr[SECTOR_SIZE * j + i]; + rs_encode (m, ds, rr); + for (j = 0; j < rr; j++) + rptr[SECTOR_SIZE * j + i] = m[j + ds]; + free (m); + } +} +#endif + +#if !defined (STANDALONE) +void +grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size, + grub_size_t redundancy) +{ + grub_size_t s = data_size; + grub_size_t rs = redundancy; + gf_single_t *ptr = buffer; + gf_single_t *rptr = ptr + s; + void *tmp; + + tmp = xmalloc (data_size); + grub_memcpy (tmp, buffer, data_size); + + /* Nothing to do. */ + if (!rs) + goto exit; + + init_powx (); + + while (s > 0) + { + grub_size_t tt; + grub_size_t cs, crs; + cs = s; + crs = rs; + tt = cs + crs; + if (tt > MAX_BLOCK_SIZE) + { + cs = ((cs * (MAX_BLOCK_SIZE / 512)) / tt) * 512; + crs = ((crs * (MAX_BLOCK_SIZE / 512)) / tt) * 512; + } + encode_block (ptr, cs, rptr, crs); + ptr += cs; + rptr += crs; + s -= cs; + rs -= crs; + } + +#ifndef TEST + assert (grub_memcmp (tmp, buffer, data_size) == 0); +#endif +exit: + free (tmp); +} +#endif + +void REED_SOLOMON_ATTRIBUTE +grub_reed_solomon_recover (void *ptr_, grub_size_t s, grub_size_t rs) +{ + gf_single_t *ptr = ptr_; + gf_single_t *rptr = ptr + s; + grub_uint8_t *cptr; + + /* Nothing to do. */ + if (!rs) + return; + + for (cptr = rptr + rs - 1; cptr >= rptr; cptr--) + if (*cptr) + break; + if (rptr + rs - 1 - cptr > (grub_ssize_t) rs / 2) + return; + + init_powx (); + + while (s > 0) + { + grub_size_t tt; + grub_size_t cs, crs; + cs = s; + crs = rs; + tt = cs + crs; + if (tt > MAX_BLOCK_SIZE) + { + cs = ((cs * (MAX_BLOCK_SIZE / 512)) / tt) * 512; + crs = ((crs * (MAX_BLOCK_SIZE / 512)) / tt) * 512; + } + decode_block (ptr, cs, rptr, crs); + ptr += cs; + rptr += crs; + s -= cs; + rs -= crs; + } +} + +#ifdef TEST +int +main (int argc, char **argv) +{ + FILE *in, *out; + grub_size_t s, rs; + char *buf; + + grub_memset (gf_powx, 0xee, sizeof (gf_powx)); + grub_memset (gf_powx_inv, 0xdd, sizeof (gf_powx_inv)); + +#ifndef STANDALONE + init_powx (); +#endif + +#ifndef STANDALONE + in = grub_util_fopen ("tst.bin", "rb"); + if (!in) + return 1; + fseek (in, 0, SEEK_END); + s = ftell (in); + fseek (in, 0, SEEK_SET); + rs = 0x7007; + buf = xmalloc (s + rs + SECTOR_SIZE); + fread (buf, 1, s, in); + fclose (in); + + grub_reed_solomon_add_redundancy (buf, s, rs); + + out = grub_util_fopen ("tst_rs.bin", "wb"); + fwrite (buf, 1, s + rs, out); + fclose (out); +#else + out = grub_util_fopen ("tst_rs.bin", "rb"); + fseek (out, 0, SEEK_END); + s = ftell (out); + fseek (out, 0, SEEK_SET); + rs = 0x7007; + s -= rs; + + buf = xmalloc (s + rs + SECTOR_SIZE); + fread (buf, 1, s + rs, out); + fclose (out); +#endif +#if 1 + grub_memset (buf + 512 * 15, 0, 512); +#endif + + out = grub_util_fopen ("tst_dam.bin", "wb"); + fwrite (buf, 1, s + rs, out); + fclose (out); + grub_reed_solomon_recover (buf, s, rs); + + out = grub_util_fopen ("tst_rec.bin", "wb"); + fwrite (buf, 1, s, out); + fclose (out); + + return 0; +} +#endif diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c new file mode 100644 index 0000000..f2c1944 --- /dev/null +++ b/grub-core/lib/relocator.c @@ -0,0 +1,1657 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/relocator.h> +#include <grub/relocator_private.h> +#include <grub/mm_private.h> +#include <grub/misc.h> +#include <grub/cache.h> +#include <grub/memory.h> +#include <grub/dl.h> +#include <grub/i18n.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_relocator +{ + struct grub_relocator_chunk *chunks; + grub_phys_addr_t postchunks; + grub_phys_addr_t highestaddr; + grub_phys_addr_t highestnonpostaddr; + grub_size_t relocators_size; +}; + +struct grub_relocator_subchunk +{ + enum {CHUNK_TYPE_IN_REGION, CHUNK_TYPE_REGION_START, +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + CHUNK_TYPE_FIRMWARE, CHUNK_TYPE_LEFTOVER +#endif + } type; + grub_mm_region_t reg; + grub_phys_addr_t start; + grub_size_t size; + grub_size_t pre_size; + struct grub_relocator_extra_block *extra; +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + struct grub_relocator_fw_leftover *pre, *post; +#endif +}; + +struct grub_relocator_chunk +{ + struct grub_relocator_chunk *next; + grub_phys_addr_t src; + void *srcv; + grub_phys_addr_t target; + grub_size_t size; + struct grub_relocator_subchunk *subchunks; + unsigned nsubchunks; +}; + +struct grub_relocator_extra_block +{ + struct grub_relocator_extra_block *next; + struct grub_relocator_extra_block **prev; + grub_phys_addr_t start; + grub_phys_addr_t end; +}; + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS +struct grub_relocator_fw_leftover +{ + struct grub_relocator_fw_leftover *next; + struct grub_relocator_fw_leftover **prev; + grub_phys_addr_t quantstart; + grub_uint8_t freebytes[GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT / 8]; +}; + +static struct grub_relocator_fw_leftover *leftovers; +#endif + +static struct grub_relocator_extra_block *extra_blocks; + +void * +get_virtual_current_address (grub_relocator_chunk_t in) +{ + return in->srcv; +} + +grub_phys_addr_t +get_physical_target_address (grub_relocator_chunk_t in) +{ + return in->target; +} + +struct grub_relocator * +grub_relocator_new (void) +{ + struct grub_relocator *ret; + + grub_cpu_relocator_init (); + + ret = grub_zalloc (sizeof (struct grub_relocator)); + if (!ret) + return NULL; + + ret->postchunks = ~(grub_phys_addr_t) 0; + ret->relocators_size = grub_relocator_jumper_size; + grub_dprintf ("relocator", "relocators_size=%lu\n", + (unsigned long) ret->relocators_size); + return ret; +} + +#define DIGITSORT_BITS 8 +#define DIGITSORT_MASK ((1 << DIGITSORT_BITS) - 1) +#define BITS_IN_BYTE 8 + +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +static inline int +is_start (int type) +{ + return !(type & 1) && (type != COLLISION_START); +} + +static void +allocate_regstart (grub_phys_addr_t addr, grub_size_t size, grub_mm_region_t rb, + grub_mm_region_t *regancestor, grub_mm_header_t hancestor) +{ + grub_addr_t newreg_start, newreg_raw_start + = (grub_addr_t) rb + (addr - grub_vtop (rb)) + size; + grub_addr_t newreg_size, newreg_presize; + grub_mm_header_t new_header; + grub_mm_header_t hb = (grub_mm_header_t) (rb + 1); + +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF + grub_dprintf ("relocator", "ra = %p, rb = %p\n", regancestor, rb); +#endif + newreg_start = ALIGN_UP (newreg_raw_start, GRUB_MM_ALIGN); + newreg_presize = newreg_start - newreg_raw_start; + newreg_size = rb->size - (newreg_start - (grub_addr_t) rb); + if ((hb->size << GRUB_MM_ALIGN_LOG2) >= newreg_start + - (grub_addr_t) rb) + { + grub_mm_header_t newhnext = hb->next; + grub_size_t newhsize = ((hb->size << GRUB_MM_ALIGN_LOG2) + - (newreg_start + - (grub_addr_t) rb)) >> GRUB_MM_ALIGN_LOG2; + new_header = (void *) (newreg_start + sizeof (*rb)); + if (newhnext == hb) + newhnext = new_header; + new_header->next = newhnext; + new_header->size = newhsize; + new_header->magic = GRUB_MM_FREE_MAGIC; + } + else + { + new_header = hb->next; + if (new_header == hb) + new_header = (void *) (newreg_start + sizeof (*rb)); + } + { + struct grub_mm_header *newregfirst = rb->first; + struct grub_mm_region *newregnext = rb->next; + struct grub_mm_region *newreg = (void *) newreg_start; + hancestor->next = new_header; + if (newregfirst == hb) + newregfirst = new_header; + newreg->first = newregfirst; + newreg->next = newregnext; + newreg->pre_size = newreg_presize; + newreg->size = newreg_size; + *regancestor = newreg; + { + grub_mm_header_t h = newreg->first, hp = NULL; + do + { + if ((void *) h < (void *) (newreg + 1)) + grub_fatal ("Failed to adjust memory region: %p, %p, %p, %p, %p", + newreg, newreg->first, h, hp, hb); +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF + if ((void *) h == (void *) (newreg + 1)) + grub_dprintf ("relocator", + "Free start memory region: %p, %p, %p, %p, %p", + newreg, newreg->first, h, hp, hb); +#endif + hp = h; + h = h->next; + } + while (h != newreg->first); + } + } +} + +static void +allocate_inreg (grub_phys_addr_t paddr, grub_size_t size, + grub_mm_header_t hb, grub_mm_header_t hbp, + grub_mm_region_t rb) +{ + struct grub_mm_header *foll = NULL; + grub_addr_t vaddr = (grub_addr_t) hb + (paddr - grub_vtop (hb)); + +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF + grub_dprintf ("relocator", "inreg paddr = 0x%lx, size = %lu," + " hb = %p, hbp = %p, rb = %p, vaddr = 0x%lx\n", + (unsigned long) paddr, (unsigned long) size, hb, hbp, + rb, (unsigned long) vaddr); +#endif + + if (ALIGN_UP (vaddr + size, GRUB_MM_ALIGN) + GRUB_MM_ALIGN + <= (grub_addr_t) (hb + hb->size)) + { + foll = (void *) ALIGN_UP (vaddr + size, GRUB_MM_ALIGN); + foll->magic = GRUB_MM_FREE_MAGIC; + foll->size = hb + hb->size - foll; +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF + grub_dprintf ("relocator", "foll = %p, foll->size = %lu\n", foll, + (unsigned long) foll->size); +#endif + } + + if (vaddr - (grub_addr_t) hb >= sizeof (*hb)) + { + hb->size = ((vaddr - (grub_addr_t) hb) >> GRUB_MM_ALIGN_LOG2); + if (foll) + { + foll->next = hb; + hbp->next = foll; + if (rb->first == hb) + { + rb->first = foll; + } + } + } + else + { + if (foll) + { + foll->next = hb->next; + } + else + foll = hb->next; + + hbp->next = foll; + if (rb->first == hb) + { + rb->first = foll; + } + if (rb->first == hb) + { + rb->first = (void *) (rb + 1); + } + } +} + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS +static void +check_leftover (struct grub_relocator_fw_leftover *lo) +{ + unsigned i; + for (i = 0; i < sizeof (lo->freebytes); i++) + if (lo->freebytes[i] != 0xff) + return; + grub_relocator_firmware_free_region (lo->quantstart, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + *lo->prev = lo->next; + if (lo->next) + lo->next->prev = lo->prev; +} +#endif + +static void +free_subchunk (const struct grub_relocator_subchunk *subchu) +{ + switch (subchu->type) + { + case CHUNK_TYPE_REGION_START: + { + grub_mm_region_t r1, r2, *rp; + grub_mm_header_t h; + grub_size_t pre_size; + r1 = subchu->reg; + r2 = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) subchu->reg + + (grub_vtop (subchu->reg) + - subchu->start) + subchu->size, + GRUB_MM_ALIGN); + for (rp = &grub_mm_base; *rp && *rp != r2; rp = &((*rp)->next)); + pre_size = subchu->pre_size; + + if (*rp) + { + grub_mm_header_t h2, *hp; + r1->first = r2->first; + r1->next = r2->next; + r1->pre_size = pre_size; + r1->size = r2->size + (r2 - r1) * sizeof (*r2); + *rp = r1; + h = (grub_mm_header_t) (r1 + 1); + h->next = r2->first; + h->magic = GRUB_MM_FREE_MAGIC; + h->size = (r2 - r1 - 1); + for (hp = &r2->first, h2 = *hp; h2->next != r2->first; + hp = &(h2->next), h2 = *hp) + if (h2 == (grub_mm_header_t) (r2 + 1)) + break; + if (h2 == (grub_mm_header_t) (r2 + 1)) + { + h->size = h2->size + (h2 - h); + h->next = h2->next; + *hp = h; + if (hp == &r2->first) + { + for (h2 = r2->first; h2->next != r2->first; h2 = h2->next); + h2->next = h; + } + } + else + { + h2->next = h; + } + } + else + { + r1->pre_size = pre_size; + r1->size = (r2 - r1) * sizeof (*r2); + /* Find where to insert this region. + Put a smaller one before bigger ones, + to prevent fragmentation. */ + for (rp = &grub_mm_base; *rp; rp = &((*rp)->next)) + if ((*rp)->size > r1->size) + break; + r1->next = *rp; + *rp = r1->next; + h = (grub_mm_header_t) (r1 + 1); + r1->first = h; + h->next = h; + h->magic = GRUB_MM_FREE_MAGIC; + h->size = (r2 - r1 - 1); + } + for (r2 = grub_mm_base; r2; r2 = r2->next) + if ((grub_addr_t) r2 + r2->size == (grub_addr_t) r1) + break; + if (r2) + { + grub_mm_header_t hl2, hl, g; + g = (grub_mm_header_t) ((grub_addr_t) r2 + r2->size); + g->size = (grub_mm_header_t) r1 - g; + r2->size += r1->size; + for (hl = r2->first; hl->next != r2->first; hl = hl->next); + for (hl2 = r1->first; hl2->next != r1->first; hl2 = hl2->next); + hl2->next = r2->first; + r2->first = r1->first; + hl->next = r2->first; + *rp = (*rp)->next; + grub_free (g + 1); + } + break; + } + case CHUNK_TYPE_IN_REGION: + { + grub_mm_header_t h = (grub_mm_header_t) ALIGN_DOWN ((grub_addr_t) subchu->start, + GRUB_MM_ALIGN); + h->size + = ((subchu->start + subchu->size + GRUB_MM_ALIGN - 1) / GRUB_MM_ALIGN) + - (subchu->start / GRUB_MM_ALIGN) - 1; + h->next = h; + h->magic = GRUB_MM_ALLOC_MAGIC; + grub_free (h + 1); + break; + } +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + case CHUNK_TYPE_FIRMWARE: + case CHUNK_TYPE_LEFTOVER: + { + grub_addr_t fstart, fend; + fstart = ALIGN_UP (subchu->start, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + fend = ALIGN_DOWN (subchu->start + subchu->size, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + if (fstart < fend) + grub_relocator_firmware_free_region (fstart, fend - fstart); +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + if (subchu->pre) + { + int off = subchu->start - fstart + - GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + grub_memset (subchu->pre->freebytes + off / 8 + 1, + 0xff, sizeof (subchu->pre->freebytes) - off / 8 - 1); + subchu->pre->freebytes[off / 8] |= ~((1 << (off % 8)) - 1); + check_leftover (subchu->pre); + } + if (subchu->post) + { + int off = subchu->start + subchu->size - fend; + grub_memset (subchu->pre->freebytes, + 0xff, sizeof (subchu->pre->freebytes) - off / 8); + subchu->pre->freebytes[off / 8] |= ((1 << (8 - (off % 8))) - 1); + check_leftover (subchu->post); + } +#endif + *subchu->extra->prev = subchu->extra->next; + grub_free (subchu->extra); + } + break; +#endif + } +} + +static int +malloc_in_range (struct grub_relocator *rel, + grub_addr_t start, grub_addr_t end, grub_addr_t align, + grub_size_t size, struct grub_relocator_chunk *res, + int from_low_priv, int collisioncheck) +{ + grub_mm_region_t r, *ra, base_saved; + struct grub_relocator_mmap_event *events = NULL, *eventt = NULL, *t; + /* 128 is just in case of additional malloc (shouldn't happen). */ + unsigned maxevents = 2 + 128; + grub_mm_header_t p, pa; + unsigned *counter; + int nallocs = 0; + unsigned j, N = 0; + grub_addr_t target = 0; + + grub_dprintf ("relocator", + "trying to allocate in 0x%lx-0x%lx aligned 0x%lx size 0x%lx\n", + (unsigned long) start, (unsigned long) end, + (unsigned long) align, (unsigned long) size); + + start = ALIGN_UP (start, align); + end = ALIGN_DOWN (end - size, align) + size; + + if (end < start + size) + return 0; + + /* We have to avoid any allocations when filling scanline events. + Hence 2-stages. + */ + for (r = grub_mm_base; r; r = r->next) + { + p = r->first; + do + { + if ((grub_addr_t) p < (grub_addr_t) (r + 1) + || (grub_addr_t) p >= (grub_addr_t) (r + 1) + r->size) + grub_fatal ("%d: out of range pointer: %p\n", __LINE__, p); + maxevents += 2; + p = p->next; + } + while (p != r->first); + maxevents += 4; + } + + if (collisioncheck && rel) + { + struct grub_relocator_chunk *chunk; + for (chunk = rel->chunks; chunk; chunk = chunk->next) + maxevents += 2; + } + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + { + struct grub_relocator_extra_block *cur; + for (cur = extra_blocks; cur; cur = cur->next) + maxevents += 2; + } + for (r = grub_mm_base; r; r = r->next) + maxevents += 2; + + maxevents += grub_relocator_firmware_get_max_events (); +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + { + struct grub_relocator_fw_leftover *cur; + for (cur = leftovers; cur; cur = cur->next) + { + int l = 0; + unsigned i; + for (i = 0; i < GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; i++) + { + if (l != ((cur->freebytes[i / 8] >> (i % 8)) & 1)) + maxevents++; + l = ((cur->freebytes[i / 8] >> (i % 8)) & 1); + } + if (l) + maxevents++; + } + } +#endif + + eventt = grub_calloc (maxevents, sizeof (events[0])); + counter = grub_malloc ((DIGITSORT_MASK + 2) * sizeof (counter[0])); + events = grub_calloc (maxevents, sizeof (events[0])); + if (!events || !eventt || !counter) + { + grub_dprintf ("relocator", "events or counter allocation failed %d\n", + maxevents); + grub_free (events); + grub_free (eventt); + grub_free (counter); + return 0; + } + + if (collisioncheck && rel) + { + struct grub_relocator_chunk *chunk; + for (chunk = rel->chunks; chunk; chunk = chunk->next) + { + events[N].type = COLLISION_START; + events[N].pos = chunk->target; + N++; + events[N].type = COLLISION_END; + events[N].pos = chunk->target + chunk->size; + N++; + } + } + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + for (r = grub_mm_base; r; r = r->next) + { +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF + grub_dprintf ("relocator", "Blocking at 0x%lx-0x%lx\n", + (unsigned long) r - r->pre_size, + (unsigned long) (r + 1) + r->size); +#endif + events[N].type = FIRMWARE_BLOCK_START; + events[N].pos = (grub_addr_t) r - r->pre_size; + N++; + events[N].type = FIRMWARE_BLOCK_END; + events[N].pos = (grub_addr_t) (r + 1) + r->size; + N++; + } + { + struct grub_relocator_extra_block *cur; + for (cur = extra_blocks; cur; cur = cur->next) + { +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF + grub_dprintf ("relocator", "Blocking at 0x%lx-0x%lx\n", + (unsigned long) cur->start, (unsigned long) cur->end); +#endif + events[N].type = FIRMWARE_BLOCK_START; + events[N].pos = cur->start; + N++; + events[N].type = FIRMWARE_BLOCK_END; + events[N].pos = cur->end; + N++; + } + } + + N += grub_relocator_firmware_fill_events (events + N); + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + { + struct grub_relocator_fw_leftover *cur; + for (cur = leftovers; cur; cur = cur->next) + { + unsigned i; + int l = 0; + for (i = 0; i < GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; i++) + { + if (l != ((cur->freebytes[i / 8] >> (i % 8)) & 1)) + { + events[N].type = l ? REG_LEFTOVER_END : REG_LEFTOVER_START; + events[N].pos = cur->quantstart + i; + events[N].leftover = cur; + N++; + } + l = ((cur->freebytes[i / 8] >> (i % 8)) & 1); + } + if (l) + { + events[N].type = REG_LEFTOVER_END; + events[N].pos = cur->quantstart + i; + events[N].leftover = cur; + N++; + } + } + } +#endif +#endif + + /* No malloc from this point. */ + base_saved = grub_mm_base; + grub_mm_base = NULL; + + for (ra = &base_saved, r = *ra; r; ra = &(r->next), r = *ra) + { + pa = r->first; + p = pa->next; + if (p->magic == GRUB_MM_ALLOC_MAGIC) + continue; + do + { + if (p->magic != GRUB_MM_FREE_MAGIC) + grub_fatal ("%s:%d free magic broken at %p (0x%x)\n", + __FILE__, + __LINE__, p, p->magic); + if (p == (grub_mm_header_t) (r + 1)) + { + events[N].type = REG_BEG_START; + events[N].pos = grub_vtop (r) - r->pre_size; + events[N].reg = r; + events[N].regancestor = ra; + events[N].head = p; + events[N].hancestor = pa; + N++; + events[N].type = REG_BEG_END; + events[N].pos = grub_vtop (p + p->size) - sizeof (*r) + - sizeof (struct grub_mm_header); + N++; + } + else + { + events[N].type = IN_REG_START; + events[N].pos = grub_vtop (p); + events[N].head = p; + events[N].hancestor = pa; + events[N].reg = r; + N++; + events[N].type = IN_REG_END; + events[N].pos = grub_vtop (p + p->size); + N++; + } + pa = p; + p = pa->next; + } + while (pa != r->first); + } + + /* Put ending events after starting events. */ + { + int st = 0, e = N / 2; + for (j = 0; j < N; j++) + if (is_start (events[j].type) || events[j].type == COLLISION_START) + eventt[st++] = events[j]; + else + eventt[e++] = events[j]; + t = eventt; + eventt = events; + events = t; + } + + { + unsigned i; + for (i = 0; i < (BITS_IN_BYTE * sizeof (grub_addr_t) / DIGITSORT_BITS); + i++) + { + grub_memset (counter, 0, (1 + (1 << DIGITSORT_BITS)) * sizeof (counter[0])); + for (j = 0; j < N; j++) + counter[((events[j].pos >> (DIGITSORT_BITS * i)) + & DIGITSORT_MASK) + 1]++; + for (j = 0; j <= DIGITSORT_MASK; j++) + counter[j+1] += counter[j]; + for (j = 0; j < N; j++) + eventt[counter[((events[j].pos >> (DIGITSORT_BITS * i)) + & DIGITSORT_MASK)]++] = events[j]; + t = eventt; + eventt = events; + events = t; + } + } + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + retry: +#endif + + /* Now events are nicely sorted. */ + { + int nstarted = 0, ncollisions = 0, nstartedfw = 0, nblockfw = 0; +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + int nlefto = 0; +#else + const int nlefto = 0; +#endif + grub_addr_t starta = 0; + for (j = from_low_priv ? 0 : N - 1; from_low_priv ? j < N : (j + 1); + from_low_priv ? j++ : j--) + { + int isinsidebefore, isinsideafter; + isinsidebefore = (!ncollisions && (nstarted || (((nlefto || nstartedfw) + && !nblockfw)))); + switch (events[j].type) + { +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + case REG_FIRMWARE_START: + nstartedfw++; + break; + + case REG_FIRMWARE_END: + nstartedfw--; + break; + + case FIRMWARE_BLOCK_START: + nblockfw++; + break; + + case FIRMWARE_BLOCK_END: + nblockfw--; + break; +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + case REG_LEFTOVER_START: + nlefto++; + break; + + case REG_LEFTOVER_END: + nlefto--; + break; +#endif + + case COLLISION_START: + ncollisions++; + break; + + case COLLISION_END: + ncollisions--; + break; + + case IN_REG_START: + case REG_BEG_START: + nstarted++; + break; + + case IN_REG_END: + case REG_BEG_END: + nstarted--; + break; + } + isinsideafter = (!ncollisions && (nstarted || ((nlefto || nstartedfw) + && !nblockfw))); + if (from_low_priv) { + if (!isinsidebefore && isinsideafter) + starta = ALIGN_UP (events[j].pos, align); + + if (isinsidebefore && !isinsideafter) + { + target = starta; + if (target < start) + target = start; + if (target + size <= end && target + size <= events[j].pos) + /* Found an usable address. */ + goto found; + } + } else { + if (!isinsidebefore && isinsideafter) + { + if (events[j].pos >= size) + starta = ALIGN_DOWN (events[j].pos - size, align) + size; + else + starta = 0; + } + if (isinsidebefore && !isinsideafter && starta >= size) + { + target = starta - size; + if (target > end - size) + target = end - size; + if (target >= start && target >= events[j].pos) + goto found; + } + } + } + } + + grub_mm_base = base_saved; + grub_free (events); + grub_free (eventt); + grub_free (counter); + return 0; + + found: + { + int inreg = 0, regbeg = 0, ncol = 0; +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + int fwin = 0, fwb = 0, fwlefto = 0; +#endif +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + int last_lo = 0; +#endif + int last_start = 0; + for (j = 0; j < N; j++) + { + int typepre; + if (ncol) + typepre = -1; + else if (regbeg) + typepre = CHUNK_TYPE_REGION_START; + else if (inreg) + typepre = CHUNK_TYPE_IN_REGION; +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + else if (fwin && !fwb) + typepre = CHUNK_TYPE_FIRMWARE; + else if (fwlefto && !fwb) + typepre = CHUNK_TYPE_LEFTOVER; +#endif + else + typepre = -1; + + if (j != 0 && events[j - 1].pos != events[j].pos) + { + grub_addr_t alloc_start, alloc_end; + alloc_start = max (events[j - 1].pos, target); + alloc_end = min (events[j].pos, target + size); + if (alloc_end > alloc_start) + { + switch (typepre) + { + case CHUNK_TYPE_REGION_START: + allocate_regstart (alloc_start, alloc_end - alloc_start, + events[last_start].reg, + events[last_start].regancestor, + events[last_start].hancestor); + /* TODO: maintain a reverse lookup tree for hancestor. */ + { + unsigned k; + for (k = 0; k < N; k++) + if (events[k].hancestor == events[last_start].head) + events[k].hancestor = events[last_start].hancestor; + } + break; + case CHUNK_TYPE_IN_REGION: + allocate_inreg (alloc_start, alloc_end - alloc_start, + events[last_start].head, + events[last_start].hancestor, + events[last_start].reg); + { + unsigned k; + for (k = 0; k < N; k++) + if (events[k].hancestor == events[last_start].head) + events[k].hancestor = events[last_start].hancestor; + } + break; +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + case CHUNK_TYPE_FIRMWARE: + { + grub_addr_t fstart, fend; + fstart + = ALIGN_DOWN (alloc_start, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + fend + = ALIGN_UP (alloc_end, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF + grub_dprintf ("relocator", "requesting %lx-%lx\n", + (unsigned long) fstart, + (unsigned long) fend); +#endif + /* The failure here can be very expensive. */ + if (!grub_relocator_firmware_alloc_region (fstart, + fend - fstart)) + { + if (from_low_priv) + start = fend; + else + end = fstart; + goto retry; + } + break; + } +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + case CHUNK_TYPE_LEFTOVER: + { + unsigned offstart = alloc_start + % GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + unsigned offend = alloc_end + % GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + struct grub_relocator_fw_leftover *lo + = events[last_lo].leftover; + if (offend == 0 && alloc_end != alloc_start) + offend = GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + lo->freebytes[offstart / 8] + &= ((1 << (8 - (start % 8))) - 1); + grub_memset (lo->freebytes + (offstart + 7) / 8, 0, + offend / 8 - (offstart + 7) / 8); + lo->freebytes[offend / 8] &= ~((1 << (offend % 8)) - 1); + } + break; +#endif + } + nallocs++; + } + } + + switch (events[j].type) + { + case REG_BEG_START: + case IN_REG_START: + if (events[j].type == REG_BEG_START && + (grub_addr_t) (events[j].reg + 1) > target) + regbeg++; + else + inreg++; + last_start = j; + break; + + case REG_BEG_END: + case IN_REG_END: + if (regbeg) + regbeg--; + else + inreg--; + break; + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + case REG_FIRMWARE_START: + fwin++; + break; + + case REG_FIRMWARE_END: + fwin--; + break; + + case FIRMWARE_BLOCK_START: + fwb++; + break; + + case FIRMWARE_BLOCK_END: + fwb--; + break; +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + case REG_LEFTOVER_START: + fwlefto++; + last_lo = j; + break; + + case REG_LEFTOVER_END: + fwlefto--; + break; +#endif + case COLLISION_START: + ncol++; + break; + case COLLISION_END: + ncol--; + break; + } + + } + } + + /* Malloc is available again. */ + grub_mm_base = base_saved; + + grub_free (eventt); + grub_free (counter); + + { + int last_start = 0; + int inreg = 0, regbeg = 0, ncol = 0; +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + int fwin = 0, fwlefto = 0, fwb = 0; +#endif + unsigned cural = 0; + int oom = 0; + res->subchunks = grub_calloc (nallocs, sizeof (res->subchunks[0])); + if (!res->subchunks) + oom = 1; + res->nsubchunks = nallocs; + + for (j = 0; j < N; j++) + { + int typepre; + if (ncol) + typepre = -1; + else if (regbeg) + typepre = CHUNK_TYPE_REGION_START; + else if (inreg) + typepre = CHUNK_TYPE_IN_REGION; +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + else if (fwin && !fwb) + typepre = CHUNK_TYPE_FIRMWARE; + else if (fwlefto && !fwb) + typepre = CHUNK_TYPE_LEFTOVER; +#endif + else + typepre = -1; + + if (j != 0 && events[j - 1].pos != events[j].pos) + { + grub_addr_t alloc_start, alloc_end; + struct grub_relocator_subchunk tofree; + struct grub_relocator_subchunk *curschu = &tofree; + if (!oom) + curschu = &res->subchunks[cural]; + alloc_start = max (events[j - 1].pos, target); + alloc_end = min (events[j].pos, target + size); + if (alloc_end > alloc_start) + { +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF + grub_dprintf ("relocator", "subchunk 0x%lx-0x%lx, %d\n", + (unsigned long) alloc_start, + (unsigned long) alloc_end, typepre); +#endif + curschu->type = typepre; + curschu->start = alloc_start; + curschu->size = alloc_end - alloc_start; + if (typepre == CHUNK_TYPE_REGION_START + || typepre == CHUNK_TYPE_IN_REGION) + { + curschu->reg = events[last_start].reg; + curschu->pre_size = alloc_start - events[j - 1].pos; + } + if (!oom && (typepre == CHUNK_TYPE_REGION_START +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + || typepre == CHUNK_TYPE_FIRMWARE +#endif + )) + { + struct grub_relocator_extra_block *ne; + ne = grub_malloc (sizeof (*ne)); + if (!ne) + { + oom = 1; + grub_memcpy (&tofree, curschu, sizeof (tofree)); + } + else + { + ne->start = alloc_start; + ne->end = alloc_end; + ne->next = extra_blocks; + ne->prev = &extra_blocks; + if (extra_blocks) + extra_blocks->prev = &(ne->next); + extra_blocks = ne; + curschu->extra = ne; + } + } + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + if (!oom && typepre == CHUNK_TYPE_FIRMWARE) + { + grub_addr_t fstart, fend; + + fstart + = ALIGN_DOWN (alloc_start, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + fend + = ALIGN_UP (alloc_end, + GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); + + { + struct grub_relocator_fw_leftover *lo1 = NULL; + struct grub_relocator_fw_leftover *lo2 = NULL; + if (fstart != alloc_start) + lo1 = grub_malloc (sizeof (*lo1)); + if (fend != alloc_end) + lo2 = grub_malloc (sizeof (*lo2)); + if ((!lo1 && fstart != alloc_start) + || (!lo2 && fend != alloc_end)) + { + struct grub_relocator_extra_block *ne; + grub_free (lo1); + grub_free (lo2); + lo1 = NULL; + lo2 = NULL; + oom = 1; + grub_memcpy (&tofree, curschu, sizeof (tofree)); + ne = extra_blocks; + extra_blocks = extra_blocks->next; + grub_free (ne); + } + if (lo1) + { + lo1->quantstart = fstart; + grub_memset (lo1->freebytes, 0xff, + (alloc_start - fstart) / 8); + lo1->freebytes[(alloc_start - fstart) / 8] + = (1 << ((alloc_start - fstart) % 8)) - 1; + grub_memset (lo1->freebytes + + ((alloc_start - fstart) / 8) + 1, 0, + sizeof (lo1->freebytes) + - (alloc_start - fstart) / 8 - 1); + lo1->next = leftovers; + lo1->prev = &leftovers; + if (leftovers) + leftovers->prev = &lo1->next; + leftovers = lo1; + } + if (lo2) + { + lo2->quantstart + = fend - GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; + grub_memset (lo2->freebytes, 0, + (alloc_end - lo2->quantstart) / 8); + lo2->freebytes[(alloc_end - lo2->quantstart) / 8] + = ~((1 << ((alloc_end - lo2->quantstart) % 8)) - 1); + grub_memset (lo2->freebytes + + ((alloc_end - lo2->quantstart) / 8) + + 1, 0, sizeof (lo2->freebytes) + - (alloc_end - lo2->quantstart) / 8 - 1); + lo2->prev = &leftovers; + if (leftovers) + leftovers->prev = &lo2->next; + lo2->next = leftovers; + leftovers = lo2; + } + curschu->pre = lo1; + curschu->post = lo2; + } + } + + if (typepre == CHUNK_TYPE_LEFTOVER) + { + curschu->pre = events[last_start].leftover; + curschu->post = events[last_start].leftover; + } +#endif + + if (!oom) + cural++; + else + free_subchunk (&tofree); + } + } + + switch (events[j].type) + { + case REG_BEG_START: + case IN_REG_START: + if (events[j].type == REG_BEG_START && + (grub_addr_t) (events[j].reg + 1) > target) + regbeg++; + else + inreg++; + last_start = j; + break; + + case REG_BEG_END: + case IN_REG_END: + inreg = regbeg = 0; + break; + +#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + case REG_FIRMWARE_START: + fwin++; + break; + + case REG_FIRMWARE_END: + fwin--; + break; + + case FIRMWARE_BLOCK_START: + fwb++; + break; + + case FIRMWARE_BLOCK_END: + fwb--; + break; +#endif + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + case REG_LEFTOVER_START: + fwlefto++; + break; + + case REG_LEFTOVER_END: + fwlefto--; + break; +#endif + case COLLISION_START: + ncol++; + break; + case COLLISION_END: + ncol--; + break; + } + } + if (oom) + { + unsigned i; + for (i = 0; i < cural; i++) + free_subchunk (&res->subchunks[i]); + grub_free (res->subchunks); + grub_dprintf ("relocator", "allocation failed with out-of-memory\n"); + grub_free (events); + + return 0; + } + } + + res->src = target; + res->size = size; + + grub_free (events); + + grub_dprintf ("relocator", "allocated: 0x%lx+0x%lx\n", (unsigned long) target, + (unsigned long) size); + + return 1; +} + +static void +adjust_limits (struct grub_relocator *rel, + grub_phys_addr_t *min_addr, grub_phys_addr_t *max_addr, + grub_phys_addr_t in_min, grub_phys_addr_t in_max) +{ + struct grub_relocator_chunk *chunk; + + *min_addr = 0; + *max_addr = rel->postchunks; + + /* Keep chunks in memory in the same order as they'll be after relocation. */ + for (chunk = rel->chunks; chunk; chunk = chunk->next) + { + if (chunk->target > in_max && chunk->src < *max_addr + && chunk->src < rel->postchunks) + *max_addr = chunk->src; + if (chunk->target + chunk->size <= in_min + && chunk->src + chunk->size > *min_addr + && chunk->src < rel->postchunks) + *min_addr = chunk->src + chunk->size; + } +} + +grub_err_t +grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, + grub_relocator_chunk_t *out, + grub_phys_addr_t target, grub_size_t size) +{ + struct grub_relocator_chunk *chunk; + grub_phys_addr_t min_addr = 0, max_addr; + + if (target > ~size) + return grub_error (GRUB_ERR_BUG, "address is out of range"); + + adjust_limits (rel, &min_addr, &max_addr, target, target); + + for (chunk = rel->chunks; chunk; chunk = chunk->next) + if ((chunk->target <= target && target < chunk->target + chunk->size) + || (target <= chunk->target && chunk->target < target + size)) + return grub_error (GRUB_ERR_BUG, "overlap detected"); + + chunk = grub_malloc (sizeof (struct grub_relocator_chunk)); + if (!chunk) + return grub_errno; + + grub_dprintf ("relocator", + "min_addr = 0x%llx, max_addr = 0x%llx, target = 0x%llx\n", + (unsigned long long) min_addr, (unsigned long long) max_addr, + (unsigned long long) target); + + do + { + /* A trick to improve Linux allocation. */ +#if defined (__i386__) || defined (__x86_64__) + if (target < 0x100000) + if (malloc_in_range (rel, rel->highestnonpostaddr, ~(grub_addr_t)0, 1, + size, chunk, 0, 1)) + { + if (rel->postchunks > chunk->src) + rel->postchunks = chunk->src; + break; + } +#endif + if (malloc_in_range (rel, target, max_addr, 1, size, chunk, 1, 0)) + break; + + if (malloc_in_range (rel, min_addr, target, 1, size, chunk, 0, 0)) + break; + + if (malloc_in_range (rel, rel->highestnonpostaddr, ~(grub_addr_t)0, 1, + size, chunk, 0, 1)) + { + if (rel->postchunks > chunk->src) + rel->postchunks = chunk->src; + break; + } + + grub_dprintf ("relocator", "not allocated\n"); + grub_free (chunk); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + } + while (0); + + grub_dprintf ("relocator", "allocated 0x%llx/0x%llx\n", + (unsigned long long) chunk->src, (unsigned long long) target); + + if (rel->highestaddr < target + size) + rel->highestaddr = target + size; + + if (rel->highestaddr < chunk->src + size) + rel->highestaddr = chunk->src + size; + + if (chunk->src < rel->postchunks) + { + if (rel->highestnonpostaddr < target + size) + rel->highestnonpostaddr = target + size; + + if (rel->highestnonpostaddr < chunk->src + size) + rel->highestnonpostaddr = chunk->src + size; + } + + grub_dprintf ("relocator", "relocators_size=%ld\n", + (unsigned long) rel->relocators_size); + + if (chunk->src < target) + rel->relocators_size += grub_relocator_backward_size; + if (chunk->src > target) + rel->relocators_size += grub_relocator_forward_size; + + grub_dprintf ("relocator", "relocators_size=%ld\n", + (unsigned long) rel->relocators_size); + + chunk->target = target; + chunk->size = size; + chunk->next = rel->chunks; + rel->chunks = chunk; + grub_dprintf ("relocator", "cur = %p, next = %p\n", rel->chunks, + rel->chunks->next); + + chunk->srcv = grub_map_memory (chunk->src, chunk->size); + *out = chunk; +#ifdef DEBUG_RELOCATOR + grub_memset (chunk->srcv, 0xfa, chunk->size); + grub_mm_check (); +#endif + return GRUB_ERR_NONE; +} + +/* Context for grub_relocator_alloc_chunk_align. */ +struct grub_relocator_alloc_chunk_align_ctx +{ + grub_phys_addr_t min_addr, max_addr; + grub_size_t size, align; + int preference; + struct grub_relocator_chunk *chunk; + int found; +}; + +/* Helper for grub_relocator_alloc_chunk_align. */ +static int +grub_relocator_alloc_chunk_align_iter (grub_uint64_t addr, grub_uint64_t sz, + grub_memory_type_t type, void *data) +{ + struct grub_relocator_alloc_chunk_align_ctx *ctx = data; + grub_uint64_t candidate; + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + candidate = ALIGN_UP (addr, ctx->align); + if (candidate < ctx->min_addr) + candidate = ALIGN_UP (ctx->min_addr, ctx->align); + if (candidate + ctx->size > addr + sz + || candidate > ALIGN_DOWN (ctx->max_addr, ctx->align)) + return 0; + if (ctx->preference == GRUB_RELOCATOR_PREFERENCE_HIGH) + candidate = ALIGN_DOWN (min (addr + sz - ctx->size, ctx->max_addr), + ctx->align); + if (!ctx->found || (ctx->preference == GRUB_RELOCATOR_PREFERENCE_HIGH + && candidate > ctx->chunk->target)) + ctx->chunk->target = candidate; + if (!ctx->found || (ctx->preference == GRUB_RELOCATOR_PREFERENCE_LOW + && candidate < ctx->chunk->target)) + ctx->chunk->target = candidate; + ctx->found = 1; + return 0; +} + +grub_err_t +grub_relocator_alloc_chunk_align (struct grub_relocator *rel, + grub_relocator_chunk_t *out, + grub_phys_addr_t min_addr, + grub_phys_addr_t max_addr, + grub_size_t size, grub_size_t align, + int preference, + int avoid_efi_boot_services) +{ + struct grub_relocator_alloc_chunk_align_ctx ctx = { + .min_addr = min_addr, + .max_addr = max_addr, + .size = size, + .align = align, + .preference = preference, + .found = 0 + }; + grub_addr_t min_addr2 = 0, max_addr2; + + if (size && (max_addr > ~size)) + max_addr = ~size + 1; + +#ifdef GRUB_MACHINE_PCBIOS + if (min_addr < 0x1000) + min_addr = 0x1000; +#endif + + grub_dprintf ("relocator", "chunks = %p\n", rel->chunks); + + ctx.chunk = grub_malloc (sizeof (struct grub_relocator_chunk)); + if (!ctx.chunk) + return grub_errno; + + if (malloc_in_range (rel, min_addr, max_addr, align, + size, ctx.chunk, + preference != GRUB_RELOCATOR_PREFERENCE_HIGH, 1)) + { + grub_dprintf ("relocator", "allocated 0x%llx/0x%llx\n", + (unsigned long long) ctx.chunk->src, + (unsigned long long) ctx.chunk->src); + grub_dprintf ("relocator", "chunks = %p\n", rel->chunks); + ctx.chunk->target = ctx.chunk->src; + ctx.chunk->size = size; + ctx.chunk->next = rel->chunks; + rel->chunks = ctx.chunk; + ctx.chunk->srcv = grub_map_memory (ctx.chunk->src, ctx.chunk->size); + *out = ctx.chunk; + return GRUB_ERR_NONE; + } + + adjust_limits (rel, &min_addr2, &max_addr2, min_addr, max_addr); + grub_dprintf ("relocator", "Adjusted limits from %lx-%lx to %lx-%lx\n", + (unsigned long) min_addr, (unsigned long) max_addr, + (unsigned long) min_addr2, (unsigned long) max_addr2); + + do + { + if (malloc_in_range (rel, min_addr2, max_addr2, align, + size, ctx.chunk, 1, 1)) + break; + + if (malloc_in_range (rel, rel->highestnonpostaddr, ~(grub_addr_t)0, 1, + size, ctx.chunk, 0, 1)) + { + if (rel->postchunks > ctx.chunk->src) + rel->postchunks = ctx.chunk->src; + break; + } + + return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + } + while (0); + + { +#ifdef GRUB_MACHINE_EFI + grub_efi_mmap_iterate (grub_relocator_alloc_chunk_align_iter, &ctx, + avoid_efi_boot_services); +#elif defined (__powerpc__) || defined (GRUB_MACHINE_XEN) + (void) avoid_efi_boot_services; + grub_machine_mmap_iterate (grub_relocator_alloc_chunk_align_iter, &ctx); +#else + (void) avoid_efi_boot_services; + grub_mmap_iterate (grub_relocator_alloc_chunk_align_iter, &ctx); +#endif + if (!ctx.found) + return grub_error (GRUB_ERR_BAD_OS, "couldn't find suitable memory target"); + } + while (1) + { + struct grub_relocator_chunk *chunk2; + for (chunk2 = rel->chunks; chunk2; chunk2 = chunk2->next) + if ((chunk2->target <= ctx.chunk->target + && ctx.chunk->target < chunk2->target + chunk2->size) + || (ctx.chunk->target <= chunk2->target && chunk2->target + < ctx.chunk->target + size)) + { + if (preference == GRUB_RELOCATOR_PREFERENCE_HIGH) + ctx.chunk->target = ALIGN_DOWN (chunk2->target, align); + else + ctx.chunk->target = ALIGN_UP (chunk2->target + chunk2->size, + align); + break; + } + if (!chunk2) + break; + } + + grub_dprintf ("relocator", "relocators_size=%ld\n", + (unsigned long) rel->relocators_size); + + if (ctx.chunk->src < ctx.chunk->target) + rel->relocators_size += grub_relocator_backward_size; + if (ctx.chunk->src > ctx.chunk->target) + rel->relocators_size += grub_relocator_forward_size; + + grub_dprintf ("relocator", "relocators_size=%ld\n", + (unsigned long) rel->relocators_size); + + ctx.chunk->size = size; + ctx.chunk->next = rel->chunks; + rel->chunks = ctx.chunk; + grub_dprintf ("relocator", "cur = %p, next = %p\n", rel->chunks, + rel->chunks->next); + ctx.chunk->srcv = grub_map_memory (ctx.chunk->src, ctx.chunk->size); + *out = ctx.chunk; +#ifdef DEBUG_RELOCATOR + grub_memset (ctx.chunk->srcv, 0xfa, ctx.chunk->size); + grub_mm_check (); +#endif + return GRUB_ERR_NONE; +} + +void +grub_relocator_unload (struct grub_relocator *rel) +{ + struct grub_relocator_chunk *chunk, *next; + if (!rel) + return; + for (chunk = rel->chunks; chunk; chunk = next) + { + unsigned i; + for (i = 0; i < chunk->nsubchunks; i++) + free_subchunk (&chunk->subchunks[i]); + grub_unmap_memory (chunk->srcv, chunk->size); + next = chunk->next; + grub_free (chunk->subchunks); + grub_free (chunk); + } + grub_free (rel); +} + +grub_err_t +grub_relocator_prepare_relocs (struct grub_relocator *rel, grub_addr_t addr, + void **relstart, grub_size_t *relsize) +{ + grub_uint8_t *rels; + grub_uint8_t *rels0; + struct grub_relocator_chunk *sorted; + grub_size_t nchunks = 0; + unsigned j; + struct grub_relocator_chunk movers_chunk; + + grub_dprintf ("relocator", "Preparing relocs (size=%ld)\n", + (unsigned long) rel->relocators_size); + + if (!malloc_in_range (rel, 0, ~(grub_addr_t)0 - rel->relocators_size + 1, + grub_relocator_align, + rel->relocators_size, &movers_chunk, 1, 1)) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + movers_chunk.srcv = rels = rels0 + = grub_map_memory (movers_chunk.src, movers_chunk.size); + + if (relsize) + *relsize = rel->relocators_size; + + grub_dprintf ("relocator", "Relocs allocated at %p\n", movers_chunk.srcv); + + { + unsigned i; + grub_size_t count[257]; + struct grub_relocator_chunk *from, *to, *tmp; + + grub_memset (count, 0, sizeof (count)); + + { + struct grub_relocator_chunk *chunk; + for (chunk = rel->chunks; chunk; chunk = chunk->next) + { + grub_dprintf ("relocator", "chunk %p->%p, 0x%lx\n", + (void *) chunk->src, (void *) chunk->target, + (unsigned long) chunk->size); + nchunks++; + count[(chunk->src & 0xff) + 1]++; + } + } + from = grub_calloc (nchunks, sizeof (sorted[0])); + to = grub_calloc (nchunks, sizeof (sorted[0])); + if (!from || !to) + { + grub_free (from); + grub_free (to); + return grub_errno; + } + + for (j = 0; j < 256; j++) + count[j+1] += count[j]; + + { + struct grub_relocator_chunk *chunk; + for (chunk = rel->chunks; chunk; chunk = chunk->next) + from[count[chunk->src & 0xff]++] = *chunk; + } + + for (i = 1; i < GRUB_CPU_SIZEOF_VOID_P; i++) + { + grub_memset (count, 0, sizeof (count)); + for (j = 0; j < nchunks; j++) + count[((from[j].src >> (8 * i)) & 0xff) + 1]++; + for (j = 0; j < 256; j++) + count[j+1] += count[j]; + for (j = 0; j < nchunks; j++) + to[count[(from[j].src >> (8 * i)) & 0xff]++] = from[j]; + tmp = to; + to = from; + from = tmp; + } + sorted = from; + grub_free (to); + } + + for (j = 0; j < nchunks; j++) + { + grub_dprintf ("relocator", "sorted chunk %p->%p, 0x%lx\n", + (void *) sorted[j].src, (void *) sorted[j].target, + (unsigned long) sorted[j].size); + if (sorted[j].src < sorted[j].target) + { + grub_cpu_relocator_backward ((void *) rels, + sorted[j].srcv, + grub_map_memory (sorted[j].target, + sorted[j].size), + sorted[j].size); + rels += grub_relocator_backward_size; + } + if (sorted[j].src > sorted[j].target) + { + grub_cpu_relocator_forward ((void *) rels, + sorted[j].srcv, + grub_map_memory (sorted[j].target, + sorted[j].size), + sorted[j].size); + rels += grub_relocator_forward_size; + } + if (sorted[j].src == sorted[j].target) + grub_arch_sync_caches (sorted[j].srcv, sorted[j].size); + } + grub_cpu_relocator_jumper ((void *) rels, (grub_addr_t) addr); + *relstart = rels0; + grub_free (sorted); + return GRUB_ERR_NONE; +} + +void +grub_mm_check_real (const char *file, int line) +{ + grub_mm_region_t r; + grub_mm_header_t p, pa; + + for (r = grub_mm_base; r; r = r->next) + { + pa = r->first; + p = pa->next; + if (p->magic == GRUB_MM_ALLOC_MAGIC) + continue; + do + { + if ((grub_addr_t) p < (grub_addr_t) (r + 1) + || (grub_addr_t) p >= (grub_addr_t) (r + 1) + r->size) + grub_fatal ("%s:%d: out of range pointer: %p\n", file, line, p); + if (p->magic != GRUB_MM_FREE_MAGIC) + grub_fatal ("%s:%d free magic broken at %p (0x%x)\n", file, + line, p, p->magic); + pa = p; + p = pa->next; + } + while (pa != r->first); + } +} diff --git a/grub-core/lib/riscv/setjmp.S b/grub-core/lib/riscv/setjmp.S new file mode 100644 index 0000000..b48ef29 --- /dev/null +++ b/grub-core/lib/riscv/setjmp.S @@ -0,0 +1,84 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> +#include <grub/dl.h> + + .file "setjmp.S" + +GRUB_MOD_LICENSE "GPLv3+" + + .text + +#if __riscv_xlen == 64 +#define STORE_IDX(reg, idx) sd reg, (idx*8)(a0) +#define LOAD_IDX(reg, idx) ld reg, (idx*8)(a0) +#else +#define STORE_IDX(reg, idx) sw reg, (idx*4)(a0) +#define LOAD_IDX(reg, idx) lw reg, (idx*4)(a0) +#endif + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + /* Preserve all callee-saved registers and the SP */ + STORE_IDX(s0, 0) + STORE_IDX(s1, 1) + STORE_IDX(s2, 2) + STORE_IDX(s3, 3) + STORE_IDX(s4, 4) + STORE_IDX(s5, 5) + STORE_IDX(s6, 6) + STORE_IDX(s7, 7) + STORE_IDX(s8, 8) + STORE_IDX(s9, 9) + STORE_IDX(s10, 10) + STORE_IDX(s11, 11) + STORE_IDX(ra, 12) + STORE_IDX(sp, 13) + li a0, 0 + ret + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + LOAD_IDX(s0, 0) + LOAD_IDX(s1, 1) + LOAD_IDX(s2, 2) + LOAD_IDX(s3, 3) + LOAD_IDX(s4, 4) + LOAD_IDX(s5, 5) + LOAD_IDX(s6, 6) + LOAD_IDX(s7, 7) + LOAD_IDX(s8, 8) + LOAD_IDX(s9, 9) + LOAD_IDX(s10, 10) + LOAD_IDX(s11, 11) + LOAD_IDX(ra, 12) + LOAD_IDX(sp, 13) + + /* Move the return value in place, but return 1 if passed 0. */ + beq a1, zero, longjmp_1 + mv a0, a1 + ret + + longjmp_1: + li a0, 1 + ret diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S new file mode 100644 index 0000000..aa297ab --- /dev/null +++ b/grub-core/lib/setjmp.S @@ -0,0 +1,22 @@ +#if defined(__i386__) +#include "./i386/setjmp.S" +#elif defined(__x86_64__) +#include "./x86_64/setjmp.S" +#elif defined(__sparc__) +#include "./sparc64/setjmp.S" +#elif defined(__mips__) +#include "./mips/setjmp.S" +#elif defined(__powerpc__) || defined(__PPC__) +#include "./powerpc/setjmp.S" +#elif defined(__ia64__) +#include "./ia64/setjmp.S" +#include "./ia64/longjmp.S" +#elif defined(__arm__) +#include "./arm/setjmp.S" +#elif defined(__aarch64__) +#include "./arm64/setjmp.S" +#elif defined(__riscv) +#include "./riscv/setjmp.S" +#else +#error "Unknown target cpu type" +#endif diff --git a/grub-core/lib/sparc64/setjmp.S b/grub-core/lib/sparc64/setjmp.S new file mode 100644 index 0000000..6c11bdd --- /dev/null +++ b/grub-core/lib/sparc64/setjmp.S @@ -0,0 +1,54 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2007,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> +#include <grub/dl.h> + + .file "setjmp.S" + +GRUB_MOD_LICENSE "GPLv3+" + + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + stx %o7, [%o0 + 0x00] + stx %sp, [%o0 + 0x08] + stx %fp, [%o0 + 0x10] + retl + clr %o0 + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + ldx [%o0 + 0x10], %g1 + movrz %o1, 1, %o1 + + save %sp, -64, %sp + flushw + restore + + ldx [%o0 + 0x00], %o7 + ldx [%o0 + 0x08], %fp + sub %fp, 192, %sp + stx %g1, [%sp + 2047 + (14 * 8)] + retl + restore %o1, 0, %o0 diff --git a/grub-core/lib/syslinux_parse.c b/grub-core/lib/syslinux_parse.c new file mode 100644 index 0000000..ff244d2 --- /dev/null +++ b/grub-core/lib/syslinux_parse.c @@ -0,0 +1,1555 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/mm.h> +#include <grub/file.h> +#include <grub/normal.h> +#include <grub/syslinux_parse.h> + +struct syslinux_say +{ + struct syslinux_say *next; + struct syslinux_say *prev; + char msg[0]; +}; + +struct initrd_list +{ + struct initrd_list *next; + char *file; +}; + +struct syslinux_menuentry +{ + struct syslinux_menuentry *next; + struct syslinux_menuentry *prev; + char *label; + char *extlabel; + char *kernel_file; + struct initrd_list *initrds; + struct initrd_list *initrds_last; + char *append; + char *argument; + char *help; + char *comments; + grub_size_t commentslen; + char hotkey; + int make_default; + struct syslinux_say *say; + + enum { KERNEL_NO_KERNEL, KERNEL_LINUX, KERNEL_CHAINLOADER, + KERNEL_BIN, KERNEL_PXE, KERNEL_CHAINLOADER_BPB, + KERNEL_COM32, KERNEL_COM, KERNEL_IMG, KERNEL_CONFIG, LOCALBOOT } + entry_type; +}; + +struct syslinux_menu +{ + struct syslinux_menu *parent; + struct syslinux_menuentry *entries; + char *def; + char *comments; + char *background; + const char *root_read_directory; + const char *root_target_directory; + const char *current_read_directory; + const char *current_target_directory; + const char *filename; + grub_size_t commentslen; + unsigned long timeout; + struct syslinux_say *say; + grub_syslinux_flavour_t flavour; +}; + +struct output_buffer +{ + grub_size_t alloc; + grub_size_t ptr; + char *buf; +}; + +static grub_err_t +syslinux_parse_real (struct syslinux_menu *menu); +static grub_err_t +config_file (struct output_buffer *outbuf, + const char *root, const char *target_root, + const char *cwd, const char *target_cwd, + const char *fname, struct syslinux_menu *parent, + grub_syslinux_flavour_t flav); +static grub_err_t +print_entry (struct output_buffer *outbuf, + struct syslinux_menu *menu, + const char *str); + +static grub_err_t +ensure_space (struct output_buffer *outbuf, grub_size_t len) +{ + grub_size_t newlen; + char *newbuf; + if (len < outbuf->alloc - outbuf->ptr) + return GRUB_ERR_NONE; + newlen = (outbuf->ptr + len + 10) * 2; + newbuf = grub_realloc (outbuf->buf, newlen); + if (!newbuf) + return grub_errno; + outbuf->alloc = newlen; + outbuf->buf = newbuf; + return GRUB_ERR_NONE; +} + +static grub_err_t +print (struct output_buffer *outbuf, const char *str, grub_size_t len) +{ + grub_err_t err; + err = ensure_space (outbuf, len); + if (err) + return err; + grub_memcpy (&outbuf->buf[outbuf->ptr], str, len); + outbuf->ptr += len; + return GRUB_ERR_NONE; +} + +static grub_err_t +add_comment (struct syslinux_menu *menu, const char *comment, int nl) +{ + if (menu->entries) + { + if (menu->entries->commentslen == 0 && *comment == 0) + return GRUB_ERR_NONE; + menu->entries->comments = grub_realloc (menu->entries->comments, + menu->entries->commentslen + + 2 + grub_strlen (comment)); + if (!menu->entries->comments) + return grub_errno; + menu->entries->commentslen + += grub_stpcpy (menu->entries->comments + menu->entries->commentslen, + comment) + - (menu->entries->comments + menu->entries->commentslen); + if (nl) + menu->entries->comments[menu->entries->commentslen++] = '\n'; + menu->entries->comments[menu->entries->commentslen] = '\0'; + } + else + { + if (menu->commentslen == 0 && *comment == 0) + return GRUB_ERR_NONE; + menu->comments = grub_realloc (menu->comments, menu->commentslen + + 2 + grub_strlen (comment)); + if (!menu->comments) + return grub_errno; + menu->commentslen += grub_stpcpy (menu->comments + menu->commentslen, + comment) + - (menu->comments + menu->commentslen); + if (nl) + menu->comments[menu->commentslen++] = '\n'; + menu->comments[menu->commentslen] = '\0'; + } + return GRUB_ERR_NONE; +} + + +#define print_string(x) do { err = print (outbuf, x, sizeof (x) - 1); if (err) return err; } while (0) + +static grub_err_t +print_num (struct output_buffer *outbuf, int n) +{ + char buf[20]; + grub_snprintf (buf, sizeof (buf), "%d", n); + return print (outbuf, buf, grub_strlen (buf)); +} + +static grub_err_t +label (const char *line, struct syslinux_menu *menu) +{ + struct syslinux_menuentry *entry; + + entry = grub_malloc (sizeof (*entry)); + if (!entry) + return grub_errno; + grub_memset (entry, 0, sizeof (*entry)); + entry->label = grub_strdup (line); + if (!entry->label) + { + grub_free (entry); + return grub_errno; + } + entry->next = menu->entries; + entry->prev = NULL; + if (menu->entries) + menu->entries->prev = entry; + menu->entries = entry; + return GRUB_ERR_NONE; +} + +static grub_err_t +kernel (const char *line, struct syslinux_menu *menu) +{ + const char *end = line + grub_strlen (line); + + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->kernel_file = grub_strdup (line); + if (!menu->entries->kernel_file) + return grub_errno; + + menu->entries->entry_type = KERNEL_LINUX; + + if (end - line >= 2 && grub_strcmp (end - 2, ".0") == 0) + menu->entries->entry_type = KERNEL_PXE; + + if (end - line >= 4 && grub_strcasecmp (end - 4, ".bin") == 0) + menu->entries->entry_type = KERNEL_BIN; + + if (end - line >= 3 && grub_strcasecmp (end - 3, ".bs") == 0) + menu->entries->entry_type = KERNEL_CHAINLOADER; + + if (end - line >= 4 && grub_strcasecmp (end - 4, ".bss") == 0) + menu->entries->entry_type = KERNEL_CHAINLOADER_BPB; + + if (end - line >= 4 && grub_strcasecmp (end - 4, ".c32") == 0) + menu->entries->entry_type = KERNEL_COM32; + + if (end - line >= 4 && grub_strcasecmp (end - 4, ".cbt") == 0) + menu->entries->entry_type = KERNEL_COM; + + if (end - line >= 4 && grub_strcasecmp (end - 4, ".com") == 0) + menu->entries->entry_type = KERNEL_COM; + + if (end - line >= 4 && grub_strcasecmp (end - 4, ".img") == 0) + menu->entries->entry_type = KERNEL_IMG; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_linux (const char *line, struct syslinux_menu *menu) +{ + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->kernel_file = grub_strdup (line); + if (!menu->entries->kernel_file) + return grub_errno; + menu->entries->entry_type = KERNEL_LINUX; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_boot (const char *line, struct syslinux_menu *menu) +{ + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->kernel_file = grub_strdup (line); + if (!menu->entries->kernel_file) + return grub_errno; + menu->entries->entry_type = KERNEL_CHAINLOADER; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_bss (const char *line, struct syslinux_menu *menu) +{ + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->kernel_file = grub_strdup (line); + if (!menu->entries->kernel_file) + return grub_errno; + menu->entries->entry_type = KERNEL_CHAINLOADER_BPB; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_pxe (const char *line, struct syslinux_menu *menu) +{ + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->kernel_file = grub_strdup (line); + if (!menu->entries->kernel_file) + return grub_errno; + menu->entries->entry_type = KERNEL_PXE; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_fdimage (const char *line, struct syslinux_menu *menu) +{ + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->kernel_file = grub_strdup (line); + if (!menu->entries->kernel_file) + return grub_errno; + menu->entries->entry_type = KERNEL_IMG; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_comboot (const char *line, struct syslinux_menu *menu) +{ + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->kernel_file = grub_strdup (line); + if (!menu->entries->kernel_file) + return grub_errno; + menu->entries->entry_type = KERNEL_COM; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_com32 (const char *line, struct syslinux_menu *menu) +{ + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->kernel_file = grub_strdup (line); + if (!menu->entries->kernel_file) + return grub_errno; + menu->entries->entry_type = KERNEL_COM32; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_config (const char *line, struct syslinux_menu *menu) +{ + const char *space; + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + for (space = line; *space && !grub_isspace (*space); space++); + menu->entries->kernel_file = grub_strndup (line, space - line); + if (!menu->entries->kernel_file) + return grub_errno; + for (; *space && grub_isspace (*space); space++); + if (*space) + { + menu->entries->argument = grub_strdup (space); + if (!menu->entries->argument) + return grub_errno; + } + menu->entries->entry_type = KERNEL_CONFIG; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_append (const char *line, struct syslinux_menu *menu) +{ + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->append = grub_strdup (line); + if (!menu->entries->append) + return grub_errno; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_initrd (const char *line, struct syslinux_menu *menu) +{ + struct initrd_list *ninitrd; + const char *comma; + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + while (*line) + { + for (comma = line; *comma && *comma != ','; comma++); + + ninitrd = grub_malloc (sizeof (*ninitrd)); + if (!ninitrd) + return grub_errno; + ninitrd->file = grub_strndup (line, comma - line); + if (!ninitrd->file) + { + grub_free (ninitrd); + return grub_errno; + } + ninitrd->next = NULL; + if (menu->entries->initrds_last) + menu->entries->initrds_last->next = ninitrd; + else + { + menu->entries->initrds_last = ninitrd; + menu->entries->initrds = ninitrd; + } + + line = comma; + while (*line == ',') + line++; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_default (const char *line, struct syslinux_menu *menu) +{ + menu->def = grub_strdup (line); + if (!menu->def) + return grub_errno; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_timeout (const char *line, struct syslinux_menu *menu) +{ + menu->timeout = grub_strtoul (line, NULL, 0); + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_menudefault (const char *line __attribute__ ((unused)), + struct syslinux_menu *menu) +{ + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->make_default = 1; + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_menubackground (const char *line, + struct syslinux_menu *menu) +{ + menu->background = grub_strdup (line); + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_localboot (const char *line, + struct syslinux_menu *menu) +{ + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->kernel_file = grub_strdup (line); + if (!menu->entries->kernel_file) + return grub_errno; + menu->entries->entry_type = LOCALBOOT; + + return GRUB_ERR_NONE; +} + +static grub_err_t +cmd_extlabel (const char *line, struct syslinux_menu *menu) +{ + const char *in; + char *out; + + if (!menu->entries) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label"); + + menu->entries->extlabel = grub_malloc (grub_strlen (line) + 1); + if (!menu->entries->extlabel) + return grub_errno; + in = line; + out = menu->entries->extlabel; + while (*in) + { + if (in[0] == '^' && in[1]) + { + menu->entries->hotkey = grub_tolower (in[1]); + in++; + } + *out++ = *in++; + } + *out = 0; + + return GRUB_ERR_NONE; +} + + +static grub_err_t +cmd_say (const char *line, struct syslinux_menu *menu) +{ + struct syslinux_say *nsay; + nsay = grub_malloc (sizeof (*nsay) + grub_strlen (line) + 1); + if (!nsay) + return grub_errno; + nsay->prev = NULL; + if (menu->entries) + { + nsay->next = menu->entries->say; + menu->entries->say = nsay; + } + else + { + nsay->next = menu->say; + menu->say = nsay; + } + + if (nsay->next) + nsay->next->prev = nsay; + + grub_memcpy (nsay->msg, line, grub_strlen (line) + 1); + return GRUB_ERR_NONE; +} + +static char * +get_read_filename (struct syslinux_menu *menu, + const char *filename) +{ + return grub_xasprintf ("%s/%s", + filename[0] == '/' ? menu->root_read_directory + : menu->current_read_directory, filename); +} + +static char * +get_target_filename (struct syslinux_menu *menu, + const char *filename) +{ + return grub_xasprintf ("%s/%s", + filename[0] == '/' ? menu->root_target_directory + : menu->current_target_directory, filename); +} + +static grub_err_t +syslinux_parse (const char *filename, + struct syslinux_menu *menu) +{ + const char *old_filename = menu->filename; + grub_err_t ret; + char *nf; + nf = get_read_filename (menu, filename); + if (!nf) + return grub_errno; + menu->filename = nf; + ret = syslinux_parse_real (menu); + if (ret == GRUB_ERR_FILE_NOT_FOUND + || ret == GRUB_ERR_BAD_FILENAME) + { + grub_errno = ret = GRUB_ERR_NONE; + add_comment (menu, "# File ", 0); + add_comment (menu, nf, 0); + add_comment (menu, " not found", 1); + } + grub_free (nf); + menu->filename = old_filename; + return ret; +} + +struct +{ + const char *name1; + const char *name2; + grub_err_t (*parse) (const char *line, struct syslinux_menu *menu); +} commands[] = { + /* FIXME: support tagname. */ + {"include", NULL, syslinux_parse}, + {"menu", "include", syslinux_parse}, + {"label", NULL, label}, + {"kernel", NULL, kernel}, + {"linux", NULL, cmd_linux}, + {"boot", NULL, cmd_boot}, + {"bss", NULL, cmd_bss}, + {"pxe", NULL, cmd_pxe}, + {"fdimage", NULL, cmd_fdimage}, + {"comboot", NULL, cmd_comboot}, + {"com32", NULL, cmd_com32}, + {"config", NULL, cmd_config}, + {"append", NULL, cmd_append}, + /* FIXME: ipappend not supported. */ + {"localboot", NULL, cmd_localboot}, + {"initrd", NULL, cmd_initrd}, + {"default", NULL, cmd_default}, + {"menu", "label", cmd_extlabel}, + /* FIXME: MENU LABEL not supported. */ + /* FIXME: MENU HIDDEN not supported. */ + /* FIXME: MENU SEPARATOR not supported. */ + /* FIXME: MENU INDENT not supported. */ + /* FIXME: MENU DISABLE not supported. */ + /* FIXME: MENU HIDE not supported. */ + {"menu", "default", cmd_menudefault}, + /* FIXME: MENU PASSWD not supported. */ + /* FIXME: MENU MASTER PASSWD not supported. */ + {"menu", "background", cmd_menubackground}, + /* FIXME: MENU BEGIN not supported. */ + /* FIXME: MENU GOTO not supported. */ + /* FIXME: MENU EXIT not supported. */ + /* FIXME: MENU QUIT not supported. */ + /* FIXME: MENU START not supported. */ + /* FIXME: MENU AUTOBOOT not supported. */ + /* FIXME: MENU TABMSG not supported. */ + /* FIXME: MENU NOTABMSG not supported. */ + /* FIXME: MENU PASSPROMPT not supported. */ + /* FIXME: MENU COLOR not supported. */ + /* FIXME: MENU MSGCOLOR not supported. */ + /* FIXME: MENU WIDTH not supported. */ + /* FIXME: MENU MARGIN not supported. */ + /* FIXME: MENU PASSWORDMARGIN not supported. */ + /* FIXME: MENU ROWS not supported. */ + /* FIXME: MENU TABMSGROW not supported. */ + /* FIXME: MENU CMDLINEROW not supported. */ + /* FIXME: MENU ENDROW not supported. */ + /* FIXME: MENU PASSWORDROW not supported. */ + /* FIXME: MENU TIMEOUTROW not supported. */ + /* FIXME: MENU HELPMSGROW not supported. */ + /* FIXME: MENU HELPMSGENDROW not supported. */ + /* FIXME: MENU HIDDENROW not supported. */ + /* FIXME: MENU HSHIFT not supported. */ + /* FIXME: MENU VSHIFT not supported. */ + {"timeout", NULL, cmd_timeout}, + /* FIXME: TOTALTIMEOUT not supported. */ + /* FIXME: ONTIMEOUT not supported. */ + /* FIXME: ONERROR not supported. */ + /* FIXME: SERIAL not supported. */ + /* FIXME: CONSOLE not supported. */ + /* FIXME: FONT not supported. */ + /* FIXME: KBDMAP not supported. */ + {"say", NULL, cmd_say}, + /* FIXME: DISPLAY not supported. */ + /* FIXME: F* not supported. */ + + /* Commands to control interface behaviour which aren't needed with GRUB. + If they are important in your environment please contact GRUB team. + */ + {"prompt", NULL, NULL}, + {"nocomplete", NULL, NULL}, + {"noescape", NULL, NULL}, + {"implicit", NULL, NULL}, + {"allowoptions", NULL, NULL} +}; + +static grub_err_t +helptext (const char *line, grub_file_t file, struct syslinux_menu *menu) +{ + char *help; + char *buf = NULL; + grub_size_t helplen, alloclen = 0; + + help = grub_strdup (line); + if (!help) + return grub_errno; + helplen = grub_strlen (line); + while ((grub_free (buf), buf = grub_file_getline (file))) + { + char *ptr; + grub_size_t needlen; + for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); + if (grub_strncasecmp (ptr, "endtext", sizeof ("endtext") - 1) == 0) + { + ptr += sizeof ("endtext") - 1; + for (; *ptr && (grub_isspace (*ptr) || *ptr == '\n' || *ptr == '\r'); + ptr++); + if (!*ptr) + { + menu->entries->help = help; + grub_free (buf); + return GRUB_ERR_NONE; + } + } + needlen = helplen + 1 + grub_strlen (buf); + if (alloclen < needlen) + { + alloclen = 2 * needlen; + help = grub_realloc (help, alloclen); + if (!help) + { + grub_free (buf); + return grub_errno; + } + } + helplen += grub_stpcpy (help + helplen, buf) - (help + helplen); + } + + grub_free (buf); + grub_free (help); + return grub_errno; +} + + +static grub_err_t +syslinux_parse_real (struct syslinux_menu *menu) +{ + grub_file_t file; + char *buf = NULL; + grub_err_t err = GRUB_ERR_NONE; + + file = grub_file_open (menu->filename, GRUB_FILE_TYPE_CONFIG); + if (!file) + return grub_errno; + while ((grub_free (buf), buf = grub_file_getline (file))) + { + const char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5; + char *end; + unsigned i; + end = buf + grub_strlen (buf); + while (end > buf && (end[-1] == '\n' || end[-1] == '\r')) + end--; + *end = 0; + for (ptr1 = buf; *ptr1 && grub_isspace (*ptr1); ptr1++); + if (*ptr1 == '#' || *ptr1 == 0) + { + err = add_comment (menu, ptr1, 1); + if (err) + goto fail; + continue; + } + for (ptr2 = ptr1; !grub_isspace (*ptr2) && *ptr2; ptr2++); + for (ptr3 = ptr2; grub_isspace (*ptr3) && *ptr3; ptr3++); + for (ptr4 = ptr3; !grub_isspace (*ptr4) && *ptr4; ptr4++); + for (ptr5 = ptr4; grub_isspace (*ptr5) && *ptr5; ptr5++); + for (i = 0; i < ARRAY_SIZE(commands); i++) + if (grub_strlen (commands[i].name1) == (grub_size_t) (ptr2 - ptr1) + && grub_strncasecmp (commands[i].name1, ptr1, ptr2 - ptr1) == 0 + && (commands[i].name2 == NULL + || (grub_strlen (commands[i].name2) + == (grub_size_t) (ptr4 - ptr3) + && grub_strncasecmp (commands[i].name2, ptr3, ptr4 - ptr3) + == 0))) + break; + if (i == ARRAY_SIZE(commands)) + { + if (sizeof ("text") - 1 == ptr2 - ptr1 + && grub_strncasecmp ("text", ptr1, ptr2 - ptr1) == 0 + && (sizeof ("help") - 1 == ptr4 - ptr3 + && grub_strncasecmp ("help", ptr3, ptr4 - ptr3) == 0)) + { + if (helptext (ptr5, file, menu)) + { + grub_free (buf); + return 1; + } + continue; + } + + add_comment (menu, " # UNSUPPORTED command '", 0); + add_comment (menu, ptr1, 0); + add_comment (menu, "'", 1); + + continue; + } + if (commands[i].parse) + { + err = commands[i].parse (commands[i].name2 + ? ptr5 : ptr3, menu); + if (err) + goto fail; + } + } + fail: + grub_file_close (file); + grub_free (buf); + return err; +} + +static grub_err_t +print_escaped (struct output_buffer *outbuf, + const char *from, const char *to) +{ + const char *ptr; + grub_err_t err; + if (!to) + to = from + grub_strlen (from); + err = ensure_space (outbuf, (to - from) * 4 + 2); + if (err) + return err; + outbuf->buf[outbuf->ptr++] = '\''; + for (ptr = from; *ptr && ptr < to; ptr++) + { + if (*ptr == '\'') + { + outbuf->buf[outbuf->ptr++] = '\''; + outbuf->buf[outbuf->ptr++] = '\\'; + outbuf->buf[outbuf->ptr++] = '\''; + outbuf->buf[outbuf->ptr++] = '\''; + } + else + outbuf->buf[outbuf->ptr++] = *ptr; + } + outbuf->buf[outbuf->ptr++] = '\''; + return GRUB_ERR_NONE; +} + +static grub_err_t +print_file (struct output_buffer *outbuf, + struct syslinux_menu *menu, const char *from, const char *to) +{ + grub_err_t err; + if (!to) + to = from + grub_strlen (from); + err = print_escaped (outbuf, from[0] == '/' + ? menu->root_target_directory + : menu->current_target_directory, NULL); + if (err) + return err; + + err = print (outbuf, "/", 1); + if (err) + return err; + return print_escaped (outbuf, from, to); +} + +/* + * Makefile.am mimics this when generating tests/syslinux/ubuntu10.04_grub.cfg, + * so changes here may need to be reflected there too. + */ +static void +simplify_filename (char *str) +{ + char *iptr, *optr = str; + for (iptr = str; *iptr; iptr++) + { + if (*iptr == '/' && optr != str && optr[-1] == '/') + continue; + if (iptr[0] == '/' && iptr[1] == '.' && iptr[2] == '/') + { + iptr += 2; + continue; + } + if (iptr[0] == '/' && iptr[1] == '.' && iptr[2] == '.' + && iptr[3] == '/') + { + iptr += 3; + while (optr >= str && *optr != '/') + optr--; + if (optr < str) + { + str[0] = '/'; + optr = str; + } + optr++; + continue; + } + *optr++ = *iptr; + } + *optr = '\0'; +} + +static grub_err_t +print_config (struct output_buffer *outbuf, + struct syslinux_menu *menu, + const char *filename, const char *basedir) +{ + struct syslinux_menu *menuptr; + grub_err_t err = GRUB_ERR_NONE; + char *new_cwd = NULL; + char *new_target_cwd = NULL; + char *newname = NULL; + int depth = 0; + + new_cwd = get_read_filename (menu, basedir); + if (!new_cwd) + { + err = grub_errno; + goto out; + } + new_target_cwd = get_target_filename (menu, basedir); + if (!new_target_cwd) + { + err = grub_errno; + goto out; + } + newname = get_read_filename (menu, filename); + if (!newname) + { + err = grub_errno; + goto out; + } + simplify_filename (newname); + + print_string ("#"); + print_file (outbuf, menu, filename, NULL); + print_string (" "); + err = print (outbuf, newname, grub_strlen (newname)); + if (err) + return err; + print_string (":\n"); + + for (menuptr = menu; menuptr; menuptr = menuptr->parent, depth++) + if (grub_strcmp (menuptr->filename, newname) == 0 + || depth > 20) + break; + if (menuptr) + { + print_string (" syslinux_configfile -r "); + print_file (outbuf, menu, "/", NULL); + print_string (" -c "); + print_file (outbuf, menu, basedir, NULL); + print_string (" "); + print_file (outbuf, menu, filename, NULL); + print_string ("\n"); + } + else + { + err = config_file (outbuf, menu->root_read_directory, + menu->root_target_directory, new_cwd, new_target_cwd, + newname, menu, menu->flavour); + if (err == GRUB_ERR_FILE_NOT_FOUND + || err == GRUB_ERR_BAD_FILENAME) + { + grub_errno = err = GRUB_ERR_NONE; + print_string ("# File "); + err = print (outbuf, newname, grub_strlen (newname)); + if (err) + goto out; + print_string (" not found\n"); + } + } + + out: + grub_free (newname); + grub_free (new_cwd); + grub_free (new_target_cwd); + return err; +} + +static grub_err_t +write_entry (struct output_buffer *outbuf, + struct syslinux_menu *menu, + struct syslinux_menuentry *curentry) +{ + grub_err_t err; + if (curentry->comments) + { + err = print (outbuf, curentry->comments, + grub_strlen (curentry->comments)); + if (err) + return err; + } + { + struct syslinux_say *say; + for (say = curentry->say; say && say->next; say = say->next); + for (; say && say->prev; say = say->prev) + { + print_string ("echo "); + if (print_escaped (outbuf, say->msg, NULL)) return grub_errno; + print_string ("\n"); + } + } + + /* FIXME: support help text. */ + switch (curentry->entry_type) + { + case KERNEL_LINUX: + { + const char *ptr; + const char *initrd = NULL, *initrde= NULL; + for (ptr = curentry->append; ptr && *ptr; ptr++) + if ((ptr == curentry->append || grub_isspace (ptr[-1])) + && grub_strncasecmp (ptr, "initrd=", sizeof ("initrd=") - 1) + == 0) + break; + if (ptr && *ptr) + { + initrd = ptr + sizeof ("initrd=") - 1; + for (initrde = initrd; *initrde && !grub_isspace (*initrde); initrde++); + } + print_string (" if test x$grub_platform = xpc; then " + "linux_suffix=16; else linux_suffix= ; fi\n"); + print_string (" linux$linux_suffix "); + print_file (outbuf, menu, curentry->kernel_file, NULL); + print_string (" "); + if (curentry->append) + { + err = print (outbuf, curentry->append, grub_strlen (curentry->append)); + if (err) + return err; + } + print_string ("\n"); + if (initrd || curentry->initrds) + { + struct initrd_list *lst; + print_string (" initrd$linux_suffix "); + if (initrd) + { + print_file (outbuf, menu, initrd, initrde); + print_string (" "); + } + for (lst = curentry->initrds; lst; lst = lst->next) + { + print_file (outbuf, menu, lst->file, NULL); + print_string (" "); + } + + print_string ("\n"); + } + } + break; + case KERNEL_CHAINLOADER: + print_string (" chainloader "); + print_file (outbuf, menu, curentry->kernel_file, NULL); + print_string ("\n"); + break; + case KERNEL_CHAINLOADER_BPB: + print_string (" chainloader --bpb "); + print_file (outbuf, menu, curentry->kernel_file, NULL); + print_string ("\n"); + break; + case LOCALBOOT: + /* FIXME: support -1. */ + /* FIXME: PXELINUX. */ + { + int n = grub_strtol (curentry->kernel_file, NULL, 0); + if (n >= 0 && n <= 0x02) + { + print_string (" root=fd"); + if (print_num (outbuf, n)) + return grub_errno; + print_string (";\n chainloader +1;\n"); + + break; + } + if (n >= 0x80 && n < 0x8a) + { + print_string (" root=hd"); + if (print_num (outbuf, n - 0x80)) + return grub_errno; + print_string (";\n chainloader +1;\n"); + break; + } + print_string (" # UNSUPPORTED localboot type "); + print_string ("\ntrue;\n"); + if (print_num (outbuf, n)) + return grub_errno; + print_string ("\n"); + break; + } + case KERNEL_COM32: + case KERNEL_COM: + { + char *basename = NULL; + + { + char *ptr; + for (ptr = curentry->kernel_file; *ptr; ptr++) + if (*ptr == '/' || *ptr == '\\') + basename = ptr; + } + if (!basename) + basename = curentry->kernel_file; + else + basename++; + if (grub_strcasecmp (basename, "chain.c32") == 0) + { + char *file = NULL; + int is_fd = -1, devn = 0; + int part = -1; + int swap = 0; + char *ptr; + for (ptr = curentry->append; *ptr; ) + { + while (grub_isspace (*ptr)) + ptr++; + /* FIXME: support mbr: and boot. */ + if (ptr[0] == 'h' && ptr[1] == 'd') + { + is_fd = 0; + devn = grub_strtoul (ptr + 2, (const char **)&ptr, 0); + continue; + } + if (grub_strncasecmp (ptr, "file=", 5) == 0) + { + file = ptr + 5; + for (ptr = file; *ptr && !grub_isspace (*ptr); ptr++); + if (*ptr) + { + *ptr = 0; + ptr++; + } + continue; + } + if (grub_strncasecmp (ptr, "swap", sizeof ("swap") - 1) == 0) + { + swap = 1; + ptr += sizeof ("swap") - 1; + continue; + } + + if (ptr[0] == 'f' && ptr[1] == 'd') + { + is_fd = 1; + devn = grub_strtoul (ptr + 2, (const char **)&ptr, 0); + continue; + } + if (grub_isdigit (ptr[0])) + { + part = grub_strtoul (ptr, (const char **)&ptr, 0); + continue; + } + /* FIXME: isolinux, ntldr, cmldr, *dos, seg, hide + FIXME: sethidden. */ + print_string (" # UNSUPPORTED option "); + if (print (outbuf, ptr, grub_strlen (ptr))) + return 0; + print_string ("\n"); + break; + } + if (is_fd == -1) + { + print_string (" # no drive specified\n"); + break; + } + if (!*ptr) + { + print_string (is_fd ? " root=fd": " root=hd"); + if (print_num (outbuf, devn)) + return grub_errno; + if (part != -1) + { + print_string (","); + if (print_num (outbuf, part + 1)) + return grub_errno; + } + print_string (";\n"); + if (file) + { + print_string (" chainloader "); + print_file (outbuf, menu, file, NULL); + print_string (";\n"); + } + else + print_string (" chainloader +1;\n"); + if (swap) + print_string (" drivemap -s hd0 \"root\";\n"); + } + break; + } + + if (grub_strcasecmp (basename, "mboot.c32") == 0) + { + char *ptr; + int first = 1; + int is_kernel = 1; + for (ptr = curentry->append; *ptr; ) + { + char *ptrr = ptr; + while (*ptr && !grub_isspace (*ptr)) + ptr++; + if (ptrr + 2 == ptr && ptrr[0] == '-' && ptrr[1] == '-') + { + print_string ("\n"); + first = 1; + continue; + } + if (first) + { + if (is_kernel) + print_string (" multiboot "); + else + print_string (" module "); + first = 0; + is_kernel = 0; + if (print_file (outbuf, menu, ptrr, ptr)) + return grub_errno; + continue; + } + if (print_escaped (outbuf, ptrr, ptr)) + return grub_errno; + } + break; + } + + if (grub_strcasecmp (basename, "ifcpu64.c32") == 0) + { + char *lm, *lme, *pae = 0, *paee = 0, *i386s = 0, *i386e = 0; + char *ptr; + ptr = curentry->append; + while (grub_isspace (*ptr)) + ptr++; + lm = ptr; + while (*ptr && !grub_isspace (*ptr)) + ptr++; + lme = ptr; + while (grub_isspace (*ptr)) + ptr++; + if (ptr[0] == '-' && ptr[1] == '-') + { + ptr += 2; + while (grub_isspace (*ptr)) + ptr++; + pae = ptr; + while (*ptr && !grub_isspace (*ptr)) + ptr++; + paee = ptr; + } + while (grub_isspace (*ptr)) + ptr++; + if (ptr[0] == '-' && ptr[1] == '-') + { + ptr += 2; + while (grub_isspace (*ptr)) + ptr++; + i386s = ptr; + while (*ptr && !grub_isspace (*ptr)) + ptr++; + i386e = ptr; + } + *lme = '\0'; + if (paee) + *paee = '\0'; + if (i386e) + *i386e = '\0'; + if (!i386s) + { + i386s = pae; + pae = 0; + } + print_string ("if cpuid --long-mode; then true;\n"); + if (print_entry (outbuf, menu, lm)) + return grub_errno; + if (pae) + { + print_string ("elif cpuid --pae; then true;\n"); + if (print_entry (outbuf, menu, pae)) + return grub_errno; + } + print_string ("else\n"); + if (print_entry (outbuf, menu, i386s)) + return grub_errno; + print_string ("fi\n"); + break; + } + + if (grub_strcasecmp (basename, "reboot.c32") == 0) + { + print_string (" reboot\n"); + break; + } + + if (grub_strcasecmp (basename, "poweroff.com") == 0) + { + print_string (" halt\n"); + break; + } + + if (grub_strcasecmp (basename, "whichsys.c32") == 0) + { + grub_syslinux_flavour_t flavour = GRUB_SYSLINUX_ISOLINUX; + const char *flav[] = + { + [GRUB_SYSLINUX_ISOLINUX] = "iso", + [GRUB_SYSLINUX_PXELINUX] = "pxe", + [GRUB_SYSLINUX_SYSLINUX] = "sys" + }; + char *ptr; + for (ptr = curentry->append; *ptr; ) + { + char *bptr, c; + while (grub_isspace (*ptr)) + ptr++; + if (grub_strncasecmp (ptr, "-iso-", 5) == 0) + { + ptr += sizeof ("-iso-") - 1; + flavour = GRUB_SYSLINUX_ISOLINUX; + continue; + } + if (grub_strncasecmp (ptr, "-pxe-", 5) == 0) + { + ptr += sizeof ("-pxe-") - 1; + flavour = GRUB_SYSLINUX_PXELINUX; + continue; + } + if (grub_strncasecmp (ptr, "-sys-", 5) == 0) + { + ptr += sizeof ("-sys-") - 1; + flavour = GRUB_SYSLINUX_SYSLINUX; + continue; + } + bptr = ptr; + while (*ptr && !grub_isspace (*ptr)) + ptr++; + c = *ptr; + *ptr = '\0'; + if (menu->flavour == GRUB_SYSLINUX_UNKNOWN + && flavour == GRUB_SYSLINUX_ISOLINUX) + { + print_string ("if [ x$syslinux_flavour = xiso -o x$syslinux_flavour = x ]; then true;\n"); + menu->flavour = GRUB_SYSLINUX_ISOLINUX; + print_entry (outbuf, menu, bptr); + menu->flavour = GRUB_SYSLINUX_UNKNOWN; + print_string ("fi\n"); + } + else if (menu->flavour == GRUB_SYSLINUX_UNKNOWN) + { + print_string ("if [ x$syslinux_flavour = x"); + err = print (outbuf, flav[flavour], grub_strlen (flav[flavour])); + if (err) + return err; + print_string (" ]; then true;\n"); + menu->flavour = flavour; + print_entry (outbuf, menu, bptr); + menu->flavour = GRUB_SYSLINUX_UNKNOWN; + print_string ("fi\n"); + } + if (menu->flavour != GRUB_SYSLINUX_UNKNOWN + && menu->flavour == flavour) + print_entry (outbuf, menu, bptr); + *ptr = c; + } + break; + } + + if (grub_strcasecmp (basename, "menu.c32") == 0 || + grub_strcasecmp (basename, "vesamenu.c32") == 0) + { + char *ptr; + char *end; + + ptr = curentry->append; + if (!ptr) + return grub_errno; + + while (*ptr) + { + end = ptr; + for (end = ptr; *end && !grub_isspace (*end); end++); + if (*end) + *end++ = '\0'; + + /* "~" is supposed to be current file, so let's skip it */ + if (grub_strcmp (ptr, "~") != 0) + { + err = print_config (outbuf, menu, ptr, ""); + if (err != GRUB_ERR_NONE) + break; + } + for (ptr = end; *ptr && grub_isspace (*ptr); ptr++); + } + err = GRUB_ERR_NONE; + break; + } + + /* FIXME: gdb, GFXBoot, Hdt, Ifcpu, Ifplop, Kbdmap, + FIXME: Linux, Lua, Meminfo, rosh, Sanbboot */ + + print_string (" # UNSUPPORTED com(32) "); + err = print (outbuf, basename, grub_strlen (basename)); + if (err) + return err; + print_string ("\ntrue;\n"); + break; + } + case KERNEL_CONFIG: + { + const char *ap; + ap = curentry->append; + if (!ap) + ap = curentry->argument; + if (!ap) + ap = ""; + print_config (outbuf, menu, curentry->kernel_file, ap); + } + break; + case KERNEL_NO_KERNEL: + /* FIXME: support this. */ + case KERNEL_BIN: + case KERNEL_PXE: + case KERNEL_IMG: + print_string (" # UNSUPPORTED entry type "); + if (print_num (outbuf, curentry->entry_type)) + return grub_errno; + print_string ("\ntrue;\n"); + break; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +print_entry (struct output_buffer *outbuf, + struct syslinux_menu *menu, + const char *str) +{ + struct syslinux_menuentry *curentry; + for (curentry = menu->entries; curentry; curentry = curentry->next) + if (grub_strcasecmp (curentry->label, str) == 0) + { + grub_err_t err; + err = write_entry (outbuf, menu, curentry); + if (err) + return err; + } + return GRUB_ERR_NONE; +} + +static void +free_menu (struct syslinux_menu *menu) +{ + struct syslinux_say *say, *nsay; + struct syslinux_menuentry *entry, *nentry; + + grub_free (menu->def); + grub_free (menu->comments); + grub_free (menu->background); + for (say = menu->say; say ; say = nsay) + { + nsay = say->next; + grub_free (say); + } + + for (entry = menu->entries; entry ; entry = nentry) + { + nentry = entry->next; + struct initrd_list *initrd, *ninitrd; + + for (initrd = entry->initrds; initrd ; initrd = ninitrd) + { + ninitrd = initrd->next; + grub_free (initrd->file); + grub_free (initrd); + } + + grub_free (entry->comments); + grub_free (entry->kernel_file); + grub_free (entry->label); + grub_free (entry->extlabel); + grub_free (entry->append); + grub_free (entry->help); + grub_free (entry); + } +} + +static grub_err_t +config_file (struct output_buffer *outbuf, + const char *root, const char *target_root, + const char *cwd, const char *target_cwd, + const char *fname, struct syslinux_menu *parent, + grub_syslinux_flavour_t flav) +{ + grub_err_t err; + struct syslinux_menu menu; + struct syslinux_menuentry *curentry, *lentry; + struct syslinux_say *say; + + grub_memset (&menu, 0, sizeof (menu)); + menu.flavour = flav; + menu.root_read_directory = root; + menu.root_target_directory = target_root; + menu.current_read_directory = cwd; + menu.current_target_directory = target_cwd; + + menu.filename = fname; + menu.parent = parent; + err = syslinux_parse_real (&menu); + if (err) + return err; + + for (say = menu.say; say && say->next; say = say->next); + for (; say && say->prev; say = say->prev) + { + print_string ("echo "); + err = print_escaped (outbuf, say->msg, NULL); + if (err) + return err; + print_string ("\n"); + } + + if (menu.background) + { + print_string (" background_image "); + err = print_file (outbuf, &menu, menu.background, NULL); + if (err) + return err; + print_string ("\n"); + } + + if (menu.comments) + { + err = print (outbuf, menu.comments, grub_strlen (menu.comments)); + if (err) + return err; + } + + if (menu.timeout == 0 && menu.entries && menu.def) + { + err = print_entry (outbuf, &menu, menu.def); + if (err) + return err; + } + else if (menu.entries) + { + for (curentry = menu.entries; curentry->next; curentry = curentry->next); + lentry = curentry; + + print_string ("set timeout="); + err = print_num (outbuf, (menu.timeout + 9) / 10); + if (err) + return err; + print_string ("\n"); + + if (menu.def) + { + print_string (" default="); + err = print_escaped (outbuf, menu.def, NULL); + if (err) + return err; + print_string ("\n"); + } + for (curentry = lentry; curentry; curentry = curentry->prev) + { + print_string ("menuentry "); + err = print_escaped (outbuf, + curentry->extlabel ? : curentry->label, NULL); + if (err) + return err; + if (curentry->hotkey) + { + char hk[] = { curentry->hotkey, '\0' }; + print_string (" --hotkey '"); + print_string (hk); + print_string ("'"); + } + print_string (" --id "); + err = print_escaped (outbuf, curentry->label, NULL); + if (err) + return err; + print_string (" {\n"); + + err = write_entry (outbuf, &menu, curentry); + if (err) + return err; + + print_string ("}\n"); + } + } + free_menu (&menu); + return GRUB_ERR_NONE; +} + +char * +grub_syslinux_config_file (const char *base, const char *target_base, + const char *cwd, const char *target_cwd, + const char *fname, grub_syslinux_flavour_t flav) +{ + struct output_buffer outbuf = { 0, 0, 0 }; + grub_err_t err; + err = config_file (&outbuf, base, target_base, cwd, target_cwd, + fname, NULL, flav); + if (err) + return NULL; + err = print (&outbuf, "\0", 1); + if (err) + return NULL; + return outbuf.buf; +} diff --git a/grub-core/lib/uboot/reboot.c b/grub-core/lib/uboot/reboot.c new file mode 100644 index 0000000..00a2507 --- /dev/null +++ b/grub-core/lib/uboot/reboot.c @@ -0,0 +1,31 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/kernel.h> +#include <grub/misc.h> +#include <grub/uboot/uboot.h> +#include <grub/loader.h> + +void +grub_reboot (void) +{ + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); + + grub_uboot_reset (); + while (1); +} diff --git a/grub-core/lib/x86_64/efi/relocator.c b/grub-core/lib/x86_64/efi/relocator.c new file mode 100644 index 0000000..7d200a1 --- /dev/null +++ b/grub-core/lib/x86_64/efi/relocator.c @@ -0,0 +1,79 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * Copyright (C) 2016 Oracle and/or its affiliates. All rights reserved. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/mm.h> +#include <grub/misc.h> + +#include <grub/types.h> +#include <grub/err.h> + +#include <grub/i386/relocator.h> +#include <grub/relocator_private.h> + +extern grub_uint64_t grub_relocator64_rax; +extern grub_uint64_t grub_relocator64_rbx; +extern grub_uint64_t grub_relocator64_rcx; +extern grub_uint64_t grub_relocator64_rdx; +extern grub_uint64_t grub_relocator64_rip; +extern grub_uint64_t grub_relocator64_rsi; + +extern grub_uint8_t grub_relocator64_efi_start; +extern grub_uint8_t grub_relocator64_efi_end; + +#define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start) + +grub_err_t +grub_relocator64_efi_boot (struct grub_relocator *rel, + struct grub_relocator64_efi_state state) +{ + grub_err_t err; + void *relst; + grub_relocator_chunk_t ch; + + /* + * 64-bit relocator code may live above 4 GiB quite well. + * However, I do not want ask for problems. Just in case. + */ + err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0, 0x100000000, + RELOCATOR_SIZEOF (64_efi), 16, + GRUB_RELOCATOR_PREFERENCE_NONE, 1); + if (err) + return err; + + /* Do not touch %rsp! It points to EFI created stack. */ + grub_relocator64_rax = state.rax; + grub_relocator64_rbx = state.rbx; + grub_relocator64_rcx = state.rcx; + grub_relocator64_rdx = state.rdx; + grub_relocator64_rip = state.rip; + grub_relocator64_rsi = state.rsi; + + grub_memmove (get_virtual_current_address (ch), &grub_relocator64_efi_start, + RELOCATOR_SIZEOF (64_efi)); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); + if (err) + return err; + + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/x86_64/relocator_asm.S b/grub-core/lib/x86_64/relocator_asm.S new file mode 100644 index 0000000..2ab6d8c --- /dev/null +++ b/grub-core/lib/x86_64/relocator_asm.S @@ -0,0 +1,85 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> +#include <grub/i386/memory.h> + + .p2align 2 + +VARIABLE(grub_relocator_backward_start) + /* mov imm32, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator_backward_dest) + .long 0, 0 + movq %rax, %rdi + + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator_backward_src) + .long 0, 0 + movq %rax, %rsi + + /* mov imm64, %rcx */ + .byte 0x48 + .byte 0xb9 +VARIABLE(grub_relocator_backward_chunk_size) + .long 0, 0 + + add %rcx, %rsi + add %rcx, %rdi + + /* Backward movsb is implicitly off-by-one. compensate that. */ + sub $1, %rsi + sub $1, %rdi + + /* Backward copy. */ + std + + rep + movsb +VARIABLE(grub_relocator_backward_end) + + +VARIABLE(grub_relocator_forward_start) + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator_forward_dest) + .long 0, 0 + movq %rax, %rdi + + /* mov imm64, %rax */ + .byte 0x48 + .byte 0xb8 +VARIABLE(grub_relocator_forward_src) + .long 0, 0 + movq %rax, %rsi + + /* mov imm64, %rcx */ + .byte 0x48 + .byte 0xb9 +VARIABLE(grub_relocator_forward_chunk_size) + .long 0, 0 + + /* Forward copy. */ + cld + rep + movsb +VARIABLE(grub_relocator_forward_end) diff --git a/grub-core/lib/x86_64/setjmp.S b/grub-core/lib/x86_64/setjmp.S new file mode 100644 index 0000000..6b151bc --- /dev/null +++ b/grub-core/lib/x86_64/setjmp.S @@ -0,0 +1,68 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2007 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/symbol.h> +#include <grub/dl.h> + + .file "setjmp.S" + +GRUB_MOD_LICENSE "GPLv3+" + + .text + +/* + * jmp_buf: + * rbx rsp rbp r12 r13 r14 r15 rip + * 0 8 16 24 32 40 48 56 + */ + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + pop %rsi /* Return address, and adjust the stack */ + xorq %rax, %rax + movq %rbx, 0(%rdi) /* RBX */ + movq %rsp, 8(%rdi) /* RSP */ + push %rsi + movq %rbp, 16(%rdi) /* RBP */ + movq %r12, 24(%rdi) /* R12 */ + movq %r13, 32(%rdi) /* R13 */ + movq %r14, 40(%rdi) /* R14 */ + movq %r15, 48(%rdi) /* R15 */ + movq %rsi, 56(%rdi) /* RSI */ + ret + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + movl %esi, %eax + orl %eax, %eax + jnz 1f + incl %eax +1: + + movq (%rdi), %rbx + movq 8(%rdi), %rsp + movq 16(%rdi), %rbp + movq 24(%rdi), %r12 + movq 32(%rdi), %r13 + movq 40(%rdi), %r14 + movq 48(%rdi), %r15 + jmp *56(%rdi) diff --git a/grub-core/lib/x86_64/xen/relocator.S b/grub-core/lib/x86_64/xen/relocator.S new file mode 100644 index 0000000..f5364ed --- /dev/null +++ b/grub-core/lib/x86_64/xen/relocator.S @@ -0,0 +1,133 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/x86_64/memory.h> +#include <grub/x86_64/types.h> +#include <grub/symbol.h> +#include <grub/xen.h> + +/* Macro to load an imm64 value stored by the C-part into %rax: */ +#define MOV_IMM64_RAX(var) .byte 0x48, 0xb8; VARIABLE(var); .quad 0 + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE(grub_relocator_xen_remap_start) +LOCAL(base): + /* Remap the remapper to it's new address. */ + MOV_IMM64_RAX(grub_relocator_xen_remapper_virt) + + movq %rax, %rdi /* %rdi: new virtual address of remapper */ + movq %rax, %rbx /* Remember new virtual address */ + + MOV_IMM64_RAX(grub_relocator_xen_remapper_map) + + movq %rax, %rsi /* %rsi: page table entry */ + + movq $UVMF_INVLPG, %rdx /* %rdx: flags (inv. single entry) */ + movq $__HYPERVISOR_update_va_mapping, %rax + syscall /* Do the remap operation */ + + addq $(LOCAL(cont) - LOCAL(base)), %rbx + + jmp *%rbx /* Continue with new virtual address */ + +LOCAL(cont): + /* Modify mappings of new page tables to be read-only. */ + MOV_IMM64_RAX(grub_relocator_xen_mfn_list) + + movq %rax, %rbx /* %rbx is the base of the p2m list */ + leaq EXT_C(grub_relocator_xen_paging_areas) (%rip), %r8 + +1: + movq 0(%r8), %r12 /* Get start pfn of the current area */ + movq GRUB_TARGET_SIZEOF_LONG(%r8), %rcx /* Get # of pg tables */ + testq %rcx, %rcx /* 0 -> last area reached */ + jz 3f +2: + movq %r12, %rdi + shlq $PAGE_SHIFT, %rdi /* virtual address (1:1 mapping) */ + movq (%rbx, %r12, 8), %rsi /* mfn */ + shlq $PAGE_SHIFT, %rsi + orq $(GRUB_PAGE_PRESENT | GRUB_PAGE_USER), %rsi /* Build pte */ + movq $UVMF_INVLPG, %rdx + movq %rcx, %r9 /* %rcx clobbered by hypercall */ + movq $__HYPERVISOR_update_va_mapping, %rax + syscall + + movq %r9, %rcx + incq %r12 /* next pfn */ + + loop 2b + + addq $(2 * GRUB_TARGET_SIZEOF_LONG), %r8 /* next pg table area */ + jmp 1b + +3: + /* Switch page tables: pin new L4 pt, load cr3, unpin old L4. */ + leaq EXT_C(grub_relocator_xen_mmu_op) (%rip), %rdi + movq $3, %rsi /* 3 mmu ops */ + movq $0, %rdx /* pdone (not used) */ + movq $DOMID_SELF, %r10 + movq $__HYPERVISOR_mmuext_op, %rax + syscall + + /* Continue in virtual kernel mapping. */ + MOV_IMM64_RAX(grub_relocator_xen_remap_continue) + + jmp *%rax + +VARIABLE(grub_relocator_xen_paging_areas) + /* array of start, size pairs, size 0 is end marker */ + .quad 0, 0, 0, 0, 0, 0, 0, 0 + +VARIABLE(grub_relocator_xen_mmu_op) + .space 256 + +VARIABLE(grub_relocator_xen_remap_end) + + +VARIABLE(grub_relocator_xen_start) + /* Unmap old remapper area. */ + MOV_IMM64_RAX(grub_relocator_xen_remapper_virt2) + + movq %rax, %rdi + + xorq %rax, %rax /* Invalid pte */ + movq %rax, %rsi + + movq $UVMF_INVLPG, %rdx + movq $__HYPERVISOR_update_va_mapping, %rax + syscall + + /* Prepare registers for starting kernel. */ + MOV_IMM64_RAX(grub_relocator_xen_stack) + + movq %rax, %rsp + + MOV_IMM64_RAX(grub_relocator_xen_start_info) + + movq %rax, %rsi + + cld + + MOV_IMM64_RAX(grub_relocator_xen_entry_point) + + /* Now start the new kernel. */ + jmp *%rax + +VARIABLE(grub_relocator_xen_end) diff --git a/grub-core/lib/xen/datetime.c b/grub-core/lib/xen/datetime.c new file mode 100644 index 0000000..d96176e --- /dev/null +++ b/grub-core/lib/xen/datetime.c @@ -0,0 +1,40 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/datetime.h> +#include <grub/dl.h> +#include <grub/misc.h> +#include <grub/xen.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +grub_err_t +grub_get_datetime (struct grub_datetime *datetime) +{ + long long nix; + nix = (grub_xen_shared_info->wc_sec + + grub_divmod64 (grub_xen_shared_info->vcpu_info[0].time.system_time, 1000000000, 0)); + grub_unixtime2datetime (nix, datetime); + return GRUB_ERR_NONE; +} + +grub_err_t +grub_set_datetime (struct grub_datetime *datetime __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_IO, "setting time isn't supported"); +} diff --git a/grub-core/lib/xen/halt.c b/grub-core/lib/xen/halt.c new file mode 100644 index 0000000..2aceead --- /dev/null +++ b/grub-core/lib/xen/halt.c @@ -0,0 +1,32 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/mm.h> +#include <grub/misc.h> +#include <grub/kernel.h> +#include <grub/xen.h> + +void +grub_halt (void) +{ + struct sched_shutdown arg; + + arg.reason = SHUTDOWN_poweroff; + grub_xen_sched_op (SCHEDOP_shutdown, &arg); + for (;;); +} diff --git a/grub-core/lib/xen/reboot.c b/grub-core/lib/xen/reboot.c new file mode 100644 index 0000000..fd7609a --- /dev/null +++ b/grub-core/lib/xen/reboot.c @@ -0,0 +1,32 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/mm.h> +#include <grub/misc.h> +#include <grub/kernel.h> +#include <grub/xen.h> + +void +grub_reboot (void) +{ + struct sched_shutdown arg; + + arg.reason = SHUTDOWN_reboot; + grub_xen_sched_op (SCHEDOP_shutdown, &arg); + for (;;); +} diff --git a/grub-core/lib/xen/relocator.c b/grub-core/lib/xen/relocator.c new file mode 100644 index 0000000..4d0cbca --- /dev/null +++ b/grub-core/lib/xen/relocator.c @@ -0,0 +1,137 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/mm.h> +#include <grub/misc.h> + +#include <grub/types.h> +#include <grub/err.h> +#include <grub/term.h> +#include <grub/xen.h> + +#include <grub/xen/relocator.h> +#include <grub/relocator_private.h> + +typedef grub_addr_t grub_xen_reg_t; + +struct grub_relocator_xen_paging_area { + grub_xen_reg_t start; + grub_xen_reg_t size; +} GRUB_PACKED; + +extern grub_uint8_t grub_relocator_xen_start; +extern grub_uint8_t grub_relocator_xen_end; +extern grub_uint8_t grub_relocator_xen_remap_start; +extern grub_uint8_t grub_relocator_xen_remap_end; +extern grub_xen_reg_t grub_relocator_xen_stack; +extern grub_xen_reg_t grub_relocator_xen_start_info; +extern grub_xen_reg_t grub_relocator_xen_entry_point; +extern grub_xen_reg_t grub_relocator_xen_remapper_virt; +extern grub_xen_reg_t grub_relocator_xen_remapper_virt2; +extern grub_xen_reg_t grub_relocator_xen_remapper_map; +extern grub_xen_reg_t grub_relocator_xen_mfn_list; +extern struct grub_relocator_xen_paging_area + grub_relocator_xen_paging_areas[XEN_MAX_MAPPINGS]; +extern grub_xen_reg_t grub_relocator_xen_remap_continue; +#ifdef __i386__ +extern grub_xen_reg_t grub_relocator_xen_mmu_op_addr; +extern grub_xen_reg_t grub_relocator_xen_paging_areas_addr; +extern grub_xen_reg_t grub_relocator_xen_remapper_map_high; +#endif +extern mmuext_op_t grub_relocator_xen_mmu_op[3]; + +#define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start) + +grub_err_t +grub_relocator_xen_boot (struct grub_relocator *rel, + struct grub_relocator_xen_state state, + grub_uint64_t remapper_pfn, + grub_addr_t remapper_virt, + grub_uint64_t trampoline_pfn, + grub_addr_t trampoline_virt) +{ + grub_err_t err; + void *relst; + int i; + grub_relocator_chunk_t ch, ch_tramp; + grub_xen_mfn_t *mfn_list = + (grub_xen_mfn_t *) grub_xen_start_page_addr->mfn_list; + + err = grub_relocator_alloc_chunk_addr (rel, &ch, remapper_pfn << 12, + RELOCATOR_SIZEOF (_xen_remap)); + if (err) + return err; + err = grub_relocator_alloc_chunk_addr (rel, &ch_tramp, trampoline_pfn << 12, + RELOCATOR_SIZEOF (_xen)); + if (err) + return err; + + grub_relocator_xen_stack = state.stack; + grub_relocator_xen_start_info = state.start_info; + grub_relocator_xen_entry_point = state.entry_point; + for (i = 0; i < XEN_MAX_MAPPINGS; i++) + { + grub_relocator_xen_paging_areas[i].start = state.paging_start[i]; + grub_relocator_xen_paging_areas[i].size = state.paging_size[i]; + } + grub_relocator_xen_remapper_virt = remapper_virt; + grub_relocator_xen_remapper_virt2 = remapper_virt; + grub_relocator_xen_remap_continue = trampoline_virt; + + grub_relocator_xen_remapper_map = (mfn_list[remapper_pfn] << 12) | 5; +#ifdef __i386__ + grub_relocator_xen_remapper_map_high = (mfn_list[remapper_pfn] >> 20); + grub_relocator_xen_mmu_op_addr = (char *) &grub_relocator_xen_mmu_op + - (char *) &grub_relocator_xen_remap_start + remapper_virt; + grub_relocator_xen_paging_areas_addr = + (char *) &grub_relocator_xen_paging_areas + - (char *) &grub_relocator_xen_remap_start + remapper_virt; +#endif + + grub_relocator_xen_mfn_list = state.mfn_list; + + grub_memset (grub_relocator_xen_mmu_op, 0, + sizeof (grub_relocator_xen_mmu_op)); +#ifdef __i386__ + grub_relocator_xen_mmu_op[0].cmd = MMUEXT_PIN_L3_TABLE; +#else + grub_relocator_xen_mmu_op[0].cmd = MMUEXT_PIN_L4_TABLE; +#endif + grub_relocator_xen_mmu_op[0].arg1.mfn = mfn_list[state.paging_start[0]]; + grub_relocator_xen_mmu_op[1].cmd = MMUEXT_NEW_BASEPTR; + grub_relocator_xen_mmu_op[1].arg1.mfn = mfn_list[state.paging_start[0]]; + grub_relocator_xen_mmu_op[2].cmd = MMUEXT_UNPIN_TABLE; + grub_relocator_xen_mmu_op[2].arg1.mfn = + mfn_list[grub_xen_start_page_addr->pt_base >> 12]; + + grub_memmove (get_virtual_current_address (ch), + &grub_relocator_xen_remap_start, + RELOCATOR_SIZEOF (_xen_remap)); + grub_memmove (get_virtual_current_address (ch_tramp), + &grub_relocator_xen_start, RELOCATOR_SIZEOF (_xen)); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + &relst, NULL); + if (err) + return err; + + ((void (*)(void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/xzembed/xz.h b/grub-core/lib/xzembed/xz.h new file mode 100644 index 0000000..f7b32d8 --- /dev/null +++ b/grub-core/lib/xzembed/xz.h @@ -0,0 +1,188 @@ +/* xz.h - XZ decompressor */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#ifndef XZ_H +#define XZ_H + +#include <config.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#include <grub/misc.h> + +#ifndef GRUB_POSIX_BOOL_DEFINED +typedef enum { false = 0, true = 1 } bool; +#endif + +/** + * enum xz_ret - Return codes + * @XZ_OK: Everything is OK so far. More input or more output + * space is required to continue. + * @XZ_STREAM_END: Operation finished successfully. + * @XZ_MEMLIMIT_ERROR: Not enough memory was preallocated at decoder + * initialization time. + * @XZ_FORMAT_ERROR: File format was not recognized (wrong magic bytes). + * @XZ_OPTIONS_ERROR: This implementation doesn't support the requested + * compression options. In the decoder this means that + * the header CRC32 matches, but the header itself + * specifies something that we don't support. + * @XZ_DATA_ERROR: Compressed data is corrupt. + * @XZ_BUF_ERROR: Cannot make any progress. Details are slightly + * different between multi-call and single-call mode; + * more information below. + * + * In multi-call mode, XZ_BUF_ERROR is returned when two consecutive calls + * to XZ code cannot consume any input and cannot produce any new output. + * This happens when there is no new input available, or the output buffer + * is full while at least one output byte is still pending. Assuming your + * code is not buggy, you can get this error only when decoding a compressed + * stream that is truncated or otherwise corrupt. + * + * In single-call mode, XZ_BUF_ERROR is returned only when the output buffer + * is too small, or the compressed input is corrupt in a way that makes the + * decoder produce more output than the caller expected. When it is + * (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR + * is used instead of XZ_BUF_ERROR. + */ +enum xz_ret { + XZ_OK, + XZ_STREAM_END, + XZ_MEMLIMIT_ERROR, + XZ_FORMAT_ERROR, + XZ_OPTIONS_ERROR, + XZ_DATA_ERROR, + XZ_BUF_ERROR +}; + +/** + * struct xz_buf - Passing input and output buffers to XZ code + * @in: Beginning of the input buffer. This may be NULL if and only + * if in_pos is equal to in_size. + * @in_pos: Current position in the input buffer. This must not exceed + * in_size. + * @in_size: Size of the input buffer + * @out: Beginning of the output buffer. This may be NULL if and only + * if out_pos is equal to out_size. + * @out_pos: Current position in the output buffer. This must not exceed + * out_size. + * @out_size: Size of the output buffer + * + * Only the contents of the output buffer from out[out_pos] onward, and + * the variables in_pos and out_pos are modified by the XZ code. + */ +struct xz_buf { + const uint8_t *in; + size_t in_pos; + size_t in_size; + + uint8_t *out; + size_t out_pos; + size_t out_size; +}; + +/** + * struct xz_dec - Opaque type to hold the XZ decoder state + */ +struct xz_dec; + +/** + * xz_dec_init() - Allocate and initialize a XZ decoder state + * @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for + * multi-call decoding, or special value of zero to indicate + * single-call decoding mode. + * + * If dict_max > 0, the decoder is initialized to work in multi-call mode. + * dict_max number of bytes of memory is preallocated for the LZMA2 + * dictionary. This way there is no risk that xz_dec_run() could run out + * of memory, since xz_dec_run() will never allocate any memory. Instead, + * if the preallocated dictionary is too small for decoding the given input + * stream, xz_dec_run() will return XZ_MEMLIMIT_ERROR. Thus, it is important + * to know what kind of data will be decoded to avoid allocating excessive + * amount of memory for the dictionary. + * + * LZMA2 dictionary is always 2^n bytes or 2^n + 2^(n-1) bytes (the latter + * sizes are less common in practice). In the kernel, dictionary sizes of + * 64 KiB, 128 KiB, 256 KiB, 512 KiB, and 1 MiB are probably the only + * reasonable values. + * + * If dict_max == 0, the decoder is initialized to work in single-call mode. + * In single-call mode, xz_dec_run() decodes the whole stream at once. The + * caller must provide enough output space or the decoding will fail. The + * output space is used as the dictionary buffer, which is why there is + * no need to allocate the dictionary as part of the decoder's internal + * state. + * + * Because the output buffer is used as the workspace, streams encoded using + * a big dictionary are not a problem in single-call. It is enough that the + * output buffer is is big enough to hold the actual uncompressed data; it + * can be smaller than the dictionary size stored in the stream headers. + * + * On success, xz_dec_init() returns a pointer to struct xz_dec, which is + * ready to be used with xz_dec_run(). On error, xz_dec_init() returns NULL. + */ +struct xz_dec * xz_dec_init(uint32_t dict_max); + +/** + * xz_dec_run() - Run the XZ decoder + * @s: Decoder state allocated using xz_dec_init() + * @b: Input and output buffers + * + * In multi-call mode, this function may return any of the values listed in + * enum xz_ret. + * + * In single-call mode, this function never returns XZ_OK. If an error occurs + * in single-call mode (return value is not XZ_STREAM_END), b->in_pos and + * b->out_pos are not modified, and the contents of the output buffer from + * b->out[b->out_pos] onward are undefined. + * + * NOTE: In single-call mode, the contents of the output buffer are undefined + * also after XZ_BUF_ERROR. This is because with some filter chains, there + * may be a second pass over the output buffer, and this pass cannot be + * properly done if the output buffer is truncated. Thus, you cannot give + * the single-call decoder a too small buffer and then expect to get that + * amount valid data from the beginning of the stream. You must use the + * multi-call decoder if you don't want to uncompress the whole stream. + */ +enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b); + +/** + * xz_dec_reset() - Reset an already allocated decoder state + * @s: Decoder state allocated using xz_dec_init() + * + * This function can be used to reset the multi-call decoder state without + * freeing and reallocating memory with xz_dec_end() and xz_dec_init(). + * + * In single-call mode, xz_dec_reset() is always called in the beginning of + * xz_dec_run(). Thus, explicit call to xz_dec_reset() is useful only in + * multi-call mode. + */ +void xz_dec_reset(struct xz_dec *s); + +/** + * xz_dec_end() - Free the memory allocated for the decoder state + * @s: Decoder state allocated using xz_dec_init(). If s is NULL, + * this function does nothing. + */ +void xz_dec_end(struct xz_dec *s); + +#endif diff --git a/grub-core/lib/xzembed/xz_config.h b/grub-core/lib/xzembed/xz_config.h new file mode 100644 index 0000000..24d570f --- /dev/null +++ b/grub-core/lib/xzembed/xz_config.h @@ -0,0 +1,152 @@ +/* xz_config.h - Private includes and definitions for userspace use */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#ifndef XZ_CONFIG_H +#define XZ_CONFIG_H + +/* Enable BCJ filter decoders. */ + +#ifndef GRUB_EMBED_DECOMPRESSOR + +#define XZ_DEC_X86 +#define XZ_DEC_POWERPC +#define XZ_DEC_IA64 +#define XZ_DEC_ARM +#define XZ_DEC_ARMTHUMB +#define XZ_DEC_SPARC + +#else + +#if defined(__i386__) || defined(__x86_64__) + #define XZ_DEC_X86 +#endif + +#ifdef __powerpc__ + #define XZ_DEC_POWERPC +#endif + +#ifdef __ia64__ + #define XZ_DEC_IA64 +#endif + +#ifdef __arm__ + #define XZ_DEC_ARM +#endif + +#ifdef __arm__ + #define XZ_DEC_ARMTHUMB +#endif + +#ifdef __sparc__ + #define XZ_DEC_SPARC +#endif +#endif + +#include "xz.h" +#include <stdlib.h> + +#define kmalloc(size, flags) malloc(size) +#define kfree(ptr) free(ptr) +#define vmalloc(size) malloc(size) +#define vfree(ptr) free(ptr) + +#define memeq(a, b, size) (memcmp(a, b, size) == 0) +#define memzero(buf, size) memset(buf, 0, size) + +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define min_t(type, x, y) min(x, y) + +/* + * Some functions have been marked with __always_inline to keep the + * performance reasonable even when the compiler is optimizing for + * small code size. You may be able to save a few bytes by #defining + * __always_inline to plain inline, but don't complain if the code + * becomes slow. + * + * NOTE: System headers on GNU/Linux may #define this macro already, + * so if you want to change it, it you need to #undef it first. + */ +#ifndef __always_inline +# ifdef __GNUC__ +# define __always_inline \ + inline __attribute__((__always_inline__)) +# else +# define __always_inline inline +# endif +#endif + +/* + * Some functions are marked to never be inlined to reduce stack usage. + * If you don't care about stack usage, you may want to modify this so + * that noinline_for_stack is #defined to be empty even when using GCC. + * Doing so may save a few bytes in binary size. + */ +#ifndef noinline_for_stack +# ifdef __GNUC__ +# define noinline_for_stack __attribute__((__noinline__)) +# else +# define noinline_for_stack +# endif +#endif + +/* Inline functions to access unaligned unsigned 32-bit integers */ +static inline uint32_t get_unaligned_le32(const uint8_t *buf) +{ + return (uint32_t)buf[0] + | ((uint32_t)buf[1] << 8) + | ((uint32_t)buf[2] << 16) + | ((uint32_t)buf[3] << 24); +} + +static inline uint32_t get_unaligned_be32(const uint8_t *buf) +{ + return (uint32_t)(buf[0] << 24) + | ((uint32_t)buf[1] << 16) + | ((uint32_t)buf[2] << 8) + | (uint32_t)buf[3]; +} + +static inline void put_unaligned_le32(uint32_t val, uint8_t *buf) +{ + buf[0] = (uint8_t)val; + buf[1] = (uint8_t)(val >> 8); + buf[2] = (uint8_t)(val >> 16); + buf[3] = (uint8_t)(val >> 24); +} + +static inline void put_unaligned_be32(uint32_t val, uint8_t *buf) +{ + buf[0] = (uint8_t)(val >> 24); + buf[1] = (uint8_t)(val >> 16); + buf[2] = (uint8_t)(val >> 8); + buf[3] = (uint8_t)val; +} + +/* + * Use get_unaligned_le32() also for aligned access for simplicity. On + * little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr)) + * could save a few bytes in code size. + */ +#define get_le32 get_unaligned_le32 + +#endif diff --git a/grub-core/lib/xzembed/xz_dec_bcj.c b/grub-core/lib/xzembed/xz_dec_bcj.c new file mode 100644 index 0000000..bf6b586 --- /dev/null +++ b/grub-core/lib/xzembed/xz_dec_bcj.c @@ -0,0 +1,578 @@ +/* xz_dec_bcj.c - Branch/Call/Jump (BCJ) filter decoders */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#include "xz_private.h" + +struct xz_dec_bcj { + /* Type of the BCJ filter being used */ + enum { + BCJ_X86 = 4, /* x86 or x86-64 */ + BCJ_POWERPC = 5, /* Big endian only */ + BCJ_IA64 = 6, /* Big or little endian */ + BCJ_ARM = 7, /* Little endian only */ + BCJ_ARMTHUMB = 8, /* Little endian only */ + BCJ_SPARC = 9 /* Big or little endian */ + } type; + + /* + * Return value of the next filter in the chain. We need to preserve + * this information across calls, because we must not call the next + * filter anymore once it has returned XZ_STREAM_END. + */ + enum xz_ret ret; + + /* True if we are operating in single-call mode. */ + bool single_call; + + /* + * Absolute position relative to the beginning of the uncompressed + * data (in a single .xz Block). We care only about the lowest 32 + * bits so this doesn't need to be uint64_t even with big files. + */ + uint32_t pos; + + /* x86 filter state */ + uint32_t x86_prev_mask; + + /* Temporary space to hold the variables from struct xz_buf */ + uint8_t *out; + size_t out_pos; + size_t out_size; + + struct { + /* Amount of already filtered data in the beginning of buf */ + size_t filtered; + + /* Total amount of data currently stored in buf */ + size_t size; + + /* + * Buffer to hold a mix of filtered and unfiltered data. This + * needs to be big enough to hold Alignment + 2 * Look-ahead: + * + * Type Alignment Look-ahead + * x86 1 4 + * PowerPC 4 0 + * IA-64 16 0 + * ARM 4 0 + * ARM-Thumb 2 2 + * SPARC 4 0 + */ + uint8_t buf[16]; + } temp; +}; + +#ifdef XZ_DEC_X86 +/* + * This is macro used to test the most significant byte of a memory address + * in an x86 instruction. + */ +#define bcj_x86_test_msbyte(b) ((b) == 0x00 || (b) == 0xFF) + +static noinline_for_stack size_t bcj_x86( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + static const bool mask_to_allowed_status[8] + = { true, true, true, false, true, false, false, false }; + + static const uint8_t mask_to_bit_num[8] = { 0, 1, 2, 2, 3, 3, 3, 3 }; + + size_t i; + size_t prev_pos = (size_t)-1; + uint32_t prev_mask = s->x86_prev_mask; + uint32_t src; + uint32_t dest; + uint32_t j; + uint8_t b; + + if (size <= 4) + return 0; + + size -= 4; + for (i = 0; i < size; ++i) { + if ((buf[i] & 0xFE) != 0xE8) + continue; + + prev_pos = i - prev_pos; + if (prev_pos > 3) { + prev_mask = 0; + } else { + prev_mask = (prev_mask << (prev_pos - 1)) & 7; + if (prev_mask != 0) { + b = buf[i + 4 - mask_to_bit_num[prev_mask]]; + if (!mask_to_allowed_status[prev_mask] + || bcj_x86_test_msbyte(b)) { + prev_pos = i; + prev_mask = (prev_mask << 1) | 1; + continue; + } + } + } + + prev_pos = i; + + if (bcj_x86_test_msbyte(buf[i + 4])) { + src = get_unaligned_le32(buf + i + 1); + while (true) { + dest = src - (s->pos + (uint32_t)i + 5); + if (prev_mask == 0) + break; + + j = mask_to_bit_num[prev_mask] * 8; + b = (uint8_t)(dest >> (24 - j)); + if (!bcj_x86_test_msbyte(b)) + break; + + src = dest ^ (((uint32_t)1 << (32 - j)) - 1); + } + + dest &= 0x01FFFFFF; + dest |= (uint32_t)0 - (dest & 0x01000000); + put_unaligned_le32(dest, buf + i + 1); + i += 4; + } else { + prev_mask = (prev_mask << 1) | 1; + } + } + + prev_pos = i - prev_pos; + s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1); + return i; +} +#endif + +#ifdef XZ_DEC_POWERPC +static noinline_for_stack size_t bcj_powerpc( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + size_t i; + uint32_t instr; + + for (i = 0; i + 3 < size; i += 4) { + instr = get_unaligned_be32(buf + i); + if ((instr & 0xFC000003) == 0x48000001) { + instr &= 0x03FFFFFC; + instr -= s->pos + (uint32_t)i; + instr &= 0x03FFFFFC; + instr |= 0x48000001; + put_unaligned_be32(instr, buf + i); + } + } + + return i; +} +#endif + +#ifdef XZ_DEC_IA64 +static noinline_for_stack size_t bcj_ia64( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + static const uint8_t branch_table[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 6, 6, 0, 0, 7, 7, + 4, 4, 0, 0, 4, 4, 0, 0 + }; + + /* + * The local variables take a little bit stack space, but it's less + * than what LZMA2 decoder takes, so it doesn't make sense to reduce + * stack usage here without doing that for the LZMA2 decoder too. + */ + + /* Loop counters */ + size_t i; + size_t j; + + /* Instruction slot (0, 1, or 2) in the 128-bit instruction word */ + uint32_t slot; + + /* Bitwise offset of the instruction indicated by slot */ + uint32_t bit_pos; + + /* bit_pos split into byte and bit parts */ + uint32_t byte_pos; + uint32_t bit_res; + + /* Address part of an instruction */ + uint32_t addr; + + /* Mask used to detect which instructions to convert */ + uint32_t mask; + + /* 41-bit instruction stored somewhere in the lowest 48 bits */ + uint64_t instr; + + /* Instruction normalized with bit_res for easier manipulation */ + uint64_t norm; + + for (i = 0; i + 16 <= size; i += 16) { + mask = branch_table[buf[i] & 0x1F]; + for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) { + if (((mask >> slot) & 1) == 0) + continue; + + byte_pos = bit_pos >> 3; + bit_res = bit_pos & 7; + instr = 0; + for (j = 0; j < 6; ++j) + instr |= (uint64_t)(buf[i + j + byte_pos]) + << (8 * j); + + norm = instr >> bit_res; + + if (((norm >> 37) & 0x0F) == 0x05 + && ((norm >> 9) & 0x07) == 0) { + addr = (norm >> 13) & 0x0FFFFF; + addr |= ((uint32_t)(norm >> 36) & 1) << 20; + addr <<= 4; + addr -= s->pos + (uint32_t)i; + addr >>= 4; + + norm &= ~((uint64_t)0x8FFFFF << 13); + norm |= (uint64_t)(addr & 0x0FFFFF) << 13; + norm |= (uint64_t)(addr & 0x100000) + << (36 - 20); + + instr &= (1 << bit_res) - 1; + instr |= norm << bit_res; + + for (j = 0; j < 6; j++) + buf[i + j + byte_pos] + = (uint8_t)(instr >> (8 * j)); + } + } + } + + return i; +} +#endif + +#ifdef XZ_DEC_ARM +static noinline_for_stack size_t bcj_arm( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + size_t i; + uint32_t addr; + + for (i = 0; i + 4 <= size; i += 4) { + if (buf[i + 3] == 0xEB) { + addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8) + | ((uint32_t)buf[i + 2] << 16); + addr <<= 2; + addr -= s->pos + (uint32_t)i + 8; + addr >>= 2; + buf[i] = (uint8_t)addr; + buf[i + 1] = (uint8_t)(addr >> 8); + buf[i + 2] = (uint8_t)(addr >> 16); + } + } + + return i; +} +#endif + +#ifdef XZ_DEC_ARMTHUMB +static noinline_for_stack size_t bcj_armthumb( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + size_t i; + uint32_t addr; + + for (i = 0; i + 4 <= size; i += 2) { + if ((buf[i + 1] & 0xF8) == 0xF0 + && (buf[i + 3] & 0xF8) == 0xF8) { + addr = (((uint32_t)buf[i + 1] & 0x07) << 19) + | ((uint32_t)buf[i] << 11) + | (((uint32_t)buf[i + 3] & 0x07) << 8) + | (uint32_t)buf[i + 2]; + addr <<= 1; + addr -= s->pos + (uint32_t)i + 4; + addr >>= 1; + buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07)); + buf[i] = (uint8_t)(addr >> 11); + buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07)); + buf[i + 2] = (uint8_t)addr; + i += 2; + } + } + + return i; +} +#endif + +#ifdef XZ_DEC_SPARC +static noinline_for_stack size_t bcj_sparc( + struct xz_dec_bcj *s, uint8_t *buf, size_t size) +{ + size_t i; + uint32_t instr; + + for (i = 0; i + 4 <= size; i += 4) { + instr = get_unaligned_be32(buf + i); + if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) { + instr <<= 2; + instr -= s->pos + (uint32_t)i; + instr >>= 2; + instr = ((uint32_t)0x40000000 - (instr & 0x400000)) + | 0x40000000 | (instr & 0x3FFFFF); + put_unaligned_be32(instr, buf + i); + } + } + + return i; +} +#endif + +/* + * Apply the selected BCJ filter. Update *pos and s->pos to match the amount + * of data that got filtered. + * + * NOTE: This is implemented as a switch statement to avoid using function + * pointers, which could be problematic in the kernel boot code, which must + * avoid pointers to static data (at least on x86). + */ +static void bcj_apply(struct xz_dec_bcj *s, + uint8_t *buf, size_t *pos, size_t size) +{ + size_t filtered; + + buf += *pos; + size -= *pos; + + switch (s->type) { +#ifdef XZ_DEC_X86 + case BCJ_X86: + filtered = bcj_x86(s, buf, size); + break; +#endif +#ifdef XZ_DEC_POWERPC + case BCJ_POWERPC: + filtered = bcj_powerpc(s, buf, size); + break; +#endif +#ifdef XZ_DEC_IA64 + case BCJ_IA64: + filtered = bcj_ia64(s, buf, size); + break; +#endif +#ifdef XZ_DEC_ARM + case BCJ_ARM: + filtered = bcj_arm(s, buf, size); + break; +#endif +#ifdef XZ_DEC_ARMTHUMB + case BCJ_ARMTHUMB: + filtered = bcj_armthumb(s, buf, size); + break; +#endif +#ifdef XZ_DEC_SPARC + case BCJ_SPARC: + filtered = bcj_sparc(s, buf, size); + break; +#endif + default: + /* Never reached but silence compiler warnings. */ + filtered = 0; + break; + } + + *pos += filtered; + s->pos += filtered; +} + +/* + * Flush pending filtered data from temp to the output buffer. + * Move the remaining mixture of possibly filtered and unfiltered + * data to the beginning of temp. + */ +static void bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b) +{ + size_t copy_size; + + copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos); + memcpy(b->out + b->out_pos, s->temp.buf, copy_size); + b->out_pos += copy_size; + + s->temp.filtered -= copy_size; + s->temp.size -= copy_size; + memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size); +} + +/* + * The BCJ filter functions are primitive in sense that they process the + * data in chunks of 1-16 bytes. To hide this issue, this function does + * some buffering. + */ +enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, + struct xz_dec_lzma2 *lzma2, struct xz_buf *b) +{ + size_t out_start; + + /* + * Flush pending already filtered data to the output buffer. Return + * immediatelly if we couldn't flush everything, or if the next + * filter in the chain had already returned XZ_STREAM_END. + */ + if (s->temp.filtered > 0) { + bcj_flush(s, b); + if (s->temp.filtered > 0) + return XZ_OK; + + if (s->ret == XZ_STREAM_END) + return XZ_STREAM_END; + } + + /* + * If we have more output space than what is currently pending in + * temp, copy the unfiltered data from temp to the output buffer + * and try to fill the output buffer by decoding more data from the + * next filter in the chain. Apply the BCJ filter on the new data + * in the output buffer. If everything cannot be filtered, copy it + * to temp and rewind the output buffer position accordingly. + */ + if (s->temp.size < b->out_size - b->out_pos) { + out_start = b->out_pos; + memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); + b->out_pos += s->temp.size; + + s->ret = xz_dec_lzma2_run(lzma2, b); + if (s->ret != XZ_STREAM_END + && (s->ret != XZ_OK || s->single_call)) + return s->ret; + + bcj_apply(s, b->out, &out_start, b->out_pos); + + /* + * As an exception, if the next filter returned XZ_STREAM_END, + * we can do that too, since the last few bytes that remain + * unfiltered are meant to remain unfiltered. + */ + if (s->ret == XZ_STREAM_END) + return XZ_STREAM_END; + + s->temp.size = b->out_pos - out_start; + b->out_pos -= s->temp.size; + memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); + } + + /* + * If we have unfiltered data in temp, try to fill by decoding more + * data from the next filter. Apply the BCJ filter on temp. Then we + * hopefully can fill the actual output buffer by copying filtered + * data from temp. A mix of filtered and unfiltered data may be left + * in temp; it will be taken care on the next call to this function. + */ + if (s->temp.size > 0) { + /* Make b->out{,_pos,_size} temporarily point to s->temp. */ + s->out = b->out; + s->out_pos = b->out_pos; + s->out_size = b->out_size; + b->out = s->temp.buf; + b->out_pos = s->temp.size; + b->out_size = sizeof(s->temp.buf); + + s->ret = xz_dec_lzma2_run(lzma2, b); + + s->temp.size = b->out_pos; + b->out = s->out; + b->out_pos = s->out_pos; + b->out_size = s->out_size; + + if (s->ret != XZ_OK && s->ret != XZ_STREAM_END) + return s->ret; + + bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size); + + /* + * If the next filter returned XZ_STREAM_END, we mark that + * everything is filtered, since the last unfiltered bytes + * of the stream are meant to be left as is. + */ + if (s->ret == XZ_STREAM_END) + s->temp.filtered = s->temp.size; + + bcj_flush(s, b); + if (s->temp.filtered > 0) + return XZ_OK; + } + + return s->ret; +} + +#ifdef GRUB_EMBED_DECOMPRESSOR +struct xz_dec_bcj bcj; +#endif + +struct xz_dec_bcj * xz_dec_bcj_create(bool single_call) +{ + struct xz_dec_bcj *s; +#ifdef GRUB_EMBED_DECOMPRESSOR + s = &bcj; +#else + s = kmalloc(sizeof(*s), GFP_KERNEL); +#endif + if (s != NULL) + s->single_call = single_call; + + return s; +} + +enum xz_ret xz_dec_bcj_reset( + struct xz_dec_bcj *s, uint8_t id) +{ + switch (id) { +#ifdef XZ_DEC_X86 + case BCJ_X86: +#endif +#ifdef XZ_DEC_POWERPC + case BCJ_POWERPC: +#endif +#ifdef XZ_DEC_IA64 + case BCJ_IA64: +#endif +#ifdef XZ_DEC_ARM + case BCJ_ARM: +#endif +#ifdef XZ_DEC_ARMTHUMB + case BCJ_ARMTHUMB: +#endif +#ifdef XZ_DEC_SPARC + case BCJ_SPARC: +#endif + break; + + default: + /* Unsupported Filter ID */ + return XZ_OPTIONS_ERROR; + } + + s->type = id; + s->ret = XZ_OK; + s->pos = 0; + s->x86_prev_mask = 0; + s->temp.filtered = 0; + s->temp.size = 0; + + return XZ_OK; +} diff --git a/grub-core/lib/xzembed/xz_dec_lzma2.c b/grub-core/lib/xzembed/xz_dec_lzma2.c new file mode 100644 index 0000000..af7b770 --- /dev/null +++ b/grub-core/lib/xzembed/xz_dec_lzma2.c @@ -0,0 +1,1188 @@ +/* xz_dec_lzma2.c - LZMA2 decoder */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#include "xz_private.h" +#include "xz_lzma2.h" + +#pragma GCC diagnostic warning "-Wattributes" + +/* + * Range decoder initialization eats the first five bytes of each LZMA chunk. + */ +#define RC_INIT_BYTES 5 + +/* + * Minimum number of usable input buffer to safely decode one LZMA symbol. + * The worst case is that we decode 22 bits using probabilities and 26 + * direct bits. This may decode at maximum of 20 bytes of input. However, + * lzma_main() does an extra normalization before returning, thus we + * need to put 21 here. + */ +#define LZMA_IN_REQUIRED 21 + +/* + * Dictionary (history buffer) + * + * These are always true: + * start <= pos <= full <= end + * pos <= limit <= end + * + * In multi-call mode, also these are true: + * end == size + * size <= allocated + * + * Most of these variables are size_t to support single-call mode, + * in which the dictionary variables address the actual output + * buffer directly. + */ +struct dictionary { + /* Beginning of the history buffer */ + uint8_t *buf; + + /* Old position in buf (before decoding more data) */ + size_t start; + + /* Position in buf */ + size_t pos; + + /* + * How full dictionary is. This is used to detect corrupt input that + * would read beyond the beginning of the uncompressed stream. + */ + size_t full; + + /* Write limit; we don't write to buf[limit] or later bytes. */ + size_t limit; + + /* + * End of the dictionary buffer. In multi-call mode, this is + * the same as the dictionary size. In single-call mode, this + * indicates the size of the output buffer. + */ + size_t end; + + /* + * Size of the dictionary as specified in Block Header. This is used + * together with "full" to detect corrupt input that would make us + * read beyond the beginning of the uncompressed stream. + */ + uint32_t size; + + /* + * Amount of memory allocated for the dictionary. A special + * value of zero indicates that we are in single-call mode, + * where the output buffer works as the dictionary. + */ + uint32_t allocated; +}; + +/* Range decoder */ +struct rc_dec { + uint32_t range; + uint32_t code; + + /* + * Number of initializing bytes remaining to be read + * by rc_read_init(). + */ + uint32_t init_bytes_left; + + /* + * Buffer from which we read our input. It can be either + * temp.buf or the caller-provided input buffer. + */ + const uint8_t *in; + size_t in_pos; + size_t in_limit; +}; + +/* Probabilities for a length decoder. */ +struct lzma_len_dec { + /* Probability of match length being at least 10 */ + uint16_t choice; + + /* Probability of match length being at least 18 */ + uint16_t choice2; + + /* Probabilities for match lengths 2-9 */ + uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS]; + + /* Probabilities for match lengths 10-17 */ + uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS]; + + /* Probabilities for match lengths 18-273 */ + uint16_t high[LEN_HIGH_SYMBOLS]; +}; + +struct lzma_dec { + /* + * LZMA properties or related bit masks (number of literal + * context bits, a mask dervied from the number of literal + * position bits, and a mask dervied from the number + * position bits) + */ + uint32_t lc; + uint32_t literal_pos_mask; /* (1 << lp) - 1 */ + uint32_t pos_mask; /* (1 << pb) - 1 */ + + /* Types of the most recently seen LZMA symbols */ + enum lzma_state state; + + /* Distances of latest four matches */ + uint32_t rep0; + uint32_t rep1; + uint32_t rep2; + uint32_t rep3; + + /* + * Length of a match. This is updated so that dict_repeat can + * be called again to finish repeating the whole match. + */ + uint32_t len; + + /* If 1, it's a match. Otherwise it's a single 8-bit literal. */ + uint16_t is_match[STATES][POS_STATES_MAX]; + + /* If 1, it's a repeated match. The distance is one of rep0 .. rep3. */ + uint16_t is_rep[STATES]; + + /* + * If 0, distance of a repeated match is rep0. + * Otherwise check is_rep1. + */ + uint16_t is_rep0[STATES]; + + /* + * If 0, distance of a repeated match is rep1. + * Otherwise check is_rep2. + */ + uint16_t is_rep1[STATES]; + + /* If 0, distance of a repeated match is rep2. Otherwise it is rep3. */ + uint16_t is_rep2[STATES]; + + /* + * If 1, the repeated match has length of one byte. Otherwise + * the length is decoded from rep_len_decoder. + */ + uint16_t is_rep0_long[STATES][POS_STATES_MAX]; + + /* + * Probability tree for the highest two bits of the match + * distance. There is a separate probability tree for match + * lengths of 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273]. + */ + uint16_t dist_slot[DIST_STATES][DIST_SLOTS]; + + /* + * Probility trees for additional bits for match distance + * when the distance is in the range [4, 127]. + */ + uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END]; + + /* + * Probability tree for the lowest four bits of a match + * distance that is equal to or greater than 128. + */ + uint16_t dist_align[ALIGN_SIZE]; + + /* Length of a normal match */ + struct lzma_len_dec match_len_dec; + + /* Length of a repeated match */ + struct lzma_len_dec rep_len_dec; + + /* Probabilities of literals */ + uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE]; +}; + +struct xz_dec_lzma2 { + /* LZMA2 */ + struct { + /* Position in xz_dec_lzma2_run(). */ + enum lzma2_seq { + SEQ_CONTROL, + SEQ_UNCOMPRESSED_1, + SEQ_UNCOMPRESSED_2, + SEQ_COMPRESSED_0, + SEQ_COMPRESSED_1, + SEQ_PROPERTIES, + SEQ_LZMA_PREPARE, + SEQ_LZMA_RUN, + SEQ_COPY + } sequence; + + /* + * Next position after decoding the compressed size of + * the chunk. + */ + enum lzma2_seq next_sequence; + + /* Uncompressed size of LZMA chunk (2 MiB at maximum) */ + uint32_t uncompressed; + + /* + * Compressed size of LZMA chunk or compressed/uncompressed + * size of uncompressed chunk (64 KiB at maximum) + */ + uint32_t compressed; + + /* + * True if dictionary reset is needed. This is false before + * the first chunk (LZMA or uncompressed). + */ + bool need_dict_reset; + + /* + * True if new LZMA properties are needed. This is false + * before the first LZMA chunk. + */ + bool need_props; + } lzma2; + + /* + * Temporary buffer which holds small number of input bytes between + * decoder calls. See lzma2_lzma() for details. + */ + struct { + uint32_t size; + uint8_t buf[3 * LZMA_IN_REQUIRED]; + } temp; + + struct dictionary dict; + struct rc_dec rc; + struct lzma_dec lzma; +}; + +/************** + * Dictionary * + **************/ + +/* + * Reset the dictionary state. When in single-call mode, set up the beginning + * of the dictionary to point to the actual output buffer. + */ +static void dict_reset(struct dictionary *dict, struct xz_buf *b) +{ + if (dict->allocated == 0) { + dict->buf = b->out + b->out_pos; + dict->end = b->out_size - b->out_pos; + } + dict->start = 0; + dict->pos = 0; + dict->limit = 0; + dict->full = 0; +} + +/* Set dictionary write limit */ +static void dict_limit(struct dictionary *dict, size_t out_max) +{ + if (dict->end - dict->pos <= out_max) + dict->limit = dict->end; + else + dict->limit = dict->pos + out_max; +} + +/* Return true if at least one byte can be written into the dictionary. */ +static inline bool dict_has_space(const struct dictionary *dict) +{ + return dict->pos < dict->limit; +} + +/* + * Get a byte from the dictionary at the given distance. The distance is + * assumed to valid, or as a special case, zero when the dictionary is + * still empty. This special case is needed for single-call decoding to + * avoid writing a '\0' to the end of the destination buffer. + */ +static inline uint32_t dict_get( + const struct dictionary *dict, uint32_t dist) +{ + size_t offset = dict->pos - dist - 1; + + if (dist >= dict->pos) + offset += dict->end; + + return dict->full > 0 ? dict->buf[offset] : 0; +} + +/* + * Put one byte into the dictionary. It is assumed that there is space for it. + */ +static inline void dict_put(struct dictionary *dict, uint8_t b) +{ + dict->buf[dict->pos++] = b; + + if (dict->full < dict->pos) + dict->full = dict->pos; +} + +/* + * Repeat given number of bytes from the given distance. If the distance is + * invalid, false is returned. On success, true is returned and *len is + * updated to indicate how many bytes were left to be repeated. + */ +static bool dict_repeat( + struct dictionary *dict, uint32_t *len, uint32_t dist) +{ + size_t back; + uint32_t left; + + if (dist >= dict->full || dist >= dict->size) + return false; + + left = min_t(size_t, dict->limit - dict->pos, *len); + *len -= left; + + back = dict->pos - dist - 1; + if (dist >= dict->pos) + back += dict->end; + + do { + dict->buf[dict->pos++] = dict->buf[back++]; + if (back == dict->end) + back = 0; + } while (--left > 0); + + if (dict->full < dict->pos) + dict->full = dict->pos; + + return true; +} + +/* Copy uncompressed data as is from input to dictionary and output buffers. */ +static void dict_uncompressed( + struct dictionary *dict, struct xz_buf *b, uint32_t *left) +{ + size_t copy_size; + + while (*left > 0 && b->in_pos < b->in_size + && b->out_pos < b->out_size) { + copy_size = min(b->in_size - b->in_pos, + b->out_size - b->out_pos); + if (copy_size > dict->end - dict->pos) + copy_size = dict->end - dict->pos; + if (copy_size > *left) + copy_size = *left; + + *left -= copy_size; + + memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size); + dict->pos += copy_size; + + if (dict->full < dict->pos) + dict->full = dict->pos; + + if (dict->allocated != 0) { + if (dict->pos == dict->end) + dict->pos = 0; + + memcpy(b->out + b->out_pos, b->in + b->in_pos, + copy_size); + } + + dict->start = dict->pos; + + b->out_pos += copy_size; + b->in_pos += copy_size; + + } +} + +/* + * Flush pending data from dictionary to b->out. It is assumed that there is + * enough space in b->out. This is guaranteed because caller uses dict_limit() + * before decoding data into the dictionary. + */ +static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) +{ + size_t copy_size = dict->pos - dict->start; + + if (dict->allocated != 0) { + if (dict->pos == dict->end) + dict->pos = 0; + + memcpy(b->out + b->out_pos, dict->buf + dict->start, + copy_size); + } + + dict->start = dict->pos; + b->out_pos += copy_size; + return copy_size; +} + +/***************** + * Range decoder * + *****************/ + +/* Reset the range decoder. */ +static void rc_reset(struct rc_dec *rc) +{ + rc->range = (uint32_t)-1; + rc->code = 0; + rc->init_bytes_left = RC_INIT_BYTES; +} + +/* + * Read the first five initial bytes into rc->code if they haven't been + * read already. (Yes, the first byte gets completely ignored.) + */ +static bool rc_read_init(struct rc_dec *rc, struct xz_buf *b) +{ + while (rc->init_bytes_left > 0) { + if (b->in_pos == b->in_size) + return false; + + rc->code = (rc->code << 8) + b->in[b->in_pos++]; + --rc->init_bytes_left; + } + + return true; +} + +/* Return true if there may not be enough input for the next decoding loop. */ +static inline bool rc_limit_exceeded(const struct rc_dec *rc) +{ + return rc->in_pos > rc->in_limit; +} + +/* + * Return true if it is possible (from point of view of range decoder) that + * we have reached the end of the LZMA chunk. + */ +static inline bool rc_is_finished(const struct rc_dec *rc) +{ + return rc->code == 0; +} + +/* Read the next input byte if needed. */ +static __always_inline void rc_normalize(struct rc_dec *rc) +{ + if (rc->range < RC_TOP_VALUE) { + rc->range <<= RC_SHIFT_BITS; + rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++]; + } +} + +/* + * Decode one bit. In some versions, this function has been splitted in three + * functions so that the compiler is supposed to be able to more easily avoid + * an extra branch. In this particular version of the LZMA decoder, this + * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3 + * on x86). Using a non-splitted version results in nicer looking code too. + * + * NOTE: This must return an int. Do not make it return a bool or the speed + * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care, + * and it generates 10-20 % faster code than GCC 3.x from this file anyway.) + */ +static __always_inline int rc_bit(struct rc_dec *rc, uint16_t *prob) +{ + uint32_t bound; + int bit; + + rc_normalize(rc); + bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob; + if (rc->code < bound) { + rc->range = bound; + *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS; + bit = 0; + } else { + rc->range -= bound; + rc->code -= bound; + *prob -= *prob >> RC_MOVE_BITS; + bit = 1; + } + + return bit; +} + +/* Decode a bittree starting from the most significant bit. */ +static __always_inline uint32_t rc_bittree( + struct rc_dec *rc, uint16_t *probs, uint32_t limit) +{ + uint32_t symbol = 1; + + do { + if (rc_bit(rc, &probs[symbol])) + symbol = (symbol << 1) + 1; + else + symbol <<= 1; + } while (symbol < limit); + + return symbol; +} + +/* Decode a bittree starting from the least significant bit. */ +static __always_inline void rc_bittree_reverse(struct rc_dec *rc, + uint16_t *probs, uint32_t *dest, uint32_t limit) +{ + uint32_t symbol = 1; + uint32_t i = 0; + + do { + if (rc_bit(rc, &probs[symbol])) { + symbol = (symbol << 1) + 1; + *dest += 1 << i; + } else { + symbol <<= 1; + } + } while (++i < limit); +} + +/* Decode direct bits (fixed fifty-fifty probability) */ +static inline void rc_direct( + struct rc_dec *rc, uint32_t *dest, uint32_t limit) +{ + uint32_t mask; + + do { + rc_normalize(rc); + rc->range >>= 1; + rc->code -= rc->range; + mask = (uint32_t)0 - (rc->code >> 31); + rc->code += rc->range & mask; + *dest = (*dest << 1) + (mask + 1); + } while (--limit > 0); +} + +/******** + * LZMA * + ********/ + +/* Get pointer to literal coder probability array. */ +static uint16_t * lzma_literal_probs(struct xz_dec_lzma2 *s) +{ + uint32_t prev_byte = dict_get(&s->dict, 0); + uint32_t low = prev_byte >> (8 - s->lzma.lc); + uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc; + return s->lzma.literal[low + high]; +} + +/* Decode a literal (one 8-bit byte) */ +static void lzma_literal(struct xz_dec_lzma2 *s) +{ + uint16_t *probs; + uint32_t symbol; + uint32_t match_byte; + uint32_t match_bit; + uint32_t offset; + uint32_t i; + + probs = lzma_literal_probs(s); + + if (lzma_state_is_literal(s->lzma.state)) { + symbol = rc_bittree(&s->rc, probs, 0x100); + } else { + symbol = 1; + match_byte = dict_get(&s->dict, s->lzma.rep0) << 1; + offset = 0x100; + + do { + match_bit = match_byte & offset; + match_byte <<= 1; + i = offset + match_bit + symbol; + + if (rc_bit(&s->rc, &probs[i])) { + symbol = (symbol << 1) + 1; + offset &= match_bit; + } else { + symbol <<= 1; + offset &= ~match_bit; + } + } while (symbol < 0x100); + } + + dict_put(&s->dict, (uint8_t)symbol); + lzma_state_literal(&s->lzma.state); +} + +/* Decode the length of the match into s->lzma.len. */ +static void lzma_len(struct xz_dec_lzma2 *s, struct lzma_len_dec *l, + uint32_t pos_state) +{ + uint16_t *probs; + uint32_t limit; + + if (!rc_bit(&s->rc, &l->choice)) { + probs = l->low[pos_state]; + limit = LEN_LOW_SYMBOLS; + s->lzma.len = MATCH_LEN_MIN; + } else { + if (!rc_bit(&s->rc, &l->choice2)) { + probs = l->mid[pos_state]; + limit = LEN_MID_SYMBOLS; + s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; + } else { + probs = l->high; + limit = LEN_HIGH_SYMBOLS; + s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS + + LEN_MID_SYMBOLS; + } + } + + s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit; +} + +/* Decode a match. The distance will be stored in s->lzma.rep0. */ +static void lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state) +{ + uint16_t *probs; + uint32_t dist_slot; + uint32_t limit; + + lzma_state_match(&s->lzma.state); + + s->lzma.rep3 = s->lzma.rep2; + s->lzma.rep2 = s->lzma.rep1; + s->lzma.rep1 = s->lzma.rep0; + + lzma_len(s, &s->lzma.match_len_dec, pos_state); + + probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)]; + dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS; + + if (dist_slot < DIST_MODEL_START) { + s->lzma.rep0 = dist_slot; + } else { + limit = (dist_slot >> 1) - 1; + s->lzma.rep0 = 2 + (dist_slot & 1); + + if (dist_slot < DIST_MODEL_END) { + s->lzma.rep0 <<= limit; + probs = s->lzma.dist_special + s->lzma.rep0 + - dist_slot - 1; + rc_bittree_reverse(&s->rc, probs, + &s->lzma.rep0, limit); + } else { + rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS); + s->lzma.rep0 <<= ALIGN_BITS; + rc_bittree_reverse(&s->rc, s->lzma.dist_align, + &s->lzma.rep0, ALIGN_BITS); + } + } +} + +/* + * Decode a repeated match. The distance is one of the four most recently + * seen matches. The distance will be stored in s->lzma.rep0. + */ +static void lzma_rep_match(struct xz_dec_lzma2 *s, uint32_t pos_state) +{ + uint32_t tmp; + + if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state])) { + if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[ + s->lzma.state][pos_state])) { + lzma_state_short_rep(&s->lzma.state); + s->lzma.len = 1; + return; + } + } else { + if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state])) { + tmp = s->lzma.rep1; + } else { + if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state])) { + tmp = s->lzma.rep2; + } else { + tmp = s->lzma.rep3; + s->lzma.rep3 = s->lzma.rep2; + } + + s->lzma.rep2 = s->lzma.rep1; + } + + s->lzma.rep1 = s->lzma.rep0; + s->lzma.rep0 = tmp; + } + + lzma_state_long_rep(&s->lzma.state); + lzma_len(s, &s->lzma.rep_len_dec, pos_state); +} + +/* LZMA decoder core */ +static bool lzma_main(struct xz_dec_lzma2 *s) +{ + uint32_t pos_state; + + /* + * If the dictionary was reached during the previous call, try to + * finish the possibly pending repeat in the dictionary. + */ + if (dict_has_space(&s->dict) && s->lzma.len > 0) + dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0); + + /* + * Decode more LZMA symbols. One iteration may consume up to + * LZMA_IN_REQUIRED - 1 bytes. + */ + while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc)) { + pos_state = s->dict.pos & s->lzma.pos_mask; + + if (!rc_bit(&s->rc, &s->lzma.is_match[ + s->lzma.state][pos_state])) { + lzma_literal(s); + } else { + if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state])) + lzma_rep_match(s, pos_state); + else + lzma_match(s, pos_state); + + if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0)) + return false; + } + } + + /* + * Having the range decoder always normalized when we are outside + * this function makes it easier to correctly handle end of the chunk. + */ + rc_normalize(&s->rc); + + return true; +} + +/* + * Reset the LZMA decoder and range decoder state. Dictionary is nore reset + * here, because LZMA state may be reset without resetting the dictionary. + */ +static void lzma_reset(struct xz_dec_lzma2 *s) +{ + uint16_t *probs; + size_t i; + + s->lzma.state = STATE_LIT_LIT; + s->lzma.rep0 = 0; + s->lzma.rep1 = 0; + s->lzma.rep2 = 0; + s->lzma.rep3 = 0; + + /* + * All probabilities are initialized to the same value. This hack + * makes the code smaller by avoiding a separate loop for each + * probability array. + * + * This could be optimized so that only that part of literal + * probabilities that are actually required. In the common case + * we would write 12 KiB less. + */ + probs = s->lzma.is_match[0]; + for (i = 0; i < PROBS_TOTAL; ++i) + probs[i] = RC_BIT_MODEL_TOTAL / 2; + + rc_reset(&s->rc); +} + +/* + * Decode and validate LZMA properties (lc/lp/pb) and calculate the bit masks + * from the decoded lp and pb values. On success, the LZMA decoder state is + * reset and true is returned. + */ +static bool lzma_props(struct xz_dec_lzma2 *s, uint8_t props) +{ + if (props > (4 * 5 + 4) * 9 + 8) + return false; + + s->lzma.pos_mask = 0; + while (props >= 9 * 5) { + props -= 9 * 5; + ++s->lzma.pos_mask; + } + + s->lzma.pos_mask = (1 << s->lzma.pos_mask) - 1; + + s->lzma.literal_pos_mask = 0; + while (props >= 9) { + props -= 9; + ++s->lzma.literal_pos_mask; + } + + s->lzma.lc = props; + + if (s->lzma.lc + s->lzma.literal_pos_mask > 4) + return false; + + s->lzma.literal_pos_mask = (1 << s->lzma.literal_pos_mask) - 1; + + lzma_reset(s); + + return true; +} + +/********* + * LZMA2 * + *********/ + +/* + * The LZMA decoder assumes that if the input limit (s->rc.in_limit) hasn't + * been exceeded, it is safe to read up to LZMA_IN_REQUIRED bytes. This + * wrapper function takes care of making the LZMA decoder's assumption safe. + * + * As long as there is plenty of input left to be decoded in the current LZMA + * chunk, we decode directly from the caller-supplied input buffer until + * there's LZMA_IN_REQUIRED bytes left. Those remaining bytes are copied into + * s->temp.buf, which (hopefully) gets filled on the next call to this + * function. We decode a few bytes from the temporary buffer so that we can + * continue decoding from the caller-supplied input buffer again. + */ +static bool lzma2_lzma(struct xz_dec_lzma2 *s, struct xz_buf *b) +{ + size_t in_avail; + uint32_t tmp; + + in_avail = b->in_size - b->in_pos; + if (s->temp.size > 0 || s->lzma2.compressed == 0) { + tmp = 2 * LZMA_IN_REQUIRED - s->temp.size; + if (tmp > s->lzma2.compressed - s->temp.size) + tmp = s->lzma2.compressed - s->temp.size; + if (tmp > in_avail) + tmp = in_avail; + + memcpy(s->temp.buf + s->temp.size, b->in + b->in_pos, tmp); + + if (s->temp.size + tmp == s->lzma2.compressed) { + memzero(s->temp.buf + s->temp.size + tmp, + sizeof(s->temp.buf) + - s->temp.size - tmp); + s->rc.in_limit = s->temp.size + tmp; + } else if (s->temp.size + tmp < LZMA_IN_REQUIRED) { + s->temp.size += tmp; + b->in_pos += tmp; + return true; + } else { + s->rc.in_limit = s->temp.size + tmp - LZMA_IN_REQUIRED; + } + + s->rc.in = s->temp.buf; + s->rc.in_pos = 0; + + if (!lzma_main(s) || s->rc.in_pos > s->temp.size + tmp) + return false; + + s->lzma2.compressed -= s->rc.in_pos; + + if (s->rc.in_pos < s->temp.size) { + s->temp.size -= s->rc.in_pos; + memmove(s->temp.buf, s->temp.buf + s->rc.in_pos, + s->temp.size); + return true; + } + + b->in_pos += s->rc.in_pos - s->temp.size; + s->temp.size = 0; + } + + in_avail = b->in_size - b->in_pos; + if (in_avail >= LZMA_IN_REQUIRED) { + s->rc.in = b->in; + s->rc.in_pos = b->in_pos; + + if (in_avail >= s->lzma2.compressed + LZMA_IN_REQUIRED) + s->rc.in_limit = b->in_pos + s->lzma2.compressed; + else + s->rc.in_limit = b->in_size - LZMA_IN_REQUIRED; + + if (!lzma_main(s)) + return false; + + in_avail = s->rc.in_pos - b->in_pos; + if (in_avail > s->lzma2.compressed) + return false; + + s->lzma2.compressed -= in_avail; + b->in_pos = s->rc.in_pos; + } + + in_avail = b->in_size - b->in_pos; + if (in_avail < LZMA_IN_REQUIRED) { + if (in_avail > s->lzma2.compressed) + in_avail = s->lzma2.compressed; + + memcpy(s->temp.buf, b->in + b->in_pos, in_avail); + s->temp.size = in_avail; + b->in_pos += in_avail; + } + + return true; +} + +/* + * Take care of the LZMA2 control layer, and forward the job of actual LZMA + * decoding or copying of uncompressed chunks to other functions. + */ +enum xz_ret xz_dec_lzma2_run( + struct xz_dec_lzma2 *s, struct xz_buf *b) +{ + uint32_t tmp; + + while (b->in_pos < b->in_size || s->lzma2.sequence == SEQ_LZMA_RUN) { + switch (s->lzma2.sequence) { + case SEQ_CONTROL: + /* + * LZMA2 control byte + * + * Exact values: + * 0x00 End marker + * 0x01 Dictionary reset followed by + * an uncompressed chunk + * 0x02 Uncompressed chunk (no dictionary reset) + * + * Highest three bits (s->control & 0xE0): + * 0xE0 Dictionary reset, new properties and state + * reset, followed by LZMA compressed chunk + * 0xC0 New properties and state reset, followed + * by LZMA compressed chunk (no dictionary + * reset) + * 0xA0 State reset using old properties, + * followed by LZMA compressed chunk (no + * dictionary reset) + * 0x80 LZMA chunk (no dictionary or state reset) + * + * For LZMA compressed chunks, the lowest five bits + * (s->control & 1F) are the highest bits of the + * uncompressed size (bits 16-20). + * + * A new LZMA2 stream must begin with a dictionary + * reset. The first LZMA chunk must set new + * properties and reset the LZMA state. + * + * Values that don't match anything described above + * are invalid and we return XZ_DATA_ERROR. + */ + tmp = b->in[b->in_pos++]; + + if (tmp >= 0xE0 || tmp == 0x01) { + s->lzma2.need_props = true; + s->lzma2.need_dict_reset = false; + dict_reset(&s->dict, b); + } else if (s->lzma2.need_dict_reset) { + return XZ_DATA_ERROR; + } + + if (tmp >= 0x80) { + s->lzma2.uncompressed = (tmp & 0x1F) << 16; + s->lzma2.sequence = SEQ_UNCOMPRESSED_1; + + if (tmp >= 0xC0) { + /* + * When there are new properties, + * state reset is done at + * SEQ_PROPERTIES. + */ + s->lzma2.need_props = false; + s->lzma2.next_sequence + = SEQ_PROPERTIES; + + } else if (s->lzma2.need_props) { + return XZ_DATA_ERROR; + + } else { + s->lzma2.next_sequence + = SEQ_LZMA_PREPARE; + if (tmp >= 0xA0) + lzma_reset(s); + } + } else { + if (tmp == 0x00) + return XZ_STREAM_END; + + if (tmp > 0x02) + return XZ_DATA_ERROR; + + s->lzma2.sequence = SEQ_COMPRESSED_0; + s->lzma2.next_sequence = SEQ_COPY; + } + + break; + + case SEQ_UNCOMPRESSED_1: + s->lzma2.uncompressed + += (uint32_t)b->in[b->in_pos++] << 8; + s->lzma2.sequence = SEQ_UNCOMPRESSED_2; + break; + + case SEQ_UNCOMPRESSED_2: + s->lzma2.uncompressed + += (uint32_t)b->in[b->in_pos++] + 1; + s->lzma2.sequence = SEQ_COMPRESSED_0; + break; + + case SEQ_COMPRESSED_0: + s->lzma2.compressed + = (uint32_t)b->in[b->in_pos++] << 8; + s->lzma2.sequence = SEQ_COMPRESSED_1; + break; + + case SEQ_COMPRESSED_1: + s->lzma2.compressed + += (uint32_t)b->in[b->in_pos++] + 1; + s->lzma2.sequence = s->lzma2.next_sequence; + break; + + case SEQ_PROPERTIES: + if (!lzma_props(s, b->in[b->in_pos++])) + return XZ_DATA_ERROR; + + s->lzma2.sequence = SEQ_LZMA_PREPARE; + + /* Fall through */ + + case SEQ_LZMA_PREPARE: + if (s->lzma2.compressed < RC_INIT_BYTES) + return XZ_DATA_ERROR; + + if (!rc_read_init(&s->rc, b)) + return XZ_OK; + + s->lzma2.compressed -= RC_INIT_BYTES; + s->lzma2.sequence = SEQ_LZMA_RUN; + + /* Fall through */ + + case SEQ_LZMA_RUN: + /* + * Set dictionary limit to indicate how much we want + * to be encoded at maximum. Decode new data into the + * dictionary. Flush the new data from dictionary to + * b->out. Check if we finished decoding this chunk. + * In case the dictionary got full but we didn't fill + * the output buffer yet, we may run this loop + * multiple times without changing s->lzma2.sequence. + */ + dict_limit(&s->dict, min_t(size_t, + b->out_size - b->out_pos, + s->lzma2.uncompressed)); + if (!lzma2_lzma(s, b)) + return XZ_DATA_ERROR; + + s->lzma2.uncompressed -= dict_flush(&s->dict, b); + + if (s->lzma2.uncompressed == 0) { + if (s->lzma2.compressed > 0 || s->lzma.len > 0 + || !rc_is_finished(&s->rc)) + return XZ_DATA_ERROR; + + rc_reset(&s->rc); + s->lzma2.sequence = SEQ_CONTROL; + + } else if (b->out_pos == b->out_size + || (b->in_pos == b->in_size + && s->temp.size + < s->lzma2.compressed)) { + return XZ_OK; + } + + break; + + case SEQ_COPY: + dict_uncompressed(&s->dict, b, &s->lzma2.compressed); + if (s->lzma2.compressed > 0) + return XZ_OK; + + s->lzma2.sequence = SEQ_CONTROL; + break; + } + } + + return XZ_OK; +} + +#ifdef GRUB_EMBED_DECOMPRESSOR +#include <grub/decompressor.h> +static struct xz_dec_lzma2 lzma2; +#endif + +struct xz_dec_lzma2 * xz_dec_lzma2_create(uint32_t dict_max) +{ + struct xz_dec_lzma2 *s; + +#ifndef GRUB_EMBED_DECOMPRESSOR + /* Maximum supported dictionary by this implementation is 3 GiB. */ + if (dict_max > ((uint32_t)3 << 30)) + return NULL; + + s = kmalloc(sizeof(*s), GFP_KERNEL); + if (s == NULL) + return NULL; + + if (dict_max > 0) { + s->dict.buf = vmalloc(dict_max); + if (s->dict.buf == NULL) { + kfree(s); + return NULL; + } + } + +#else + s = &lzma2; + s->dict.buf = grub_decompressor_scratch; +#endif + + s->dict.allocated = dict_max; + + return s; +} + +enum xz_ret xz_dec_lzma2_reset( + struct xz_dec_lzma2 *s, uint8_t props) +{ + /* This limits dictionary size to 3 GiB (39) to keep parsing simpler. */ + if (props > ( min (DICT_BIT_SIZE,39)) ) + return XZ_OPTIONS_ERROR; + + s->dict.size = 2 + (props & 1); + s->dict.size <<= (props >> 1) + 11; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->dict.allocated > 0 && s->dict.allocated < s->dict.size) + { + /* enlarge dictionary buffer */ + uint8_t * newdict = realloc(s->dict.buf,s->dict.size); + + if (! newdict) + return XZ_MEMLIMIT_ERROR; + + s->dict.buf = newdict; + s->dict.allocated = s->dict.size; + } +#endif + s->dict.end = s->dict.size; + + s->lzma.len = 0; + + s->lzma2.sequence = SEQ_CONTROL; + s->lzma2.need_dict_reset = true; + + s->temp.size = 0; + + return XZ_OK; +} + +void xz_dec_lzma2_end(struct xz_dec_lzma2 *s __attribute__ ((unused))) +{ +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->dict.allocated > 0) + vfree(s->dict.buf); + + kfree(s); +#endif +} diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c new file mode 100644 index 0000000..a29751e --- /dev/null +++ b/grub-core/lib/xzembed/xz_dec_stream.c @@ -0,0 +1,1042 @@ +/* xz_dec_stream.c - .xz Stream decoder */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#include "xz_config.h" +#include "xz_private.h" +#include "xz_stream.h" + +#include <grub/crypto.h> + +/* Hash used to validate the Index field */ +struct xz_dec_hash { + vli_type unpadded; + vli_type uncompressed; +#ifndef GRUB_EMBED_DECOMPRESSOR + uint64_t *hash_context; +#endif +}; + +/* Enough for up to 512 bits. */ +#define MAX_HASH_SIZE 64 + +struct xz_dec { + /* Position in dec_main() */ + enum { + SEQ_STREAM_HEADER, + SEQ_BLOCK_START, + SEQ_BLOCK_HEADER, + SEQ_BLOCK_UNCOMPRESS, + SEQ_BLOCK_PADDING, + SEQ_BLOCK_CHECK, + SEQ_INDEX, + SEQ_INDEX_PADDING, + SEQ_INDEX_CRC32, + SEQ_STREAM_FOOTER + } sequence; + + /* Position in variable-length integers and Check fields */ + uint32_t pos; + + /* Variable-length integer decoded by dec_vli() */ + vli_type vli; + + /* Saved in_pos and out_pos */ + size_t in_start; + size_t out_start; + + /* CRC32 value in Block or Index */ +#ifndef GRUB_EMBED_DECOMPRESSOR + uint8_t hash_value[MAX_HASH_SIZE]; /* need for crc32_validate*/ +#endif + int have_hash_value; +#ifndef GRUB_EMBED_DECOMPRESSOR + uint64_t *hash_context; + uint64_t *crc32_context; +#endif + + /* Hash function calculated from uncompressed data */ +#ifndef GRUB_EMBED_DECOMPRESSOR + const gcry_md_spec_t *hash; + const gcry_md_spec_t *crc32; + grub_uint8_t hash_id; +#endif + grub_size_t hash_size; + + /* True if we are operating in single-call mode. */ + bool single_call; + + /* + * True if the next call to xz_dec_run() is allowed to return + * XZ_BUF_ERROR. + */ + bool allow_buf_error; + + /* Information stored in Block Header */ + struct { + /* + * Value stored in the Compressed Size field, or + * VLI_UNKNOWN if Compressed Size is not present. + */ + vli_type compressed; + + /* + * Value stored in the Uncompressed Size field, or + * VLI_UNKNOWN if Uncompressed Size is not present. + */ + vli_type uncompressed; + + /* Size of the Block Header field */ + uint32_t size; + } block_header; + + /* Information collected when decoding Blocks */ + struct { + /* Observed compressed size of the current Block */ + vli_type compressed; + + /* Observed uncompressed size of the current Block */ + vli_type uncompressed; + + /* Number of Blocks decoded so far */ + vli_type count; + + /* + * Hash calculated from the Block sizes. This is used to + * validate the Index field. + */ + struct xz_dec_hash hash; + } block; + + /* Variables needed when verifying the Index field */ + struct { + /* Position in dec_index() */ + enum { + SEQ_INDEX_COUNT, + SEQ_INDEX_UNPADDED, + SEQ_INDEX_UNCOMPRESSED + } sequence; + + /* Size of the Index in bytes */ + vli_type size; + + /* Number of Records (matches block.count in valid files) */ + vli_type count; + + /* + * Hash calculated from the Records (matches block.hash in + * valid files). + */ + struct xz_dec_hash hash; + } index; + + /* + * Temporary buffer needed to hold Stream Header, Block Header, + * and Stream Footer. The Block Header is the biggest (1 KiB) + * so we reserve space according to that. buf[] has to be aligned + * to a multiple of four bytes; the size_t variables before it + * should guarantee this. + */ + struct { + size_t pos; + size_t size; + uint8_t buf[1024]; + } temp; + + struct xz_dec_lzma2 *lzma2; + +#ifdef XZ_DEC_BCJ + struct xz_dec_bcj *bcj; + bool bcj_active; +#endif +}; + +/* + * Fill s->temp by copying data starting from b->in[b->in_pos]. Caller + * must have set s->temp.pos to indicate how much data we are supposed + * to copy into s->temp.buf. Return true once s->temp.pos has reached + * s->temp.size. + */ +static bool fill_temp(struct xz_dec *s, struct xz_buf *b) +{ + size_t copy_size = min_t(size_t, + b->in_size - b->in_pos, s->temp.size - s->temp.pos); + + memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size); + b->in_pos += copy_size; + s->temp.pos += copy_size; + + if (s->temp.pos == s->temp.size) { + s->temp.pos = 0; + return true; + } + + return false; +} + +/* Decode a variable-length integer (little-endian base-128 encoding) */ +static enum xz_ret dec_vli(struct xz_dec *s, + const uint8_t *in, size_t *in_pos, size_t in_size) +{ + uint8_t b; + + if (s->pos == 0) + s->vli = 0; + + while (*in_pos < in_size) { + b = in[*in_pos]; + ++*in_pos; + + s->vli |= (vli_type)(b & 0x7F) << s->pos; + + if ((b & 0x80) == 0) { + /* Don't allow non-minimal encodings. */ + if (b == 0 && s->pos != 0) + return XZ_DATA_ERROR; + + s->pos = 0; + return XZ_STREAM_END; + } + + s->pos += 7; + if (s->pos == 7 * VLI_BYTES_MAX) + return XZ_DATA_ERROR; + } + + return XZ_OK; +} + +/* + * Decode the Compressed Data field from a Block. Update and validate + * the observed compressed and uncompressed sizes of the Block so that + * they don't exceed the values possibly stored in the Block Header + * (validation assumes that no integer overflow occurs, since vli_type + * is normally uint64_t). Update the CRC32 if presence of the CRC32 + * field was indicated in Stream Header. + * + * Once the decoding is finished, validate that the observed sizes match + * the sizes possibly stored in the Block Header. Update the hash and + * Block count, which are later used to validate the Index field. + */ +static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b) +{ + enum xz_ret ret; + + s->in_start = b->in_pos; + s->out_start = b->out_pos; + +#ifdef XZ_DEC_BCJ + if (s->bcj_active) + ret = xz_dec_bcj_run(s->bcj, s->lzma2, b); + else +#endif + ret = xz_dec_lzma2_run(s->lzma2, b); + + s->block.compressed += b->in_pos - s->in_start; + s->block.uncompressed += b->out_pos - s->out_start; + + /* + * There is no need to separately check for VLI_UNKNOWN, since + * the observed sizes are always smaller than VLI_UNKNOWN. + */ + if (s->block.compressed > s->block_header.compressed + || s->block.uncompressed + > s->block_header.uncompressed) + return XZ_DATA_ERROR; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->hash) + s->hash->write(s->hash_context,b->out + s->out_start, + b->out_pos - s->out_start); + if (s->crc32) + s->crc32->write(s->crc32_context,b->out + s->out_start, + b->out_pos - s->out_start); +#endif + + if (ret == XZ_STREAM_END) { + if (s->block_header.compressed != VLI_UNKNOWN + && s->block_header.compressed + != s->block.compressed) + return XZ_DATA_ERROR; + + if (s->block_header.uncompressed != VLI_UNKNOWN + && s->block_header.uncompressed + != s->block.uncompressed) + return XZ_DATA_ERROR; + + s->block.hash.unpadded += s->block_header.size + + s->block.compressed; + s->block.hash.unpadded += s->hash_size; + + s->block.hash.uncompressed += s->block.uncompressed; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->hash) + s->hash->write(s->block.hash.hash_context, + (const uint8_t *)&s->block.hash, + 2 * sizeof(vli_type)); +#endif + + ++s->block.count; + } + + return ret; +} + +/* Update the Index size and the CRC32 value. */ +static void index_update(struct xz_dec *s, const struct xz_buf *b) +{ + size_t in_used = b->in_pos - s->in_start; + s->index.size += in_used; +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->hash) + s->hash->write(s->hash_context,b->in + s->in_start, in_used); + if (s->crc32) + s->crc32->write(s->crc32_context,b->in + s->in_start, in_used); +#endif +} + +/* + * Decode the Number of Records, Unpadded Size, and Uncompressed Size + * fields from the Index field. That is, Index Padding and CRC32 are not + * decoded by this function. + * + * This can return XZ_OK (more input needed), XZ_STREAM_END (everything + * successfully decoded), or XZ_DATA_ERROR (input is corrupt). + */ +static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) +{ + enum xz_ret ret; + + do { + ret = dec_vli(s, b->in, &b->in_pos, b->in_size); + if (ret != XZ_STREAM_END) { + index_update(s, b); + return ret; + } + + switch (s->index.sequence) { + case SEQ_INDEX_COUNT: + s->index.count = s->vli; + + /* + * Validate that the Number of Records field + * indicates the same number of Records as + * there were Blocks in the Stream. + */ + if (s->index.count != s->block.count) + return XZ_DATA_ERROR; + + s->index.sequence = SEQ_INDEX_UNPADDED; + break; + + case SEQ_INDEX_UNPADDED: + s->index.hash.unpadded += s->vli; + s->index.sequence = SEQ_INDEX_UNCOMPRESSED; + break; + + case SEQ_INDEX_UNCOMPRESSED: + s->index.hash.uncompressed += s->vli; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->hash) + s->hash->write(s->index.hash.hash_context, + (const uint8_t *)&s->index.hash, 2 * sizeof(vli_type)); +#endif + + --s->index.count; + s->index.sequence = SEQ_INDEX_UNPADDED; + break; + } + } while (s->index.count > 0); + + return XZ_STREAM_END; +} + +/* + * Validate that the next four input bytes match the value of s->crc32. + * s->pos must be zero when starting to validate the first byte. + */ +static enum xz_ret hash_validate(struct xz_dec *s, struct xz_buf *b, + int crc32) +{ +#ifndef GRUB_EMBED_DECOMPRESSOR + const gcry_md_spec_t *hash = crc32 ? s->crc32 : s->hash; + void *hash_context = crc32 ? s->crc32_context + : s->hash_context; + if(!s->have_hash_value && hash + && sizeof (s->hash_value) >= hash->mdlen) + { + hash->final(hash_context); + grub_memcpy (s->hash_value, hash->read(hash_context), + hash->mdlen); + s->have_hash_value = 1; + if (s->hash_id == 1 || crc32) + { + grub_uint8_t t; + t = s->hash_value[0]; + s->hash_value[0] = s->hash_value[3]; + s->hash_value[3] = t; + t = s->hash_value[1]; + s->hash_value[1] = s->hash_value[2]; + s->hash_value[2] = t; + } + } +#endif + + if (b->in_pos == b->in_size) + return XZ_OK; + + if (!crc32 && s->hash_size == 0) + s->pos += 8; + + while (s->pos < (crc32 ? 32 : s->hash_size * 8)) { + if (b->in_pos == b->in_size) + return XZ_OK; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (hash && s->hash_value[s->pos / 8] != b->in[b->in_pos]) + return XZ_DATA_ERROR; +#endif + b->in_pos++; + + s->pos += 8; + + } + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->hash) + s->hash->init(s->hash_context); + if (s->crc32) + s->crc32->init(s->crc32_context); +#endif + s->have_hash_value = 0; + s->pos = 0; + + return XZ_STREAM_END; +} + +static const struct +{ + const char *name; + grub_size_t size; +} hashes[] = { + [0x01] = { "CRC32", 4}, + [0x04] = { "CRC64", 8}, + [0x0A] = { "SHA256", 32}, +}; + +/* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */ +static enum xz_ret dec_stream_header(struct xz_dec *s) +{ + if (! memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE)) + return XZ_FORMAT_ERROR; + +#ifndef GRUB_EMBED_DECOMPRESSOR + s->crc32 = grub_crypto_lookup_md_by_name ("CRC32"); + + if (s->crc32) + { + uint8_t readhash[4]; + uint8_t computed_hash[4]; + + if(4 != s->crc32->mdlen) + return XZ_DATA_ERROR; + + grub_crypto_hash (s->crc32, computed_hash, + s->temp.buf + HEADER_MAGIC_SIZE, 2); + + readhash[0] = s->temp.buf[HEADER_MAGIC_SIZE + 5]; + readhash[1] = s->temp.buf[HEADER_MAGIC_SIZE + 4]; + readhash[2] = s->temp.buf[HEADER_MAGIC_SIZE + 3]; + readhash[3] = s->temp.buf[HEADER_MAGIC_SIZE + 2]; + + if (grub_memcmp (readhash, computed_hash, + s->crc32->mdlen) != 0) + return XZ_DATA_ERROR; + } +#endif + +#ifndef GRUB_EMBED_DECOMPRESSOR + /* + * Decode the Stream Flags field. + */ + if (s->temp.buf[HEADER_MAGIC_SIZE] != 0 + || s->temp.buf[HEADER_MAGIC_SIZE + 1] >= ARRAY_SIZE (hashes) + || (hashes[s->temp.buf[HEADER_MAGIC_SIZE + 1]].name == 0 + && s->temp.buf[HEADER_MAGIC_SIZE + 1] != 0)) + return XZ_OPTIONS_ERROR; + + s->hash_id = s->temp.buf[HEADER_MAGIC_SIZE + 1]; + + if (s->crc32) + { + s->crc32_context = kmalloc(s->crc32->contextsize, GFP_KERNEL); + if (s->crc32_context == NULL) + return XZ_MEMLIMIT_ERROR; + s->crc32->init(s->crc32_context); + } +#endif + + if (s->temp.buf[HEADER_MAGIC_SIZE + 1]) + { + s->hash_size = hashes[s->temp.buf[HEADER_MAGIC_SIZE + 1]].size; +#ifndef GRUB_EMBED_DECOMPRESSOR + s->hash = grub_crypto_lookup_md_by_name (hashes[s->temp.buf[HEADER_MAGIC_SIZE + 1]].name); + if (s->hash) + { + if (s->hash->mdlen != s->hash_size) + return XZ_OPTIONS_ERROR; + s->hash_context = kmalloc(s->hash->contextsize, GFP_KERNEL); + if (s->hash_context == NULL) + { + kfree(s->crc32_context); + return XZ_MEMLIMIT_ERROR; + } + + s->index.hash.hash_context = kmalloc(s->hash->contextsize, + GFP_KERNEL); + if (s->index.hash.hash_context == NULL) + { + kfree(s->hash_context); + kfree(s->crc32_context); + return XZ_MEMLIMIT_ERROR; + } + + s->block.hash.hash_context = kmalloc(s->hash->contextsize, GFP_KERNEL); + if (s->block.hash.hash_context == NULL) + { + kfree(s->index.hash.hash_context); + kfree(s->hash_context); + kfree(s->crc32_context); + return XZ_MEMLIMIT_ERROR; + } + + s->hash->init(s->hash_context); + s->hash->init(s->index.hash.hash_context); + s->hash->init(s->block.hash.hash_context); + } +#endif + } + else + { +#ifndef GRUB_EMBED_DECOMPRESSOR + s->hash = 0; +#endif + s->hash_size = 0; + } + + s->have_hash_value = 0; + + + return XZ_OK; +} + +/* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */ +static enum xz_ret dec_stream_footer(struct xz_dec *s) +{ + if (! memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE)) + return XZ_DATA_ERROR; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->crc32) + { + uint8_t readhash[4]; + uint8_t computed_hash[4]; + + if (4 != s->crc32->mdlen) + return XZ_DATA_ERROR; + + grub_crypto_hash (s->crc32, computed_hash, + s->temp.buf + 4, 6); + + readhash[0] = s->temp.buf[3]; + readhash[1] = s->temp.buf[2]; + readhash[2] = s->temp.buf[1]; + readhash[3] = s->temp.buf[0]; + + if(grub_memcmp (readhash, computed_hash, + s->crc32->mdlen) != 0) + return XZ_DATA_ERROR; + } +#endif + + + /* + * Validate Backward Size. Note that we never added the size of the + * Index CRC32 field to s->index.size, thus we use s->index.size / 4 + * instead of s->index.size / 4 - 1. + */ + if ((s->index.size >> 2) != get_le32(s->temp.buf + 4)) + return XZ_DATA_ERROR; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->hash_id) + return XZ_DATA_ERROR; +#endif + + /* + * Use XZ_STREAM_END instead of XZ_OK to be more convenient + * for the caller. + */ + return XZ_STREAM_END; +} + +/* Decode the Block Header and initialize the filter chain. */ +static enum xz_ret dec_block_header(struct xz_dec *s) +{ + enum xz_ret ret; + + /* + * Validate the CRC32. We know that the temp buffer is at least + * eight bytes so this is safe. + */ + s->temp.size -= 4; +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->crc32) + { + uint8_t readhash[4], computed_hash[4]; + + if(4 != s->crc32->mdlen) + return XZ_DATA_ERROR; + + grub_crypto_hash (s->crc32, computed_hash, + s->temp.buf, s->temp.size); + + readhash[3] = s->temp.buf[s->temp.size]; + readhash[2] = s->temp.buf[s->temp.size + 1]; + readhash[1] = s->temp.buf[s->temp.size + 2]; + readhash[0] = s->temp.buf[s->temp.size + 3]; + + if(grub_memcmp (readhash, computed_hash, + s->crc32->mdlen) != 0) + return XZ_DATA_ERROR; + } +#endif + + s->temp.pos = 2; + + /* + * Catch unsupported Block Flags. We support only one or two filters + * in the chain, so we catch that with the same test. + */ +#ifdef XZ_DEC_BCJ + if (s->temp.buf[1] & 0x3E) +#else + if (s->temp.buf[1] & 0x3F) +#endif + return XZ_OPTIONS_ERROR; + + /* Compressed Size */ + if (s->temp.buf[1] & 0x40) { + if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) + != XZ_STREAM_END) + return XZ_DATA_ERROR; + + s->block_header.compressed = s->vli; + } else { + s->block_header.compressed = VLI_UNKNOWN; + } + + /* Uncompressed Size */ + if (s->temp.buf[1] & 0x80) { + if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) + != XZ_STREAM_END) + return XZ_DATA_ERROR; + + s->block_header.uncompressed = s->vli; + } else { + s->block_header.uncompressed = VLI_UNKNOWN; + } + +#ifdef XZ_DEC_BCJ + /* If there are two filters, the first one must be a BCJ filter. */ + s->bcj_active = s->temp.buf[1] & 0x01; + if (s->bcj_active) { + if (s->temp.size - s->temp.pos < 2) + return XZ_OPTIONS_ERROR; + + ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]); + if (ret != XZ_OK) + return ret; + + /* + * We don't support custom start offset, + * so Size of Properties must be zero. + */ + if (s->temp.buf[s->temp.pos++] != 0x00) + return XZ_OPTIONS_ERROR; + } +#endif + + /* Valid Filter Flags always take at least two bytes. */ + if (s->temp.size - s->temp.pos < 2) + return XZ_DATA_ERROR; + + /* Filter ID = LZMA2 */ + if (s->temp.buf[s->temp.pos++] != 0x21) + return XZ_OPTIONS_ERROR; + + /* Size of Properties = 1-byte Filter Properties */ + if (s->temp.buf[s->temp.pos++] != 0x01) + return XZ_OPTIONS_ERROR; + + /* Filter Properties contains LZMA2 dictionary size. */ + if (s->temp.size - s->temp.pos < 1) + return XZ_DATA_ERROR; + + ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]); + if (ret != XZ_OK) + return ret; + + /* The rest must be Header Padding. */ + while (s->temp.pos < s->temp.size) + if (s->temp.buf[s->temp.pos++] != 0x00) + return XZ_OPTIONS_ERROR; + + s->temp.pos = 0; + s->block.compressed = 0; + s->block.uncompressed = 0; + + return XZ_OK; +} + +static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) +{ + enum xz_ret ret; + + /* + * Store the start position for the case when we are in the middle + * of the Index field. + */ + s->in_start = b->in_pos; + + while (true) { + switch (s->sequence) { + case SEQ_STREAM_HEADER: + /* + * Stream Header is copied to s->temp, and then + * decoded from there. This way if the caller + * gives us only little input at a time, we can + * still keep the Stream Header decoding code + * simple. Similar approach is used in many places + * in this file. + */ + if (!fill_temp(s, b)) + return XZ_OK; + + ret = dec_stream_header(s); + if (ret != XZ_OK) + return ret; + + s->sequence = SEQ_BLOCK_START; + + /* FALLTHROUGH */ + case SEQ_BLOCK_START: + /* We need one byte of input to continue. */ + if (b->in_pos == b->in_size) + return XZ_OK; + + /* See if this is the beginning of the Index field. */ + if (b->in[b->in_pos] == 0) { + s->in_start = b->in_pos++; + s->sequence = SEQ_INDEX; + break; + } + + /* + * Calculate the size of the Block Header and + * prepare to decode it. + */ + s->block_header.size + = ((uint32_t)b->in[b->in_pos] + 1) * 4; + + s->temp.size = s->block_header.size; + s->temp.pos = 0; + s->sequence = SEQ_BLOCK_HEADER; + + /* FALLTHROUGH */ + case SEQ_BLOCK_HEADER: + if (!fill_temp(s, b)) + return XZ_OK; + + ret = dec_block_header(s); + if (ret != XZ_OK) + return ret; + + s->sequence = SEQ_BLOCK_UNCOMPRESS; + + /* FALLTHROUGH */ + case SEQ_BLOCK_UNCOMPRESS: + ret = dec_block(s, b); + if (ret != XZ_STREAM_END) + return ret; + + s->sequence = SEQ_BLOCK_PADDING; + + case SEQ_BLOCK_PADDING: + /* + * Size of Compressed Data + Block Padding + * must be a multiple of four. We don't need + * s->block.compressed for anything else + * anymore, so we use it here to test the size + * of the Block Padding field. + */ + while (s->block.compressed & 3) { + if (b->in_pos == b->in_size) + return XZ_OK; + + if (b->in[b->in_pos++] != 0) + return XZ_DATA_ERROR; + + ++s->block.compressed; + } + + s->sequence = SEQ_BLOCK_CHECK; + + /* FALLTHROUGH */ + case SEQ_BLOCK_CHECK: + ret = hash_validate(s, b, 0); + if (ret != XZ_STREAM_END) + return ret; + + s->sequence = SEQ_BLOCK_START; + break; + + case SEQ_INDEX: + ret = dec_index(s, b); + if (ret != XZ_STREAM_END) + return ret; + + s->sequence = SEQ_INDEX_PADDING; + + case SEQ_INDEX_PADDING: + while ((s->index.size + (b->in_pos - s->in_start)) + & 3) { + if (b->in_pos == b->in_size) { + index_update(s, b); + return XZ_OK; + } + + if (b->in[b->in_pos++] != 0) + return XZ_DATA_ERROR; + } + + /* Finish the CRC32 value and Index size. */ + index_update(s, b); + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->hash) + { + /* Compare the hashes to validate the Index field. */ + s->hash->final(s->block.hash.hash_context); + s->hash->final(s->index.hash.hash_context); + + if (s->block.hash.unpadded != s->index.hash.unpadded + || s->block.hash.uncompressed != s->index.hash.uncompressed + || grub_memcmp (s->hash->read(s->block.hash.hash_context), + s->hash->read(s->index.hash.hash_context), + s->hash->mdlen) != 0) + return XZ_DATA_ERROR; + } +#endif + + s->sequence = SEQ_INDEX_CRC32; + + /* FALLTHROUGH */ + case SEQ_INDEX_CRC32: + ret = hash_validate(s, b, 1); + if (ret != XZ_STREAM_END) + return ret; + + s->temp.size = STREAM_HEADER_SIZE; + s->sequence = SEQ_STREAM_FOOTER; + + /* FALLTHROUGH */ + case SEQ_STREAM_FOOTER: + if (!fill_temp(s, b)) + return XZ_OK; + + return dec_stream_footer(s); + } + } + + /* Never reached */ +} + +/* + * xz_dec_run() is a wrapper for dec_main() to handle some special cases in + * multi-call and single-call decoding. + * + * In multi-call mode, we must return XZ_BUF_ERROR when it seems clear that we + * are not going to make any progress anymore. This is to prevent the caller + * from calling us infinitely when the input file is truncated or otherwise + * corrupt. Since zlib-style API allows that the caller fills the input buffer + * only when the decoder doesn't produce any new output, we have to be careful + * to avoid returning XZ_BUF_ERROR too easily: XZ_BUF_ERROR is returned only + * after the second consecutive call to xz_dec_run() that makes no progress. + * + * In single-call mode, if we couldn't decode everything and no error + * occurred, either the input is truncated or the output buffer is too small. + * Since we know that the last input byte never produces any output, we know + * that if all the input was consumed and decoding wasn't finished, the file + * must be corrupt. Otherwise the output buffer has to be too small or the + * file is corrupt in a way that decoding it produces too big output. + * + * If single-call decoding fails, we reset b->in_pos and b->out_pos back to + * their original values. This is because with some filter chains there won't + * be any valid uncompressed data in the output buffer unless the decoding + * actually succeeds (that's the price to pay of using the output buffer as + * the workspace). + */ +enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b) +{ + size_t in_start; + size_t out_start; + enum xz_ret ret; + + if (s->single_call) + xz_dec_reset(s); + + in_start = b->in_pos; + out_start = b->out_pos; + ret = dec_main(s, b); + + if (s->single_call) { + if (ret == XZ_OK) + ret = b->in_pos == b->in_size + ? XZ_DATA_ERROR : XZ_BUF_ERROR; + + if (ret != XZ_STREAM_END) { + b->in_pos = in_start; + b->out_pos = out_start; + } + + } else if (ret == XZ_OK && in_start == b->in_pos + && out_start == b->out_pos) { + if (s->allow_buf_error) + ret = XZ_BUF_ERROR; + + s->allow_buf_error = true; + } else { + s->allow_buf_error = false; + } + + return ret; +} + +#ifdef GRUB_EMBED_DECOMPRESSOR +struct xz_dec decoder; +#endif + +struct xz_dec * xz_dec_init(uint32_t dict_max) +{ + struct xz_dec *s; +#ifdef GRUB_EMBED_DECOMPRESSOR + s = &decoder; +#else + s = kmalloc(sizeof(*s), GFP_KERNEL); + if (s == NULL) + return NULL; +#endif + + memset (s, 0, sizeof (*s)); + + s->single_call = dict_max == 0; + +#ifdef XZ_DEC_BCJ + s->bcj = xz_dec_bcj_create(s->single_call); + if (s->bcj == NULL) + goto error_bcj; +#endif + + s->lzma2 = xz_dec_lzma2_create(dict_max); + if (s->lzma2 == NULL) + goto error_lzma2; + + xz_dec_reset(s); + return s; + +error_lzma2: +#ifdef XZ_DEC_BCJ + xz_dec_bcj_end(s->bcj); +error_bcj: +#endif +#ifndef GRUB_EMBED_DECOMPRESSOR + kfree(s); +#endif + return NULL; +} + +void xz_dec_reset(struct xz_dec *s) +{ + s->sequence = SEQ_STREAM_HEADER; + s->allow_buf_error = false; + s->pos = 0; + + { +#ifndef GRUB_EMBED_DECOMPRESSOR + uint64_t *t; + t = s->block.hash.hash_context; +#endif + memzero(&s->block, sizeof(s->block)); +#ifndef GRUB_EMBED_DECOMPRESSOR + s->block.hash.hash_context = t; + t = s->index.hash.hash_context; +#endif + memzero(&s->index, sizeof(s->index)); +#ifndef GRUB_EMBED_DECOMPRESSOR + s->index.hash.hash_context = t; +#endif + } + s->temp.pos = 0; + s->temp.size = STREAM_HEADER_SIZE; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->hash) + { + s->hash->init(s->hash_context); + s->hash->init(s->index.hash.hash_context); + s->hash->init(s->block.hash.hash_context); + } +#endif + s->have_hash_value = 0; +} + +void xz_dec_end(struct xz_dec *s) +{ + if (s != NULL) { + xz_dec_lzma2_end(s->lzma2); +#ifndef GRUB_EMBED_DECOMPRESSOR + kfree(s->index.hash.hash_context); + kfree(s->block.hash.hash_context); + kfree(s->hash_context); + kfree(s->crc32_context); +#endif +#ifdef XZ_DEC_BCJ + xz_dec_bcj_end(s->bcj); +#endif +#ifndef GRUB_EMBED_DECOMPRESSOR + kfree(s); +#endif + } +} diff --git a/grub-core/lib/xzembed/xz_lzma2.h b/grub-core/lib/xzembed/xz_lzma2.h new file mode 100644 index 0000000..15e553d --- /dev/null +++ b/grub-core/lib/xzembed/xz_lzma2.h @@ -0,0 +1,236 @@ +/* xz_lzma2.h - LZMA2 definitions */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#ifndef XZ_LZMA2_H +#define XZ_LZMA2_H + +/* dictionary size hard limit + * actual size limit is calculated as shown in 5.3.1 + * http://tukaani.org/xz/xz-file-format.txt + * + * if bits > 39 dictionary_size = UINT32_MAX + * else + * dictionary_size = 2 | (bits & 1); + * dictionary_size <<= bits / 2 + 11; + * + * i.e. + * 0 - 4 KiB + * 6 - 32 KiB + * 30 - 128MiB + * 39 - 3072 MiB + * 40 - 4096 MiB - 1 B + * note: implementation supports 39 at maximum + */ +#define DICT_BIT_SIZE 30 + +/* Range coder constants */ +#define RC_SHIFT_BITS 8 +#define RC_TOP_BITS 24 +#define RC_TOP_VALUE (1 << RC_TOP_BITS) +#define RC_BIT_MODEL_TOTAL_BITS 11 +#define RC_BIT_MODEL_TOTAL (1 << RC_BIT_MODEL_TOTAL_BITS) +#define RC_MOVE_BITS 5 + +/* + * Maximum number of position states. A position state is the lowest pb + * number of bits of the current uncompressed offset. In some places there + * are different sets of probabilities for different position states. + */ +#define POS_STATES_MAX (1 << 4) + +/* + * This enum is used to track which LZMA symbols have occurred most recently + * and in which order. This information is used to predict the next symbol. + * + * Symbols: + * - Literal: One 8-bit byte + * - Match: Repeat a chunk of data at some distance + * - Long repeat: Multi-byte match at a recently seen distance + * - Short repeat: One-byte repeat at a recently seen distance + * + * The symbol names are in from STATE_oldest_older_previous. REP means + * either short or long repeated match, and NONLIT means any non-literal. + */ +enum lzma_state { + STATE_LIT_LIT, + STATE_MATCH_LIT_LIT, + STATE_REP_LIT_LIT, + STATE_SHORTREP_LIT_LIT, + STATE_MATCH_LIT, + STATE_REP_LIT, + STATE_SHORTREP_LIT, + STATE_LIT_MATCH, + STATE_LIT_LONGREP, + STATE_LIT_SHORTREP, + STATE_NONLIT_MATCH, + STATE_NONLIT_REP +}; + +/* Total number of states */ +#define STATES 12 + +/* The lowest 7 states indicate that the previous state was a literal. */ +#define LIT_STATES 7 + +/* Indicate that the latest symbol was a literal. */ +static inline void lzma_state_literal(enum lzma_state *state) +{ + if (*state <= STATE_SHORTREP_LIT_LIT) + *state = STATE_LIT_LIT; + else if (*state <= STATE_LIT_SHORTREP) + *state -= 3; + else + *state -= 6; +} + +/* Indicate that the latest symbol was a match. */ +static inline void lzma_state_match(enum lzma_state *state) +{ + *state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH; +} + +/* Indicate that the latest state was a long repeated match. */ +static inline void lzma_state_long_rep(enum lzma_state *state) +{ + *state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP; +} + +/* Indicate that the latest symbol was a short match. */ +static inline void lzma_state_short_rep(enum lzma_state *state) +{ + *state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP; +} + +/* Test if the previous symbol was a literal. */ +static inline bool lzma_state_is_literal(enum lzma_state state) +{ + return state < LIT_STATES; +} + +/* Each literal coder is divided in three sections: + * - 0x001-0x0FF: Without match byte + * - 0x101-0x1FF: With match byte; match bit is 0 + * - 0x201-0x2FF: With match byte; match bit is 1 + * + * Match byte is used when the previous LZMA symbol was something else than + * a literal (that is, it was some kind of match). + */ +#define LITERAL_CODER_SIZE 0x300 + +/* Maximum number of literal coders */ +#define LITERAL_CODERS_MAX (1 << 4) + +/* Minimum length of a match is two bytes. */ +#define MATCH_LEN_MIN 2 + +/* Match length is encoded with 4, 5, or 10 bits. + * + * Length Bits + * 2-9 4 = Choice=0 + 3 bits + * 10-17 5 = Choice=1 + Choice2=0 + 3 bits + * 18-273 10 = Choice=1 + Choice2=1 + 8 bits + */ +#define LEN_LOW_BITS 3 +#define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS) +#define LEN_MID_BITS 3 +#define LEN_MID_SYMBOLS (1 << LEN_MID_BITS) +#define LEN_HIGH_BITS 8 +#define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS) +#define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS) + +/* + * Maximum length of a match is 273 which is a result of the encoding + * described above. + */ +#define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1) + +/* + * Different sets of probabilities are used for match distances that have + * very short match length: Lengths of 2, 3, and 4 bytes have a separate + * set of probabilities for each length. The matches with longer length + * use a shared set of probabilities. + */ +#define DIST_STATES 4 + +/* + * Get the index of the appropriate probability array for decoding + * the distance slot. + */ +static inline uint32_t lzma_get_dist_state(uint32_t len) +{ + return len < DIST_STATES + MATCH_LEN_MIN + ? len - MATCH_LEN_MIN : DIST_STATES - 1; +} + +/* + * The highest two bits of a 32-bit match distance are encoded using six bits. + * This six-bit value is called a distance slot. This way encoding a 32-bit + * value takes 6-36 bits, larger values taking more bits. + */ +#define DIST_SLOT_BITS 6 +#define DIST_SLOTS (1 << DIST_SLOT_BITS) + +/* Match distances up to 127 are fully encoded using probabilities. Since + * the highest two bits (distance slot) are always encoded using six bits, + * the distances 0-3 don't need any additional bits to encode, since the + * distance slot itself is the same as the actual distance. DIST_MODEL_START + * indicates the first distance slot where at least one additional bit is + * needed. + */ +#define DIST_MODEL_START 4 + +/* + * Match distances greater than 127 are encoded in three pieces: + * - distance slot: the highest two bits + * - direct bits: 2-26 bits below the highest two bits + * - alignment bits: four lowest bits + * + * Direct bits don't use any probabilities. + * + * The distance slot value of 14 is for distances 128-191. + */ +#define DIST_MODEL_END 14 + +/* Distance slots that indicate a distance <= 127. */ +#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2) +#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS) + +/* + * For match distances greater than 127, only the highest two bits and the + * lowest four bits (alignment) is encoded using probabilities. + */ +#define ALIGN_BITS 4 +#define ALIGN_SIZE (1 << ALIGN_BITS) +#define ALIGN_MASK (ALIGN_SIZE - 1) + +/* Total number of all probability variables */ +#define PROBS_TOTAL (1846 + LITERAL_CODERS_MAX * LITERAL_CODER_SIZE) + +/* + * LZMA remembers the four most recent match distances. Reusing these + * distances tends to take less space than re-encoding the actual + * distance value. + */ +#define REPS 4 + +#endif diff --git a/grub-core/lib/xzembed/xz_private.h b/grub-core/lib/xzembed/xz_private.h new file mode 100644 index 0000000..fc845c9 --- /dev/null +++ b/grub-core/lib/xzembed/xz_private.h @@ -0,0 +1,96 @@ +/* xz_private.h - Private includes and definitions */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#ifndef XZ_PRIVATE_H +#define XZ_PRIVATE_H + +/* + * For userspace builds, use a separate header to define the required + * macros and functions. This makes it easier to adapt the code into + * different environments and avoids clutter in the Linux kernel tree. + */ +#include "xz_config.h" + +/* + * If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ. + * XZ_DEC_BCJ is used to enable generic support for BCJ decoders. + */ +#ifndef XZ_DEC_BCJ +# if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) \ + || defined(XZ_DEC_IA64) || defined(XZ_DEC_ARM) \ + || defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) \ + || defined(XZ_DEC_SPARC) +# define XZ_DEC_BCJ +# endif +#endif + +/* + * Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used + * before calling xz_dec_lzma2_run(). + */ +struct xz_dec_lzma2 * xz_dec_lzma2_create( + uint32_t dict_max); + +/* + * Decode the LZMA2 properties (one byte) and reset the decoder. Return + * XZ_OK on success, XZ_MEMLIMIT_ERROR if the preallocated dictionary is not + * big enough, and XZ_OPTIONS_ERROR if props indicates something that this + * decoder doesn't support. + */ +enum xz_ret xz_dec_lzma2_reset( + struct xz_dec_lzma2 *s, uint8_t props); + +/* Decode raw LZMA2 stream from b->in to b->out. */ +enum xz_ret xz_dec_lzma2_run( + struct xz_dec_lzma2 *s, struct xz_buf *b); + +/* Free the memory allocated for the LZMA2 decoder. */ +void xz_dec_lzma2_end(struct xz_dec_lzma2 *s); + +/* + * Allocate memory for BCJ decoders. xz_dec_bcj_reset() must be used before + * calling xz_dec_bcj_run(). + */ +struct xz_dec_bcj * xz_dec_bcj_create(bool single_call); + +/* + * Decode the Filter ID of a BCJ filter. This implementation doesn't + * support custom start offsets, so no decoding of Filter Properties + * is needed. Returns XZ_OK if the given Filter ID is supported. + * Otherwise XZ_OPTIONS_ERROR is returned. + */ +enum xz_ret xz_dec_bcj_reset( + struct xz_dec_bcj *s, uint8_t id); + +/* + * Decode raw BCJ + LZMA2 stream. This must be used only if there actually is + * a BCJ filter in the chain. If the chain has only LZMA2, xz_dec_lzma2_run() + * must be called directly. + */ +enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, + struct xz_dec_lzma2 *lzma2, struct xz_buf *b); + +/* Free the memory allocated for the BCJ filters. */ +#define xz_dec_bcj_end(s) kfree(s) + +#endif diff --git a/grub-core/lib/xzembed/xz_stream.h b/grub-core/lib/xzembed/xz_stream.h new file mode 100644 index 0000000..f58397a --- /dev/null +++ b/grub-core/lib/xzembed/xz_stream.h @@ -0,0 +1,53 @@ +/* xz_stream.h - Definitions for handling the .xz file format */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * This file is based on code from XZ embedded project + * http://tukaani.org/xz/embedded.html + */ + +#ifndef XZ_STREAM_H +#define XZ_STREAM_H + +/* + * See the .xz file format specification at + * http://tukaani.org/xz/xz-file-format.txt + * to understand the container format. + */ + +#define STREAM_HEADER_SIZE 12 + +#define HEADER_MAGIC "\3757zXZ\0" +#define HEADER_MAGIC_SIZE 6 + +#define FOOTER_MAGIC "YZ" +#define FOOTER_MAGIC_SIZE 2 + +/* + * Variable-length integer can hold a 63-bit unsigned integer, or a special + * value to indicate that the value is unknown. + */ +typedef uint64_t vli_type; + +#define VLI_MAX ((vli_type)-1 / 2) +#define VLI_UNKNOWN ((vli_type)-1) + +/* Maximum encoded size of a VLI */ +#define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7) + +#endif diff --git a/grub-core/lib/zstd/bitstream.h b/grub-core/lib/zstd/bitstream.h new file mode 100644 index 0000000..2f91460 --- /dev/null +++ b/grub-core/lib/zstd/bitstream.h @@ -0,0 +1,458 @@ +/* ****************************************************************** + bitstream + Part of FSE library + Copyright (C) 2013-present, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - Source repository : https://github.com/Cyan4973/FiniteStateEntropy +****************************************************************** */ +#ifndef BITSTREAM_H_MODULE +#define BITSTREAM_H_MODULE + +#if defined (__cplusplus) +extern "C" { +#endif + +/* +* This API consists of small unitary functions, which must be inlined for best performance. +* Since link-time-optimization is not available for all compilers, +* these functions are defined into a .h to be included. +*/ + +/*-**************************************** +* Dependencies +******************************************/ +#include "mem.h" /* unaligned access routines */ +#include "debug.h" /* assert(), DEBUGLOG(), RAWLOG() */ +#include "error_private.h" /* error codes and messages */ + + +/*========================================= +* Target specific +=========================================*/ +#if defined(__BMI__) && defined(__GNUC__) +# include <immintrin.h> /* support for bextr (experimental) */ +#endif + +#define STREAM_ACCUMULATOR_MIN_32 25 +#define STREAM_ACCUMULATOR_MIN_64 57 +#define STREAM_ACCUMULATOR_MIN ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64)) + + +/*-****************************************** +* bitStream encoding API (write forward) +********************************************/ +/* bitStream can mix input from multiple sources. + * A critical property of these streams is that they encode and decode in **reverse** direction. + * So the first bit sequence you add will be the last to be read, like a LIFO stack. + */ +typedef struct { + size_t bitContainer; + unsigned bitPos; + char* startPtr; + char* ptr; + char* endPtr; +} BIT_CStream_t; + +MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity); +MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits); +MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC); +MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC); + +/* Start with initCStream, providing the size of buffer to write into. +* bitStream will never write outside of this buffer. +* `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code. +* +* bits are first added to a local register. +* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems. +* Writing data into memory is an explicit operation, performed by the flushBits function. +* Hence keep track how many bits are potentially stored into local register to avoid register overflow. +* After a flushBits, a maximum of 7 bits might still be stored into local register. +* +* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers. +* +* Last operation is to close the bitStream. +* The function returns the final size of CStream in bytes. +* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable) +*/ + + +/*-******************************************** +* bitStream decoding API (read backward) +**********************************************/ +typedef struct { + size_t bitContainer; + unsigned bitsConsumed; + const char* ptr; + const char* start; + const char* limitPtr; +} BIT_DStream_t; + +typedef enum { BIT_DStream_unfinished = 0, + BIT_DStream_endOfBuffer = 1, + BIT_DStream_completed = 2, + BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */ + /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */ + +MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize); +MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits); +MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD); +MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD); + + +/* Start by invoking BIT_initDStream(). +* A chunk of the bitStream is then stored into a local register. +* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t). +* You can then retrieve bitFields stored into the local register, **in reverse order**. +* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method. +* A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished. +* Otherwise, it can be less than that, so proceed accordingly. +* Checking if DStream has reached its end can be performed with BIT_endOfDStream(). +*/ + + +/*-**************************************** +* unsafe API +******************************************/ +MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits); +/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */ + +MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC); +/* unsafe version; does not check buffer overflow */ + +MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits); +/* faster, but works only if nbBits >= 1 */ + + + +/*-************************************************************** +* Internal functions +****************************************************************/ +MEM_STATIC unsigned BIT_highbit32 (U32 val) +{ + assert(val != 0); + { +# if defined(_MSC_VER) /* Visual */ + unsigned long r=0; + _BitScanReverse ( &r, val ); + return (unsigned) r; +# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ + return 31 - __builtin_clz (val); +# else /* Software version */ + static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, + 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, + 19, 27, 23, 6, 26, 5, 4, 31 }; + U32 v = val; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27]; +# endif + } +} + +/*===== Local Constants =====*/ +static const unsigned BIT_mask[] = { + 0, 1, 3, 7, 0xF, 0x1F, + 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, + 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, + 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, + 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF, + 0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */ +#define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0])) + +/*-************************************************************** +* bitStream encoding +****************************************************************/ +/*! BIT_initCStream() : + * `dstCapacity` must be > sizeof(size_t) + * @return : 0 if success, + * otherwise an error code (can be tested using ERR_isError()) */ +MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, + void* startPtr, size_t dstCapacity) +{ + bitC->bitContainer = 0; + bitC->bitPos = 0; + bitC->startPtr = (char*)startPtr; + bitC->ptr = bitC->startPtr; + bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer); + if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall); + return 0; +} + +/*! BIT_addBits() : + * can add up to 31 bits into `bitC`. + * Note : does not check for register overflow ! */ +MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, + size_t value, unsigned nbBits) +{ + MEM_STATIC_ASSERT(BIT_MASK_SIZE == 32); + assert(nbBits < BIT_MASK_SIZE); + assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8); + bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos; + bitC->bitPos += nbBits; +} + +/*! BIT_addBitsFast() : + * works only if `value` is _clean_, + * meaning all high bits above nbBits are 0 */ +MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, + size_t value, unsigned nbBits) +{ + assert((value>>nbBits) == 0); + assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8); + bitC->bitContainer |= value << bitC->bitPos; + bitC->bitPos += nbBits; +} + +/*! BIT_flushBitsFast() : + * assumption : bitContainer has not overflowed + * unsafe version; does not check buffer overflow */ +MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC) +{ + size_t const nbBytes = bitC->bitPos >> 3; + assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8); + MEM_writeLEST(bitC->ptr, bitC->bitContainer); + bitC->ptr += nbBytes; + assert(bitC->ptr <= bitC->endPtr); + bitC->bitPos &= 7; + bitC->bitContainer >>= nbBytes*8; +} + +/*! BIT_flushBits() : + * assumption : bitContainer has not overflowed + * safe version; check for buffer overflow, and prevents it. + * note : does not signal buffer overflow. + * overflow will be revealed later on using BIT_closeCStream() */ +MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC) +{ + size_t const nbBytes = bitC->bitPos >> 3; + assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8); + MEM_writeLEST(bitC->ptr, bitC->bitContainer); + bitC->ptr += nbBytes; + if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr; + bitC->bitPos &= 7; + bitC->bitContainer >>= nbBytes*8; +} + +/*! BIT_closeCStream() : + * @return : size of CStream, in bytes, + * or 0 if it could not fit into dstBuffer */ +MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC) +{ + BIT_addBitsFast(bitC, 1, 1); /* endMark */ + BIT_flushBits(bitC); + if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */ + return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0); +} + + +/*-******************************************************** +* bitStream decoding +**********************************************************/ +/*! BIT_initDStream() : + * Initialize a BIT_DStream_t. + * `bitD` : a pointer to an already allocated BIT_DStream_t structure. + * `srcSize` must be the *exact* size of the bitStream, in bytes. + * @return : size of stream (== srcSize), or an errorCode if a problem is detected + */ +MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize) +{ + if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); } + + bitD->start = (const char*)srcBuffer; + bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer); + + if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */ + bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer); + bitD->bitContainer = MEM_readLEST(bitD->ptr); + { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1]; + bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */ + if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ } + } else { + bitD->ptr = bitD->start; + bitD->bitContainer = *(const BYTE*)(bitD->start); + switch(srcSize) + { + case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16); + /* fall-through */ + + case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24); + /* fall-through */ + + case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32); + /* fall-through */ + + case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; + /* fall-through */ + + case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16; + /* fall-through */ + + case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8; + /* fall-through */ + + default: break; + } + { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1]; + bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; + if (lastByte == 0) return ERROR(corruption_detected); /* endMark not present */ + } + bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8; + } + + return srcSize; +} + +MEM_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start) +{ + return bitContainer >> start; +} + +MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) +{ +#if defined(__BMI__) && defined(__GNUC__) && __GNUC__*1000+__GNUC_MINOR__ >= 4008 /* experimental */ +# if defined(__x86_64__) + if (sizeof(bitContainer)==8) + return _bextr_u64(bitContainer, start, nbBits); + else +# endif + return _bextr_u32(bitContainer, start, nbBits); +#else + assert(nbBits < BIT_MASK_SIZE); + return (bitContainer >> start) & BIT_mask[nbBits]; +#endif +} + +MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) +{ + assert(nbBits < BIT_MASK_SIZE); + return bitContainer & BIT_mask[nbBits]; +} + +/*! BIT_lookBits() : + * Provides next n bits from local register. + * local register is not modified. + * On 32-bits, maxNbBits==24. + * On 64-bits, maxNbBits==56. + * @return : value extracted */ +MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) +{ +#if defined(__BMI__) && defined(__GNUC__) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */ + return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits); +#else + U32 const regMask = sizeof(bitD->bitContainer)*8 - 1; + return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask); +#endif +} + +/*! BIT_lookBitsFast() : + * unsafe version; only works if nbBits >= 1 */ +MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits) +{ + U32 const regMask = sizeof(bitD->bitContainer)*8 - 1; + assert(nbBits >= 1); + return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask); +} + +MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) +{ + bitD->bitsConsumed += nbBits; +} + +/*! BIT_readBits() : + * Read (consume) next n bits from local register and update. + * Pay attention to not read more than nbBits contained into local register. + * @return : extracted value. */ +MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits) +{ + size_t const value = BIT_lookBits(bitD, nbBits); + BIT_skipBits(bitD, nbBits); + return value; +} + +/*! BIT_readBitsFast() : + * unsafe version; only works only if nbBits >= 1 */ +MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits) +{ + size_t const value = BIT_lookBitsFast(bitD, nbBits); + assert(nbBits >= 1); + BIT_skipBits(bitD, nbBits); + return value; +} + +/*! BIT_reloadDStream() : + * Refill `bitD` from buffer previously set in BIT_initDStream() . + * This function is safe, it guarantees it will not read beyond src buffer. + * @return : status of `BIT_DStream_t` internal register. + * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */ +MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD) +{ + if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */ + return BIT_DStream_overflow; + + if (bitD->ptr >= bitD->limitPtr) { + bitD->ptr -= bitD->bitsConsumed >> 3; + bitD->bitsConsumed &= 7; + bitD->bitContainer = MEM_readLEST(bitD->ptr); + return BIT_DStream_unfinished; + } + if (bitD->ptr == bitD->start) { + if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer; + return BIT_DStream_completed; + } + /* start < ptr < limitPtr */ + { U32 nbBytes = bitD->bitsConsumed >> 3; + BIT_DStream_status result = BIT_DStream_unfinished; + if (bitD->ptr - nbBytes < bitD->start) { + nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */ + result = BIT_DStream_endOfBuffer; + } + bitD->ptr -= nbBytes; + bitD->bitsConsumed -= nbBytes*8; + bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */ + return result; + } +} + +/*! BIT_endOfDStream() : + * @return : 1 if DStream has _exactly_ reached its end (all bits consumed). + */ +MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream) +{ + return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8)); +} + +#if defined (__cplusplus) +} +#endif + +#endif /* BITSTREAM_H_MODULE */ diff --git a/grub-core/lib/zstd/compiler.h b/grub-core/lib/zstd/compiler.h new file mode 100644 index 0000000..07f875e --- /dev/null +++ b/grub-core/lib/zstd/compiler.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_COMPILER_H +#define ZSTD_COMPILER_H + +/*-******************************************************* +* Compiler specifics +*********************************************************/ +/* force inlining */ +#if defined (__GNUC__) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# define INLINE_KEYWORD inline +#else +# define INLINE_KEYWORD +#endif + +#if defined(__GNUC__) +# define FORCE_INLINE_ATTR __attribute__((always_inline)) +#elif defined(_MSC_VER) +# define FORCE_INLINE_ATTR __forceinline +#else +# define FORCE_INLINE_ATTR +#endif + +/** + * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant + * parameters. They must be inlined for the compiler to elimininate the constant + * branches. + */ +#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR +/** + * HINT_INLINE is used to help the compiler generate better code. It is *not* + * used for "templates", so it can be tweaked based on the compilers + * performance. + * + * gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the + * always_inline attribute. + * + * clang up to 5.0.0 (trunk) benefit tremendously from the always_inline + * attribute. + */ +#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5 +# define HINT_INLINE static INLINE_KEYWORD +#else +# define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR +#endif + +/* force no inlining */ +#ifdef _MSC_VER +# define FORCE_NOINLINE static __declspec(noinline) +#else +# ifdef __GNUC__ +# define FORCE_NOINLINE static __attribute__((__noinline__)) +# else +# define FORCE_NOINLINE static +# endif +#endif + +/* target attribute */ +#ifndef __has_attribute + #define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif +#if defined(__GNUC__) +# define TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) +#else +# define TARGET_ATTRIBUTE(target) +#endif + +/* Enable runtime BMI2 dispatch based on the CPU. + * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default. + */ +#ifndef DYNAMIC_BMI2 + #if ((defined(__clang__) && __has_attribute(__target__)) \ + || (defined(__GNUC__) \ + && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \ + && (defined(__x86_64__) || defined(_M_X86)) \ + && !defined(__BMI2__) + # define DYNAMIC_BMI2 1 + #else + # define DYNAMIC_BMI2 0 + #endif +#endif + +/* prefetch + * can be disabled, by declaring NO_PREFETCH macro + * All prefetch invocations use a single default locality 2, + * generating instruction prefetcht1, + * which, according to Intel, means "load data into L2 cache". + * This is a good enough "middle ground" for the time being, + * though in theory, it would be better to specialize locality depending on data being prefetched. + * Tests could not determine any sensible difference based on locality value. */ +#if defined(NO_PREFETCH) +# define PREFETCH(ptr) (void)(ptr) /* disabled */ +#else +# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */ +# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ +# define PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1) +# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) +# define PREFETCH(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */) +# else +# define PREFETCH(ptr) (void)(ptr) /* disabled */ +# endif +#endif /* NO_PREFETCH */ + +#define CACHELINE_SIZE 64 + +#define PREFETCH_AREA(p, s) { \ + const char* const _ptr = (const char*)(p); \ + size_t const _size = (size_t)(s); \ + size_t _pos; \ + for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \ + PREFETCH(_ptr + _pos); \ + } \ +} + +/* disable warnings */ +#ifdef _MSC_VER /* Visual Studio */ +# include <intrin.h> /* For Visual 2005 */ +# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */ +# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ +# pragma warning(disable : 4324) /* disable: C4324: padded structure */ +#endif + +#endif /* ZSTD_COMPILER_H */ diff --git a/grub-core/lib/zstd/cpu.h b/grub-core/lib/zstd/cpu.h new file mode 100644 index 0000000..eeb428a --- /dev/null +++ b/grub-core/lib/zstd/cpu.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_COMMON_CPU_H +#define ZSTD_COMMON_CPU_H + +/** + * Implementation taken from folly/CpuId.h + * https://github.com/facebook/folly/blob/master/folly/CpuId.h + */ + +#include <string.h> + +#include "mem.h" + +#ifdef _MSC_VER +#include <intrin.h> +#endif + +typedef struct { + U32 f1c; + U32 f1d; + U32 f7b; + U32 f7c; +} ZSTD_cpuid_t; + +MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) { + U32 f1c = 0; + U32 f1d = 0; + U32 f7b = 0; + U32 f7c = 0; +#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) + int reg[4]; + __cpuid((int*)reg, 0); + { + int const n = reg[0]; + if (n >= 1) { + __cpuid((int*)reg, 1); + f1c = (U32)reg[2]; + f1d = (U32)reg[3]; + } + if (n >= 7) { + __cpuidex((int*)reg, 7, 0); + f7b = (U32)reg[1]; + f7c = (U32)reg[2]; + } + } +#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__) + /* The following block like the normal cpuid branch below, but gcc + * reserves ebx for use of its pic register so we must specially + * handle the save and restore to avoid clobbering the register + */ + U32 n; + __asm__( + "pushl %%ebx\n\t" + "cpuid\n\t" + "popl %%ebx\n\t" + : "=a"(n) + : "a"(0) + : "ecx", "edx"); + if (n >= 1) { + U32 f1a; + __asm__( + "pushl %%ebx\n\t" + "cpuid\n\t" + "popl %%ebx\n\t" + : "=a"(f1a), "=c"(f1c), "=d"(f1d) + : "a"(1)); + } + if (n >= 7) { + __asm__( + "pushl %%ebx\n\t" + "cpuid\n\t" + "movl %%ebx, %%eax\n\r" + "popl %%ebx" + : "=a"(f7b), "=c"(f7c) + : "a"(7), "c"(0) + : "edx"); + } +#elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__) + U32 n; + __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx"); + if (n >= 1) { + U32 f1a; + __asm__("cpuid" : "=a"(f1a), "=c"(f1c), "=d"(f1d) : "a"(1) : "ebx"); + } + if (n >= 7) { + U32 f7a; + __asm__("cpuid" + : "=a"(f7a), "=b"(f7b), "=c"(f7c) + : "a"(7), "c"(0) + : "edx"); + } +#endif + { + ZSTD_cpuid_t cpuid; + cpuid.f1c = f1c; + cpuid.f1d = f1d; + cpuid.f7b = f7b; + cpuid.f7c = f7c; + return cpuid; + } +} + +#define X(name, r, bit) \ + MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) { \ + return ((cpuid.r) & (1U << bit)) != 0; \ + } + +/* cpuid(1): Processor Info and Feature Bits. */ +#define C(name, bit) X(name, f1c, bit) + C(sse3, 0) + C(pclmuldq, 1) + C(dtes64, 2) + C(monitor, 3) + C(dscpl, 4) + C(vmx, 5) + C(smx, 6) + C(eist, 7) + C(tm2, 8) + C(ssse3, 9) + C(cnxtid, 10) + C(fma, 12) + C(cx16, 13) + C(xtpr, 14) + C(pdcm, 15) + C(pcid, 17) + C(dca, 18) + C(sse41, 19) + C(sse42, 20) + C(x2apic, 21) + C(movbe, 22) + C(popcnt, 23) + C(tscdeadline, 24) + C(aes, 25) + C(xsave, 26) + C(osxsave, 27) + C(avx, 28) + C(f16c, 29) + C(rdrand, 30) +#undef C +#define D(name, bit) X(name, f1d, bit) + D(fpu, 0) + D(vme, 1) + D(de, 2) + D(pse, 3) + D(tsc, 4) + D(msr, 5) + D(pae, 6) + D(mce, 7) + D(cx8, 8) + D(apic, 9) + D(sep, 11) + D(mtrr, 12) + D(pge, 13) + D(mca, 14) + D(cmov, 15) + D(pat, 16) + D(pse36, 17) + D(psn, 18) + D(clfsh, 19) + D(ds, 21) + D(acpi, 22) + D(mmx, 23) + D(fxsr, 24) + D(sse, 25) + D(sse2, 26) + D(ss, 27) + D(htt, 28) + D(tm, 29) + D(pbe, 31) +#undef D + +/* cpuid(7): Extended Features. */ +#define B(name, bit) X(name, f7b, bit) + B(bmi1, 3) + B(hle, 4) + B(avx2, 5) + B(smep, 7) + B(bmi2, 8) + B(erms, 9) + B(invpcid, 10) + B(rtm, 11) + B(mpx, 14) + B(avx512f, 16) + B(avx512dq, 17) + B(rdseed, 18) + B(adx, 19) + B(smap, 20) + B(avx512ifma, 21) + B(pcommit, 22) + B(clflushopt, 23) + B(clwb, 24) + B(avx512pf, 26) + B(avx512er, 27) + B(avx512cd, 28) + B(sha, 29) + B(avx512bw, 30) + B(avx512vl, 31) +#undef B +#define C(name, bit) X(name, f7c, bit) + C(prefetchwt1, 0) + C(avx512vbmi, 1) +#undef C + +#undef X + +#endif /* ZSTD_COMMON_CPU_H */ diff --git a/grub-core/lib/zstd/debug.c b/grub-core/lib/zstd/debug.c new file mode 100644 index 0000000..3ebdd1c --- /dev/null +++ b/grub-core/lib/zstd/debug.c @@ -0,0 +1,44 @@ +/* ****************************************************************** + debug + Part of FSE library + Copyright (C) 2013-present, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - Source repository : https://github.com/Cyan4973/FiniteStateEntropy +****************************************************************** */ + + +/* + * This module only hosts one global variable + * which can be used to dynamically influence the verbosity of traces, + * such as DEBUGLOG and RAWLOG + */ + +#include "debug.h" + +int g_debuglevel = DEBUGLEVEL; diff --git a/grub-core/lib/zstd/debug.h b/grub-core/lib/zstd/debug.h new file mode 100644 index 0000000..0c04ad2 --- /dev/null +++ b/grub-core/lib/zstd/debug.h @@ -0,0 +1,123 @@ +/* ****************************************************************** + debug + Part of FSE library + Copyright (C) 2013-present, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - Source repository : https://github.com/Cyan4973/FiniteStateEntropy +****************************************************************** */ + + +/* + * The purpose of this header is to enable debug functions. + * They regroup assert(), DEBUGLOG() and RAWLOG() for run-time, + * and DEBUG_STATIC_ASSERT() for compile-time. + * + * By default, DEBUGLEVEL==0, which means run-time debug is disabled. + * + * Level 1 enables assert() only. + * Starting level 2, traces can be generated and pushed to stderr. + * The higher the level, the more verbose the traces. + * + * It's possible to dynamically adjust level using variable g_debug_level, + * which is only declared if DEBUGLEVEL>=2, + * and is a global variable, not multi-thread protected (use with care) + */ + +#ifndef DEBUG_H_12987983217 +#define DEBUG_H_12987983217 + +#if defined (__cplusplus) +extern "C" { +#endif + + +/* static assert is triggered at compile time, leaving no runtime artefact, + * but can only work with compile-time constants. + * This variant can only be used inside a function. */ +#define DEBUG_STATIC_ASSERT(c) (void)sizeof(char[(c) ? 1 : -1]) + + +/* DEBUGLEVEL is expected to be defined externally, + * typically through compiler command line. + * Value must be a number. */ +#ifndef DEBUGLEVEL +# define DEBUGLEVEL 0 +#endif + +/* recommended values for DEBUGLEVEL : + * 0 : no debug, all run-time functions disabled + * 1 : no display, enables assert() only + * 2 : reserved, for currently active debug path + * 3 : events once per object lifetime (CCtx, CDict, etc.) + * 4 : events once per frame + * 5 : events once per block + * 6 : events once per sequence (verbose) + * 7+: events at every position (*very* verbose) + * + * It's generally inconvenient to output traces > 5. + * In which case, it's possible to selectively enable higher verbosity levels + * by modifying g_debug_level. + */ + +#if (DEBUGLEVEL>=1) +# include <assert.h> +#else +# ifndef assert /* assert may be already defined, due to prior #include <assert.h> */ +# define assert(condition) ((void)0) /* disable assert (default) */ +# endif +#endif + +#if (DEBUGLEVEL>=2) +# include <stdio.h> +extern int g_debuglevel; /* here, this variable is only declared, + it actually lives in debug.c, + and is shared by the whole process. + It's typically used to enable very verbose levels + on selective conditions (such as position in src) */ + +# define RAWLOG(l, ...) { \ + if (l<=g_debuglevel) { \ + fprintf(stderr, __VA_ARGS__); \ + } } +# define DEBUGLOG(l, ...) { \ + if (l<=g_debuglevel) { \ + fprintf(stderr, __FILE__ ": " __VA_ARGS__); \ + fprintf(stderr, " \n"); \ + } } +#else +# define RAWLOG(l, ...) {} /* disabled */ +# define DEBUGLOG(l, ...) {} /* disabled */ +#endif + + +#if defined (__cplusplus) +} +#endif + +#endif /* DEBUG_H_12987983217 */ diff --git a/grub-core/lib/zstd/entropy_common.c b/grub-core/lib/zstd/entropy_common.c new file mode 100644 index 0000000..b12944e --- /dev/null +++ b/grub-core/lib/zstd/entropy_common.c @@ -0,0 +1,236 @@ +/* + Common functions of New Generation Entropy library + Copyright (C) 2016, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy + - Public forum : https://groups.google.com/forum/#!forum/lz4c +*************************************************************************** */ + +/* ************************************* +* Dependencies +***************************************/ +#include "mem.h" +#include "error_private.h" /* ERR_*, ERROR */ +#define FSE_STATIC_LINKING_ONLY /* FSE_MIN_TABLELOG */ +#include "fse.h" +#define HUF_STATIC_LINKING_ONLY /* HUF_TABLELOG_ABSOLUTEMAX */ +#include "huf.h" + + +/*=== Version ===*/ +unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; } + + +/*=== Error Management ===*/ +unsigned FSE_isError(size_t code) { return ERR_isError(code); } +const char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); } + +unsigned HUF_isError(size_t code) { return ERR_isError(code); } +const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } + + +/*-************************************************************** +* FSE NCount encoding-decoding +****************************************************************/ +size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + const BYTE* const istart = (const BYTE*) headerBuffer; + const BYTE* const iend = istart + hbSize; + const BYTE* ip = istart; + int nbBits; + int remaining; + int threshold; + U32 bitStream; + int bitCount; + unsigned charnum = 0; + int previous0 = 0; + + if (hbSize < 4) { + /* This function only works when hbSize >= 4 */ + char buffer[4]; + memset(buffer, 0, sizeof(buffer)); + memcpy(buffer, headerBuffer, hbSize); + { size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr, + buffer, sizeof(buffer)); + if (FSE_isError(countSize)) return countSize; + if (countSize > hbSize) return ERROR(corruption_detected); + return countSize; + } } + assert(hbSize >= 4); + + /* init */ + memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */ + bitStream = MEM_readLE32(ip); + nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ + if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); + bitStream >>= 4; + bitCount = 4; + *tableLogPtr = nbBits; + remaining = (1<<nbBits)+1; + threshold = 1<<nbBits; + nbBits++; + + while ((remaining>1) & (charnum<=*maxSVPtr)) { + if (previous0) { + unsigned n0 = charnum; + while ((bitStream & 0xFFFF) == 0xFFFF) { + n0 += 24; + if (ip < iend-5) { + ip += 2; + bitStream = MEM_readLE32(ip) >> bitCount; + } else { + bitStream >>= 16; + bitCount += 16; + } } + while ((bitStream & 3) == 3) { + n0 += 3; + bitStream >>= 2; + bitCount += 2; + } + n0 += bitStream & 3; + bitCount += 2; + if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall); + while (charnum < n0) normalizedCounter[charnum++] = 0; + if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { + assert((bitCount >> 3) <= 3); /* For first condition to work */ + ip += bitCount>>3; + bitCount &= 7; + bitStream = MEM_readLE32(ip) >> bitCount; + } else { + bitStream >>= 2; + } } + { int const max = (2*threshold-1) - remaining; + int count; + + if ((bitStream & (threshold-1)) < (U32)max) { + count = bitStream & (threshold-1); + bitCount += nbBits-1; + } else { + count = bitStream & (2*threshold-1); + if (count >= threshold) count -= max; + bitCount += nbBits; + } + + count--; /* extra accuracy */ + remaining -= count < 0 ? -count : count; /* -1 means +1 */ + normalizedCounter[charnum++] = (short)count; + previous0 = !count; + while (remaining < threshold) { + nbBits--; + threshold >>= 1; + } + + if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { + ip += bitCount>>3; + bitCount &= 7; + } else { + bitCount -= (int)(8 * (iend - 4 - ip)); + ip = iend - 4; + } + bitStream = MEM_readLE32(ip) >> (bitCount & 31); + } } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */ + if (remaining != 1) return ERROR(corruption_detected); + if (bitCount > 32) return ERROR(corruption_detected); + *maxSVPtr = charnum-1; + + ip += (bitCount+7)>>3; + return ip-istart; +} + + +/*! HUF_readStats() : + Read compact Huffman tree, saved by HUF_writeCTable(). + `huffWeight` is destination buffer. + `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32. + @return : size read from `src` , or an error Code . + Note : Needed by HUF_readCTable() and HUF_readDTableX?() . +*/ +size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize) +{ + U32 weightTotal; + const BYTE* ip = (const BYTE*) src; + size_t iSize; + size_t oSize; + + if (!srcSize) return ERROR(srcSize_wrong); + iSize = ip[0]; + /* memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ + + if (iSize >= 128) { /* special header */ + oSize = iSize - 127; + iSize = ((oSize+1)/2); + if (iSize+1 > srcSize) return ERROR(srcSize_wrong); + if (oSize >= hwSize) return ERROR(corruption_detected); + ip += 1; + { U32 n; + for (n=0; n<oSize; n+=2) { + huffWeight[n] = ip[n/2] >> 4; + huffWeight[n+1] = ip[n/2] & 15; + } } } + else { /* header compressed with FSE (normal case) */ + FSE_DTable fseWorkspace[FSE_DTABLE_SIZE_U32(6)]; /* 6 is max possible tableLog for HUF header (maybe even 5, to be tested) */ + if (iSize+1 > srcSize) return ERROR(srcSize_wrong); + oSize = FSE_decompress_wksp(huffWeight, hwSize-1, ip+1, iSize, fseWorkspace, 6); /* max (hwSize-1) values decoded, as last one is implied */ + if (FSE_isError(oSize)) return oSize; + } + + /* collect weight stats */ + memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32)); + weightTotal = 0; + { U32 n; for (n=0; n<oSize; n++) { + if (huffWeight[n] >= HUF_TABLELOG_MAX) return ERROR(corruption_detected); + rankStats[huffWeight[n]]++; + weightTotal += (1 << huffWeight[n]) >> 1; + } } + if (weightTotal == 0) return ERROR(corruption_detected); + + /* get last non-null symbol weight (implied, total must be 2^n) */ + { U32 const tableLog = BIT_highbit32(weightTotal) + 1; + if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected); + *tableLogPtr = tableLog; + /* determine last weight */ + { U32 const total = 1 << tableLog; + U32 const rest = total - weightTotal; + U32 const verif = 1 << BIT_highbit32(rest); + U32 const lastWeight = BIT_highbit32(rest) + 1; + if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ + huffWeight[oSize] = (BYTE)lastWeight; + rankStats[lastWeight]++; + } } + + /* check tree construction validity */ + if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */ + + /* results */ + *nbSymbolsPtr = (U32)(oSize+1); + return iSize+1; +} diff --git a/grub-core/lib/zstd/error_private.c b/grub-core/lib/zstd/error_private.c new file mode 100644 index 0000000..d004ee6 --- /dev/null +++ b/grub-core/lib/zstd/error_private.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/* The purpose of this file is to have a single list of error strings embedded in binary */ + +#include "error_private.h" + +const char* ERR_getErrorString(ERR_enum code) +{ + static const char* const notErrorCode = "Unspecified error code"; + switch( code ) + { + case PREFIX(no_error): return "No error detected"; + case PREFIX(GENERIC): return "Error (generic)"; + case PREFIX(prefix_unknown): return "Unknown frame descriptor"; + case PREFIX(version_unsupported): return "Version not supported"; + case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter"; + case PREFIX(frameParameter_windowTooLarge): return "Frame requires too much memory for decoding"; + case PREFIX(corruption_detected): return "Corrupted block detected"; + case PREFIX(checksum_wrong): return "Restored data doesn't match checksum"; + case PREFIX(parameter_unsupported): return "Unsupported parameter"; + case PREFIX(parameter_outOfBound): return "Parameter is out of bound"; + case PREFIX(init_missing): return "Context should be init first"; + case PREFIX(memory_allocation): return "Allocation error : not enough memory"; + case PREFIX(workSpace_tooSmall): return "workSpace buffer is not large enough"; + case PREFIX(stage_wrong): return "Operation not authorized at current processing stage"; + case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported"; + case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large"; + case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small"; + case PREFIX(dictionary_corrupted): return "Dictionary is corrupted"; + case PREFIX(dictionary_wrong): return "Dictionary mismatch"; + case PREFIX(dictionaryCreation_failed): return "Cannot create Dictionary from provided samples"; + case PREFIX(dstSize_tooSmall): return "Destination buffer is too small"; + case PREFIX(srcSize_wrong): return "Src size is incorrect"; + /* following error codes are not stable and may be removed or changed in a future version */ + case PREFIX(frameIndex_tooLarge): return "Frame index is too large"; + case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking"; + case PREFIX(maxCode): + default: return notErrorCode; + } +} diff --git a/grub-core/lib/zstd/error_private.h b/grub-core/lib/zstd/error_private.h new file mode 100644 index 0000000..0d2fa7e --- /dev/null +++ b/grub-core/lib/zstd/error_private.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/* Note : this module is expected to remain private, do not expose it */ + +#ifndef ERROR_H_MODULE +#define ERROR_H_MODULE + +#if defined (__cplusplus) +extern "C" { +#endif + + +/* **************************************** +* Dependencies +******************************************/ +#include <stddef.h> /* size_t */ +#include "zstd_errors.h" /* enum list */ + + +/* **************************************** +* Compiler-specific +******************************************/ +#if defined(__GNUC__) +# define ERR_STATIC static __attribute__((unused)) +#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define ERR_STATIC static inline +#elif defined(_MSC_VER) +# define ERR_STATIC static __inline +#else +# define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ +#endif + + +/*-**************************************** +* Customization (error_public.h) +******************************************/ +typedef ZSTD_ErrorCode ERR_enum; +#define PREFIX(name) ZSTD_error_##name + + +/*-**************************************** +* Error codes handling +******************************************/ +#undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */ +#define ERROR(name) ZSTD_ERROR(name) +#define ZSTD_ERROR(name) ((size_t)-PREFIX(name)) + +ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); } + +ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); } + + +/*-**************************************** +* Error Strings +******************************************/ + +const char* ERR_getErrorString(ERR_enum code); /* error_private.c */ + +ERR_STATIC const char* ERR_getErrorName(size_t code) +{ + return ERR_getErrorString(ERR_getErrorCode(code)); +} + +#if defined (__cplusplus) +} +#endif + +#endif /* ERROR_H_MODULE */ diff --git a/grub-core/lib/zstd/fse.h b/grub-core/lib/zstd/fse.h new file mode 100644 index 0000000..a5a6b6d --- /dev/null +++ b/grub-core/lib/zstd/fse.h @@ -0,0 +1,708 @@ +/* ****************************************************************** + FSE : Finite State Entropy codec + Public Prototypes declaration + Copyright (C) 2013-2016, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - Source repository : https://github.com/Cyan4973/FiniteStateEntropy +****************************************************************** */ + +#if defined (__cplusplus) +extern "C" { +#endif + +#ifndef FSE_H +#define FSE_H + + +/*-***************************************** +* Dependencies +******************************************/ +#include <stddef.h> /* size_t, ptrdiff_t */ + + +/*-***************************************** +* FSE_PUBLIC_API : control library symbols visibility +******************************************/ +#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4) +# define FSE_PUBLIC_API __attribute__ ((visibility ("default"))) +#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */ +# define FSE_PUBLIC_API __declspec(dllexport) +#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1) +# define FSE_PUBLIC_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +#else +# define FSE_PUBLIC_API +#endif + +/*------ Version ------*/ +#define FSE_VERSION_MAJOR 0 +#define FSE_VERSION_MINOR 9 +#define FSE_VERSION_RELEASE 0 + +#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE +#define FSE_QUOTE(str) #str +#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str) +#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION) + +#define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE) +FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */ + + +/*-**************************************** +* FSE simple functions +******************************************/ +/*! FSE_compress() : + Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'. + 'dst' buffer must be already allocated. Compression runs faster is dstCapacity >= FSE_compressBound(srcSize). + @return : size of compressed data (<= dstCapacity). + Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!! + if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead. + if FSE_isError(return), compression failed (more details using FSE_getErrorName()) +*/ +FSE_PUBLIC_API size_t FSE_compress(void* dst, size_t dstCapacity, + const void* src, size_t srcSize); + +/*! FSE_decompress(): + Decompress FSE data from buffer 'cSrc', of size 'cSrcSize', + into already allocated destination buffer 'dst', of size 'dstCapacity'. + @return : size of regenerated data (<= maxDstSize), + or an error code, which can be tested using FSE_isError() . + + ** Important ** : FSE_decompress() does not decompress non-compressible nor RLE data !!! + Why ? : making this distinction requires a header. + Header management is intentionally delegated to the user layer, which can better manage special cases. +*/ +FSE_PUBLIC_API size_t FSE_decompress(void* dst, size_t dstCapacity, + const void* cSrc, size_t cSrcSize); + + +/*-***************************************** +* Tool functions +******************************************/ +FSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */ + +/* Error Management */ +FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */ +FSE_PUBLIC_API const char* FSE_getErrorName(size_t code); /* provides error code string (useful for debugging) */ + + +/*-***************************************** +* FSE advanced functions +******************************************/ +/*! FSE_compress2() : + Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog' + Both parameters can be defined as '0' to mean : use default value + @return : size of compressed data + Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!! + if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression. + if FSE_isError(return), it's an error code. +*/ +FSE_PUBLIC_API size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog); + + +/*-***************************************** +* FSE detailed API +******************************************/ +/*! +FSE_compress() does the following: +1. count symbol occurrence from source[] into table count[] (see hist.h) +2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog) +3. save normalized counters to memory buffer using writeNCount() +4. build encoding table 'CTable' from normalized counters +5. encode the data stream using encoding table 'CTable' + +FSE_decompress() does the following: +1. read normalized counters with readNCount() +2. build decoding table 'DTable' from normalized counters +3. decode the data stream using decoding table 'DTable' + +The following API allows targeting specific sub-functions for advanced tasks. +For example, it's possible to compress several blocks using the same 'CTable', +or to save and provide normalized distribution using external method. +*/ + +/* *** COMPRESSION *** */ + +/*! FSE_optimalTableLog(): + dynamically downsize 'tableLog' when conditions are met. + It saves CPU time, by using smaller tables, while preserving or even improving compression ratio. + @return : recommended tableLog (necessarily <= 'maxTableLog') */ +FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue); + +/*! FSE_normalizeCount(): + normalize counts so that sum(count[]) == Power_of_2 (2^tableLog) + 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1). + @return : tableLog, + or an errorCode, which can be tested using FSE_isError() */ +FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog, + const unsigned* count, size_t srcSize, unsigned maxSymbolValue); + +/*! FSE_NCountWriteBound(): + Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'. + Typically useful for allocation purpose. */ +FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog); + +/*! FSE_writeNCount(): + Compactly save 'normalizedCounter' into 'buffer'. + @return : size of the compressed table, + or an errorCode, which can be tested using FSE_isError(). */ +FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize, + const short* normalizedCounter, + unsigned maxSymbolValue, unsigned tableLog); + +/*! Constructor and Destructor of FSE_CTable. + Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */ +typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */ +FSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog); +FSE_PUBLIC_API void FSE_freeCTable (FSE_CTable* ct); + +/*! FSE_buildCTable(): + Builds `ct`, which must be already allocated, using FSE_createCTable(). + @return : 0, or an errorCode, which can be tested using FSE_isError() */ +FSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); + +/*! FSE_compress_usingCTable(): + Compress `src` using `ct` into `dst` which must be already allocated. + @return : size of compressed data (<= `dstCapacity`), + or 0 if compressed data could not fit into `dst`, + or an errorCode, which can be tested using FSE_isError() */ +FSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct); + +/*! +Tutorial : +---------- +The first step is to count all symbols. FSE_count() does this job very fast. +Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells. +'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0] +maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value) +FSE_count() will return the number of occurrence of the most frequent symbol. +This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility. +If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()). + +The next step is to normalize the frequencies. +FSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'. +It also guarantees a minimum of 1 to any Symbol with frequency >= 1. +You can use 'tableLog'==0 to mean "use default tableLog value". +If you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(), +which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default"). + +The result of FSE_normalizeCount() will be saved into a table, +called 'normalizedCounter', which is a table of signed short. +'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells. +The return value is tableLog if everything proceeded as expected. +It is 0 if there is a single symbol within distribution. +If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()). + +'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount(). +'buffer' must be already allocated. +For guaranteed success, buffer size must be at least FSE_headerBound(). +The result of the function is the number of bytes written into 'buffer'. +If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small). + +'normalizedCounter' can then be used to create the compression table 'CTable'. +The space required by 'CTable' must be already allocated, using FSE_createCTable(). +You can then use FSE_buildCTable() to fill 'CTable'. +If there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()). + +'CTable' can then be used to compress 'src', with FSE_compress_usingCTable(). +Similar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize' +The function returns the size of compressed data (without header), necessarily <= `dstCapacity`. +If it returns '0', compressed data could not fit into 'dst'. +If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()). +*/ + + +/* *** DECOMPRESSION *** */ + +/*! FSE_readNCount(): + Read compactly saved 'normalizedCounter' from 'rBuffer'. + @return : size read from 'rBuffer', + or an errorCode, which can be tested using FSE_isError(). + maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */ +FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter, + unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, + const void* rBuffer, size_t rBuffSize); + +/*! Constructor and Destructor of FSE_DTable. + Note that its size depends on 'tableLog' */ +typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ +FSE_PUBLIC_API FSE_DTable* FSE_createDTable(unsigned tableLog); +FSE_PUBLIC_API void FSE_freeDTable(FSE_DTable* dt); + +/*! FSE_buildDTable(): + Builds 'dt', which must be already allocated, using FSE_createDTable(). + return : 0, or an errorCode, which can be tested using FSE_isError() */ +FSE_PUBLIC_API size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); + +/*! FSE_decompress_usingDTable(): + Decompress compressed source `cSrc` of size `cSrcSize` using `dt` + into `dst` which must be already allocated. + @return : size of regenerated data (necessarily <= `dstCapacity`), + or an errorCode, which can be tested using FSE_isError() */ +FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt); + +/*! +Tutorial : +---------- +(Note : these functions only decompress FSE-compressed blocks. + If block is uncompressed, use memcpy() instead + If block is a single repeated byte, use memset() instead ) + +The first step is to obtain the normalized frequencies of symbols. +This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount(). +'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short. +In practice, that means it's necessary to know 'maxSymbolValue' beforehand, +or size the table to handle worst case situations (typically 256). +FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'. +The result of FSE_readNCount() is the number of bytes read from 'rBuffer'. +Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that. +If there is an error, the function will return an error code, which can be tested using FSE_isError(). + +The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'. +This is performed by the function FSE_buildDTable(). +The space required by 'FSE_DTable' must be already allocated using FSE_createDTable(). +If there is an error, the function will return an error code, which can be tested using FSE_isError(). + +`FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable(). +`cSrcSize` must be strictly correct, otherwise decompression will fail. +FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`). +If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small) +*/ + +#endif /* FSE_H */ + +#if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY) +#define FSE_H_FSE_STATIC_LINKING_ONLY + +/* *** Dependency *** */ +#include "bitstream.h" + + +/* ***************************************** +* Static allocation +*******************************************/ +/* FSE buffer bounds */ +#define FSE_NCOUNTBOUND 512 +#define FSE_BLOCKBOUND(size) (size + (size>>7)) +#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ + +/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */ +#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2)) +#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog)) + +/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */ +#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable)) +#define FSE_DTABLE_SIZE(maxTableLog) (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable)) + + +/* ***************************************** + * FSE advanced API + ***************************************** */ + +unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus); +/**< same as FSE_optimalTableLog(), which used `minus==2` */ + +/* FSE_compress_wksp() : + * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). + * FSE_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable. + */ +#define FSE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) ) +size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); + +size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits); +/**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */ + +size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue); +/**< build a fake FSE_CTable, designed to compress always the same symbolValue */ + +/* FSE_buildCTable_wksp() : + * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`). + * `wkspSize` must be >= `(1<<tableLog)`. + */ +size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); + +size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits); +/**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */ + +size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue); +/**< build a fake FSE_DTable, designed to always generate the same symbolValue */ + +size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog); +/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DTABLE_SIZE_U32(maxLog)` */ + +typedef enum { + FSE_repeat_none, /**< Cannot use the previous table */ + FSE_repeat_check, /**< Can use the previous table but it must be checked */ + FSE_repeat_valid /**< Can use the previous table and it is asumed to be valid */ + } FSE_repeat; + +/* ***************************************** +* FSE symbol compression API +*******************************************/ +/*! + This API consists of small unitary functions, which highly benefit from being inlined. + Hence their body are included in next section. +*/ +typedef struct { + ptrdiff_t value; + const void* stateTable; + const void* symbolTT; + unsigned stateLog; +} FSE_CState_t; + +static void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct); + +static void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol); + +static void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr); + +/**< +These functions are inner components of FSE_compress_usingCTable(). +They allow the creation of custom streams, mixing multiple tables and bit sources. + +A key property to keep in mind is that encoding and decoding are done **in reverse direction**. +So the first symbol you will encode is the last you will decode, like a LIFO stack. + +You will need a few variables to track your CStream. They are : + +FSE_CTable ct; // Provided by FSE_buildCTable() +BIT_CStream_t bitStream; // bitStream tracking structure +FSE_CState_t state; // State tracking structure (can have several) + + +The first thing to do is to init bitStream and state. + size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize); + FSE_initCState(&state, ct); + +Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError(); +You can then encode your input data, byte after byte. +FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time. +Remember decoding will be done in reverse direction. + FSE_encodeByte(&bitStream, &state, symbol); + +At any time, you can also add any bit sequence. +Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders + BIT_addBits(&bitStream, bitField, nbBits); + +The above methods don't commit data to memory, they just store it into local register, for speed. +Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t). +Writing data to memory is a manual operation, performed by the flushBits function. + BIT_flushBits(&bitStream); + +Your last FSE encoding operation shall be to flush your last state value(s). + FSE_flushState(&bitStream, &state); + +Finally, you must close the bitStream. +The function returns the size of CStream in bytes. +If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible) +If there is an error, it returns an errorCode (which can be tested using FSE_isError()). + size_t size = BIT_closeCStream(&bitStream); +*/ + + +/* ***************************************** +* FSE symbol decompression API +*******************************************/ +typedef struct { + size_t state; + const void* table; /* precise table may vary, depending on U16 */ +} FSE_DState_t; + + +static void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt); + +static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); + +static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr); + +/**< +Let's now decompose FSE_decompress_usingDTable() into its unitary components. +You will decode FSE-encoded symbols from the bitStream, +and also any other bitFields you put in, **in reverse order**. + +You will need a few variables to track your bitStream. They are : + +BIT_DStream_t DStream; // Stream context +FSE_DState_t DState; // State context. Multiple ones are possible +FSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable() + +The first thing to do is to init the bitStream. + errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize); + +You should then retrieve your initial state(s) +(in reverse flushing order if you have several ones) : + errorCode = FSE_initDState(&DState, &DStream, DTablePtr); + +You can then decode your data, symbol after symbol. +For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'. +Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out). + unsigned char symbol = FSE_decodeSymbol(&DState, &DStream); + +You can retrieve any bitfield you eventually stored into the bitStream (in reverse order) +Note : maximum allowed nbBits is 25, for 32-bits compatibility + size_t bitField = BIT_readBits(&DStream, nbBits); + +All above operations only read from local register (which size depends on size_t). +Refueling the register from memory is manually performed by the reload method. + endSignal = FSE_reloadDStream(&DStream); + +BIT_reloadDStream() result tells if there is still some more data to read from DStream. +BIT_DStream_unfinished : there is still some data left into the DStream. +BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled. +BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed. +BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted. + +When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop, +to properly detect the exact end of stream. +After each decoded symbol, check if DStream is fully consumed using this simple test : + BIT_reloadDStream(&DStream) >= BIT_DStream_completed + +When it's done, verify decompression is fully completed, by checking both DStream and the relevant states. +Checking if DStream has reached its end is performed by : + BIT_endOfDStream(&DStream); +Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible. + FSE_endOfDState(&DState); +*/ + + +/* ***************************************** +* FSE unsafe API +*******************************************/ +static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); +/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */ + + +/* ***************************************** +* Implementation of inlined functions +*******************************************/ +typedef struct { + int deltaFindState; + U32 deltaNbBits; +} FSE_symbolCompressionTransform; /* total 8 bytes */ + +MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct) +{ + const void* ptr = ct; + const U16* u16ptr = (const U16*) ptr; + const U32 tableLog = MEM_read16(ptr); + statePtr->value = (ptrdiff_t)1<<tableLog; + statePtr->stateTable = u16ptr+2; + statePtr->symbolTT = ((const U32*)ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1)); + statePtr->stateLog = tableLog; +} + + +/*! FSE_initCState2() : +* Same as FSE_initCState(), but the first symbol to include (which will be the last to be read) +* uses the smallest state value possible, saving the cost of this symbol */ +MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol) +{ + FSE_initCState(statePtr, ct); + { const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; + const U16* stateTable = (const U16*)(statePtr->stateTable); + U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16); + statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits; + statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; + } +} + +MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, U32 symbol) +{ + FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; + const U16* const stateTable = (const U16*)(statePtr->stateTable); + U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16); + BIT_addBits(bitC, statePtr->value, nbBitsOut); + statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; +} + +MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr) +{ + BIT_addBits(bitC, statePtr->value, statePtr->stateLog); + BIT_flushBits(bitC); +} + + +/* FSE_getMaxNbBits() : + * Approximate maximum cost of a symbol, in bits. + * Fractional get rounded up (i.e : a symbol with a normalized frequency of 3 gives the same result as a frequency of 2) + * note 1 : assume symbolValue is valid (<= maxSymbolValue) + * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */ +MEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue) +{ + const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr; + return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16; +} + +/* FSE_bitCost() : + * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits) + * note 1 : assume symbolValue is valid (<= maxSymbolValue) + * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */ +MEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog) +{ + const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr; + U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16; + U32 const threshold = (minNbBits+1) << 16; + assert(tableLog < 16); + assert(accuracyLog < 31-tableLog); /* ensure enough room for renormalization double shift */ + { U32 const tableSize = 1 << tableLog; + U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize); + U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog; /* linear interpolation (very approximate) */ + U32 const bitMultiplier = 1 << accuracyLog; + assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold); + assert(normalizedDeltaFromThreshold <= bitMultiplier); + return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold; + } +} + + +/* ====== Decompression ====== */ + +typedef struct { + U16 tableLog; + U16 fastMode; +} FSE_DTableHeader; /* sizeof U32 */ + +typedef struct +{ + unsigned short newState; + unsigned char symbol; + unsigned char nbBits; +} FSE_decode_t; /* size == U32 */ + +MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt) +{ + const void* ptr = dt; + const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr; + DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog); + BIT_reloadDStream(bitD); + DStatePtr->table = dt + 1; +} + +MEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr) +{ + FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + return DInfo.symbol; +} + +MEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) +{ + FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + U32 const nbBits = DInfo.nbBits; + size_t const lowBits = BIT_readBits(bitD, nbBits); + DStatePtr->state = DInfo.newState + lowBits; +} + +MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) +{ + FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + U32 const nbBits = DInfo.nbBits; + BYTE const symbol = DInfo.symbol; + size_t const lowBits = BIT_readBits(bitD, nbBits); + + DStatePtr->state = DInfo.newState + lowBits; + return symbol; +} + +/*! FSE_decodeSymbolFast() : + unsafe, only works if no symbol has a probability > 50% */ +MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) +{ + FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + U32 const nbBits = DInfo.nbBits; + BYTE const symbol = DInfo.symbol; + size_t const lowBits = BIT_readBitsFast(bitD, nbBits); + + DStatePtr->state = DInfo.newState + lowBits; + return symbol; +} + +MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) +{ + return DStatePtr->state == 0; +} + + + +#ifndef FSE_COMMONDEFS_ONLY + +/* ************************************************************** +* Tuning parameters +****************************************************************/ +/*!MEMORY_USAGE : +* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) +* Increasing memory usage improves compression ratio +* Reduced memory usage can improve speed, due to cache effect +* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ +#ifndef FSE_MAX_MEMORY_USAGE +# define FSE_MAX_MEMORY_USAGE 14 +#endif +#ifndef FSE_DEFAULT_MEMORY_USAGE +# define FSE_DEFAULT_MEMORY_USAGE 13 +#endif + +/*!FSE_MAX_SYMBOL_VALUE : +* Maximum symbol value authorized. +* Required for proper stack allocation */ +#ifndef FSE_MAX_SYMBOL_VALUE +# define FSE_MAX_SYMBOL_VALUE 255 +#endif + +/* ************************************************************** +* template functions type & suffix +****************************************************************/ +#define FSE_FUNCTION_TYPE BYTE +#define FSE_FUNCTION_EXTENSION +#define FSE_DECODE_TYPE FSE_decode_t + + +#endif /* !FSE_COMMONDEFS_ONLY */ + + +/* *************************************************************** +* Constants +*****************************************************************/ +#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2) +#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG) +#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1) +#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2) +#define FSE_MIN_TABLELOG 5 + +#define FSE_TABLELOG_ABSOLUTE_MAX 15 +#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX +# error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" +#endif + +#define FSE_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3) + + +#endif /* FSE_STATIC_LINKING_ONLY */ + + +#if defined (__cplusplus) +} +#endif diff --git a/grub-core/lib/zstd/fse_decompress.c b/grub-core/lib/zstd/fse_decompress.c new file mode 100644 index 0000000..2227b84 --- /dev/null +++ b/grub-core/lib/zstd/fse_decompress.c @@ -0,0 +1,309 @@ +/* ****************************************************************** + FSE : Finite State Entropy decoder + Copyright (C) 2013-2015, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy + - Public forum : https://groups.google.com/forum/#!forum/lz4c +****************************************************************** */ + + +/* ************************************************************** +* Includes +****************************************************************/ +#include <stdlib.h> /* malloc, free, qsort */ +#include <string.h> /* memcpy, memset */ +#include "bitstream.h" +#include "compiler.h" +#define FSE_STATIC_LINKING_ONLY +#include "fse.h" +#include "error_private.h" + + +/* ************************************************************** +* Error Management +****************************************************************/ +#define FSE_isError ERR_isError +#define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */ + +/* check and forward error code */ +#define CHECK_F(f) { size_t const e = f; if (FSE_isError(e)) return e; } + + +/* ************************************************************** +* Templates +****************************************************************/ +/* + designed to be included + for type-specific functions (template emulation in C) + Objective is to write these functions only once, for improved maintenance +*/ + +/* safety checks */ +#ifndef FSE_FUNCTION_EXTENSION +# error "FSE_FUNCTION_EXTENSION must be defined" +#endif +#ifndef FSE_FUNCTION_TYPE +# error "FSE_FUNCTION_TYPE must be defined" +#endif + +/* Function names */ +#define FSE_CAT(X,Y) X##Y +#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y) +#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y) + + +/* Function templates */ +FSE_DTable* FSE_createDTable (unsigned tableLog) +{ + if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; + return (FSE_DTable*)calloc( FSE_DTABLE_SIZE_U32(tableLog), sizeof (U32) ); +} + +void FSE_freeDTable (FSE_DTable* dt) +{ + free(dt); +} + +size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) +{ + void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */ + FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr); + U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1]; + + U32 const maxSV1 = maxSymbolValue + 1; + U32 const tableSize = 1 << tableLog; + U32 highThreshold = tableSize-1; + + /* Sanity Checks */ + if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge); + if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); + + /* Init, lay down lowprob symbols */ + { FSE_DTableHeader DTableH; + DTableH.tableLog = (U16)tableLog; + DTableH.fastMode = 1; + { S16 const largeLimit= (S16)(1 << (tableLog-1)); + U32 s; + for (s=0; s<maxSV1; s++) { + if (normalizedCounter[s]==-1) { + tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s; + symbolNext[s] = 1; + } else { + if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0; + symbolNext[s] = normalizedCounter[s]; + } } } + memcpy(dt, &DTableH, sizeof(DTableH)); + } + + /* Spread symbols */ + { U32 const tableMask = tableSize-1; + U32 const step = FSE_TABLESTEP(tableSize); + U32 s, position = 0; + for (s=0; s<maxSV1; s++) { + int i; + for (i=0; i<normalizedCounter[s]; i++) { + tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s; + position = (position + step) & tableMask; + while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */ + } } + if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ + } + + /* Build Decoding table */ + { U32 u; + for (u=0; u<tableSize; u++) { + FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol); + U32 const nextState = symbolNext[symbol]++; + tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) ); + tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize); + } } + + return 0; +} + + +#ifndef FSE_COMMONDEFS_ONLY + +/*-******************************************************* +* Decompression (Byte symbols) +*********************************************************/ +size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue) +{ + void* ptr = dt; + FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; + void* dPtr = dt + 1; + FSE_decode_t* const cell = (FSE_decode_t*)dPtr; + + DTableH->tableLog = 0; + DTableH->fastMode = 0; + + cell->newState = 0; + cell->symbol = symbolValue; + cell->nbBits = 0; + + return 0; +} + + +size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits) +{ + void* ptr = dt; + FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; + void* dPtr = dt + 1; + FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr; + const unsigned tableSize = 1 << nbBits; + const unsigned tableMask = tableSize - 1; + const unsigned maxSV1 = tableMask+1; + unsigned s; + + /* Sanity checks */ + if (nbBits < 1) return ERROR(GENERIC); /* min size */ + + /* Build Decoding Table */ + DTableH->tableLog = (U16)nbBits; + DTableH->fastMode = 1; + for (s=0; s<maxSV1; s++) { + dinfo[s].newState = 0; + dinfo[s].symbol = (BYTE)s; + dinfo[s].nbBits = (BYTE)nbBits; + } + + return 0; +} + +FORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic( + void* dst, size_t maxDstSize, + const void* cSrc, size_t cSrcSize, + const FSE_DTable* dt, const unsigned fast) +{ + BYTE* const ostart = (BYTE*) dst; + BYTE* op = ostart; + BYTE* const omax = op + maxDstSize; + BYTE* const olimit = omax-3; + + BIT_DStream_t bitD; + FSE_DState_t state1; + FSE_DState_t state2; + + /* Init */ + CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize)); + + FSE_initDState(&state1, &bitD, dt); + FSE_initDState(&state2, &bitD, dt); + +#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD) + + /* 4 symbols per loop */ + for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) & (op<olimit) ; op+=4) { + op[0] = FSE_GETSYMBOL(&state1); + + if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ + BIT_reloadDStream(&bitD); + + op[1] = FSE_GETSYMBOL(&state2); + + if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ + { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } } + + op[2] = FSE_GETSYMBOL(&state1); + + if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ + BIT_reloadDStream(&bitD); + + op[3] = FSE_GETSYMBOL(&state2); + } + + /* tail */ + /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */ + while (1) { + if (op>(omax-2)) return ERROR(dstSize_tooSmall); + *op++ = FSE_GETSYMBOL(&state1); + if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) { + *op++ = FSE_GETSYMBOL(&state2); + break; + } + + if (op>(omax-2)) return ERROR(dstSize_tooSmall); + *op++ = FSE_GETSYMBOL(&state2); + if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) { + *op++ = FSE_GETSYMBOL(&state1); + break; + } } + + return op-ostart; +} + + +size_t FSE_decompress_usingDTable(void* dst, size_t originalSize, + const void* cSrc, size_t cSrcSize, + const FSE_DTable* dt) +{ + const void* ptr = dt; + const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr; + const U32 fastMode = DTableH->fastMode; + + /* select fast mode (static) */ + if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1); + return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0); +} + + +size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog) +{ + const BYTE* const istart = (const BYTE*)cSrc; + const BYTE* ip = istart; + short counting[FSE_MAX_SYMBOL_VALUE+1]; + unsigned tableLog; + unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; + + /* normal FSE decoding mode */ + size_t const NCountLength = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize); + if (FSE_isError(NCountLength)) return NCountLength; + //if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */ + if (tableLog > maxLog) return ERROR(tableLog_tooLarge); + ip += NCountLength; + cSrcSize -= NCountLength; + + CHECK_F( FSE_buildDTable (workSpace, counting, maxSymbolValue, tableLog) ); + + return FSE_decompress_usingDTable (dst, dstCapacity, ip, cSrcSize, workSpace); /* always return, even if it is an error code */ +} + + +typedef FSE_DTable DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; + +size_t FSE_decompress(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize) +{ + DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */ + return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, dt, FSE_MAX_TABLELOG); +} + + + +#endif /* FSE_COMMONDEFS_ONLY */ diff --git a/grub-core/lib/zstd/huf.h b/grub-core/lib/zstd/huf.h new file mode 100644 index 0000000..de94641 --- /dev/null +++ b/grub-core/lib/zstd/huf.h @@ -0,0 +1,334 @@ +/* ****************************************************************** + huff0 huffman codec, + part of Finite State Entropy library + Copyright (C) 2013-present, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - Source repository : https://github.com/Cyan4973/FiniteStateEntropy +****************************************************************** */ + +#if defined (__cplusplus) +extern "C" { +#endif + +#ifndef HUF_H_298734234 +#define HUF_H_298734234 + +/* *** Dependencies *** */ +#include <stddef.h> /* size_t */ + + +/* *** library symbols visibility *** */ +/* Note : when linking with -fvisibility=hidden on gcc, or by default on Visual, + * HUF symbols remain "private" (internal symbols for library only). + * Set macro FSE_DLL_EXPORT to 1 if you want HUF symbols visible on DLL interface */ +#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4) +# define HUF_PUBLIC_API __attribute__ ((visibility ("default"))) +#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */ +# define HUF_PUBLIC_API __declspec(dllexport) +#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1) +# define HUF_PUBLIC_API __declspec(dllimport) /* not required, just to generate faster code (saves a function pointer load from IAT and an indirect jump) */ +#else +# define HUF_PUBLIC_API +#endif + + +/* ========================== */ +/* *** simple functions *** */ +/* ========================== */ + +/** HUF_compress() : + * Compress content from buffer 'src', of size 'srcSize', into buffer 'dst'. + * 'dst' buffer must be already allocated. + * Compression runs faster if `dstCapacity` >= HUF_compressBound(srcSize). + * `srcSize` must be <= `HUF_BLOCKSIZE_MAX` == 128 KB. + * @return : size of compressed data (<= `dstCapacity`). + * Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!! + * if HUF_isError(return), compression failed (more details using HUF_getErrorName()) + */ +HUF_PUBLIC_API size_t HUF_compress(void* dst, size_t dstCapacity, + const void* src, size_t srcSize); + +/** HUF_decompress() : + * Decompress HUF data from buffer 'cSrc', of size 'cSrcSize', + * into already allocated buffer 'dst', of minimum size 'dstSize'. + * `originalSize` : **must** be the ***exact*** size of original (uncompressed) data. + * Note : in contrast with FSE, HUF_decompress can regenerate + * RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data, + * because it knows size to regenerate (originalSize). + * @return : size of regenerated data (== originalSize), + * or an error code, which can be tested using HUF_isError() + */ +HUF_PUBLIC_API size_t HUF_decompress(void* dst, size_t originalSize, + const void* cSrc, size_t cSrcSize); + + +/* *** Tool functions *** */ +#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */ +HUF_PUBLIC_API size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */ + +/* Error Management */ +HUF_PUBLIC_API unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */ +HUF_PUBLIC_API const char* HUF_getErrorName(size_t code); /**< provides error code string (useful for debugging) */ + + +/* *** Advanced function *** */ + +/** HUF_compress2() : + * Same as HUF_compress(), but offers control over `maxSymbolValue` and `tableLog`. + * `maxSymbolValue` must be <= HUF_SYMBOLVALUE_MAX . + * `tableLog` must be `<= HUF_TABLELOG_MAX` . */ +HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned tableLog); + +/** HUF_compress4X_wksp() : + * Same as HUF_compress2(), but uses externally allocated `workSpace`. + * `workspace` must have minimum alignment of 4, and be at least as large as HUF_WORKSPACE_SIZE */ +#define HUF_WORKSPACE_SIZE (6 << 10) +#define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32)) +HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned tableLog, + void* workSpace, size_t wkspSize); + +#endif /* HUF_H_298734234 */ + +/* ****************************************************************** + * WARNING !! + * The following section contains advanced and experimental definitions + * which shall never be used in the context of a dynamic library, + * because they are not guaranteed to remain stable in the future. + * Only consider them in association with static linking. + * *****************************************************************/ +#if defined(HUF_STATIC_LINKING_ONLY) && !defined(HUF_H_HUF_STATIC_LINKING_ONLY) +#define HUF_H_HUF_STATIC_LINKING_ONLY + +/* *** Dependencies *** */ +#include "mem.h" /* U32 */ + + +/* *** Constants *** */ +#define HUF_TABLELOG_MAX 12 /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */ +#define HUF_TABLELOG_DEFAULT 11 /* default tableLog value when none specified */ +#define HUF_SYMBOLVALUE_MAX 255 + +#define HUF_TABLELOG_ABSOLUTEMAX 15 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ +#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX) +# error "HUF_TABLELOG_MAX is too large !" +#endif + + +/* **************************************** +* Static allocation +******************************************/ +/* HUF buffer bounds */ +#define HUF_CTABLEBOUND 129 +#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true when incompressible is pre-filtered with fast heuristic */ +#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ + +/* static allocation of HUF's Compression Table */ +#define HUF_CTABLE_SIZE_U32(maxSymbolValue) ((maxSymbolValue)+1) /* Use tables of U32, for proper alignment */ +#define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_U32(maxSymbolValue) * sizeof(U32)) +#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \ + U32 name##hb[HUF_CTABLE_SIZE_U32(maxSymbolValue)]; \ + void* name##hv = &(name##hb); \ + HUF_CElt* name = (HUF_CElt*)(name##hv) /* no final ; */ + +/* static allocation of HUF's DTable */ +typedef U32 HUF_DTable; +#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog))) +#define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \ + HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) } +#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \ + HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) } + + +/* **************************************** +* Advanced decompression functions +******************************************/ +size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ +size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ + +size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */ +size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */ +size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< considers RLE and uncompressed as errors */ +size_t HUF_decompress4X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ +size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */ +size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ +size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */ + + +/* **************************************** + * HUF detailed API + * ****************************************/ + +/*! HUF_compress() does the following: + * 1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within "fse.h") + * 2. (optional) refine tableLog using HUF_optimalTableLog() + * 3. build Huffman table from count using HUF_buildCTable() + * 4. save Huffman table to memory buffer using HUF_writeCTable() + * 5. encode the data stream using HUF_compress4X_usingCTable() + * + * The following API allows targeting specific sub-functions for advanced tasks. + * For example, it's possible to compress several blocks using the same 'CTable', + * or to save and regenerate 'CTable' using external methods. + */ +unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue); +typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */ +size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */ +size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog); +size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); + +typedef enum { + HUF_repeat_none, /**< Cannot use the previous table */ + HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */ + HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */ + } HUF_repeat; +/** HUF_compress4X_repeat() : + * Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. + * If it uses hufTable it does not modify hufTable or repeat. + * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used. + * If preferRepeat then the old table will always be used if valid. */ +size_t HUF_compress4X_repeat(void* dst, size_t dstSize, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned tableLog, + void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */ + HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2); + +/** HUF_buildCTable_wksp() : + * Same as HUF_buildCTable(), but using externally allocated scratch buffer. + * `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE. + */ +#define HUF_CTABLE_WORKSPACE_SIZE_U32 (2*HUF_SYMBOLVALUE_MAX +1 +1) +#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned)) +size_t HUF_buildCTable_wksp (HUF_CElt* tree, + const U32* count, U32 maxSymbolValue, U32 maxNbBits, + void* workSpace, size_t wkspSize); + +/*! HUF_readStats() : + * Read compact Huffman tree, saved by HUF_writeCTable(). + * `huffWeight` is destination buffer. + * @return : size read from `src` , or an error Code . + * Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */ +size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, + U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize); + +/** HUF_readCTable() : + * Loading a CTable saved with HUF_writeCTable() */ +size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize); + +/** HUF_getNbBits() : + * Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX + * Note 1 : is not inlined, as HUF_CElt definition is private + * Note 2 : const void* used, so that it can provide a statically allocated table as argument (which uses type U32) */ +U32 HUF_getNbBits(const void* symbolTable, U32 symbolValue); + +/* + * HUF_decompress() does the following: + * 1. select the decompression algorithm (X1, X2) based on pre-computed heuristics + * 2. build Huffman table from save, using HUF_readDTableX?() + * 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable() + */ + +/** HUF_selectDecoder() : + * Tells which decoder is likely to decode faster, + * based on a set of pre-computed metrics. + * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 . + * Assumption : 0 < dstSize <= 128 KB */ +U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize); + +/** + * The minimum workspace size for the `workSpace` used in + * HUF_readDTableX1_wksp() and HUF_readDTableX2_wksp(). + * + * The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when + * HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15. + * Buffer overflow errors may potentially occur if code modifications result in + * a required workspace size greater than that specified in the following + * macro. + */ +#define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10) +#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32)) + +size_t HUF_readDTableX1 (HUF_DTable* DTable, const void* src, size_t srcSize); +size_t HUF_readDTableX1_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize); +size_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize); +size_t HUF_readDTableX2_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize); + +size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); +size_t HUF_decompress4X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); +size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); + + +/* ====================== */ +/* single stream variants */ +/* ====================== */ + +size_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog); +size_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ +size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); +/** HUF_compress1X_repeat() : + * Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. + * If it uses hufTable it does not modify hufTable or repeat. + * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used. + * If preferRepeat then the old table will always be used if valid. */ +size_t HUF_compress1X_repeat(void* dst, size_t dstSize, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned tableLog, + void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */ + HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2); + +size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */ +size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */ + +size_t HUF_decompress1X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); +size_t HUF_decompress1X_DCtx_wksp (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); +size_t HUF_decompress1X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ +size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */ +size_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ +size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */ + +size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */ +size_t HUF_decompress1X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); +size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); + +/* BMI2 variants. + * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0. + */ +size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2); +size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2); +size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2); +size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2); + +#endif /* HUF_STATIC_LINKING_ONLY */ + +#if defined (__cplusplus) +} +#endif diff --git a/grub-core/lib/zstd/huf_decompress.c b/grub-core/lib/zstd/huf_decompress.c new file mode 100644 index 0000000..83ecaff --- /dev/null +++ b/grub-core/lib/zstd/huf_decompress.c @@ -0,0 +1,1096 @@ +/* ****************************************************************** + huff0 huffman decoder, + part of Finite State Entropy library + Copyright (C) 2013-present, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy +****************************************************************** */ + +/* ************************************************************** +* Dependencies +****************************************************************/ +#include <string.h> /* memcpy, memset */ +#include "compiler.h" +#include "bitstream.h" /* BIT_* */ +#include "fse.h" /* to compress headers */ +#define HUF_STATIC_LINKING_ONLY +#include "huf.h" +#include "error_private.h" + + +/* ************************************************************** +* Error Management +****************************************************************/ +#define HUF_isError ERR_isError +#define CHECK_F(f) { size_t const err_ = (f); if (HUF_isError(err_)) return err_; } + + +/* ************************************************************** +* Byte alignment for workSpace management +****************************************************************/ +#define HUF_ALIGN(x, a) HUF_ALIGN_MASK((x), (a) - 1) +#define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) + + +/*-***************************/ +/* generic DTableDesc */ +/*-***************************/ +typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc; + +static DTableDesc HUF_getDTableDesc(const HUF_DTable* table) +{ + DTableDesc dtd; + memcpy(&dtd, table, sizeof(dtd)); + return dtd; +} + + +/*-***************************/ +/* single-symbol decoding */ +/*-***************************/ +typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX1; /* single-symbol decoding */ + +size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize) +{ + U32 tableLog = 0; + U32 nbSymbols = 0; + size_t iSize; + void* const dtPtr = DTable + 1; + HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr; + + U32* rankVal; + BYTE* huffWeight; + size_t spaceUsed32 = 0; + + rankVal = (U32 *)workSpace + spaceUsed32; + spaceUsed32 += HUF_TABLELOG_ABSOLUTEMAX + 1; + huffWeight = (BYTE *)((U32 *)workSpace + spaceUsed32); + spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2; + + if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge); + + DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable)); + /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */ + + iSize = HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); + if (HUF_isError(iSize)) return iSize; + + /* Table header */ + { DTableDesc dtd = HUF_getDTableDesc(DTable); + if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */ + dtd.tableType = 0; + dtd.tableLog = (BYTE)tableLog; + memcpy(DTable, &dtd, sizeof(dtd)); + } + + /* Calculate starting value for each rank */ + { U32 n, nextRankStart = 0; + for (n=1; n<tableLog+1; n++) { + U32 const current = nextRankStart; + nextRankStart += (rankVal[n] << (n-1)); + rankVal[n] = current; + } } + + /* fill DTable */ + { U32 n; + for (n=0; n<nbSymbols; n++) { + U32 const w = huffWeight[n]; + U32 const length = (1 << w) >> 1; + U32 u; + HUF_DEltX1 D; + D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w); + for (u = rankVal[w]; u < rankVal[w] + length; u++) + dt[u] = D; + rankVal[w] += length; + } } + + return iSize; +} + +size_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_readDTableX1_wksp(DTable, src, srcSize, + workSpace, sizeof(workSpace)); +} + +FORCE_INLINE_TEMPLATE BYTE +HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog) +{ + size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */ + BYTE const c = dt[val].byte; + BIT_skipBits(Dstream, dt[val].nbBits); + return c; +} + +#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \ + *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog) + +#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr) \ + if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \ + HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) + +#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr) \ + if (MEM_64bits()) \ + HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) + +HINT_INLINE size_t +HUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog) +{ + BYTE* const pStart = p; + + /* up to 4 symbols at a time */ + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) { + HUF_DECODE_SYMBOLX1_2(p, bitDPtr); + HUF_DECODE_SYMBOLX1_1(p, bitDPtr); + HUF_DECODE_SYMBOLX1_2(p, bitDPtr); + HUF_DECODE_SYMBOLX1_0(p, bitDPtr); + } + + /* [0-3] symbols remaining */ + if (MEM_32bits()) + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd)) + HUF_DECODE_SYMBOLX1_0(p, bitDPtr); + + /* no more data to retrieve from bitstream, no need to reload */ + while (p < pEnd) + HUF_DECODE_SYMBOLX1_0(p, bitDPtr); + + return pEnd-pStart; +} + +FORCE_INLINE_TEMPLATE size_t +HUF_decompress1X1_usingDTable_internal_body( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + BYTE* op = (BYTE*)dst; + BYTE* const oend = op + dstSize; + const void* dtPtr = DTable + 1; + const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr; + BIT_DStream_t bitD; + DTableDesc const dtd = HUF_getDTableDesc(DTable); + U32 const dtLog = dtd.tableLog; + + CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) ); + + HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog); + + if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected); + + return dstSize; +} + +FORCE_INLINE_TEMPLATE size_t +HUF_decompress4X1_usingDTable_internal_body( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + /* Check */ + if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ + + { const BYTE* const istart = (const BYTE*) cSrc; + BYTE* const ostart = (BYTE*) dst; + BYTE* const oend = ostart + dstSize; + const void* const dtPtr = DTable + 1; + const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr; + + /* Init */ + BIT_DStream_t bitD1; + BIT_DStream_t bitD2; + BIT_DStream_t bitD3; + BIT_DStream_t bitD4; + size_t const length1 = MEM_readLE16(istart); + size_t const length2 = MEM_readLE16(istart+2); + size_t const length3 = MEM_readLE16(istart+4); + size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6); + const BYTE* const istart1 = istart + 6; /* jumpTable */ + const BYTE* const istart2 = istart1 + length1; + const BYTE* const istart3 = istart2 + length2; + const BYTE* const istart4 = istart3 + length3; + const size_t segmentSize = (dstSize+3) / 4; + BYTE* const opStart2 = ostart + segmentSize; + BYTE* const opStart3 = opStart2 + segmentSize; + BYTE* const opStart4 = opStart3 + segmentSize; + BYTE* op1 = ostart; + BYTE* op2 = opStart2; + BYTE* op3 = opStart3; + BYTE* op4 = opStart4; + U32 endSignal = BIT_DStream_unfinished; + DTableDesc const dtd = HUF_getDTableDesc(DTable); + U32 const dtLog = dtd.tableLog; + + if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ + CHECK_F( BIT_initDStream(&bitD1, istart1, length1) ); + CHECK_F( BIT_initDStream(&bitD2, istart2, length2) ); + CHECK_F( BIT_initDStream(&bitD3, istart3, length3) ); + CHECK_F( BIT_initDStream(&bitD4, istart4, length4) ); + + /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */ + endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); + while ( (endSignal==BIT_DStream_unfinished) && (op4<(oend-3)) ) { + HUF_DECODE_SYMBOLX1_2(op1, &bitD1); + HUF_DECODE_SYMBOLX1_2(op2, &bitD2); + HUF_DECODE_SYMBOLX1_2(op3, &bitD3); + HUF_DECODE_SYMBOLX1_2(op4, &bitD4); + HUF_DECODE_SYMBOLX1_1(op1, &bitD1); + HUF_DECODE_SYMBOLX1_1(op2, &bitD2); + HUF_DECODE_SYMBOLX1_1(op3, &bitD3); + HUF_DECODE_SYMBOLX1_1(op4, &bitD4); + HUF_DECODE_SYMBOLX1_2(op1, &bitD1); + HUF_DECODE_SYMBOLX1_2(op2, &bitD2); + HUF_DECODE_SYMBOLX1_2(op3, &bitD3); + HUF_DECODE_SYMBOLX1_2(op4, &bitD4); + HUF_DECODE_SYMBOLX1_0(op1, &bitD1); + HUF_DECODE_SYMBOLX1_0(op2, &bitD2); + HUF_DECODE_SYMBOLX1_0(op3, &bitD3); + HUF_DECODE_SYMBOLX1_0(op4, &bitD4); + BIT_reloadDStream(&bitD1); + BIT_reloadDStream(&bitD2); + BIT_reloadDStream(&bitD3); + BIT_reloadDStream(&bitD4); + } + + /* check corruption */ + /* note : should not be necessary : op# advance in lock step, and we control op4. + * but curiously, binary generated by gcc 7.2 & 7.3 with -mbmi2 runs faster when >=1 test is present */ + if (op1 > opStart2) return ERROR(corruption_detected); + if (op2 > opStart3) return ERROR(corruption_detected); + if (op3 > opStart4) return ERROR(corruption_detected); + /* note : op4 supposed already verified within main loop */ + + /* finish bitStreams one by one */ + HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog); + HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog); + HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog); + HUF_decodeStreamX1(op4, &bitD4, oend, dt, dtLog); + + /* check */ + { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); + if (!endCheck) return ERROR(corruption_detected); } + + /* decoded size */ + return dstSize; + } +} + + +typedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize, + const void *cSrc, + size_t cSrcSize, + const HUF_DTable *DTable); +#if DYNAMIC_BMI2 + +#define HUF_DGEN(fn) \ + \ + static size_t fn##_default( \ + void* dst, size_t dstSize, \ + const void* cSrc, size_t cSrcSize, \ + const HUF_DTable* DTable) \ + { \ + return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \ + } \ + \ + static TARGET_ATTRIBUTE("bmi2") size_t fn##_bmi2( \ + void* dst, size_t dstSize, \ + const void* cSrc, size_t cSrcSize, \ + const HUF_DTable* DTable) \ + { \ + return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \ + } \ + \ + static size_t fn(void* dst, size_t dstSize, void const* cSrc, \ + size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \ + { \ + if (bmi2) { \ + return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable); \ + } \ + return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable); \ + } + +#else + +#define HUF_DGEN(fn) \ + static size_t fn(void* dst, size_t dstSize, void const* cSrc, \ + size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \ + { \ + (void)bmi2; \ + return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \ + } + +#endif + +HUF_DGEN(HUF_decompress1X1_usingDTable_internal) +HUF_DGEN(HUF_decompress4X1_usingDTable_internal) + + + +size_t HUF_decompress1X1_usingDTable( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + DTableDesc dtd = HUF_getDTableDesc(DTable); + if (dtd.tableType != 0) return ERROR(GENERIC); + return HUF_decompress1X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); +} + +size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + void* workSpace, size_t wkspSize) +{ + const BYTE* ip = (const BYTE*) cSrc; + + size_t const hSize = HUF_readDTableX1_wksp(DCtx, cSrc, cSrcSize, workSpace, wkspSize); + if (HUF_isError(hSize)) return hSize; + if (hSize >= cSrcSize) return ERROR(srcSize_wrong); + ip += hSize; cSrcSize -= hSize; + + return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0); +} + + +size_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); + return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize); +} + +size_t HUF_decompress4X1_usingDTable( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + DTableDesc dtd = HUF_getDTableDesc(DTable); + if (dtd.tableType != 0) return ERROR(GENERIC); + return HUF_decompress4X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); +} + +static size_t HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + void* workSpace, size_t wkspSize, int bmi2) +{ + const BYTE* ip = (const BYTE*) cSrc; + + size_t const hSize = HUF_readDTableX1_wksp (dctx, cSrc, cSrcSize, + workSpace, wkspSize); + if (HUF_isError(hSize)) return hSize; + if (hSize >= cSrcSize) return ERROR(srcSize_wrong); + ip += hSize; cSrcSize -= hSize; + + return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2); +} + +size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + void* workSpace, size_t wkspSize) +{ + return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, 0); +} + + +size_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} +size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); + return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); +} + + +/* *************************/ +/* double-symbols decoding */ +/* *************************/ + +typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2; /* double-symbols decoding */ +typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t; +typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1]; +typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX]; + + +/* HUF_fillDTableX2Level2() : + * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */ +static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 consumed, + const U32* rankValOrigin, const int minWeight, + const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, + U32 nbBitsBaseline, U16 baseSeq) +{ + HUF_DEltX2 DElt; + U32 rankVal[HUF_TABLELOG_MAX + 1]; + + /* get pre-calculated rankVal */ + memcpy(rankVal, rankValOrigin, sizeof(rankVal)); + + /* fill skipped values */ + if (minWeight>1) { + U32 i, skipSize = rankVal[minWeight]; + MEM_writeLE16(&(DElt.sequence), baseSeq); + DElt.nbBits = (BYTE)(consumed); + DElt.length = 1; + for (i = 0; i < skipSize; i++) + DTable[i] = DElt; + } + + /* fill DTable */ + { U32 s; for (s=0; s<sortedListSize; s++) { /* note : sortedSymbols already skipped */ + const U32 symbol = sortedSymbols[s].symbol; + const U32 weight = sortedSymbols[s].weight; + const U32 nbBits = nbBitsBaseline - weight; + const U32 length = 1 << (sizeLog-nbBits); + const U32 start = rankVal[weight]; + U32 i = start; + const U32 end = start + length; + + MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8))); + DElt.nbBits = (BYTE)(nbBits + consumed); + DElt.length = 2; + do { DTable[i++] = DElt; } while (i<end); /* since length >= 1 */ + + rankVal[weight] += length; + } } +} + + +static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog, + const sortedSymbol_t* sortedList, const U32 sortedListSize, + const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight, + const U32 nbBitsBaseline) +{ + U32 rankVal[HUF_TABLELOG_MAX + 1]; + const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */ + const U32 minBits = nbBitsBaseline - maxWeight; + U32 s; + + memcpy(rankVal, rankValOrigin, sizeof(rankVal)); + + /* fill DTable */ + for (s=0; s<sortedListSize; s++) { + const U16 symbol = sortedList[s].symbol; + const U32 weight = sortedList[s].weight; + const U32 nbBits = nbBitsBaseline - weight; + const U32 start = rankVal[weight]; + const U32 length = 1 << (targetLog-nbBits); + + if (targetLog-nbBits >= minBits) { /* enough room for a second symbol */ + U32 sortedRank; + int minWeight = nbBits + scaleLog; + if (minWeight < 1) minWeight = 1; + sortedRank = rankStart[minWeight]; + HUF_fillDTableX2Level2(DTable+start, targetLog-nbBits, nbBits, + rankValOrigin[nbBits], minWeight, + sortedList+sortedRank, sortedListSize-sortedRank, + nbBitsBaseline, symbol); + } else { + HUF_DEltX2 DElt; + MEM_writeLE16(&(DElt.sequence), symbol); + DElt.nbBits = (BYTE)(nbBits); + DElt.length = 1; + { U32 const end = start + length; + U32 u; + for (u = start; u < end; u++) DTable[u] = DElt; + } } + rankVal[weight] += length; + } +} + +size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize) +{ + U32 tableLog, maxW, sizeOfSort, nbSymbols; + DTableDesc dtd = HUF_getDTableDesc(DTable); + U32 const maxTableLog = dtd.maxTableLog; + size_t iSize; + void* dtPtr = DTable+1; /* force compiler to avoid strict-aliasing */ + HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr; + U32 *rankStart; + + rankValCol_t* rankVal; + U32* rankStats; + U32* rankStart0; + sortedSymbol_t* sortedSymbol; + BYTE* weightList; + size_t spaceUsed32 = 0; + + rankVal = (rankValCol_t *)((U32 *)workSpace + spaceUsed32); + spaceUsed32 += (sizeof(rankValCol_t) * HUF_TABLELOG_MAX) >> 2; + rankStats = (U32 *)workSpace + spaceUsed32; + spaceUsed32 += HUF_TABLELOG_MAX + 1; + rankStart0 = (U32 *)workSpace + spaceUsed32; + spaceUsed32 += HUF_TABLELOG_MAX + 2; + sortedSymbol = (sortedSymbol_t *)workSpace + (spaceUsed32 * sizeof(U32)) / sizeof(sortedSymbol_t); + spaceUsed32 += HUF_ALIGN(sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2; + weightList = (BYTE *)((U32 *)workSpace + spaceUsed32); + spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2; + + if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge); + + rankStart = rankStart0 + 1; + memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1)); + + DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */ + if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); + /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */ + + iSize = HUF_readStats(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); + if (HUF_isError(iSize)) return iSize; + + /* check result */ + if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */ + + /* find maxWeight */ + for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */ + + /* Get start index of each weight */ + { U32 w, nextRankStart = 0; + for (w=1; w<maxW+1; w++) { + U32 current = nextRankStart; + nextRankStart += rankStats[w]; + rankStart[w] = current; + } + rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/ + sizeOfSort = nextRankStart; + } + + /* sort symbols by weight */ + { U32 s; + for (s=0; s<nbSymbols; s++) { + U32 const w = weightList[s]; + U32 const r = rankStart[w]++; + sortedSymbol[r].symbol = (BYTE)s; + sortedSymbol[r].weight = (BYTE)w; + } + rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */ + } + + /* Build rankVal */ + { U32* const rankVal0 = rankVal[0]; + { int const rescale = (maxTableLog-tableLog) - 1; /* tableLog <= maxTableLog */ + U32 nextRankVal = 0; + U32 w; + for (w=1; w<maxW+1; w++) { + U32 current = nextRankVal; + nextRankVal += rankStats[w] << (w+rescale); + rankVal0[w] = current; + } } + { U32 const minBits = tableLog+1 - maxW; + U32 consumed; + for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) { + U32* const rankValPtr = rankVal[consumed]; + U32 w; + for (w = 1; w < maxW+1; w++) { + rankValPtr[w] = rankVal0[w] >> consumed; + } } } } + + HUF_fillDTableX2(dt, maxTableLog, + sortedSymbol, sizeOfSort, + rankStart0, rankVal, maxW, + tableLog+1); + + dtd.tableLog = (BYTE)maxTableLog; + dtd.tableType = 1; + memcpy(DTable, &dtd, sizeof(dtd)); + return iSize; +} + +size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_readDTableX2_wksp(DTable, src, srcSize, + workSpace, sizeof(workSpace)); +} + + +FORCE_INLINE_TEMPLATE U32 +HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog) +{ + size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ + memcpy(op, dt+val, 2); + BIT_skipBits(DStream, dt[val].nbBits); + return dt[val].length; +} + +FORCE_INLINE_TEMPLATE U32 +HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog) +{ + size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ + memcpy(op, dt+val, 1); + if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits); + else { + if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) { + BIT_skipBits(DStream, dt[val].nbBits); + if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8)) + /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */ + DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8); + } } + return 1; +} + +#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \ + ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog) + +#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \ + if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \ + ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog) + +#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \ + if (MEM_64bits()) \ + ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog) + +HINT_INLINE size_t +HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, + const HUF_DEltX2* const dt, const U32 dtLog) +{ + BYTE* const pStart = p; + + /* up to 8 symbols at a time */ + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) { + HUF_DECODE_SYMBOLX2_2(p, bitDPtr); + HUF_DECODE_SYMBOLX2_1(p, bitDPtr); + HUF_DECODE_SYMBOLX2_2(p, bitDPtr); + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + } + + /* closer to end : up to 2 symbols at a time */ + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2)) + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + + while (p <= pEnd-2) + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); /* no need to reload : reached the end of DStream */ + + if (p < pEnd) + p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog); + + return p-pStart; +} + +FORCE_INLINE_TEMPLATE size_t +HUF_decompress1X2_usingDTable_internal_body( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + BIT_DStream_t bitD; + + /* Init */ + CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) ); + + /* decode */ + { BYTE* const ostart = (BYTE*) dst; + BYTE* const oend = ostart + dstSize; + const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */ + const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr; + DTableDesc const dtd = HUF_getDTableDesc(DTable); + HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog); + } + + /* check */ + if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected); + + /* decoded size */ + return dstSize; +} + + +FORCE_INLINE_TEMPLATE size_t +HUF_decompress4X2_usingDTable_internal_body( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ + + { const BYTE* const istart = (const BYTE*) cSrc; + BYTE* const ostart = (BYTE*) dst; + BYTE* const oend = ostart + dstSize; + const void* const dtPtr = DTable+1; + const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr; + + /* Init */ + BIT_DStream_t bitD1; + BIT_DStream_t bitD2; + BIT_DStream_t bitD3; + BIT_DStream_t bitD4; + size_t const length1 = MEM_readLE16(istart); + size_t const length2 = MEM_readLE16(istart+2); + size_t const length3 = MEM_readLE16(istart+4); + size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6); + const BYTE* const istart1 = istart + 6; /* jumpTable */ + const BYTE* const istart2 = istart1 + length1; + const BYTE* const istart3 = istart2 + length2; + const BYTE* const istart4 = istart3 + length3; + size_t const segmentSize = (dstSize+3) / 4; + BYTE* const opStart2 = ostart + segmentSize; + BYTE* const opStart3 = opStart2 + segmentSize; + BYTE* const opStart4 = opStart3 + segmentSize; + BYTE* op1 = ostart; + BYTE* op2 = opStart2; + BYTE* op3 = opStart3; + BYTE* op4 = opStart4; + U32 endSignal; + DTableDesc const dtd = HUF_getDTableDesc(DTable); + U32 const dtLog = dtd.tableLog; + + if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ + CHECK_F( BIT_initDStream(&bitD1, istart1, length1) ); + CHECK_F( BIT_initDStream(&bitD2, istart2, length2) ); + CHECK_F( BIT_initDStream(&bitD3, istart3, length3) ); + CHECK_F( BIT_initDStream(&bitD4, istart4, length4) ); + + /* 16-32 symbols per loop (4-8 symbols per stream) */ + endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); + for ( ; (endSignal==BIT_DStream_unfinished) & (op4<(oend-(sizeof(bitD4.bitContainer)-1))) ; ) { + HUF_DECODE_SYMBOLX2_2(op1, &bitD1); + HUF_DECODE_SYMBOLX2_2(op2, &bitD2); + HUF_DECODE_SYMBOLX2_2(op3, &bitD3); + HUF_DECODE_SYMBOLX2_2(op4, &bitD4); + HUF_DECODE_SYMBOLX2_1(op1, &bitD1); + HUF_DECODE_SYMBOLX2_1(op2, &bitD2); + HUF_DECODE_SYMBOLX2_1(op3, &bitD3); + HUF_DECODE_SYMBOLX2_1(op4, &bitD4); + HUF_DECODE_SYMBOLX2_2(op1, &bitD1); + HUF_DECODE_SYMBOLX2_2(op2, &bitD2); + HUF_DECODE_SYMBOLX2_2(op3, &bitD3); + HUF_DECODE_SYMBOLX2_2(op4, &bitD4); + HUF_DECODE_SYMBOLX2_0(op1, &bitD1); + HUF_DECODE_SYMBOLX2_0(op2, &bitD2); + HUF_DECODE_SYMBOLX2_0(op3, &bitD3); + HUF_DECODE_SYMBOLX2_0(op4, &bitD4); + + endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); + } + + /* check corruption */ + if (op1 > opStart2) return ERROR(corruption_detected); + if (op2 > opStart3) return ERROR(corruption_detected); + if (op3 > opStart4) return ERROR(corruption_detected); + /* note : op4 already verified within main loop */ + + /* finish bitStreams one by one */ + HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog); + HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog); + HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog); + HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog); + + /* check */ + { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); + if (!endCheck) return ERROR(corruption_detected); } + + /* decoded size */ + return dstSize; + } +} + +HUF_DGEN(HUF_decompress1X2_usingDTable_internal) +HUF_DGEN(HUF_decompress4X2_usingDTable_internal) + +size_t HUF_decompress1X2_usingDTable( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + DTableDesc dtd = HUF_getDTableDesc(DTable); + if (dtd.tableType != 1) return ERROR(GENERIC); + return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); +} + +size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + void* workSpace, size_t wkspSize) +{ + const BYTE* ip = (const BYTE*) cSrc; + + size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize, + workSpace, wkspSize); + if (HUF_isError(hSize)) return hSize; + if (hSize >= cSrcSize) return ERROR(srcSize_wrong); + ip += hSize; cSrcSize -= hSize; + + return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0); +} + + +size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); + return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); +} + +size_t HUF_decompress4X2_usingDTable( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + DTableDesc dtd = HUF_getDTableDesc(DTable); + if (dtd.tableType != 1) return ERROR(GENERIC); + return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); +} + +static size_t HUF_decompress4X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + void* workSpace, size_t wkspSize, int bmi2) +{ + const BYTE* ip = (const BYTE*) cSrc; + + size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize, + workSpace, wkspSize); + if (HUF_isError(hSize)) return hSize; + if (hSize >= cSrcSize) return ERROR(srcSize_wrong); + ip += hSize; cSrcSize -= hSize; + + return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2); +} + +size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + void* workSpace, size_t wkspSize) +{ + return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, /* bmi2 */ 0); +} + + +size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); + return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); +} + + +/* ***********************************/ +/* Universal decompression selectors */ +/* ***********************************/ + +size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + DTableDesc const dtd = HUF_getDTableDesc(DTable); + return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) : + HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); +} + +size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + DTableDesc const dtd = HUF_getDTableDesc(DTable); + return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) : + HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); +} + + +typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t; +static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] = +{ + /* single, double, quad */ + {{0,0}, {1,1}, {2,2}}, /* Q==0 : impossible */ + {{0,0}, {1,1}, {2,2}}, /* Q==1 : impossible */ + {{ 38,130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */ + {{ 448,128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */ + {{ 556,128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */ + {{ 714,128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */ + {{ 883,128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */ + {{ 897,128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */ + {{ 926,128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */ + {{ 947,128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */ + {{1107,128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */ + {{1177,128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */ + {{1242,128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */ + {{1349,128}, {2644,106}, {5260,106}}, /* Q ==13 : 81-87% */ + {{1455,128}, {2422,124}, {4174,124}}, /* Q ==14 : 87-93% */ + {{ 722,128}, {1891,145}, {1936,146}}, /* Q ==15 : 93-99% */ +}; + +/** HUF_selectDecoder() : + * Tells which decoder is likely to decode faster, + * based on a set of pre-computed metrics. + * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 . + * Assumption : 0 < dstSize <= 128 KB */ +U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize) +{ + assert(dstSize > 0); + assert(dstSize <= 128*1024); + /* decoder timing evaluation */ + { U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize); /* Q < 16 */ + U32 const D256 = (U32)(dstSize >> 8); + U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256); + U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256); + DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, to reduce cache eviction */ + return DTime1 < DTime0; +} } + + +typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); + +size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 }; + + /* validation checks */ + if (dstSize == 0) return ERROR(dstSize_tooSmall); + if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ + if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ + if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ + + { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); + return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); + } +} + +size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + /* validation checks */ + if (dstSize == 0) return ERROR(dstSize_tooSmall); + if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ + if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ + if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ + + { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); + return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) : + HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ; + } +} + +size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress4X_hufOnly_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + + +size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, + size_t dstSize, const void* cSrc, + size_t cSrcSize, void* workSpace, + size_t wkspSize) +{ + /* validation checks */ + if (dstSize == 0) return ERROR(dstSize_tooSmall); + if (cSrcSize == 0) return ERROR(corruption_detected); + + { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); + return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize): + HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize); + } +} + +size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + void* workSpace, size_t wkspSize) +{ + /* validation checks */ + if (dstSize == 0) return ERROR(dstSize_tooSmall); + if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ + if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ + if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ + + { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); + return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc, + cSrcSize, workSpace, wkspSize): + HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc, + cSrcSize, workSpace, wkspSize); + } +} + +size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + + +size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2) +{ + DTableDesc const dtd = HUF_getDTableDesc(DTable); + return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) : + HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2); +} + +size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2) +{ + const BYTE* ip = (const BYTE*) cSrc; + + size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize); + if (HUF_isError(hSize)) return hSize; + if (hSize >= cSrcSize) return ERROR(srcSize_wrong); + ip += hSize; cSrcSize -= hSize; + + return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2); +} + +size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2) +{ + DTableDesc const dtd = HUF_getDTableDesc(DTable); + return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) : + HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2); +} + +size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2) +{ + /* validation checks */ + if (dstSize == 0) return ERROR(dstSize_tooSmall); + if (cSrcSize == 0) return ERROR(corruption_detected); + + { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); + return algoNb ? HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2) : + HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2); + } +} diff --git a/grub-core/lib/zstd/mem.h b/grub-core/lib/zstd/mem.h new file mode 100644 index 0000000..2051bca --- /dev/null +++ b/grub-core/lib/zstd/mem.h @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef MEM_H_MODULE +#define MEM_H_MODULE + +#if defined (__cplusplus) +extern "C" { +#endif + +/*-**************************************** +* Dependencies +******************************************/ +#include <stddef.h> /* size_t, ptrdiff_t */ +#include <string.h> /* memcpy */ + + +/*-**************************************** +* Compiler specifics +******************************************/ +#if defined(_MSC_VER) /* Visual Studio */ +# include <stdlib.h> /* _byteswap_ulong */ +# include <intrin.h> /* _byteswap_* */ +#endif +#if defined(__GNUC__) +# define MEM_STATIC static __inline __attribute__((unused)) +#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define MEM_STATIC static inline +#elif defined(_MSC_VER) +# define MEM_STATIC static __inline +#else +# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ +#endif + +/* code only tested on 32 and 64 bits systems */ +#define MEM_STATIC_ASSERT(c) { enum { MEM_static_assert = 1/(int)(!!(c)) }; } +MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); } + + +/*-************************************************************** +* Basic Types +*****************************************************************/ +#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include <stdint.h> + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef int16_t S16; + typedef uint32_t U32; + typedef int32_t S32; + typedef uint64_t U64; + typedef int64_t S64; +#else +# include <limits.h> +#if CHAR_BIT != 8 +# error "this implementation requires char to be exactly 8-bit type" +#endif + typedef unsigned char BYTE; +#if USHRT_MAX != 65535 +# error "this implementation requires short to be exactly 16-bit type" +#endif + typedef unsigned short U16; + typedef signed short S16; +#if UINT_MAX != 4294967295 +# error "this implementation requires int to be exactly 32-bit type" +#endif + typedef unsigned int U32; + typedef signed int S32; +/* note : there are no limits defined for long long type in C90. + * limits exist in C99, however, in such case, <stdint.h> is preferred */ + typedef unsigned long long U64; + typedef signed long long S64; +#endif + + +/*-************************************************************** +* Memory I/O +*****************************************************************/ +/* MEM_FORCE_MEMORY_ACCESS : + * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. + * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. + * The below switch allow to select different access method for improved performance. + * Method 0 (default) : use `memcpy()`. Safe and portable. + * Method 1 : `__packed` statement. It depends on compiler extension (i.e., not portable). + * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. + * Method 2 : direct access. This method is portable but violate C standard. + * It can generate buggy code on targets depending on alignment. + * In some circumstances, it's the only known way to get the most performance (i.e. GCC + ARMv6) + * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details. + * Prefer these methods in priority order (0 > 1 > 2) + */ +#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ +# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) +# define MEM_FORCE_MEMORY_ACCESS 2 +# elif defined(__INTEL_COMPILER) || defined(__GNUC__) +# define MEM_FORCE_MEMORY_ACCESS 1 +# endif +#endif + +MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; } +MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; } + +MEM_STATIC unsigned MEM_isLittleEndian(void) +{ + const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ + return one.c[0]; +} + +#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2) + +/* violates C standard, by lying on structure alignment. +Only use if no other choice to achieve best performance on target platform */ +MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; } +MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; } +MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; } +MEM_STATIC size_t MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; } + +MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; } +MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; } +MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; } + +#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +#if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(WIN32)) + __pragma( pack(push, 1) ) + typedef struct { U16 v; } unalign16; + typedef struct { U32 v; } unalign32; + typedef struct { U64 v; } unalign64; + typedef struct { size_t v; } unalignArch; + __pragma( pack(pop) ) +#else + typedef struct { U16 v; } __attribute__((packed)) unalign16; + typedef struct { U32 v; } __attribute__((packed)) unalign32; + typedef struct { U64 v; } __attribute__((packed)) unalign64; + typedef struct { size_t v; } __attribute__((packed)) unalignArch; +#endif + +MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign16*)ptr)->v; } +MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign32*)ptr)->v; } +MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign64*)ptr)->v; } +MEM_STATIC size_t MEM_readST(const void* ptr) { return ((const unalignArch*)ptr)->v; } + +MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign16*)memPtr)->v = value; } +MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign32*)memPtr)->v = value; } +MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign64*)memPtr)->v = value; } + +#else + +/* default method, safe and standard. + can sometimes prove slower */ + +MEM_STATIC U16 MEM_read16(const void* memPtr) +{ + U16 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +MEM_STATIC U32 MEM_read32(const void* memPtr) +{ + U32 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +MEM_STATIC U64 MEM_read64(const void* memPtr) +{ + U64 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +MEM_STATIC size_t MEM_readST(const void* memPtr) +{ + size_t val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +MEM_STATIC void MEM_write16(void* memPtr, U16 value) +{ + memcpy(memPtr, &value, sizeof(value)); +} + +MEM_STATIC void MEM_write32(void* memPtr, U32 value) +{ + memcpy(memPtr, &value, sizeof(value)); +} + +MEM_STATIC void MEM_write64(void* memPtr, U64 value) +{ + memcpy(memPtr, &value, sizeof(value)); +} + +#endif /* MEM_FORCE_MEMORY_ACCESS */ + +MEM_STATIC U32 MEM_swap32(U32 in) +{ +#if defined(_MSC_VER) /* Visual Studio */ + return _byteswap_ulong(in); +#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403) + return __builtin_bswap32(in); +#else + return ((in << 24) & 0xff000000 ) | + ((in << 8) & 0x00ff0000 ) | + ((in >> 8) & 0x0000ff00 ) | + ((in >> 24) & 0x000000ff ); +#endif +} + +MEM_STATIC U64 MEM_swap64(U64 in) +{ +#if defined(_MSC_VER) /* Visual Studio */ + return _byteswap_uint64(in); +#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403) + return __builtin_bswap64(in); +#else + return ((in << 56) & 0xff00000000000000ULL) | + ((in << 40) & 0x00ff000000000000ULL) | + ((in << 24) & 0x0000ff0000000000ULL) | + ((in << 8) & 0x000000ff00000000ULL) | + ((in >> 8) & 0x00000000ff000000ULL) | + ((in >> 24) & 0x0000000000ff0000ULL) | + ((in >> 40) & 0x000000000000ff00ULL) | + ((in >> 56) & 0x00000000000000ffULL); +#endif +} + +MEM_STATIC size_t MEM_swapST(size_t in) +{ + if (MEM_32bits()) + return (size_t)MEM_swap32((U32)in); + else + return (size_t)MEM_swap64((U64)in); +} + +/*=== Little endian r/w ===*/ + +MEM_STATIC U16 MEM_readLE16(const void* memPtr) +{ + if (MEM_isLittleEndian()) + return MEM_read16(memPtr); + else { + const BYTE* p = (const BYTE*)memPtr; + return (U16)(p[0] + (p[1]<<8)); + } +} + +MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) +{ + if (MEM_isLittleEndian()) { + MEM_write16(memPtr, val); + } else { + BYTE* p = (BYTE*)memPtr; + p[0] = (BYTE)val; + p[1] = (BYTE)(val>>8); + } +} + +MEM_STATIC U32 MEM_readLE24(const void* memPtr) +{ + return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16); +} + +MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val) +{ + MEM_writeLE16(memPtr, (U16)val); + ((BYTE*)memPtr)[2] = (BYTE)(val>>16); +} + +MEM_STATIC U32 MEM_readLE32(const void* memPtr) +{ + if (MEM_isLittleEndian()) + return MEM_read32(memPtr); + else + return MEM_swap32(MEM_read32(memPtr)); +} + +MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32) +{ + if (MEM_isLittleEndian()) + MEM_write32(memPtr, val32); + else + MEM_write32(memPtr, MEM_swap32(val32)); +} + +MEM_STATIC U64 MEM_readLE64(const void* memPtr) +{ + if (MEM_isLittleEndian()) + return MEM_read64(memPtr); + else + return MEM_swap64(MEM_read64(memPtr)); +} + +MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64) +{ + if (MEM_isLittleEndian()) + MEM_write64(memPtr, val64); + else + MEM_write64(memPtr, MEM_swap64(val64)); +} + +MEM_STATIC size_t MEM_readLEST(const void* memPtr) +{ + if (MEM_32bits()) + return (size_t)MEM_readLE32(memPtr); + else + return (size_t)MEM_readLE64(memPtr); +} + +MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val) +{ + if (MEM_32bits()) + MEM_writeLE32(memPtr, (U32)val); + else + MEM_writeLE64(memPtr, (U64)val); +} + +/*=== Big endian r/w ===*/ + +MEM_STATIC U32 MEM_readBE32(const void* memPtr) +{ + if (MEM_isLittleEndian()) + return MEM_swap32(MEM_read32(memPtr)); + else + return MEM_read32(memPtr); +} + +MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32) +{ + if (MEM_isLittleEndian()) + MEM_write32(memPtr, MEM_swap32(val32)); + else + MEM_write32(memPtr, val32); +} + +MEM_STATIC U64 MEM_readBE64(const void* memPtr) +{ + if (MEM_isLittleEndian()) + return MEM_swap64(MEM_read64(memPtr)); + else + return MEM_read64(memPtr); +} + +MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64) +{ + if (MEM_isLittleEndian()) + MEM_write64(memPtr, MEM_swap64(val64)); + else + MEM_write64(memPtr, val64); +} + +MEM_STATIC size_t MEM_readBEST(const void* memPtr) +{ + if (MEM_32bits()) + return (size_t)MEM_readBE32(memPtr); + else + return (size_t)MEM_readBE64(memPtr); +} + +MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val) +{ + if (MEM_32bits()) + MEM_writeBE32(memPtr, (U32)val); + else + MEM_writeBE64(memPtr, (U64)val); +} + + +#if defined (__cplusplus) +} +#endif + +#endif /* MEM_H_MODULE */ diff --git a/grub-core/lib/zstd/module.c b/grub-core/lib/zstd/module.c new file mode 100644 index 0000000..e64d068 --- /dev/null +++ b/grub-core/lib/zstd/module.c @@ -0,0 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/dl.h> + +GRUB_MOD_LICENSE ("GPLv3"); diff --git a/grub-core/lib/zstd/xxhash.c b/grub-core/lib/zstd/xxhash.c new file mode 100644 index 0000000..532b816 --- /dev/null +++ b/grub-core/lib/zstd/xxhash.c @@ -0,0 +1,876 @@ +/* +* xxHash - Fast Hash algorithm +* Copyright (C) 2012-2016, Yann Collet +* +* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* You can contact the author at : +* - xxHash homepage: http://www.xxhash.com +* - xxHash source repository : https://github.com/Cyan4973/xxHash +*/ + + +/* ************************************* +* Tuning parameters +***************************************/ +/*!XXH_FORCE_MEMORY_ACCESS : + * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. + * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. + * The below switch allow to select different access method for improved performance. + * Method 0 (default) : use `memcpy()`. Safe and portable. + * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). + * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. + * Method 2 : direct access. This method doesn't depend on compiler but violate C standard. + * It can generate buggy code on targets which do not support unaligned memory accesses. + * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) + * See http://stackoverflow.com/a/32095106/646947 for details. + * Prefer these methods in priority order (0 > 1 > 2) + */ +#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ +# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) +# define XXH_FORCE_MEMORY_ACCESS 2 +# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \ + (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) +# define XXH_FORCE_MEMORY_ACCESS 1 +# endif +#endif + +/*!XXH_ACCEPT_NULL_INPUT_POINTER : + * If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer. + * When this option is enabled, xxHash output for null input pointers will be the same as a null-length input. + * By default, this option is disabled. To enable it, uncomment below define : + */ +/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */ + +/*!XXH_FORCE_NATIVE_FORMAT : + * By default, xxHash library provides endian-independant Hash values, based on little-endian convention. + * Results are therefore identical for little-endian and big-endian CPU. + * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. + * Should endian-independance be of no importance for your application, you may set the #define below to 1, + * to improve speed for Big-endian CPU. + * This option has no impact on Little_Endian CPU. + */ +#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */ +# define XXH_FORCE_NATIVE_FORMAT 0 +#endif + +/*!XXH_FORCE_ALIGN_CHECK : + * This is a minor performance trick, only useful with lots of very small keys. + * It means : check for aligned/unaligned input. + * The check costs one initial branch per hash; set to 0 when the input data + * is guaranteed to be aligned. + */ +#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ +# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) +# define XXH_FORCE_ALIGN_CHECK 0 +# else +# define XXH_FORCE_ALIGN_CHECK 1 +# endif +#endif + + +/* ************************************* +* Includes & Memory related functions +***************************************/ +/* Modify the local functions below should you wish to use some other memory routines */ +/* for malloc(), free() */ +#include <stdlib.h> +#include <stddef.h> /* size_t */ +static void* XXH_malloc(size_t s) { return malloc(s); } +static void XXH_free (void* p) { free(p); } +/* for memcpy() */ +#include <string.h> +static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } + +#ifndef XXH_STATIC_LINKING_ONLY +# define XXH_STATIC_LINKING_ONLY +#endif +#include "xxhash.h" + + +/* ************************************* +* Compiler Specific Options +***************************************/ +#if defined (__GNUC__) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# define INLINE_KEYWORD inline +#else +# define INLINE_KEYWORD +#endif + +#if defined(__GNUC__) +# define FORCE_INLINE_ATTR __attribute__((always_inline)) +#elif defined(_MSC_VER) +# define FORCE_INLINE_ATTR __forceinline +#else +# define FORCE_INLINE_ATTR +#endif + +#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR + + +#ifdef _MSC_VER +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +#endif + + +/* ************************************* +* Basic Types +***************************************/ +#ifndef MEM_MODULE +# define MEM_MODULE +# if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include <stdint.h> + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; + typedef int32_t S32; + typedef uint64_t U64; +# else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; + typedef signed int S32; + typedef unsigned long long U64; /* if your compiler doesn't support unsigned long long, replace by another 64-bit type here. Note that xxhash.h will also need to be updated. */ +# endif +#endif + + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ +static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; } +static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; } + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign; + +static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } +static U64 XXH_read64(const void* ptr) { return ((const unalign*)ptr)->u64; } + +#else + +/* portable and safe solution. Generally efficient. + * see : http://stackoverflow.com/a/32095106/646947 + */ + +static U32 XXH_read32(const void* memPtr) +{ + U32 val; + memcpy(&val, memPtr, sizeof(val)); + return val; +} + +static U64 XXH_read64(const void* memPtr) +{ + U64 val; + memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + + +/* **************************************** +* Compiler-specific Functions and Macros +******************************************/ +#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ +#if defined(_MSC_VER) +# define XXH_rotl32(x,r) _rotl(x,r) +# define XXH_rotl64(x,r) _rotl64(x,r) +#else +# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) +# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r))) +#endif + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap32 _byteswap_ulong +# define XXH_swap64 _byteswap_uint64 +#elif GCC_VERSION >= 403 +# define XXH_swap32 __builtin_bswap32 +# define XXH_swap64 __builtin_bswap64 +#else +static U32 XXH_swap32 (U32 x) +{ + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} +static U64 XXH_swap64 (U64 x) +{ + return ((x << 56) & 0xff00000000000000ULL) | + ((x << 40) & 0x00ff000000000000ULL) | + ((x << 24) & 0x0000ff0000000000ULL) | + ((x << 8) & 0x000000ff00000000ULL) | + ((x >> 8) & 0x00000000ff000000ULL) | + ((x >> 24) & 0x0000000000ff0000ULL) | + ((x >> 40) & 0x000000000000ff00ULL) | + ((x >> 56) & 0x00000000000000ffULL); +} +#endif + + +/* ************************************* +* Architecture Macros +***************************************/ +typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; + +/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */ +#ifndef XXH_CPU_LITTLE_ENDIAN + static const int g_one = 1; +# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&g_one)) +#endif + + +/* *************************** +* Memory reads +*****************************/ +typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; + +FORCE_INLINE_TEMPLATE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align) +{ + if (align==XXH_unaligned) + return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); + else + return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr); +} + +FORCE_INLINE_TEMPLATE U32 XXH_readLE32(const void* ptr, XXH_endianess endian) +{ + return XXH_readLE32_align(ptr, endian, XXH_unaligned); +} + +static U32 XXH_readBE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); +} + +FORCE_INLINE_TEMPLATE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align) +{ + if (align==XXH_unaligned) + return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); + else + return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr); +} + +FORCE_INLINE_TEMPLATE U64 XXH_readLE64(const void* ptr, XXH_endianess endian) +{ + return XXH_readLE64_align(ptr, endian, XXH_unaligned); +} + +static U64 XXH_readBE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); +} + + +/* ************************************* +* Macros +***************************************/ +#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ + + +/* ************************************* +* Constants +***************************************/ +static const U32 PRIME32_1 = 2654435761U; +static const U32 PRIME32_2 = 2246822519U; +static const U32 PRIME32_3 = 3266489917U; +static const U32 PRIME32_4 = 668265263U; +static const U32 PRIME32_5 = 374761393U; + +static const U64 PRIME64_1 = 11400714785074694791ULL; +static const U64 PRIME64_2 = 14029467366897019727ULL; +static const U64 PRIME64_3 = 1609587929392839161ULL; +static const U64 PRIME64_4 = 9650029242287828579ULL; +static const U64 PRIME64_5 = 2870177450012600261ULL; + +XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } + + +/* ************************** +* Utils +****************************/ +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dstState, const XXH32_state_t* restrict srcState) +{ + memcpy(dstState, srcState, sizeof(*dstState)); +} + +XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dstState, const XXH64_state_t* restrict srcState) +{ + memcpy(dstState, srcState, sizeof(*dstState)); +} + + +/* *************************** +* Simple Hash Functions +*****************************/ + +static U32 XXH32_round(U32 seed, U32 input) +{ + seed += input * PRIME32_2; + seed = XXH_rotl32(seed, 13); + seed *= PRIME32_1; + return seed; +} + +FORCE_INLINE_TEMPLATE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* bEnd = p + len; + U32 h32; +#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align) + +#ifdef XXH_ACCEPT_NULL_INPUT_POINTER + if (p==NULL) { + len=0; + bEnd=p=(const BYTE*)(size_t)16; + } +#endif + + if (len>=16) { + const BYTE* const limit = bEnd - 16; + U32 v1 = seed + PRIME32_1 + PRIME32_2; + U32 v2 = seed + PRIME32_2; + U32 v3 = seed + 0; + U32 v4 = seed - PRIME32_1; + + do { + v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4; + v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4; + v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4; + v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4; + } while (p<=limit); + + h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); + } else { + h32 = seed + PRIME32_5; + } + + h32 += (U32) len; + + while (p+4<=bEnd) { + h32 += XXH_get32bits(p) * PRIME32_3; + h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; + p+=4; + } + + while (p<bEnd) { + h32 += (*p) * PRIME32_5; + h32 = XXH_rotl32(h32, 11) * PRIME32_1 ; + p++; + } + + h32 ^= h32 >> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} + + +XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed) +{ +#if 0 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH32_CREATESTATE_STATIC(state); + XXH32_reset(state, seed); + XXH32_update(state, input, len); + return XXH32_digest(state); +#else + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); + } } + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); +#endif +} + + +static U64 XXH64_round(U64 acc, U64 input) +{ + acc += input * PRIME64_2; + acc = XXH_rotl64(acc, 31); + acc *= PRIME64_1; + return acc; +} + +static U64 XXH64_mergeRound(U64 acc, U64 val) +{ + val = XXH64_round(0, val); + acc ^= val; + acc = acc * PRIME64_1 + PRIME64_4; + return acc; +} + +FORCE_INLINE_TEMPLATE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + U64 h64; +#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align) + +#ifdef XXH_ACCEPT_NULL_INPUT_POINTER + if (p==NULL) { + len=0; + bEnd=p=(const BYTE*)(size_t)32; + } +#endif + + if (len>=32) { + const BYTE* const limit = bEnd - 32; + U64 v1 = seed + PRIME64_1 + PRIME64_2; + U64 v2 = seed + PRIME64_2; + U64 v3 = seed + 0; + U64 v4 = seed - PRIME64_1; + + do { + v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8; + v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8; + v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8; + v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8; + } while (p<=limit); + + h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); + h64 = XXH64_mergeRound(h64, v1); + h64 = XXH64_mergeRound(h64, v2); + h64 = XXH64_mergeRound(h64, v3); + h64 = XXH64_mergeRound(h64, v4); + + } else { + h64 = seed + PRIME64_5; + } + + h64 += (U64) len; + + while (p+8<=bEnd) { + U64 const k1 = XXH64_round(0, XXH_get64bits(p)); + h64 ^= k1; + h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; + p+=8; + } + + if (p+4<=bEnd) { + h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; + h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; + p+=4; + } + + while (p<bEnd) { + h64 ^= (*p) * PRIME64_5; + h64 = XXH_rotl64(h64, 11) * PRIME64_1; + p++; + } + + h64 ^= h64 >> 33; + h64 *= PRIME64_2; + h64 ^= h64 >> 29; + h64 *= PRIME64_3; + h64 ^= h64 >> 32; + + return h64; +} + + +XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed) +{ +#if 0 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH64_CREATESTATE_STATIC(state); + XXH64_reset(state, seed); + XXH64_update(state, input, len); + return XXH64_digest(state); +#else + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); + else + return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); + } } + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); + else + return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); +#endif +} + + +/* ************************************************** +* Advanced Hash Functions +****************************************************/ + +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) +{ + return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); +} +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) +{ + return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); +} +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + + +/*** Hash feed ***/ + +XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed) +{ + XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ + memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */ + state.v1 = seed + PRIME32_1 + PRIME32_2; + state.v2 = seed + PRIME32_2; + state.v3 = seed + 0; + state.v4 = seed - PRIME32_1; + memcpy(statePtr, &state, sizeof(state)); + return XXH_OK; +} + + +XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed) +{ + XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ + memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */ + state.v1 = seed + PRIME64_1 + PRIME64_2; + state.v2 = seed + PRIME64_2; + state.v3 = seed + 0; + state.v4 = seed - PRIME64_1; + memcpy(statePtr, &state, sizeof(state)); + return XXH_OK; +} + + +FORCE_INLINE_TEMPLATE XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + +#ifdef XXH_ACCEPT_NULL_INPUT_POINTER + if (input==NULL) return XXH_ERROR; +#endif + + state->total_len_32 += (unsigned)len; + state->large_len |= (len>=16) | (state->total_len_32>=16); + + if (state->memsize + len < 16) { /* fill in tmp buffer */ + XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len); + state->memsize += (unsigned)len; + return XXH_OK; + } + + if (state->memsize) { /* some data left from previous update */ + XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize); + { const U32* p32 = state->mem32; + state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++; + state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++; + state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++; + state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); p32++; + } + p += 16-state->memsize; + state->memsize = 0; + } + + if (p <= bEnd-16) { + const BYTE* const limit = bEnd - 16; + U32 v1 = state->v1; + U32 v2 = state->v2; + U32 v3 = state->v3; + U32 v4 = state->v4; + + do { + v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4; + v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4; + v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4; + v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) { + XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + + return XXH_OK; +} + +XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_update_endian(state_in, input, len, XXH_littleEndian); + else + return XXH32_update_endian(state_in, input, len, XXH_bigEndian); +} + + + +FORCE_INLINE_TEMPLATE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian) +{ + const BYTE * p = (const BYTE*)state->mem32; + const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize; + U32 h32; + + if (state->large_len) { + h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18); + } else { + h32 = state->v3 /* == seed */ + PRIME32_5; + } + + h32 += state->total_len_32; + + while (p+4<=bEnd) { + h32 += XXH_readLE32(p, endian) * PRIME32_3; + h32 = XXH_rotl32(h32, 17) * PRIME32_4; + p+=4; + } + + while (p<bEnd) { + h32 += (*p) * PRIME32_5; + h32 = XXH_rotl32(h32, 11) * PRIME32_1; + p++; + } + + h32 ^= h32 >> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} + + +XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_digest_endian(state_in, XXH_littleEndian); + else + return XXH32_digest_endian(state_in, XXH_bigEndian); +} + + + +/* **** XXH64 **** */ + +FORCE_INLINE_TEMPLATE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + +#ifdef XXH_ACCEPT_NULL_INPUT_POINTER + if (input==NULL) return XXH_ERROR; +#endif + + state->total_len += len; + + if (state->memsize + len < 32) { /* fill in tmp buffer */ + XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len); + state->memsize += (U32)len; + return XXH_OK; + } + + if (state->memsize) { /* tmp buffer is full */ + XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize); + state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian)); + state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian)); + state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian)); + state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian)); + p += 32-state->memsize; + state->memsize = 0; + } + + if (p+32 <= bEnd) { + const BYTE* const limit = bEnd - 32; + U64 v1 = state->v1; + U64 v2 = state->v2; + U64 v3 = state->v3; + U64 v4 = state->v4; + + do { + v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8; + v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8; + v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8; + v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) { + XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + + return XXH_OK; +} + +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_update_endian(state_in, input, len, XXH_littleEndian); + else + return XXH64_update_endian(state_in, input, len, XXH_bigEndian); +} + + + +FORCE_INLINE_TEMPLATE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian) +{ + const BYTE * p = (const BYTE*)state->mem64; + const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize; + U64 h64; + + if (state->total_len >= 32) { + U64 const v1 = state->v1; + U64 const v2 = state->v2; + U64 const v3 = state->v3; + U64 const v4 = state->v4; + + h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); + h64 = XXH64_mergeRound(h64, v1); + h64 = XXH64_mergeRound(h64, v2); + h64 = XXH64_mergeRound(h64, v3); + h64 = XXH64_mergeRound(h64, v4); + } else { + h64 = state->v3 + PRIME64_5; + } + + h64 += (U64) state->total_len; + + while (p+8<=bEnd) { + U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian)); + h64 ^= k1; + h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; + p+=8; + } + + if (p+4<=bEnd) { + h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1; + h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; + p+=4; + } + + while (p<bEnd) { + h64 ^= (*p) * PRIME64_5; + h64 = XXH_rotl64(h64, 11) * PRIME64_1; + p++; + } + + h64 ^= h64 >> 33; + h64 *= PRIME64_2; + h64 ^= h64 >> 29; + h64 *= PRIME64_3; + h64 ^= h64 >> 32; + + return h64; +} + + +XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_digest_endian(state_in, XXH_littleEndian); + else + return XXH64_digest_endian(state_in, XXH_bigEndian); +} + + +/* ************************** +* Canonical representation +****************************/ + +/*! Default XXH result types are basic unsigned 32 and 64 bits. +* The canonical representation follows human-readable write convention, aka big-endian (large digits first). +* These functions allow transformation of hash result into and from its canonical format. +* This way, hash values can be written into a file or buffer, and remain comparable across different systems and programs. +*/ + +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); + memcpy(dst, &hash, sizeof(*dst)); +} + +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); + memcpy(dst, &hash, sizeof(*dst)); +} + +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) +{ + return XXH_readBE32(src); +} + +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src) +{ + return XXH_readBE64(src); +} diff --git a/grub-core/lib/zstd/xxhash.h b/grub-core/lib/zstd/xxhash.h new file mode 100644 index 0000000..9bad1f5 --- /dev/null +++ b/grub-core/lib/zstd/xxhash.h @@ -0,0 +1,305 @@ +/* + xxHash - Extremely Fast Hash algorithm + Header File + Copyright (C) 2012-2016, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - xxHash source repository : https://github.com/Cyan4973/xxHash +*/ + +/* Notice extracted from xxHash homepage : + +xxHash is an extremely fast Hash algorithm, running at RAM speed limits. +It also successfully passes all tests from the SMHasher suite. + +Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) + +Name Speed Q.Score Author +xxHash 5.4 GB/s 10 +CrapWow 3.2 GB/s 2 Andrew +MumurHash 3a 2.7 GB/s 10 Austin Appleby +SpookyHash 2.0 GB/s 10 Bob Jenkins +SBox 1.4 GB/s 9 Bret Mulvey +Lookup3 1.2 GB/s 9 Bob Jenkins +SuperFastHash 1.2 GB/s 1 Paul Hsieh +CityHash64 1.05 GB/s 10 Pike & Alakuijala +FNV 0.55 GB/s 5 Fowler, Noll, Vo +CRC32 0.43 GB/s 9 +MD5-32 0.33 GB/s 10 Ronald L. Rivest +SHA1-32 0.28 GB/s 10 + +Q.Score is a measure of quality of the hash function. +It depends on successfully passing SMHasher test set. +10 is a perfect score. + +A 64-bits version, named XXH64, is available since r35. +It offers much better speed, but for 64-bits applications only. +Name Speed on 64 bits Speed on 32 bits +XXH64 13.8 GB/s 1.9 GB/s +XXH32 6.8 GB/s 6.0 GB/s +*/ + +#if defined (__cplusplus) +extern "C" { +#endif + +#ifndef XXHASH_H_5627135585666179 +#define XXHASH_H_5627135585666179 1 + + +/* **************************** +* Definitions +******************************/ +#include <stddef.h> /* size_t */ +typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; + + +/* **************************** +* API modifier +******************************/ +/** XXH_PRIVATE_API +* This is useful if you want to include xxhash functions in `static` mode +* in order to inline them, and remove their symbol from the public list. +* Methodology : +* #define XXH_PRIVATE_API +* #include "xxhash.h" +* `xxhash.c` is automatically included. +* It's not useful to compile and link it as a separate module anymore. +*/ +#ifdef XXH_PRIVATE_API +# ifndef XXH_STATIC_LINKING_ONLY +# define XXH_STATIC_LINKING_ONLY +# endif +# if defined(__GNUC__) +# define XXH_PUBLIC_API static __inline __attribute__((unused)) +# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define XXH_PUBLIC_API static inline +# elif defined(_MSC_VER) +# define XXH_PUBLIC_API static __inline +# else +# define XXH_PUBLIC_API static /* this version may generate warnings for unused static functions; disable the relevant warning */ +# endif +#else +# define XXH_PUBLIC_API /* do nothing */ +#endif /* XXH_PRIVATE_API */ + +/*!XXH_NAMESPACE, aka Namespace Emulation : + +If you want to include _and expose_ xxHash functions from within your own library, +but also want to avoid symbol collisions with another library which also includes xxHash, + +you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library +with the value of XXH_NAMESPACE (so avoid to keep it NULL and avoid numeric values). + +Note that no change is required within the calling program as long as it includes `xxhash.h` : +regular symbol name will be automatically translated by this header. +*/ +#ifdef XXH_NAMESPACE +# define XXH_CAT(A,B) A##B +# define XXH_NAME2(A,B) XXH_CAT(A,B) +# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) +# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) +# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) +# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) +# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) +# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) +# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) +# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) +# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) +# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) +# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) +# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) +# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) +# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) +# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) +# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) +# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) +# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) +# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) +#endif + + +/* ************************************* +* Version +***************************************/ +#define XXH_VERSION_MAJOR 0 +#define XXH_VERSION_MINOR 6 +#define XXH_VERSION_RELEASE 2 +#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) +XXH_PUBLIC_API unsigned XXH_versionNumber (void); + + +/* **************************** +* Simple Hash Functions +******************************/ +typedef unsigned int XXH32_hash_t; +typedef unsigned long long XXH64_hash_t; + +XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed); +XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed); + +/*! +XXH32() : + Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input". + The memory between input & input+length must be valid (allocated and read-accessible). + "seed" can be used to alter the result predictably. + Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s +XXH64() : + Calculate the 64-bits hash of sequence of length "len" stored at memory address "input". + "seed" can be used to alter the result predictably. + This function runs 2x faster on 64-bits systems, but slower on 32-bits systems (see benchmark). +*/ + + +/* **************************** +* Streaming Hash Functions +******************************/ +typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */ +typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ + +/*! State allocation, compatible with dynamic libraries */ + +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); + +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); + + +/* hash streaming */ + +XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed); +XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); +XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); + +XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed); +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); +XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); + +/* +These functions generate the xxHash of an input provided in multiple segments. +Note that, for small input, they are slower than single-call functions, due to state management. +For small input, prefer `XXH32()` and `XXH64()` . + +XXH state must first be allocated, using XXH*_createState() . + +Start a new hash by initializing state with a seed, using XXH*_reset(). + +Then, feed the hash state by calling XXH*_update() as many times as necessary. +Obviously, input must be allocated and read accessible. +The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. + +Finally, a hash value can be produced anytime, by using XXH*_digest(). +This function returns the nn-bits hash as an int or long long. + +It's still possible to continue inserting input into the hash state after a digest, +and generate some new hashes later on, by calling again XXH*_digest(). + +When done, free XXH state space if it was allocated dynamically. +*/ + + +/* ************************** +* Utils +****************************/ +#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* ! C99 */ +# define restrict /* disable restrict */ +#endif + +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dst_state, const XXH32_state_t* restrict src_state); +XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dst_state, const XXH64_state_t* restrict src_state); + + +/* ************************** +* Canonical representation +****************************/ +/* Default result type for XXH functions are primitive unsigned 32 and 64 bits. +* The canonical representation uses human-readable write convention, aka big-endian (large digits first). +* These functions allow transformation of hash result into and from its canonical format. +* This way, hash values can be written into a file / memory, and remain comparable on different systems and programs. +*/ +typedef struct { unsigned char digest[4]; } XXH32_canonical_t; +typedef struct { unsigned char digest[8]; } XXH64_canonical_t; + +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); + +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); + +#endif /* XXHASH_H_5627135585666179 */ + + + +/* ================================================================================================ + This section contains definitions which are not guaranteed to remain stable. + They may change in future versions, becoming incompatible with a different version of the library. + They shall only be used with static linking. + Never use these definitions in association with dynamic linking ! +=================================================================================================== */ +#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXH_STATIC_H_3543687687345) +#define XXH_STATIC_H_3543687687345 + +/* These definitions are only meant to allow allocation of XXH state + statically, on stack, or in a struct for example. + Do not use members directly. */ + + struct XXH32_state_s { + unsigned total_len_32; + unsigned large_len; + unsigned v1; + unsigned v2; + unsigned v3; + unsigned v4; + unsigned mem32[4]; /* buffer defined as U32 for alignment */ + unsigned memsize; + unsigned reserved; /* never read nor write, will be removed in a future version */ + }; /* typedef'd to XXH32_state_t */ + + struct XXH64_state_s { + unsigned long long total_len; + unsigned long long v1; + unsigned long long v2; + unsigned long long v3; + unsigned long long v4; + unsigned long long mem64[4]; /* buffer defined as U64 for alignment */ + unsigned memsize; + unsigned reserved[2]; /* never read nor write, will be removed in a future version */ + }; /* typedef'd to XXH64_state_t */ + + +# ifdef XXH_PRIVATE_API +# include "xxhash.c" /* include xxhash functions as `static`, for inlining */ +# endif + +#endif /* XXH_STATIC_LINKING_ONLY && XXH_STATIC_H_3543687687345 */ + + +#if defined (__cplusplus) +} +#endif diff --git a/grub-core/lib/zstd/zstd.h b/grub-core/lib/zstd/zstd.h new file mode 100644 index 0000000..7b6964b --- /dev/null +++ b/grub-core/lib/zstd/zstd.h @@ -0,0 +1,1516 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ +#if defined (__cplusplus) +extern "C" { +#endif + +#ifndef ZSTD_H_235446 +#define ZSTD_H_235446 + +/* ====== Dependency ======*/ +#include <stddef.h> /* size_t */ + + +/* ===== ZSTDLIB_API : control library symbols visibility ===== */ +#ifndef ZSTDLIB_VISIBILITY +# if defined(__GNUC__) && (__GNUC__ >= 4) +# define ZSTDLIB_VISIBILITY __attribute__ ((visibility ("default"))) +# else +# define ZSTDLIB_VISIBILITY +# endif +#endif +#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) +# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBILITY +#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) +# define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +#else +# define ZSTDLIB_API ZSTDLIB_VISIBILITY +#endif + + +/******************************************************************************* + Introduction + + zstd, short for Zstandard, is a fast lossless compression algorithm, targeting + real-time compression scenarios at zlib-level and better compression ratios. + The zstd compression library provides in-memory compression and decompression + functions. + + The library supports regular compression levels from 1 up to ZSTD_maxCLevel(), + which is currently 22. Levels >= 20, labeled `--ultra`, should be used with + caution, as they require more memory. The library also offers negative + compression levels, which extend the range of speed vs. ratio preferences. + The lower the level, the faster the speed (at the cost of compression). + + Compression can be done in: + - a single step (described as Simple API) + - a single step, reusing a context (described as Explicit context) + - unbounded multiple steps (described as Streaming compression) + + The compression ratio achievable on small data can be highly improved using + a dictionary. Dictionary compression can be performed in: + - a single step (described as Simple dictionary API) + - a single step, reusing a dictionary (described as Bulk-processing + dictionary API) + + Advanced experimental functions can be accessed using + `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h. + + Advanced experimental APIs should never be used with a dynamically-linked + library. They are not "stable"; their definitions or signatures may change in + the future. Only static linking is allowed. +*******************************************************************************/ + +/*------ Version ------*/ +#define ZSTD_VERSION_MAJOR 1 +#define ZSTD_VERSION_MINOR 3 +#define ZSTD_VERSION_RELEASE 6 + +#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) +ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< useful to check dll version */ + +#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE +#define ZSTD_QUOTE(str) #str +#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str) +#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION) +ZSTDLIB_API const char* ZSTD_versionString(void); /* v1.3.0+ */ + +/*************************************** +* Default constant +***************************************/ +#ifndef ZSTD_CLEVEL_DEFAULT +# define ZSTD_CLEVEL_DEFAULT 3 +#endif + +/*************************************** +* Simple API +***************************************/ +/*! ZSTD_compress() : + * Compresses `src` content as a single zstd compressed frame into already allocated `dst`. + * Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`. + * @return : compressed size written into `dst` (<= `dstCapacity), + * or an error code if it fails (which can be tested using ZSTD_isError()). */ +ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + int compressionLevel); + +/*! ZSTD_decompress() : + * `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. + * `dstCapacity` is an upper bound of originalSize to regenerate. + * If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data. + * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), + * or an errorCode if it fails (which can be tested using ZSTD_isError()). */ +ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity, + const void* src, size_t compressedSize); + +/*! ZSTD_getFrameContentSize() : added in v1.3.0 + * `src` should point to the start of a ZSTD encoded frame. + * `srcSize` must be at least as large as the frame header. + * hint : any size >= `ZSTD_frameHeaderSize_max` is large enough. + * @return : - decompressed size of `src` frame content, if known + * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined + * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) + * note 1 : a 0 return value means the frame is valid but "empty". + * note 2 : decompressed size is an optional field, it may not be present, typically in streaming mode. + * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + * In which case, it's necessary to use streaming mode to decompress data. + * Optionally, application can rely on some implicit limit, + * as ZSTD_decompress() only needs an upper bound of decompressed size. + * (For example, data could be necessarily cut into blocks <= 16 KB). + * note 3 : decompressed size is always present when compression is completed using single-pass functions, + * such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict(). + * note 4 : decompressed size can be very large (64-bits value), + * potentially larger than what local system can handle as a single memory segment. + * In which case, it's necessary to use streaming mode to decompress data. + * note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified. + * Always ensure return value fits within application's authorized limits. + * Each application can set its own limits. + * note 6 : This function replaces ZSTD_getDecompressedSize() */ +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) +ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); + +/*! ZSTD_getDecompressedSize() : + * NOTE: This function is now obsolete, in favor of ZSTD_getFrameContentSize(). + * Both functions work the same way, but ZSTD_getDecompressedSize() blends + * "empty", "unknown" and "error" results to the same return value (0), + * while ZSTD_getFrameContentSize() gives them separate return values. + * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */ +ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize); + + +/*====== Helper functions ======*/ +#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */ +ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */ +ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ +ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */ +ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */ + + +/*************************************** +* Explicit context +***************************************/ +/*= Compression context + * When compressing many times, + * it is recommended to allocate a context just once, and re-use it for each successive compression operation. + * This will make workload friendlier for system's memory. + * Use one context per thread for parallel execution in multi-threaded environments. */ +typedef struct ZSTD_CCtx_s ZSTD_CCtx; +ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void); +ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); + +/*! ZSTD_compressCCtx() : + * Same as ZSTD_compress(), requires an allocated ZSTD_CCtx (see ZSTD_createCCtx()). */ +ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* ctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + int compressionLevel); + +/*= Decompression context + * When decompressing many times, + * it is recommended to allocate a context only once, + * and re-use it for each successive compression operation. + * This will make workload friendlier for system's memory. + * Use one context per thread for parallel execution. */ +typedef struct ZSTD_DCtx_s ZSTD_DCtx; +ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void); +ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); + +/*! ZSTD_decompressDCtx() : + * Same as ZSTD_decompress(), requires an allocated ZSTD_DCtx (see ZSTD_createDCtx()) */ +ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* ctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize); + + +/************************** +* Simple dictionary API +***************************/ +/*! ZSTD_compress_usingDict() : + * Compression using a predefined Dictionary (see dictBuilder/zdict.h). + * Note : This function loads the dictionary, resulting in significant startup delay. + * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */ +ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize, + int compressionLevel); + +/*! ZSTD_decompress_usingDict() : + * Decompression using a predefined Dictionary (see dictBuilder/zdict.h). + * Dictionary must be identical to the one used during compression. + * Note : This function loads the dictionary, resulting in significant startup delay. + * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */ +ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize); + + +/********************************** + * Bulk processing dictionary API + *********************************/ +typedef struct ZSTD_CDict_s ZSTD_CDict; + +/*! ZSTD_createCDict() : + * When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once. + * ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay. + * ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only. + * `dictBuffer` can be released after ZSTD_CDict creation, since its content is copied within CDict + * Note : A ZSTD_CDict can be created with an empty dictionary, but it is inefficient for small data. */ +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize, + int compressionLevel); + +/*! ZSTD_freeCDict() : + * Function frees memory allocated by ZSTD_createCDict(). */ +ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict); + +/*! ZSTD_compress_usingCDict() : + * Compression using a digested Dictionary. + * Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times. + * Note that compression level is decided during dictionary creation. + * Frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) + * Note : ZSTD_compress_usingCDict() can be used with a ZSTD_CDict created from an empty dictionary. + * But it is inefficient for small data, and it is recommended to use ZSTD_compressCCtx(). */ +ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict); + + +typedef struct ZSTD_DDict_s ZSTD_DDict; + +/*! ZSTD_createDDict() : + * Create a digested dictionary, ready to start decompression operation without startup delay. + * dictBuffer can be released after DDict creation, as its content is copied inside DDict */ +ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize); + +/*! ZSTD_freeDDict() : + * Function frees memory allocated with ZSTD_createDDict() */ +ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict); + +/*! ZSTD_decompress_usingDDict() : + * Decompression using a digested Dictionary. + * Faster startup than ZSTD_decompress_usingDict(), recommended when same dictionary is used multiple times. */ +ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_DDict* ddict); + + +/**************************** +* Streaming +****************************/ + +typedef struct ZSTD_inBuffer_s { + const void* src; /**< start of input buffer */ + size_t size; /**< size of input buffer */ + size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */ +} ZSTD_inBuffer; + +typedef struct ZSTD_outBuffer_s { + void* dst; /**< start of output buffer */ + size_t size; /**< size of output buffer */ + size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */ +} ZSTD_outBuffer; + + + +/*-*********************************************************************** +* Streaming compression - HowTo +* +* A ZSTD_CStream object is required to track streaming operation. +* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources. +* ZSTD_CStream objects can be reused multiple times on consecutive compression operations. +* It is recommended to re-use ZSTD_CStream in situations where many streaming operations will be achieved consecutively, +* since it will play nicer with system's memory, by re-using already allocated memory. +* Use one separate ZSTD_CStream per thread for parallel execution. +* +* Start a new compression by initializing ZSTD_CStream context. +* Use ZSTD_initCStream() to start a new compression operation. +* Use variants ZSTD_initCStream_usingDict() or ZSTD_initCStream_usingCDict() for streaming with dictionary (experimental section) +* +* Use ZSTD_compressStream() as many times as necessary to consume input stream. +* The function will automatically update both `pos` fields within `input` and `output`. +* Note that the function may not consume the entire input, +* for example, because the output buffer is already full, +* in which case `input.pos < input.size`. +* The caller must check if input has been entirely consumed. +* If not, the caller must make some room to receive more compressed data, +* typically by emptying output buffer, or allocating a new output buffer, +* and then present again remaining input data. +* @return : a size hint, preferred nb of bytes to use as input for next function call +* or an error code, which can be tested using ZSTD_isError(). +* Note 1 : it's just a hint, to help latency a little, any other value will work fine. +* Note 2 : size hint is guaranteed to be <= ZSTD_CStreamInSize() +* +* At any moment, it's possible to flush whatever data might remain stuck within internal buffer, +* using ZSTD_flushStream(). `output->pos` will be updated. +* Note that, if `output->size` is too small, a single invocation of ZSTD_flushStream() might not be enough (return code > 0). +* In which case, make some room to receive more compressed data, and call again ZSTD_flushStream(). +* @return : 0 if internal buffers are entirely flushed, +* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), +* or an error code, which can be tested using ZSTD_isError(). +* +* ZSTD_endStream() instructs to finish a frame. +* It will perform a flush and write frame epilogue. +* The epilogue is required for decoders to consider a frame completed. +* flush() operation is the same, and follows same rules as ZSTD_flushStream(). +* @return : 0 if frame fully completed and fully flushed, +* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), +* or an error code, which can be tested using ZSTD_isError(). +* +* *******************************************************************/ + +typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */ + /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */ +/*===== ZSTD_CStream management functions =====*/ +ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void); +ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); + +/*===== Streaming compression functions =====*/ +ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel); +ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input); +ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); +ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); + +ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */ +ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */ + + + +/*-*************************************************************************** +* Streaming decompression - HowTo +* +* A ZSTD_DStream object is required to track streaming operations. +* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources. +* ZSTD_DStream objects can be re-used multiple times. +* +* Use ZSTD_initDStream() to start a new decompression operation, +* or ZSTD_initDStream_usingDict() if decompression requires a dictionary. +* @return : recommended first input size +* +* Use ZSTD_decompressStream() repetitively to consume your input. +* The function will update both `pos` fields. +* If `input.pos < input.size`, some input has not been consumed. +* It's up to the caller to present again remaining data. +* If `output.pos < output.size`, decoder has flushed everything it could. +* @return : 0 when a frame is completely decoded and fully flushed, +* an error code, which can be tested using ZSTD_isError(), +* any other value > 0, which means there is still some decoding to do to complete current frame. +* The return value is a suggested next input size (a hint to improve latency) that will never load more than the current frame. +* *******************************************************************************/ + +typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */ + /* For compatibility with versions <= v1.2.0, continue to consider them separated. */ +/*===== ZSTD_DStream management functions =====*/ +ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void); +ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); + +/*===== Streaming decompression functions =====*/ +ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds); +ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input); + +ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */ +ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */ + +#endif /* ZSTD_H_235446 */ + + + + +#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY) +#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY + +/**************************************************************************************** + * ADVANCED AND EXPERIMENTAL FUNCTIONS + **************************************************************************************** + * The definitions in this section are considered experimental. + * They should never be used with a dynamic library, as prototypes may change in the future. + * They are provided for advanced scenarios. + * Use them only in association with static linking. + * ***************************************************************************************/ + +ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */ + +/* --- Constants ---*/ +#define ZSTD_MAGICNUMBER 0xFD2FB528 /* v0.8+ */ +#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* v0.7+ */ +#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U + +#define ZSTD_BLOCKSIZELOG_MAX 17 +#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX) /* define, for static allocation */ + +#define ZSTD_WINDOWLOG_MAX_32 30 +#define ZSTD_WINDOWLOG_MAX_64 31 +#define ZSTD_WINDOWLOG_MAX ((unsigned)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64)) +#define ZSTD_WINDOWLOG_MIN 10 +#define ZSTD_HASHLOG_MAX ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30) +#define ZSTD_HASHLOG_MIN 6 +#define ZSTD_CHAINLOG_MAX_32 29 +#define ZSTD_CHAINLOG_MAX_64 30 +#define ZSTD_CHAINLOG_MAX ((unsigned)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64)) +#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN +#define ZSTD_HASHLOG3_MAX 17 +#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1) +#define ZSTD_SEARCHLOG_MIN 1 +#define ZSTD_SEARCHLENGTH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */ +#define ZSTD_SEARCHLENGTH_MIN 3 /* only for ZSTD_btopt, other strategies are limited to 4 */ +#define ZSTD_TARGETLENGTH_MAX ZSTD_BLOCKSIZE_MAX +#define ZSTD_TARGETLENGTH_MIN 0 /* note : comparing this constant to an unsigned results in a tautological test */ +#define ZSTD_LDM_MINMATCH_MAX 4096 +#define ZSTD_LDM_MINMATCH_MIN 4 +#define ZSTD_LDM_BUCKETSIZELOG_MAX 8 + +#define ZSTD_FRAMEHEADERSIZE_PREFIX 5 /* minimum input size to know frame header size */ +#define ZSTD_FRAMEHEADERSIZE_MIN 6 +#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* for static allocation */ +static const size_t ZSTD_frameHeaderSize_prefix = ZSTD_FRAMEHEADERSIZE_PREFIX; +static const size_t ZSTD_frameHeaderSize_min = ZSTD_FRAMEHEADERSIZE_MIN; +static const size_t ZSTD_frameHeaderSize_max = ZSTD_FRAMEHEADERSIZE_MAX; +static const size_t ZSTD_skippableHeaderSize = 8; /* magic number + skippable frame length */ + + + +/* --- Advanced types --- */ +typedef enum { ZSTD_fast=1, ZSTD_dfast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2, + ZSTD_btlazy2, ZSTD_btopt, ZSTD_btultra } ZSTD_strategy; /* from faster to stronger */ + +typedef struct { + unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */ + unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */ + unsigned hashLog; /**< dispatch table : larger == faster, more memory */ + unsigned searchLog; /**< nb of searches : larger == more compression, slower */ + unsigned searchLength; /**< match length searched : larger == faster decompression, sometimes less compression */ + unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */ + ZSTD_strategy strategy; +} ZSTD_compressionParameters; + +typedef struct { + unsigned contentSizeFlag; /**< 1: content size will be in frame header (when known) */ + unsigned checksumFlag; /**< 1: generate a 32-bits checksum at end of frame, for error detection */ + unsigned noDictIDFlag; /**< 1: no dictID will be saved into frame header (if dictionary compression) */ +} ZSTD_frameParameters; + +typedef struct { + ZSTD_compressionParameters cParams; + ZSTD_frameParameters fParams; +} ZSTD_parameters; + +typedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params; + +typedef enum { + ZSTD_dct_auto=0, /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */ + ZSTD_dct_rawContent, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */ + ZSTD_dct_fullDict /* refuses to load a dictionary if it does not respect Zstandard's specification */ +} ZSTD_dictContentType_e; + +typedef enum { + ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */ + ZSTD_dlm_byRef, /**< Reference dictionary content -- the dictionary buffer must outlive its users. */ +} ZSTD_dictLoadMethod_e; + + + +/*************************************** +* Frame size functions +***************************************/ + +/*! ZSTD_findFrameCompressedSize() : + * `src` should point to the start of a ZSTD encoded frame or skippable frame + * `srcSize` must be >= first frame size + * @return : the compressed size of the first frame starting at `src`, + * suitable to pass to `ZSTD_decompress` or similar, + * or an error code if input is invalid */ +ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize); + +/*! ZSTD_findDecompressedSize() : + * `src` should point the start of a series of ZSTD encoded and/or skippable frames + * `srcSize` must be the _exact_ size of this series + * (i.e. there should be a frame boundary exactly at `srcSize` bytes after `src`) + * @return : - decompressed size of all data in all successive frames + * - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN + * - if an error occurred: ZSTD_CONTENTSIZE_ERROR + * + * note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. + * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + * In which case, it's necessary to use streaming mode to decompress data. + * note 2 : decompressed size is always present when compression is done with ZSTD_compress() + * note 3 : decompressed size can be very large (64-bits value), + * potentially larger than what local system can handle as a single memory segment. + * In which case, it's necessary to use streaming mode to decompress data. + * note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. + * Always ensure result fits within application's authorized limits. + * Each application can set its own limits. + * note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to + * read each contained frame header. This is fast as most of the data is skipped, + * however it does mean that all frame data must be present and valid. */ +ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize); + +/*! ZSTD_frameHeaderSize() : + * srcSize must be >= ZSTD_frameHeaderSize_prefix. + * @return : size of the Frame Header, + * or an error code (if srcSize is too small) */ +ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); + + +/*************************************** +* Memory management +***************************************/ + +/*! ZSTD_sizeof_*() : + * These functions give the current memory usage of selected object. + * Object memory usage can evolve when re-used. */ +ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); +ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx); +ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); +ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds); +ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict); +ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); + +/*! ZSTD_estimate*() : + * These functions make it possible to estimate memory usage + * of a future {D,C}Ctx, before its creation. + * ZSTD_estimateCCtxSize() will provide a budget large enough for any compression level up to selected one. + * It will also consider src size to be arbitrarily "large", which is worst case. + * If srcSize is known to always be small, ZSTD_estimateCCtxSize_usingCParams() can provide a tighter estimation. + * ZSTD_estimateCCtxSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel. + * ZSTD_estimateCCtxSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_p_nbWorkers is >= 1. + * Note : CCtx size estimation is only correct for single-threaded compression. */ +ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel); +ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams); +ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params); +ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void); + +/*! ZSTD_estimateCStreamSize() : + * ZSTD_estimateCStreamSize() will provide a budget large enough for any compression level up to selected one. + * It will also consider src size to be arbitrarily "large", which is worst case. + * If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation. + * ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel. + * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParam_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_p_nbWorkers is >= 1. + * Note : CStream size estimation is only correct for single-threaded compression. + * ZSTD_DStream memory budget depends on window Size. + * This information can be passed manually, using ZSTD_estimateDStreamSize, + * or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame(); + * Note : if streaming is init with function ZSTD_init?Stream_usingDict(), + * an internal ?Dict will be created, which additional size is not estimated here. + * In this case, get total size by adding ZSTD_estimate?DictSize */ +ZSTDLIB_API size_t ZSTD_estimateCStreamSize(int compressionLevel); +ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams); +ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params); +ZSTDLIB_API size_t ZSTD_estimateDStreamSize(size_t windowSize); +ZSTDLIB_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize); + +/*! ZSTD_estimate?DictSize() : + * ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict(). + * ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced(). + * Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller. + */ +ZSTDLIB_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel); +ZSTDLIB_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod); +ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod); + +/*! ZSTD_initStatic*() : + * Initialize an object using a pre-allocated fixed-size buffer. + * workspace: The memory area to emplace the object into. + * Provided pointer *must be 8-bytes aligned*. + * Buffer must outlive object. + * workspaceSize: Use ZSTD_estimate*Size() to determine + * how large workspace must be to support target scenario. + * @return : pointer to object (same address as workspace, just different type), + * or NULL if error (size too small, incorrect alignment, etc.) + * Note : zstd will never resize nor malloc() when using a static buffer. + * If the object requires more memory than available, + * zstd will just error out (typically ZSTD_error_memory_allocation). + * Note 2 : there is no corresponding "free" function. + * Since workspace is allocated externally, it must be freed externally too. + * Note 3 : cParams : use ZSTD_getCParams() to convert a compression level + * into its associated cParams. + * Limitation 1 : currently not compatible with internal dictionary creation, triggered by + * ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict(). + * Limitation 2 : static cctx currently not compatible with multi-threading. + * Limitation 3 : static dctx is incompatible with legacy support. + */ +ZSTDLIB_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize); +ZSTDLIB_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */ + +ZSTDLIB_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize); +ZSTDLIB_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */ + +ZSTDLIB_API const ZSTD_CDict* ZSTD_initStaticCDict( + void* workspace, size_t workspaceSize, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams); + +ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict( + void* workspace, size_t workspaceSize, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType); + +/*! Custom memory allocation : + * These prototypes make it possible to pass your own allocation/free functions. + * ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below. + * All allocation/free operations will be completed using these custom variants instead of regular <stdlib.h> ones. + */ +typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); +typedef void (*ZSTD_freeFunction) (void* opaque, void* address); +typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; +static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ + +ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); +ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); +ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem); +ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem); + +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams, + ZSTD_customMem customMem); + +ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_customMem customMem); + + + +/*************************************** +* Advanced compression functions +***************************************/ + +/*! ZSTD_createCDict_byReference() : + * Create a digested dictionary for compression + * Dictionary content is simply referenced, and therefore stays in dictBuffer. + * It is important that dictBuffer outlives CDict, it must remain read accessible throughout the lifetime of CDict */ +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel); + +/*! ZSTD_getCParams() : +* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. +* `estimatedSrcSize` value is optional, select 0 if not known */ +ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); + +/*! ZSTD_getParams() : +* same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`. +* All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */ +ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); + +/*! ZSTD_checkCParams() : +* Ensure param values remain within authorized range */ +ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params); + +/*! ZSTD_adjustCParams() : + * optimize params for a given `srcSize` and `dictSize`. + * both values are optional, select `0` if unknown. */ +ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize); + +/*! ZSTD_compress_advanced() : +* Same as ZSTD_compress_usingDict(), with fine-tune control over each compression parameter */ +ZSTDLIB_API size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize, + ZSTD_parameters params); + +/*! ZSTD_compress_usingCDict_advanced() : +* Same as ZSTD_compress_usingCDict(), with fine-tune control over frame parameters */ +ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict, ZSTD_frameParameters fParams); + + +/*--- Advanced decompression functions ---*/ + +/*! ZSTD_isFrame() : + * Tells if the content of `buffer` starts with a valid Frame Identifier. + * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0. + * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled. + * Note 3 : Skippable Frame Identifiers are considered valid. */ +ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size); + +/*! ZSTD_createDDict_byReference() : + * Create a digested dictionary, ready to start decompression operation without startup delay. + * Dictionary content is referenced, and therefore stays in dictBuffer. + * It is important that dictBuffer outlives DDict, + * it must remain read accessible throughout the lifetime of DDict */ +ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize); + + +/*! ZSTD_getDictID_fromDict() : + * Provides the dictID stored within dictionary. + * if @return == 0, the dictionary is not conformant with Zstandard specification. + * It can still be loaded, but as a content-only dictionary. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize); + +/*! ZSTD_getDictID_fromDDict() : + * Provides the dictID of the dictionary loaded into `ddict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict); + +/*! ZSTD_getDictID_fromFrame() : + * Provides the dictID required to decompressed the frame stored within `src`. + * If @return == 0, the dictID could not be decoded. + * This could for one of the following reasons : + * - The frame does not require a dictionary to be decoded (most common case). + * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information. + * Note : this use case also happens when using a non-conformant dictionary. + * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`). + * - This is not a Zstandard frame. + * When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); + + +/******************************************************************** +* Advanced streaming functions +********************************************************************/ + +/*===== Advanced Streaming compression functions =====*/ +ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct. If it is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, "0" also disables frame content size field. It may be enabled in the future. */ +ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< creates of an internal CDict (incompatible with static CCtx), except if dict == NULL or dictSize < 8, in which case no dict is used. Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.*/ +ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize, + ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. dict is loaded with ZSTD_dm_auto and ZSTD_dlm_byCopy. */ +ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); /**< note : cdict will just be referenced, and must outlive compression session */ +ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize); /**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters. pledgedSrcSize must be correct. If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. */ + +/*! ZSTD_resetCStream() : + * start a new compression job, using same parameters from previous job. + * This is typically useful to skip dictionary loading stage, since it will re-use it in-place. + * Note that zcs must be init at least once before using ZSTD_resetCStream(). + * If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN. + * If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end. + * For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs, + * but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead. + * @return : 0, or an error code (which can be tested using ZSTD_isError()) + */ +ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize); + + +typedef struct { + unsigned long long ingested; /* nb input bytes read and buffered */ + unsigned long long consumed; /* nb input bytes actually compressed */ + unsigned long long produced; /* nb of compressed bytes generated and buffered */ + unsigned long long flushed; /* nb of compressed bytes flushed : not provided; can be tracked from caller side */ + unsigned currentJobID; /* MT only : latest started job nb */ + unsigned nbActiveWorkers; /* MT only : nb of workers actively compressing at probe time */ +} ZSTD_frameProgression; + +/* ZSTD_getFrameProgression() : + * tells how much data has been ingested (read from input) + * consumed (input actually compressed) and produced (output) for current frame. + * Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed. + * Aggregates progression inside active worker threads. + */ +ZSTDLIB_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx); + +/*! ZSTD_toFlushNow() : + * Tell how many bytes are ready to be flushed immediately. + * Useful for multithreading scenarios (nbWorkers >= 1). + * Probe the oldest active job, defined as oldest job not yet entirely flushed, + * and check its output buffer. + * @return : amount of data stored in oldest job and ready to be flushed immediately. + * if @return == 0, it means either : + * + there is no active job (could be checked with ZSTD_frameProgression()), or + * + oldest job is still actively compressing data, + * but everything it has produced has also been flushed so far, + * therefore flushing speed is currently limited by production speed of oldest job + * irrespective of the speed of concurrent newer jobs. + */ +ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx); + + + +/*===== Advanced Streaming decompression functions =====*/ +typedef enum { DStream_p_maxWindowSize } ZSTD_DStreamParameter_e; +ZSTDLIB_API size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue); /* obsolete : this API will be removed in a future version */ +ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); /**< note: no dictionary will be used if dict == NULL or dictSize < 8 */ +ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict is referenced, it must outlive decompression session */ +ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */ + + +/********************************************************************* +* Buffer-less and synchronous inner streaming functions +* +* This is an advanced API, giving full control over buffer management, for users which need direct control over memory. +* But it's also a complex one, with several restrictions, documented below. +* Prefer normal streaming API for an easier experience. +********************************************************************* */ + +/** + Buffer-less streaming compression (synchronous mode) + + A ZSTD_CCtx object is required to track streaming operations. + Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource. + ZSTD_CCtx object can be re-used multiple times within successive compression operations. + + Start by initializing a context. + Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression, + or ZSTD_compressBegin_advanced(), for finer parameter control. + It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx() + + Then, consume your input using ZSTD_compressContinue(). + There are some important considerations to keep in mind when using this advanced function : + - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only. + - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks. + - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario. + Worst case evaluation is provided by ZSTD_compressBound(). + ZSTD_compressContinue() doesn't guarantee recover after a failed compression. + - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog). + It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks) + - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps. + In which case, it will "discard" the relevant memory section from its history. + + Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum. + It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame. + Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders. + + `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress again. +*/ + +/*===== Buffer-less streaming compression functions =====*/ +ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel); +ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel); +ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */ +ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */ +ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */ +ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */ + +ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + + +/*- + Buffer-less streaming decompression (synchronous mode) + + A ZSTD_DCtx object is required to track streaming operations. + Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it. + A ZSTD_DCtx object can be re-used multiple times. + + First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader(). + Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough. + Data fragment must be large enough to ensure successful decoding. + `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough. + @result : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled. + >0 : `srcSize` is too small, please provide at least @result bytes on next attempt. + errorCode, which can be tested using ZSTD_isError(). + + It fills a ZSTD_frameHeader structure with important information to correctly decode the frame, + such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`). + Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information. + As a consequence, check that values remain within valid application range. + For example, do not allocate memory blindly, check that `windowSize` is within expectation. + Each application can set its own limits, depending on local restrictions. + For extended interoperability, it is recommended to support `windowSize` of at least 8 MB. + + ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes. + ZSTD_decompressContinue() is very sensitive to contiguity, + if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place, + or that previous contiguous segment is large enough to properly handle maximum back-reference distance. + There are multiple ways to guarantee this condition. + + The most memory efficient way is to use a round buffer of sufficient size. + Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(), + which can @return an error code if required value is too large for current system (in 32-bits mode). + In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one, + up to the moment there is not enough room left in the buffer to guarantee decoding another full block, + which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`. + At which point, decoding can resume from the beginning of the buffer. + Note that already decoded data stored in the buffer should be flushed before being overwritten. + + There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory. + + Finally, if you control the compression process, you can also ignore all buffer size rules, + as long as the encoder and decoder progress in "lock-step", + aka use exactly the same buffer sizes, break contiguity at the same place, etc. + + Once buffers are setup, start decompression, with ZSTD_decompressBegin(). + If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict(). + + Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively. + ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue(). + ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail. + + @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity). + It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item. + It can also be an error code, which can be tested with ZSTD_isError(). + + A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero. + Context can then be reset to start a new decompression. + + Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType(). + This information is not required to properly decode a frame. + + == Special case : skippable frames == + + Skippable frames allow integration of user-defined data into a flow of concatenated frames. + Skippable frames will be ignored (skipped) by decompressor. + The format of skippable frames is as follows : + a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F + b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits + c) Frame Content - any content (User Data) of length equal to Frame Size + For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame. + For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content. +*/ + +/*===== Buffer-less streaming decompression functions =====*/ +typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_frameType_e; +typedef struct { + unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */ + unsigned long long windowSize; /* can be very large, up to <= frameContentSize */ + unsigned blockSizeMax; + ZSTD_frameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */ + unsigned headerSize; + unsigned dictID; + unsigned checksumFlag; +} ZSTD_frameHeader; +/** ZSTD_getFrameHeader() : + * decode Frame Header, or requires larger `srcSize`. + * @return : 0, `zfhPtr` is correctly filled, + * >0, `srcSize` is too small, value is wanted `srcSize` amount, + * or an error code, which can be tested using ZSTD_isError() */ +ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */ +ZSTDLIB_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */ + +ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); +ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); +ZSTDLIB_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); + +ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx); +ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + +/* misc */ +ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx); +typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e; +ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx); + + + +/* ============================================ */ +/** New advanced API (experimental) */ +/* ============================================ */ + +/* API design : + * In this advanced API, parameters are pushed one by one into an existing context, + * using ZSTD_CCtx_set*() functions. + * Pushed parameters are sticky : they are applied to next job, and any subsequent job. + * It's possible to reset parameters to "default" using ZSTD_CCtx_reset(). + * Important : "sticky" parameters only work with `ZSTD_compress_generic()` ! + * For any other entry point, "sticky" parameters are ignored ! + * + * This API is intended to replace all others advanced / experimental API entry points. + */ + +/* note on enum design : + * All enum will be pinned to explicit values before reaching "stable API" status */ + +typedef enum { + /* Opened question : should we have a format ZSTD_f_auto ? + * Today, it would mean exactly the same as ZSTD_f_zstd1. + * But, in the future, should several formats become supported, + * on the compression side, it would mean "default format". + * On the decompression side, it would mean "automatic format detection", + * so that ZSTD_f_zstd1 would mean "accept *only* zstd frames". + * Since meaning is a little different, another option could be to define different enums for compression and decompression. + * This question could be kept for later, when there are actually multiple formats to support, + * but there is also the question of pinning enum values, and pinning value `0` is especially important */ + ZSTD_f_zstd1 = 0, /* zstd frame format, specified in zstd_compression_format.md (default) */ + ZSTD_f_zstd1_magicless, /* Variant of zstd frame format, without initial 4-bytes magic number. + * Useful to save 4 bytes per generated frame. + * Decoder cannot recognise automatically this format, requiring instructions. */ +} ZSTD_format_e; + +typedef enum { + /* compression format */ + ZSTD_p_format = 10, /* See ZSTD_format_e enum definition. + * Cast selected format as unsigned for ZSTD_CCtx_setParameter() compatibility. */ + + /* compression parameters */ + ZSTD_p_compressionLevel=100, /* Update all compression parameters according to pre-defined cLevel table + * Default level is ZSTD_CLEVEL_DEFAULT==3. + * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT. + * Note 1 : it's possible to pass a negative compression level by casting it to unsigned type. + * Note 2 : setting a level sets all default values of other compression parameters. + * Note 3 : setting compressionLevel automatically updates ZSTD_p_compressLiterals. */ + ZSTD_p_windowLog, /* Maximum allowed back-reference distance, expressed as power of 2. + * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX. + * Special: value 0 means "use default windowLog". + * Note: Using a window size greater than ZSTD_MAXWINDOWSIZE_DEFAULT (default: 2^27) + * requires explicitly allowing such window size during decompression stage. */ + ZSTD_p_hashLog, /* Size of the initial probe table, as a power of 2. + * Resulting table size is (1 << (hashLog+2)). + * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX. + * Larger tables improve compression ratio of strategies <= dFast, + * and improve speed of strategies > dFast. + * Special: value 0 means "use default hashLog". */ + ZSTD_p_chainLog, /* Size of the multi-probe search table, as a power of 2. + * Resulting table size is (1 << (chainLog+2)). + * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX. + * Larger tables result in better and slower compression. + * This parameter is useless when using "fast" strategy. + * Note it's still useful when using "dfast" strategy, + * in which case it defines a secondary probe table. + * Special: value 0 means "use default chainLog". */ + ZSTD_p_searchLog, /* Number of search attempts, as a power of 2. + * More attempts result in better and slower compression. + * This parameter is useless when using "fast" and "dFast" strategies. + * Special: value 0 means "use default searchLog". */ + ZSTD_p_minMatch, /* Minimum size of searched matches (note : repCode matches can be smaller). + * Larger values make faster compression and decompression, but decrease ratio. + * Must be clamped between ZSTD_SEARCHLENGTH_MIN and ZSTD_SEARCHLENGTH_MAX. + * Note that currently, for all strategies < btopt, effective minimum is 4. + * , for all strategies > fast, effective maximum is 6. + * Special: value 0 means "use default minMatchLength". */ + ZSTD_p_targetLength, /* Impact of this field depends on strategy. + * For strategies btopt & btultra: + * Length of Match considered "good enough" to stop search. + * Larger values make compression stronger, and slower. + * For strategy fast: + * Distance between match sampling. + * Larger values make compression faster, and weaker. + * Special: value 0 means "use default targetLength". */ + ZSTD_p_compressionStrategy, /* See ZSTD_strategy enum definition. + * Cast selected strategy as unsigned for ZSTD_CCtx_setParameter() compatibility. + * The higher the value of selected strategy, the more complex it is, + * resulting in stronger and slower compression. + * Special: value 0 means "use default strategy". */ + + ZSTD_p_enableLongDistanceMatching=160, /* Enable long distance matching. + * This parameter is designed to improve compression ratio + * for large inputs, by finding large matches at long distance. + * It increases memory usage and window size. + * Note: enabling this parameter increases ZSTD_p_windowLog to 128 MB + * except when expressly set to a different value. */ + ZSTD_p_ldmHashLog, /* Size of the table for long distance matching, as a power of 2. + * Larger values increase memory usage and compression ratio, + * but decrease compression speed. + * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX + * default: windowlog - 7. + * Special: value 0 means "automatically determine hashlog". */ + ZSTD_p_ldmMinMatch, /* Minimum match size for long distance matcher. + * Larger/too small values usually decrease compression ratio. + * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX. + * Special: value 0 means "use default value" (default: 64). */ + ZSTD_p_ldmBucketSizeLog, /* Log size of each bucket in the LDM hash table for collision resolution. + * Larger values improve collision resolution but decrease compression speed. + * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX . + * Special: value 0 means "use default value" (default: 3). */ + ZSTD_p_ldmHashEveryLog, /* Frequency of inserting/looking up entries in the LDM hash table. + * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN). + * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage. + * Larger values improve compression speed. + * Deviating far from default value will likely result in a compression ratio decrease. + * Special: value 0 means "automatically determine hashEveryLog". */ + + /* frame parameters */ + ZSTD_p_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1) + * Content size must be known at the beginning of compression, + * it is provided using ZSTD_CCtx_setPledgedSrcSize() */ + ZSTD_p_checksumFlag, /* A 32-bits checksum of content is written at end of frame (default:0) */ + ZSTD_p_dictIDFlag, /* When applicable, dictionary's ID is written into frame header (default:1) */ + + /* multi-threading parameters */ + /* These parameters are only useful if multi-threading is enabled (ZSTD_MULTITHREAD). + * They return an error otherwise. */ + ZSTD_p_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel. + * When nbWorkers >= 1, triggers asynchronous mode : + * ZSTD_compress_generic() consumes some input, flush some output if possible, and immediately gives back control to caller, + * while compression work is performed in parallel, within worker threads. + * (note : a strong exception to this rule is when first invocation sets ZSTD_e_end : it becomes a blocking call). + * More workers improve speed, but also increase memory usage. + * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */ + ZSTD_p_jobSize, /* Size of a compression job. This value is enforced only in non-blocking mode. + * Each compression job is completed in parallel, so this value indirectly controls the nb of active threads. + * 0 means default, which is dynamically determined based on compression parameters. + * Job size must be a minimum of overlapSize, or 1 MB, whichever is largest. + * The minimum size is automatically and transparently enforced */ + ZSTD_p_overlapSizeLog, /* Size of previous input reloaded at the beginning of each job. + * 0 => no overlap, 6(default) => use 1/8th of windowSize, >=9 => use full windowSize */ + + /* =================================================================== */ + /* experimental parameters - no stability guaranteed */ + /* =================================================================== */ + + ZSTD_p_forceMaxWindow=1100, /* Force back-reference distances to remain < windowSize, + * even when referencing into Dictionary content (default:0) */ + ZSTD_p_forceAttachDict, /* ZSTD supports usage of a CDict in-place + * (avoiding having to copy the compression tables + * from the CDict into the working context). Using + * a CDict in this way saves an initial setup step, + * but comes at the cost of more work per byte of + * input. ZSTD has a simple internal heuristic that + * guesses which strategy will be faster. You can + * use this flag to override that guess. + * + * Note that the by-reference, in-place strategy is + * only used when reusing a compression context + * with compatible compression parameters. (If + * incompatible / uninitialized, the working + * context needs to be cleared anyways, which is + * about as expensive as overwriting it with the + * dictionary context, so there's no savings in + * using the CDict by-ref.) + * + * Values greater than 0 force attaching the dict. + * Values less than 0 force copying the dict. + * 0 selects the default heuristic-guided behavior. + */ + +} ZSTD_cParameter; + + +/*! ZSTD_CCtx_setParameter() : + * Set one compression parameter, selected by enum ZSTD_cParameter. + * Setting a parameter is generally only possible during frame initialization (before starting compression). + * Exception : when using multi-threading mode (nbThreads >= 1), + * following parameters can be updated _during_ compression (within same frame): + * => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy. + * new parameters will be active on next job, or after a flush(). + * Note : when `value` type is not unsigned (int, or enum), cast it to unsigned for proper type checking. + * @result : informational value (typically, value being set, correctly clamped), + * or an error code (which can be tested with ZSTD_isError()). */ +ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned value); + +/*! ZSTD_CCtx_getParameter() : + * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned* value); + +/*! ZSTD_CCtx_setPledgedSrcSize() : + * Total input data size to be compressed as a single frame. + * This value will be controlled at the end, and result in error if not respected. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Note 1 : 0 means zero, empty. + * In order to mean "unknown content size", pass constant ZSTD_CONTENTSIZE_UNKNOWN. + * ZSTD_CONTENTSIZE_UNKNOWN is default value for any new compression job. + * Note 2 : If all data is provided and consumed in a single round, + * this value is overriden by srcSize instead. */ +ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize); + +/*! ZSTD_CCtx_loadDictionary() : + * Create an internal CDict from `dict` buffer. + * Decompression will have to use same dictionary. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special: Adding a NULL (or 0-size) dictionary invalidates previous dictionary, + * meaning "return to no-dictionary mode". + * Note 1 : Dictionary will be used for all future compression jobs. + * To return to "no-dictionary" situation, load a NULL dictionary + * Note 2 : Loading a dictionary involves building tables, which are dependent on compression parameters. + * For this reason, compression parameters cannot be changed anymore after loading a dictionary. + * It's also a CPU consuming operation, with non-negligible impact on latency. + * Note 3 :`dict` content will be copied internally. + * Use ZSTD_CCtx_loadDictionary_byReference() to reference dictionary content instead. + * In such a case, dictionary buffer must outlive its users. + * Note 4 : Use ZSTD_CCtx_loadDictionary_advanced() + * to precisely select how dictionary content must be interpreted. */ +ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); +ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); +ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); + + +/*! ZSTD_CCtx_refCDict() : + * Reference a prepared dictionary, to be used for all next compression jobs. + * Note that compression parameters are enforced from within CDict, + * and supercede any compression parameter previously set within CCtx. + * The dictionary will remain valid for future compression jobs using same CCtx. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special : adding a NULL CDict means "return to no-dictionary mode". + * Note 1 : Currently, only one dictionary can be managed. + * Adding a new dictionary effectively "discards" any previous one. + * Note 2 : CDict is just referenced, its lifetime must outlive CCtx. */ +ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); + +/*! ZSTD_CCtx_refPrefix() : + * Reference a prefix (single-usage dictionary) for next compression job. + * Decompression will need same prefix to properly regenerate data. + * Compressing with a prefix is similar in outcome as performing a diff and compressing it, + * but performs much faster, especially during decompression (compression speed is tunable with compression level). + * Note that prefix is **only used once**. Tables are discarded at end of compression job (ZSTD_e_end). + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary + * Note 1 : Prefix buffer is referenced. It **must** outlive compression job. + * Its contain must remain unmodified up to end of compression (ZSTD_e_end). + * Note 2 : If the intention is to diff some large src data blob with some prior version of itself, + * ensure that the window size is large enough to contain the entire source. + * See ZSTD_p_windowLog. + * Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters. + * It's a CPU consuming operation, with non-negligible impact on latency. + * If there is a need to use same prefix multiple times, consider loadDictionary instead. + * Note 4 : By default, the prefix is treated as raw content (ZSTD_dm_rawContent). + * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode. */ +ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, + const void* prefix, size_t prefixSize); +ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, + const void* prefix, size_t prefixSize, + ZSTD_dictContentType_e dictContentType); + +/*! ZSTD_CCtx_reset() : + * Return a CCtx to clean state. + * Useful after an error, or to interrupt an ongoing compression job and start a new one. + * Any internal data not yet flushed is cancelled. + * The parameters and dictionary are kept unchanged, to reset them use ZSTD_CCtx_resetParameters(). + */ +ZSTDLIB_API void ZSTD_CCtx_reset(ZSTD_CCtx* cctx); + +/*! ZSTD_CCtx_resetParameters() : + * All parameters are back to default values (compression level is ZSTD_CLEVEL_DEFAULT). + * Dictionary (if any) is dropped. + * Resetting parameters is only possible during frame initialization (before starting compression). + * To reset the context use ZSTD_CCtx_reset(). + * @return 0 or an error code (which can be checked with ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_CCtx_resetParameters(ZSTD_CCtx* cctx); + + + +typedef enum { + ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal conditions */ + ZSTD_e_flush, /* flush any data provided so far - frame will continue, future data can still reference previous data for better compression */ + ZSTD_e_end /* flush any remaining data and close current frame. Any additional data starts a new frame. */ +} ZSTD_EndDirective; + +/*! ZSTD_compress_generic() : + * Behave about the same as ZSTD_compressStream. To note : + * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_setParameter() + * - Compression parameters cannot be changed once compression is started. + * - outpot->pos must be <= dstCapacity, input->pos must be <= srcSize + * - outpot->pos and input->pos will be updated. They are guaranteed to remain below their respective limit. + * - In single-thread mode (default), function is blocking : it completed its job before returning to caller. + * - In multi-thread mode, function is non-blocking : it just acquires a copy of input, and distribute job to internal worker threads, + * and then immediately returns, just indicating that there is some data remaining to be flushed. + * The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte. + * - Exception : in multi-threading mode, if the first call requests a ZSTD_e_end directive, it is blocking : it will complete compression before giving back control to caller. + * - @return provides a minimum amount of data remaining to be flushed from internal buffers + * or an error code, which can be tested using ZSTD_isError(). + * if @return != 0, flush is not fully completed, there is still some data left within internal buffers. + * This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers. + * For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed. + * - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0), + * only ZSTD_e_end or ZSTD_e_flush operations are allowed. + * Before starting a new compression job, or changing compression parameters, + * it is required to fully flush internal buffers. + */ +ZSTDLIB_API size_t ZSTD_compress_generic (ZSTD_CCtx* cctx, + ZSTD_outBuffer* output, + ZSTD_inBuffer* input, + ZSTD_EndDirective endOp); + + +/*! ZSTD_compress_generic_simpleArgs() : + * Same as ZSTD_compress_generic(), + * but using only integral types as arguments. + * Argument list is larger than ZSTD_{in,out}Buffer, + * but can be helpful for binders from dynamic languages + * which have troubles handling structures containing memory pointers. + */ +ZSTDLIB_API size_t ZSTD_compress_generic_simpleArgs ( + ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, size_t* dstPos, + const void* src, size_t srcSize, size_t* srcPos, + ZSTD_EndDirective endOp); + + +/*! ZSTD_CCtx_params : + * Quick howto : + * - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure + * - ZSTD_CCtxParam_setParameter() : Push parameters one by one into + * an existing ZSTD_CCtx_params structure. + * This is similar to + * ZSTD_CCtx_setParameter(). + * - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to + * an existing CCtx. + * These parameters will be applied to + * all subsequent compression jobs. + * - ZSTD_compress_generic() : Do compression using the CCtx. + * - ZSTD_freeCCtxParams() : Free the memory. + * + * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams() + * for static allocation for single-threaded compression. + */ +ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void); +ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); + + +/*! ZSTD_CCtxParams_reset() : + * Reset params to default values. + */ +ZSTDLIB_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params); + +/*! ZSTD_CCtxParams_init() : + * Initializes the compression parameters of cctxParams according to + * compression level. All other parameters are reset to their default values. + */ +ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel); + +/*! ZSTD_CCtxParams_init_advanced() : + * Initializes the compression and frame parameters of cctxParams according to + * params. All other parameters are reset to their default values. + */ +ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params); + + +/*! ZSTD_CCtxParam_setParameter() : + * Similar to ZSTD_CCtx_setParameter. + * Set one compression parameter, selected by enum ZSTD_cParameter. + * Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams(). + * Note : when `value` is an enum, cast it to unsigned for proper type checking. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, unsigned value); + +/*! ZSTD_CCtxParam_getParameter() : + * Similar to ZSTD_CCtx_getParameter. + * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_CCtxParam_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, unsigned* value); + +/*! ZSTD_CCtx_setParametersUsingCCtxParams() : + * Apply a set of ZSTD_CCtx_params to the compression context. + * This can be done even after compression is started, + * if nbWorkers==0, this will have no impact until a new compression is started. + * if nbWorkers>=1, new parameters will be picked up at next job, + * with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated). + */ +ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams( + ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params); + + +/* ==================================== */ +/*=== Advanced decompression API ===*/ +/* ==================================== */ + +/* The following API works the same way as the advanced compression API : + * a context is created, parameters are pushed into it one by one, + * then the context can be used to decompress data using an interface similar to the straming API. + */ + +/*! ZSTD_DCtx_loadDictionary() : + * Create an internal DDict from dict buffer, + * to be used to decompress next frames. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary, + * meaning "return to no-dictionary mode". + * Note 1 : `dict` content will be copied internally. + * Use ZSTD_DCtx_loadDictionary_byReference() + * to reference dictionary content instead. + * In which case, the dictionary buffer must outlive its users. + * Note 2 : Loading a dictionary involves building tables, + * which has a non-negligible impact on CPU usage and latency. + * Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to select + * how dictionary content will be interpreted and loaded. + */ +ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); +ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); +ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); + + +/*! ZSTD_DCtx_refDDict() : + * Reference a prepared dictionary, to be used to decompress next frames. + * The dictionary remains active for decompression of future frames using same DCtx. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Note 1 : Currently, only one dictionary can be managed. + * Referencing a new dictionary effectively "discards" any previous one. + * Special : adding a NULL DDict means "return to no-dictionary mode". + * Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx. + */ +ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); + + +/*! ZSTD_DCtx_refPrefix() : + * Reference a prefix (single-usage dictionary) for next compression job. + * This is the reverse operation of ZSTD_CCtx_refPrefix(), + * and must use the same prefix as the one used during compression. + * Prefix is **only used once**. Reference is discarded at end of frame. + * End of frame is reached when ZSTD_DCtx_decompress_generic() returns 0. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary + * Note 2 : Prefix buffer is referenced. It **must** outlive decompression job. + * Prefix buffer must remain unmodified up to the end of frame, + * reached when ZSTD_DCtx_decompress_generic() returns 0. + * Note 3 : By default, the prefix is treated as raw content (ZSTD_dm_rawContent). + * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode. + * Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost. + * A fulldict prefix is more costly though. + */ +ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, + const void* prefix, size_t prefixSize); +ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, + const void* prefix, size_t prefixSize, + ZSTD_dictContentType_e dictContentType); + + +/*! ZSTD_DCtx_setMaxWindowSize() : + * Refuses allocating internal buffers for frames requiring a window size larger than provided limit. + * This is useful to prevent a decoder context from reserving too much memory for itself (potential attack scenario). + * This parameter is only useful in streaming mode, since no internal buffer is allocated in direct mode. + * By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_MAX) + * @return : 0, or an error code (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize); + + +/*! ZSTD_DCtx_setFormat() : + * Instruct the decoder context about what kind of data to decode next. + * This instruction is mandatory to decode data without a fully-formed header, + * such ZSTD_f_zstd1_magicless for example. + * @return : 0, or an error code (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format); + + +/*! ZSTD_getFrameHeader_advanced() : + * same as ZSTD_getFrameHeader(), + * with added capability to select a format (like ZSTD_f_zstd1_magicless) */ +ZSTDLIB_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, + const void* src, size_t srcSize, ZSTD_format_e format); + + +/*! ZSTD_decompress_generic() : + * Behave the same as ZSTD_decompressStream. + * Decompression parameters cannot be changed once decompression is started. + * @return : an error code, which can be tested using ZSTD_isError() + * if >0, a hint, nb of expected input bytes for next invocation. + * `0` means : a frame has just been fully decoded and flushed. + */ +ZSTDLIB_API size_t ZSTD_decompress_generic(ZSTD_DCtx* dctx, + ZSTD_outBuffer* output, + ZSTD_inBuffer* input); + + +/*! ZSTD_decompress_generic_simpleArgs() : + * Same as ZSTD_decompress_generic(), + * but using only integral types as arguments. + * Argument list is larger than ZSTD_{in,out}Buffer, + * but can be helpful for binders from dynamic languages + * which have troubles handling structures containing memory pointers. + */ +ZSTDLIB_API size_t ZSTD_decompress_generic_simpleArgs ( + ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, size_t* dstPos, + const void* src, size_t srcSize, size_t* srcPos); + + +/*! ZSTD_DCtx_reset() : + * Return a DCtx to clean state. + * If a decompression was ongoing, any internal data not yet flushed is cancelled. + * All parameters are back to default values, including sticky ones. + * Dictionary (if any) is dropped. + * Parameters can be modified again after a reset. + */ +ZSTDLIB_API void ZSTD_DCtx_reset(ZSTD_DCtx* dctx); + + + +/* ============================ */ +/** Block level API */ +/* ============================ */ + +/*! + Block functions produce and decode raw zstd blocks, without frame metadata. + Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes). + User will have to take in charge required information to regenerate data, such as compressed and content sizes. + + A few rules to respect : + - Compressing and decompressing require a context structure + + Use ZSTD_createCCtx() and ZSTD_createDCtx() + - It is necessary to init context before starting + + compression : any ZSTD_compressBegin*() variant, including with dictionary + + decompression : any ZSTD_decompressBegin*() variant, including with dictionary + + copyCCtx() and copyDCtx() can be used too + - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB + + If input is larger than a block size, it's necessary to split input data into multiple blocks + + For inputs larger than a single block size, consider using the regular ZSTD_compress() instead. + Frame metadata is not that costly, and quickly becomes negligible as source size grows larger. + - When a block is considered not compressible enough, ZSTD_compressBlock() result will be zero. + In which case, nothing is produced into `dst`. + + User must test for such outcome and deal directly with uncompressed data + + ZSTD_decompressBlock() doesn't accept uncompressed data as input !!! + + In case of multiple successive blocks, should some of them be uncompressed, + decoder must be informed of their existence in order to follow proper history. + Use ZSTD_insertBlock() for such a case. +*/ + +/*===== Raw zstd block functions =====*/ +ZSTDLIB_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx); +ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTDLIB_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */ + + +#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */ + +#if defined (__cplusplus) +} +#endif diff --git a/grub-core/lib/zstd/zstd_common.c b/grub-core/lib/zstd/zstd_common.c new file mode 100644 index 0000000..6f05d24 --- /dev/null +++ b/grub-core/lib/zstd/zstd_common.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + + +/*-************************************* +* Dependencies +***************************************/ +#include <stdlib.h> /* malloc, calloc, free */ +#include <string.h> /* memset */ +#include "error_private.h" +#include "zstd_internal.h" + + +/*-**************************************** +* Version +******************************************/ +unsigned ZSTD_versionNumber(void) { return ZSTD_VERSION_NUMBER; } + +const char* ZSTD_versionString(void) { return ZSTD_VERSION_STRING; } + + +/*-**************************************** +* ZSTD Error Management +******************************************/ +/*! ZSTD_isError() : + * tells if a return value is an error code */ +unsigned ZSTD_isError(size_t code) { return ERR_isError(code); } + +/*! ZSTD_getErrorName() : + * provides error code string from function result (useful for debugging) */ +const char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); } + +/*! ZSTD_getError() : + * convert a `size_t` function result into a proper ZSTD_errorCode enum */ +ZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); } + +/*! ZSTD_getErrorString() : + * provides error code string from enum */ +const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString(code); } + + + +/*=************************************************************** +* Custom allocator +****************************************************************/ +void* ZSTD_malloc(size_t size, ZSTD_customMem customMem) +{ + if (customMem.customAlloc) + return customMem.customAlloc(customMem.opaque, size); + return malloc(size); +} + +void* ZSTD_calloc(size_t size, ZSTD_customMem customMem) +{ + if (customMem.customAlloc) { + /* calloc implemented as malloc+memset; + * not as efficient as calloc, but next best guess for custom malloc */ + void* const ptr = customMem.customAlloc(customMem.opaque, size); + memset(ptr, 0, size); + return ptr; + } + return calloc(1, size); +} + +void ZSTD_free(void* ptr, ZSTD_customMem customMem) +{ + if (ptr!=NULL) { + if (customMem.customFree) + customMem.customFree(customMem.opaque, ptr); + else + free(ptr); + } +} diff --git a/grub-core/lib/zstd/zstd_decompress.c b/grub-core/lib/zstd/zstd_decompress.c new file mode 100644 index 0000000..e4b5670 --- /dev/null +++ b/grub-core/lib/zstd/zstd_decompress.c @@ -0,0 +1,3108 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + +/* *************************************************************** +* Tuning parameters +*****************************************************************/ +/*! + * HEAPMODE : + * Select how default decompression function ZSTD_decompress() allocates its context, + * on stack (0), or into heap (1, default; requires malloc()). + * Note that functions with explicit context such as ZSTD_decompressDCtx() are unaffected. + */ +#ifndef ZSTD_HEAPMODE +# define ZSTD_HEAPMODE 1 +#endif + +/*! +* LEGACY_SUPPORT : +* if set to 1+, ZSTD_decompress() can decode older formats (v0.1+) +*/ +#ifndef ZSTD_LEGACY_SUPPORT +# define ZSTD_LEGACY_SUPPORT 0 +#endif + +/*! + * MAXWINDOWSIZE_DEFAULT : + * maximum window size accepted by DStream __by default__. + * Frames requiring more memory will be rejected. + * It's possible to set a different limit using ZSTD_DCtx_setMaxWindowSize(). + */ +#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT +# define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_DEFAULTMAX) + 1) +#endif + +/*! + * NO_FORWARD_PROGRESS_MAX : + * maximum allowed nb of calls to ZSTD_decompressStream() and ZSTD_decompress_generic() + * without any forward progress + * (defined as: no byte read from input, and no byte flushed to output) + * before triggering an error. + */ +#ifndef ZSTD_NO_FORWARD_PROGRESS_MAX +# define ZSTD_NO_FORWARD_PROGRESS_MAX 16 +#endif + + +/*-******************************************************* +* Dependencies +*********************************************************/ +#include <string.h> /* memcpy, memmove, memset */ +#include "compiler.h" /* prefetch */ +#include "cpu.h" /* bmi2 */ +#include "mem.h" /* low level memory routines */ +#define FSE_STATIC_LINKING_ONLY +#include "fse.h" +#define HUF_STATIC_LINKING_ONLY +#include "huf.h" +#include "zstd_internal.h" + +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) +# include "zstd_legacy.h" +#endif + +static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict); +static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict); + + +/*-************************************* +* Errors +***************************************/ +#define ZSTD_isError ERR_isError /* for inlining */ +#define FSE_isError ERR_isError +#define HUF_isError ERR_isError + + +/*_******************************************************* +* Memory operations +**********************************************************/ +static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); } + + +/*-************************************************************* +* Context management +***************************************************************/ +typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader, + ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock, + ZSTDds_decompressLastBlock, ZSTDds_checkChecksum, + ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage; + +typedef enum { zdss_init=0, zdss_loadHeader, + zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage; + + +typedef struct { + U32 fastMode; + U32 tableLog; +} ZSTD_seqSymbol_header; + +typedef struct { + U16 nextState; + BYTE nbAdditionalBits; + BYTE nbBits; + U32 baseValue; +} ZSTD_seqSymbol; + +#define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log))) + +typedef struct { + ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]; /* Note : Space reserved for FSE Tables */ + ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]; /* is also used as temporary workspace while building hufTable during DDict creation */ + ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]; /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */ + HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */ + U32 rep[ZSTD_REP_NUM]; +} ZSTD_entropyDTables_t; + +struct ZSTD_DCtx_s +{ + const ZSTD_seqSymbol* LLTptr; + const ZSTD_seqSymbol* MLTptr; + const ZSTD_seqSymbol* OFTptr; + const HUF_DTable* HUFptr; + ZSTD_entropyDTables_t entropy; + U32 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; /* space needed when building huffman tables */ + const void* previousDstEnd; /* detect continuity */ + const void* prefixStart; /* start of current segment */ + const void* virtualStart; /* virtual start of previous segment if it was just before current one */ + const void* dictEnd; /* end of previous segment */ + size_t expected; + ZSTD_frameHeader fParams; + U64 decodedSize; + blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */ + ZSTD_dStage stage; + U32 litEntropy; + U32 fseEntropy; + XXH64_state_t xxhState; + size_t headerSize; + ZSTD_format_e format; + const BYTE* litPtr; + ZSTD_customMem customMem; + size_t litSize; + size_t rleSize; + size_t staticSize; + int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */ + + /* dictionary */ + ZSTD_DDict* ddictLocal; + const ZSTD_DDict* ddict; /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */ + U32 dictID; + int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */ + + /* streaming */ + ZSTD_dStreamStage streamStage; + char* inBuff; + size_t inBuffSize; + size_t inPos; + size_t maxWindowSize; + char* outBuff; + size_t outBuffSize; + size_t outStart; + size_t outEnd; + size_t lhSize; + void* legacyContext; + U32 previousLegacyVersion; + U32 legacyVersion; + U32 hostageByte; + int noForwardProgress; + + /* workspace */ + BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH]; + BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; +}; /* typedef'd to ZSTD_DCtx within "zstd.h" */ + +size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx) +{ + if (dctx==NULL) return 0; /* support sizeof NULL */ + return sizeof(*dctx) + + ZSTD_sizeof_DDict(dctx->ddictLocal) + + dctx->inBuffSize + dctx->outBuffSize; +} + +size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); } + + +static size_t ZSTD_startingInputLength(ZSTD_format_e format) +{ + size_t const startingInputLength = (format==ZSTD_f_zstd1_magicless) ? + ZSTD_frameHeaderSize_prefix - ZSTD_FRAMEIDSIZE : + ZSTD_frameHeaderSize_prefix; + ZSTD_STATIC_ASSERT(ZSTD_FRAMEHEADERSIZE_PREFIX >= ZSTD_FRAMEIDSIZE); + /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */ + assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) ); + return startingInputLength; +} + +static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) +{ + dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */ + dctx->staticSize = 0; + dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; + dctx->ddict = NULL; + dctx->ddictLocal = NULL; + dctx->dictEnd = NULL; + dctx->ddictIsCold = 0; + dctx->inBuff = NULL; + dctx->inBuffSize = 0; + dctx->outBuffSize = 0; + dctx->streamStage = zdss_init; + dctx->legacyContext = NULL; + dctx->previousLegacyVersion = 0; + dctx->noForwardProgress = 0; + dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); +} + +ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize) +{ + ZSTD_DCtx* const dctx = (ZSTD_DCtx*) workspace; + + if ((size_t)workspace & 7) return NULL; /* 8-aligned */ + if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL; /* minimum size */ + + ZSTD_initDCtx_internal(dctx); + dctx->staticSize = workspaceSize; + dctx->inBuff = (char*)(dctx+1); + return dctx; +} + +ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem) +{ + if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + + { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem); + if (!dctx) return NULL; + dctx->customMem = customMem; + ZSTD_initDCtx_internal(dctx); + return dctx; + } +} + +ZSTD_DCtx* ZSTD_createDCtx(void) +{ + DEBUGLOG(3, "ZSTD_createDCtx"); + return ZSTD_createDCtx_advanced(ZSTD_defaultCMem); +} + +size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx) +{ + if (dctx==NULL) return 0; /* support free on NULL */ + if (dctx->staticSize) return ERROR(memory_allocation); /* not compatible with static DCtx */ + { ZSTD_customMem const cMem = dctx->customMem; + ZSTD_freeDDict(dctx->ddictLocal); + dctx->ddictLocal = NULL; + ZSTD_free(dctx->inBuff, cMem); + dctx->inBuff = NULL; +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) + if (dctx->legacyContext) + ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion); +#endif + ZSTD_free(dctx, cMem); + return 0; + } +} + +/* no longer useful */ +void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx) +{ + size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx); + memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */ +} + + +/*-************************************************************* + * Frame header decoding + ***************************************************************/ + +/*! ZSTD_isFrame() : + * Tells if the content of `buffer` starts with a valid Frame Identifier. + * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0. + * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled. + * Note 3 : Skippable Frame Identifiers are considered valid. */ +unsigned ZSTD_isFrame(const void* buffer, size_t size) +{ + if (size < ZSTD_FRAMEIDSIZE) return 0; + { U32 const magic = MEM_readLE32(buffer); + if (magic == ZSTD_MAGICNUMBER) return 1; + if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) return 1; + } +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) + if (ZSTD_isLegacy(buffer, size)) return 1; +#endif + return 0; +} + +/** ZSTD_frameHeaderSize_internal() : + * srcSize must be large enough to reach header size fields. + * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless. + * @return : size of the Frame Header + * or an error code, which can be tested with ZSTD_isError() */ +static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format) +{ + size_t const minInputSize = ZSTD_startingInputLength(format); + if (srcSize < minInputSize) return ERROR(srcSize_wrong); + + { BYTE const fhd = ((const BYTE*)src)[minInputSize-1]; + U32 const dictID= fhd & 3; + U32 const singleSegment = (fhd >> 5) & 1; + U32 const fcsId = fhd >> 6; + return minInputSize + !singleSegment + + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId] + + (singleSegment && !fcsId); + } +} + +/** ZSTD_frameHeaderSize() : + * srcSize must be >= ZSTD_frameHeaderSize_prefix. + * @return : size of the Frame Header, + * or an error code (if srcSize is too small) */ +size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize) +{ + return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1); +} + + +/** ZSTD_getFrameHeader_advanced() : + * decode Frame Header, or require larger `srcSize`. + * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless + * @return : 0, `zfhPtr` is correctly filled, + * >0, `srcSize` is too small, value is wanted `srcSize` amount, + * or an error code, which can be tested using ZSTD_isError() */ +size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format) +{ + const BYTE* ip = (const BYTE*)src; + size_t const minInputSize = ZSTD_startingInputLength(format); + + memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */ + if (srcSize < minInputSize) return minInputSize; + if (src==NULL) return ERROR(GENERIC); /* invalid parameter */ + + if ( (format != ZSTD_f_zstd1_magicless) + && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) { + if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { + /* skippable frame */ + if (srcSize < ZSTD_skippableHeaderSize) + return ZSTD_skippableHeaderSize; /* magic number + frame length */ + memset(zfhPtr, 0, sizeof(*zfhPtr)); + zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE); + zfhPtr->frameType = ZSTD_skippableFrame; + return 0; + } + return ERROR(prefix_unknown); + } + + /* ensure there is enough `srcSize` to fully read/decode frame header */ + { size_t const fhsize = ZSTD_frameHeaderSize_internal(src, srcSize, format); + if (srcSize < fhsize) return fhsize; + zfhPtr->headerSize = (U32)fhsize; + } + + { BYTE const fhdByte = ip[minInputSize-1]; + size_t pos = minInputSize; + U32 const dictIDSizeCode = fhdByte&3; + U32 const checksumFlag = (fhdByte>>2)&1; + U32 const singleSegment = (fhdByte>>5)&1; + U32 const fcsID = fhdByte>>6; + U64 windowSize = 0; + U32 dictID = 0; + U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN; + if ((fhdByte & 0x08) != 0) + return ERROR(frameParameter_unsupported); /* reserved bits, must be zero */ + + if (!singleSegment) { + BYTE const wlByte = ip[pos++]; + U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN; + if (windowLog > ZSTD_WINDOWLOG_MAX) + return ERROR(frameParameter_windowTooLarge); + windowSize = (1ULL << windowLog); + windowSize += (windowSize >> 3) * (wlByte&7); + } + switch(dictIDSizeCode) + { + default: assert(0); /* impossible */ + case 0 : break; + case 1 : dictID = ip[pos]; pos++; break; + case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break; + case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break; + } + switch(fcsID) + { + default: assert(0); /* impossible */ + case 0 : if (singleSegment) frameContentSize = ip[pos]; break; + case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break; + case 2 : frameContentSize = MEM_readLE32(ip+pos); break; + case 3 : frameContentSize = MEM_readLE64(ip+pos); break; + } + if (singleSegment) windowSize = frameContentSize; + + zfhPtr->frameType = ZSTD_frame; + zfhPtr->frameContentSize = frameContentSize; + zfhPtr->windowSize = windowSize; + zfhPtr->blockSizeMax = (unsigned) MIN(windowSize, ZSTD_BLOCKSIZE_MAX); + zfhPtr->dictID = dictID; + zfhPtr->checksumFlag = checksumFlag; + } + return 0; +} + +/** ZSTD_getFrameHeader() : + * decode Frame Header, or require larger `srcSize`. + * note : this function does not consume input, it only reads it. + * @return : 0, `zfhPtr` is correctly filled, + * >0, `srcSize` is too small, value is wanted `srcSize` amount, + * or an error code, which can be tested using ZSTD_isError() */ +size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize) +{ + return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1); +} + + +/** ZSTD_getFrameContentSize() : + * compatible with legacy mode + * @return : decompressed size of the single frame pointed to be `src` if known, otherwise + * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined + * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */ +unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize) +{ +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) + if (ZSTD_isLegacy(src, srcSize)) { + unsigned long long const ret = ZSTD_getDecompressedSize_legacy(src, srcSize); + return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret; + } +#endif + { ZSTD_frameHeader zfh; + if (ZSTD_getFrameHeader(&zfh, src, srcSize) != 0) + return ZSTD_CONTENTSIZE_ERROR; + if (zfh.frameType == ZSTD_skippableFrame) { + return 0; + } else { + return zfh.frameContentSize; + } } +} + +/** ZSTD_findDecompressedSize() : + * compatible with legacy mode + * `srcSize` must be the exact length of some number of ZSTD compressed and/or + * skippable frames + * @return : decompressed size of the frames contained */ +unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize) +{ + unsigned long long totalDstSize = 0; + + while (srcSize >= ZSTD_frameHeaderSize_prefix) { + U32 const magicNumber = MEM_readLE32(src); + + if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { + size_t skippableSize; + if (srcSize < ZSTD_skippableHeaderSize) + return ERROR(srcSize_wrong); + skippableSize = MEM_readLE32((const BYTE *)src + ZSTD_FRAMEIDSIZE) + + ZSTD_skippableHeaderSize; + if (srcSize < skippableSize) { + return ZSTD_CONTENTSIZE_ERROR; + } + + src = (const BYTE *)src + skippableSize; + srcSize -= skippableSize; + continue; + } + + { unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize); + if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret; + + /* check for overflow */ + if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR; + totalDstSize += ret; + } + { size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize); + if (ZSTD_isError(frameSrcSize)) { + return ZSTD_CONTENTSIZE_ERROR; + } + + src = (const BYTE *)src + frameSrcSize; + srcSize -= frameSrcSize; + } + } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */ + + if (srcSize) return ZSTD_CONTENTSIZE_ERROR; + + return totalDstSize; +} + +/** ZSTD_getDecompressedSize() : +* compatible with legacy mode +* @return : decompressed size if known, 0 otherwise + note : 0 can mean any of the following : + - frame content is empty + - decompressed size field is not present in frame header + - frame header unknown / not supported + - frame header not complete (`srcSize` too small) */ +unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize) +{ + unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize); + ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_ERROR < ZSTD_CONTENTSIZE_UNKNOWN); + return (ret >= ZSTD_CONTENTSIZE_ERROR) ? 0 : ret; +} + + +/** ZSTD_decodeFrameHeader() : +* `headerSize` must be the size provided by ZSTD_frameHeaderSize(). +* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */ +static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize) +{ + size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format); + if (ZSTD_isError(result)) return result; /* invalid header */ + if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */ + if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) + return ERROR(dictionary_wrong); + if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0); + return 0; +} + + +/*-************************************************************* + * Block decoding + ***************************************************************/ + +/*! ZSTD_getcBlockSize() : +* Provides the size of compressed block from block header `src` */ +size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, + blockProperties_t* bpPtr) +{ + if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); + { U32 const cBlockHeader = MEM_readLE24(src); + U32 const cSize = cBlockHeader >> 3; + bpPtr->lastBlock = cBlockHeader & 1; + bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3); + bpPtr->origSize = cSize; /* only useful for RLE */ + if (bpPtr->blockType == bt_rle) return 1; + if (bpPtr->blockType == bt_reserved) return ERROR(corruption_detected); + return cSize; + } +} + + +static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, + const void* src, size_t srcSize) +{ + if (dst==NULL) return ERROR(dstSize_tooSmall); + if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall); + memcpy(dst, src, srcSize); + return srcSize; +} + + +static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + size_t regenSize) +{ + if (srcSize != 1) return ERROR(srcSize_wrong); + if (regenSize > dstCapacity) return ERROR(dstSize_tooSmall); + memset(dst, *(const BYTE*)src, regenSize); + return regenSize; +} + +/* Hidden declaration for fullbench */ +size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, + const void* src, size_t srcSize); +/*! ZSTD_decodeLiteralsBlock() : + * @return : nb of bytes read from src (< srcSize ) + * note : symbol not declared but exposed for fullbench */ +size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, + const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */ +{ + if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected); + + { const BYTE* const istart = (const BYTE*) src; + symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3); + + switch(litEncType) + { + case set_repeat: + if (dctx->litEntropy==0) return ERROR(dictionary_corrupted); + /* fall-through */ + + case set_compressed: + if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */ + { size_t lhSize, litSize, litCSize; + U32 singleStream=0; + U32 const lhlCode = (istart[0] >> 2) & 3; + U32 const lhc = MEM_readLE32(istart); + switch(lhlCode) + { + case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */ + /* 2 - 2 - 10 - 10 */ + singleStream = !lhlCode; + lhSize = 3; + litSize = (lhc >> 4) & 0x3FF; + litCSize = (lhc >> 14) & 0x3FF; + break; + case 2: + /* 2 - 2 - 14 - 14 */ + lhSize = 4; + litSize = (lhc >> 4) & 0x3FFF; + litCSize = lhc >> 18; + break; + case 3: + /* 2 - 2 - 18 - 18 */ + lhSize = 5; + litSize = (lhc >> 4) & 0x3FFFF; + litCSize = (lhc >> 22) + (istart[4] << 10); + break; + } + if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected); + if (litCSize + lhSize > srcSize) return ERROR(corruption_detected); + + /* prefetch huffman table if cold */ + if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) { + PREFETCH_AREA(dctx->HUFptr, sizeof(dctx->entropy.hufTable)); + } + + if (HUF_isError((litEncType==set_repeat) ? + ( singleStream ? + HUF_decompress1X_usingDTable_bmi2(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr, dctx->bmi2) : + HUF_decompress4X_usingDTable_bmi2(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr, dctx->bmi2) ) : + ( singleStream ? + HUF_decompress1X1_DCtx_wksp_bmi2(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize, + dctx->workspace, sizeof(dctx->workspace), dctx->bmi2) : + HUF_decompress4X_hufOnly_wksp_bmi2(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize, + dctx->workspace, sizeof(dctx->workspace), dctx->bmi2)))) + return ERROR(corruption_detected); + + dctx->litPtr = dctx->litBuffer; + dctx->litSize = litSize; + dctx->litEntropy = 1; + if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable; + memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); + return litCSize + lhSize; + } + + case set_basic: + { size_t litSize, lhSize; + U32 const lhlCode = ((istart[0]) >> 2) & 3; + switch(lhlCode) + { + case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */ + lhSize = 1; + litSize = istart[0] >> 3; + break; + case 1: + lhSize = 2; + litSize = MEM_readLE16(istart) >> 4; + break; + case 3: + lhSize = 3; + litSize = MEM_readLE24(istart) >> 4; + break; + } + + if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */ + if (litSize+lhSize > srcSize) return ERROR(corruption_detected); + memcpy(dctx->litBuffer, istart+lhSize, litSize); + dctx->litPtr = dctx->litBuffer; + dctx->litSize = litSize; + memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); + return lhSize+litSize; + } + /* direct reference into compressed stream */ + dctx->litPtr = istart+lhSize; + dctx->litSize = litSize; + return lhSize+litSize; + } + + case set_rle: + { U32 const lhlCode = ((istart[0]) >> 2) & 3; + size_t litSize, lhSize; + switch(lhlCode) + { + case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */ + lhSize = 1; + litSize = istart[0] >> 3; + break; + case 1: + lhSize = 2; + litSize = MEM_readLE16(istart) >> 4; + break; + case 3: + lhSize = 3; + litSize = MEM_readLE24(istart) >> 4; + if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */ + break; + } + if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected); + memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH); + dctx->litPtr = dctx->litBuffer; + dctx->litSize = litSize; + return lhSize+1; + } + default: + return ERROR(corruption_detected); /* impossible */ + } + } +} + +/* Default FSE distribution tables. + * These are pre-calculated FSE decoding tables using default distributions as defined in specification : + * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#default-distributions + * They were generated programmatically with following method : + * - start from default distributions, present in /lib/common/zstd_internal.h + * - generate tables normally, using ZSTD_buildFSETable() + * - printout the content of tables + * - pretify output, report below, test with fuzzer to ensure it's correct */ + +/* Default FSE distribution table for Literal Lengths */ +static const ZSTD_seqSymbol LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = { + { 1, 1, 1, LL_DEFAULTNORMLOG}, /* header : fastMode, tableLog */ + /* nextState, nbAddBits, nbBits, baseVal */ + { 0, 0, 4, 0}, { 16, 0, 4, 0}, + { 32, 0, 5, 1}, { 0, 0, 5, 3}, + { 0, 0, 5, 4}, { 0, 0, 5, 6}, + { 0, 0, 5, 7}, { 0, 0, 5, 9}, + { 0, 0, 5, 10}, { 0, 0, 5, 12}, + { 0, 0, 6, 14}, { 0, 1, 5, 16}, + { 0, 1, 5, 20}, { 0, 1, 5, 22}, + { 0, 2, 5, 28}, { 0, 3, 5, 32}, + { 0, 4, 5, 48}, { 32, 6, 5, 64}, + { 0, 7, 5, 128}, { 0, 8, 6, 256}, + { 0, 10, 6, 1024}, { 0, 12, 6, 4096}, + { 32, 0, 4, 0}, { 0, 0, 4, 1}, + { 0, 0, 5, 2}, { 32, 0, 5, 4}, + { 0, 0, 5, 5}, { 32, 0, 5, 7}, + { 0, 0, 5, 8}, { 32, 0, 5, 10}, + { 0, 0, 5, 11}, { 0, 0, 6, 13}, + { 32, 1, 5, 16}, { 0, 1, 5, 18}, + { 32, 1, 5, 22}, { 0, 2, 5, 24}, + { 32, 3, 5, 32}, { 0, 3, 5, 40}, + { 0, 6, 4, 64}, { 16, 6, 4, 64}, + { 32, 7, 5, 128}, { 0, 9, 6, 512}, + { 0, 11, 6, 2048}, { 48, 0, 4, 0}, + { 16, 0, 4, 1}, { 32, 0, 5, 2}, + { 32, 0, 5, 3}, { 32, 0, 5, 5}, + { 32, 0, 5, 6}, { 32, 0, 5, 8}, + { 32, 0, 5, 9}, { 32, 0, 5, 11}, + { 32, 0, 5, 12}, { 0, 0, 6, 15}, + { 32, 1, 5, 18}, { 32, 1, 5, 20}, + { 32, 2, 5, 24}, { 32, 2, 5, 28}, + { 32, 3, 5, 40}, { 32, 4, 5, 48}, + { 0, 16, 6,65536}, { 0, 15, 6,32768}, + { 0, 14, 6,16384}, { 0, 13, 6, 8192}, +}; /* LL_defaultDTable */ + +/* Default FSE distribution table for Offset Codes */ +static const ZSTD_seqSymbol OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = { + { 1, 1, 1, OF_DEFAULTNORMLOG}, /* header : fastMode, tableLog */ + /* nextState, nbAddBits, nbBits, baseVal */ + { 0, 0, 5, 0}, { 0, 6, 4, 61}, + { 0, 9, 5, 509}, { 0, 15, 5,32765}, + { 0, 21, 5,2097149}, { 0, 3, 5, 5}, + { 0, 7, 4, 125}, { 0, 12, 5, 4093}, + { 0, 18, 5,262141}, { 0, 23, 5,8388605}, + { 0, 5, 5, 29}, { 0, 8, 4, 253}, + { 0, 14, 5,16381}, { 0, 20, 5,1048573}, + { 0, 2, 5, 1}, { 16, 7, 4, 125}, + { 0, 11, 5, 2045}, { 0, 17, 5,131069}, + { 0, 22, 5,4194301}, { 0, 4, 5, 13}, + { 16, 8, 4, 253}, { 0, 13, 5, 8189}, + { 0, 19, 5,524285}, { 0, 1, 5, 1}, + { 16, 6, 4, 61}, { 0, 10, 5, 1021}, + { 0, 16, 5,65533}, { 0, 28, 5,268435453}, + { 0, 27, 5,134217725}, { 0, 26, 5,67108861}, + { 0, 25, 5,33554429}, { 0, 24, 5,16777213}, +}; /* OF_defaultDTable */ + + +/* Default FSE distribution table for Match Lengths */ +static const ZSTD_seqSymbol ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = { + { 1, 1, 1, ML_DEFAULTNORMLOG}, /* header : fastMode, tableLog */ + /* nextState, nbAddBits, nbBits, baseVal */ + { 0, 0, 6, 3}, { 0, 0, 4, 4}, + { 32, 0, 5, 5}, { 0, 0, 5, 6}, + { 0, 0, 5, 8}, { 0, 0, 5, 9}, + { 0, 0, 5, 11}, { 0, 0, 6, 13}, + { 0, 0, 6, 16}, { 0, 0, 6, 19}, + { 0, 0, 6, 22}, { 0, 0, 6, 25}, + { 0, 0, 6, 28}, { 0, 0, 6, 31}, + { 0, 0, 6, 34}, { 0, 1, 6, 37}, + { 0, 1, 6, 41}, { 0, 2, 6, 47}, + { 0, 3, 6, 59}, { 0, 4, 6, 83}, + { 0, 7, 6, 131}, { 0, 9, 6, 515}, + { 16, 0, 4, 4}, { 0, 0, 4, 5}, + { 32, 0, 5, 6}, { 0, 0, 5, 7}, + { 32, 0, 5, 9}, { 0, 0, 5, 10}, + { 0, 0, 6, 12}, { 0, 0, 6, 15}, + { 0, 0, 6, 18}, { 0, 0, 6, 21}, + { 0, 0, 6, 24}, { 0, 0, 6, 27}, + { 0, 0, 6, 30}, { 0, 0, 6, 33}, + { 0, 1, 6, 35}, { 0, 1, 6, 39}, + { 0, 2, 6, 43}, { 0, 3, 6, 51}, + { 0, 4, 6, 67}, { 0, 5, 6, 99}, + { 0, 8, 6, 259}, { 32, 0, 4, 4}, + { 48, 0, 4, 4}, { 16, 0, 4, 5}, + { 32, 0, 5, 7}, { 32, 0, 5, 8}, + { 32, 0, 5, 10}, { 32, 0, 5, 11}, + { 0, 0, 6, 14}, { 0, 0, 6, 17}, + { 0, 0, 6, 20}, { 0, 0, 6, 23}, + { 0, 0, 6, 26}, { 0, 0, 6, 29}, + { 0, 0, 6, 32}, { 0, 16, 6,65539}, + { 0, 15, 6,32771}, { 0, 14, 6,16387}, + { 0, 13, 6, 8195}, { 0, 12, 6, 4099}, + { 0, 11, 6, 2051}, { 0, 10, 6, 1027}, +}; /* ML_defaultDTable */ + + +static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U32 nbAddBits) +{ + void* ptr = dt; + ZSTD_seqSymbol_header* const DTableH = (ZSTD_seqSymbol_header*)ptr; + ZSTD_seqSymbol* const cell = dt + 1; + + DTableH->tableLog = 0; + DTableH->fastMode = 0; + + cell->nbBits = 0; + cell->nextState = 0; + assert(nbAddBits < 255); + cell->nbAdditionalBits = (BYTE)nbAddBits; + cell->baseValue = baseValue; +} + + +/* ZSTD_buildFSETable() : + * generate FSE decoding table for one symbol (ll, ml or off) */ +static void +ZSTD_buildFSETable(ZSTD_seqSymbol* dt, + const short* normalizedCounter, unsigned maxSymbolValue, + const U32* baseValue, const U32* nbAdditionalBits, + unsigned tableLog) +{ + ZSTD_seqSymbol* const tableDecode = dt+1; + U16 symbolNext[MaxSeq+1]; + + U32 const maxSV1 = maxSymbolValue + 1; + U32 const tableSize = 1 << tableLog; + U32 highThreshold = tableSize-1; + + /* Sanity Checks */ + assert(maxSymbolValue <= MaxSeq); + assert(tableLog <= MaxFSELog); + + /* Init, lay down lowprob symbols */ + { ZSTD_seqSymbol_header DTableH; + DTableH.tableLog = tableLog; + DTableH.fastMode = 1; + { S16 const largeLimit= (S16)(1 << (tableLog-1)); + U32 s; + for (s=0; s<maxSV1; s++) { + if (normalizedCounter[s]==-1) { + tableDecode[highThreshold--].baseValue = s; + symbolNext[s] = 1; + } else { + if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0; + symbolNext[s] = normalizedCounter[s]; + } } } + memcpy(dt, &DTableH, sizeof(DTableH)); + } + + /* Spread symbols */ + { U32 const tableMask = tableSize-1; + U32 const step = FSE_TABLESTEP(tableSize); + U32 s, position = 0; + for (s=0; s<maxSV1; s++) { + int i; + for (i=0; i<normalizedCounter[s]; i++) { + tableDecode[position].baseValue = s; + position = (position + step) & tableMask; + while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */ + } } + assert(position == 0); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ + } + + /* Build Decoding table */ + { U32 u; + for (u=0; u<tableSize; u++) { + U32 const symbol = tableDecode[u].baseValue; + U32 const nextState = symbolNext[symbol]++; + tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) ); + tableDecode[u].nextState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize); + assert(nbAdditionalBits[symbol] < 255); + tableDecode[u].nbAdditionalBits = (BYTE)nbAdditionalBits[symbol]; + tableDecode[u].baseValue = baseValue[symbol]; + } } +} + + +/*! ZSTD_buildSeqTable() : + * @return : nb bytes read from src, + * or an error code if it fails */ +static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymbol** DTablePtr, + symbolEncodingType_e type, U32 max, U32 maxLog, + const void* src, size_t srcSize, + const U32* baseValue, const U32* nbAdditionalBits, + const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable, + int ddictIsCold, int nbSeq) +{ + switch(type) + { + case set_rle : + if (!srcSize) return ERROR(srcSize_wrong); + if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected); + { U32 const symbol = *(const BYTE*)src; + U32 const baseline = baseValue[symbol]; + U32 const nbBits = nbAdditionalBits[symbol]; + ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits); + } + *DTablePtr = DTableSpace; + return 1; + case set_basic : + *DTablePtr = defaultTable; + return 0; + case set_repeat: + if (!flagRepeatTable) return ERROR(corruption_detected); + /* prefetch FSE table if used */ + if (ddictIsCold && (nbSeq > 24 /* heuristic */)) { + const void* const pStart = *DTablePtr; + size_t const pSize = sizeof(ZSTD_seqSymbol) * (SEQSYMBOL_TABLE_SIZE(maxLog)); + PREFETCH_AREA(pStart, pSize); + } + return 0; + case set_compressed : + { U32 tableLog; + S16 norm[MaxSeq+1]; + size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize); + if (FSE_isError(headerSize)) return ERROR(corruption_detected); + if (tableLog > maxLog) return ERROR(corruption_detected); + ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog); + *DTablePtr = DTableSpace; + return headerSize; + } + default : /* impossible */ + assert(0); + return ERROR(GENERIC); + } +} + +static const U32 LL_base[MaxLL+1] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 18, 20, 22, 24, 28, 32, 40, + 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, + 0x2000, 0x4000, 0x8000, 0x10000 }; + +static const U32 OF_base[MaxOff+1] = { + 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, + 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, + 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, + 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD }; + +static const U32 OF_bits[MaxOff+1] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31 }; + +static const U32 ML_base[MaxML+1] = { + 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 37, 39, 41, 43, 47, 51, 59, + 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, + 0x1003, 0x2003, 0x4003, 0x8003, 0x10003 }; + +/* Hidden delcaration for fullbench */ +size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, + const void* src, size_t srcSize); + +size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, + const void* src, size_t srcSize) +{ + const BYTE* const istart = (const BYTE* const)src; + const BYTE* const iend = istart + srcSize; + const BYTE* ip = istart; + int nbSeq; + DEBUGLOG(5, "ZSTD_decodeSeqHeaders"); + + /* check */ + if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong); + + /* SeqHead */ + nbSeq = *ip++; + if (!nbSeq) { *nbSeqPtr=0; return 1; } + if (nbSeq > 0x7F) { + if (nbSeq == 0xFF) { + if (ip+2 > iend) return ERROR(srcSize_wrong); + nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2; + } else { + if (ip >= iend) return ERROR(srcSize_wrong); + nbSeq = ((nbSeq-0x80)<<8) + *ip++; + } + } + *nbSeqPtr = nbSeq; + + /* FSE table descriptors */ + if (ip+4 > iend) return ERROR(srcSize_wrong); /* minimum possible size */ + { symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6); + symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3); + symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3); + ip++; + + /* Build DTables */ + { size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr, + LLtype, MaxLL, LLFSELog, + ip, iend-ip, + LL_base, LL_bits, + LL_defaultDTable, dctx->fseEntropy, + dctx->ddictIsCold, nbSeq); + if (ZSTD_isError(llhSize)) return ERROR(corruption_detected); + ip += llhSize; + } + + { size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr, + OFtype, MaxOff, OffFSELog, + ip, iend-ip, + OF_base, OF_bits, + OF_defaultDTable, dctx->fseEntropy, + dctx->ddictIsCold, nbSeq); + if (ZSTD_isError(ofhSize)) return ERROR(corruption_detected); + ip += ofhSize; + } + + { size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr, + MLtype, MaxML, MLFSELog, + ip, iend-ip, + ML_base, ML_bits, + ML_defaultDTable, dctx->fseEntropy, + dctx->ddictIsCold, nbSeq); + if (ZSTD_isError(mlhSize)) return ERROR(corruption_detected); + ip += mlhSize; + } + } + + /* prefetch dictionary content */ + if (dctx->ddictIsCold) { + size_t const dictSize = (const char*)dctx->prefixStart - (const char*)dctx->virtualStart; + size_t const psmin = MIN(dictSize, (size_t)(64*nbSeq) /* heuristic */ ); + size_t const pSize = MIN(psmin, 128 KB /* protection */ ); + const void* const pStart = (const char*)dctx->dictEnd - pSize; + PREFETCH_AREA(pStart, pSize); + dctx->ddictIsCold = 0; + } + + return ip-istart; +} + + +typedef struct { + size_t litLength; + size_t matchLength; + size_t offset; + const BYTE* match; +} seq_t; + +typedef struct { + size_t state; + const ZSTD_seqSymbol* table; +} ZSTD_fseState; + +typedef struct { + BIT_DStream_t DStream; + ZSTD_fseState stateLL; + ZSTD_fseState stateOffb; + ZSTD_fseState stateML; + size_t prevOffset[ZSTD_REP_NUM]; + const BYTE* prefixStart; + const BYTE* dictEnd; + size_t pos; +} seqState_t; + + +FORCE_NOINLINE +size_t ZSTD_execSequenceLast7(BYTE* op, + BYTE* const oend, seq_t sequence, + const BYTE** litPtr, const BYTE* const litLimit, + const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd) +{ + BYTE* const oLitEnd = op + sequence.litLength; + size_t const sequenceLength = sequence.litLength + sequence.matchLength; + BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ + BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; + const BYTE* const iLitEnd = *litPtr + sequence.litLength; + const BYTE* match = oLitEnd - sequence.offset; + + /* check */ + if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */ + if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */ + if (oLitEnd <= oend_w) return ERROR(GENERIC); /* Precondition */ + + /* copy literals */ + if (op < oend_w) { + ZSTD_wildcopy(op, *litPtr, oend_w - op); + *litPtr += oend_w - op; + op = oend_w; + } + while (op < oLitEnd) *op++ = *(*litPtr)++; + + /* copy Match */ + if (sequence.offset > (size_t)(oLitEnd - base)) { + /* offset beyond prefix */ + if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected); + match = dictEnd - (base-match); + if (match + sequence.matchLength <= dictEnd) { + memmove(oLitEnd, match, sequence.matchLength); + return sequenceLength; + } + /* span extDict & currentPrefixSegment */ + { size_t const length1 = dictEnd - match; + memmove(oLitEnd, match, length1); + op = oLitEnd + length1; + sequence.matchLength -= length1; + match = base; + } } + while (op < oMatchEnd) *op++ = *match++; + return sequenceLength; +} + + +HINT_INLINE +size_t ZSTD_execSequence(BYTE* op, + BYTE* const oend, seq_t sequence, + const BYTE** litPtr, const BYTE* const litLimit, + const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd) +{ + BYTE* const oLitEnd = op + sequence.litLength; + size_t const sequenceLength = sequence.litLength + sequence.matchLength; + BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ + BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; + const BYTE* const iLitEnd = *litPtr + sequence.litLength; + const BYTE* match = oLitEnd - sequence.offset; + + /* check */ + if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */ + if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */ + if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd); + + /* copy Literals */ + ZSTD_copy8(op, *litPtr); + if (sequence.litLength > 8) + ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */ + op = oLitEnd; + *litPtr = iLitEnd; /* update for next sequence */ + + /* copy Match */ + if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { + /* offset beyond prefix -> go into extDict */ + if (sequence.offset > (size_t)(oLitEnd - virtualStart)) + return ERROR(corruption_detected); + match = dictEnd + (match - prefixStart); + if (match + sequence.matchLength <= dictEnd) { + memmove(oLitEnd, match, sequence.matchLength); + return sequenceLength; + } + /* span extDict & currentPrefixSegment */ + { size_t const length1 = dictEnd - match; + memmove(oLitEnd, match, length1); + op = oLitEnd + length1; + sequence.matchLength -= length1; + match = prefixStart; + if (op > oend_w || sequence.matchLength < MINMATCH) { + U32 i; + for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i]; + return sequenceLength; + } + } } + /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */ + + /* match within prefix */ + if (sequence.offset < 8) { + /* close range match, overlap */ + static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */ + static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */ + int const sub2 = dec64table[sequence.offset]; + op[0] = match[0]; + op[1] = match[1]; + op[2] = match[2]; + op[3] = match[3]; + match += dec32table[sequence.offset]; + ZSTD_copy4(op+4, match); + match -= sub2; + } else { + ZSTD_copy8(op, match); + } + op += 8; match += 8; + + if (oMatchEnd > oend-(16-MINMATCH)) { + if (op < oend_w) { + ZSTD_wildcopy(op, match, oend_w - op); + match += oend_w - op; + op = oend_w; + } + while (op < oMatchEnd) *op++ = *match++; + } else { + ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */ + } + return sequenceLength; +} + + +HINT_INLINE +size_t ZSTD_execSequenceLong(BYTE* op, + BYTE* const oend, seq_t sequence, + const BYTE** litPtr, const BYTE* const litLimit, + const BYTE* const prefixStart, const BYTE* const dictStart, const BYTE* const dictEnd) +{ + BYTE* const oLitEnd = op + sequence.litLength; + size_t const sequenceLength = sequence.litLength + sequence.matchLength; + BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ + BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; + const BYTE* const iLitEnd = *litPtr + sequence.litLength; + const BYTE* match = sequence.match; + + /* check */ + if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */ + if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */ + if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd); + + /* copy Literals */ + ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */ + if (sequence.litLength > 8) + ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */ + op = oLitEnd; + *litPtr = iLitEnd; /* update for next sequence */ + + /* copy Match */ + if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { + /* offset beyond prefix */ + if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(corruption_detected); + if (match + sequence.matchLength <= dictEnd) { + memmove(oLitEnd, match, sequence.matchLength); + return sequenceLength; + } + /* span extDict & currentPrefixSegment */ + { size_t const length1 = dictEnd - match; + memmove(oLitEnd, match, length1); + op = oLitEnd + length1; + sequence.matchLength -= length1; + match = prefixStart; + if (op > oend_w || sequence.matchLength < MINMATCH) { + U32 i; + for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i]; + return sequenceLength; + } + } } + assert(op <= oend_w); + assert(sequence.matchLength >= MINMATCH); + + /* match within prefix */ + if (sequence.offset < 8) { + /* close range match, overlap */ + static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */ + static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */ + int const sub2 = dec64table[sequence.offset]; + op[0] = match[0]; + op[1] = match[1]; + op[2] = match[2]; + op[3] = match[3]; + match += dec32table[sequence.offset]; + ZSTD_copy4(op+4, match); + match -= sub2; + } else { + ZSTD_copy8(op, match); + } + op += 8; match += 8; + + if (oMatchEnd > oend-(16-MINMATCH)) { + if (op < oend_w) { + ZSTD_wildcopy(op, match, oend_w - op); + match += oend_w - op; + op = oend_w; + } + while (op < oMatchEnd) *op++ = *match++; + } else { + ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */ + } + return sequenceLength; +} + +static void +ZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqSymbol* dt) +{ + const void* ptr = dt; + const ZSTD_seqSymbol_header* const DTableH = (const ZSTD_seqSymbol_header*)ptr; + DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog); + DEBUGLOG(6, "ZSTD_initFseState : val=%u using %u bits", + (U32)DStatePtr->state, DTableH->tableLog); + BIT_reloadDStream(bitD); + DStatePtr->table = dt + 1; +} + +FORCE_INLINE_TEMPLATE void +ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD) +{ + ZSTD_seqSymbol const DInfo = DStatePtr->table[DStatePtr->state]; + U32 const nbBits = DInfo.nbBits; + size_t const lowBits = BIT_readBits(bitD, nbBits); + DStatePtr->state = DInfo.nextState + lowBits; +} + +/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum + * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1) + * bits before reloading. This value is the maximum number of bytes we read + * after reloading when we are decoding long offets. + */ +#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \ + (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \ + ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \ + : 0) + +typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e; + +FORCE_INLINE_TEMPLATE seq_t +ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets) +{ + seq_t seq = {0}; + U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits; + U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits; + U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits; + U32 const totalBits = llBits+mlBits+ofBits; + U32 const llBase = seqState->stateLL.table[seqState->stateLL.state].baseValue; + U32 const mlBase = seqState->stateML.table[seqState->stateML.state].baseValue; + U32 const ofBase = seqState->stateOffb.table[seqState->stateOffb.state].baseValue; + + /* sequence */ + { size_t offset; + if (!ofBits) + offset = 0; + else { + ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1); + ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5); + assert(ofBits <= MaxOff); + if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) { + U32 const extraBits = ofBits - MIN(ofBits, 32 - seqState->DStream.bitsConsumed); + offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits); + BIT_reloadDStream(&seqState->DStream); + if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits); + assert(extraBits <= LONG_OFFSETS_MAX_EXTRA_BITS_32); /* to avoid another reload */ + } else { + offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */ + if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); + } + } + + if (ofBits <= 1) { + offset += (llBase==0); + if (offset) { + size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; + temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */ + if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1]; + seqState->prevOffset[1] = seqState->prevOffset[0]; + seqState->prevOffset[0] = offset = temp; + } else { /* offset == 0 */ + offset = seqState->prevOffset[0]; + } + } else { + seqState->prevOffset[2] = seqState->prevOffset[1]; + seqState->prevOffset[1] = seqState->prevOffset[0]; + seqState->prevOffset[0] = offset; + } + seq.offset = offset; + } + + seq.matchLength = mlBase + + ((mlBits>0) ? BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/) : 0); /* <= 16 bits */ + if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32)) + BIT_reloadDStream(&seqState->DStream); + if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog))) + BIT_reloadDStream(&seqState->DStream); + /* Ensure there are enough bits to read the rest of data in 64-bit mode. */ + ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64); + + seq.litLength = llBase + + ((llBits>0) ? BIT_readBitsFast(&seqState->DStream, llBits/*>0*/) : 0); /* <= 16 bits */ + if (MEM_32bits()) + BIT_reloadDStream(&seqState->DStream); + + DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u", + (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset); + + /* ANS state update */ + ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */ + ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */ + if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ + ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */ + + return seq; +} + +FORCE_INLINE_TEMPLATE size_t +ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + const BYTE* ip = (const BYTE*)seqStart; + const BYTE* const iend = ip + seqSize; + BYTE* const ostart = (BYTE* const)dst; + BYTE* const oend = ostart + maxDstSize; + BYTE* op = ostart; + const BYTE* litPtr = dctx->litPtr; + const BYTE* const litEnd = litPtr + dctx->litSize; + const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart); + const BYTE* const vBase = (const BYTE*) (dctx->virtualStart); + const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd); + DEBUGLOG(5, "ZSTD_decompressSequences_body"); + + /* Regen sequences */ + if (nbSeq) { + seqState_t seqState; + dctx->fseEntropy = 1; + { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; } + CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected); + ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); + ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); + ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); + + for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) { + nbSeq--; + { seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset); + size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd); + DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); + if (ZSTD_isError(oneSeqSize)) return oneSeqSize; + op += oneSeqSize; + } } + + /* check if reached exact end */ + DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq); + if (nbSeq) return ERROR(corruption_detected); + /* save reps for next block */ + { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); } + } + + /* last literal segment */ + { size_t const lastLLSize = litEnd - litPtr; + if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall); + memcpy(op, litPtr, lastLLSize); + op += lastLLSize; + } + + return op-ostart; +} + +static size_t +ZSTD_decompressSequences_default(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} + + + +FORCE_INLINE_TEMPLATE seq_t +ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const longOffsets) +{ + seq_t seq; + U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits; + U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits; + U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits; + U32 const totalBits = llBits+mlBits+ofBits; + U32 const llBase = seqState->stateLL.table[seqState->stateLL.state].baseValue; + U32 const mlBase = seqState->stateML.table[seqState->stateML.state].baseValue; + U32 const ofBase = seqState->stateOffb.table[seqState->stateOffb.state].baseValue; + + /* sequence */ + { size_t offset; + if (!ofBits) + offset = 0; + else { + ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1); + ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5); + assert(ofBits <= MaxOff); + if (MEM_32bits() && longOffsets) { + U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1); + offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits); + if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream); + if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits); + } else { + offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */ + if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); + } + } + + if (ofBits <= 1) { + offset += (llBase==0); + if (offset) { + size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; + temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */ + if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1]; + seqState->prevOffset[1] = seqState->prevOffset[0]; + seqState->prevOffset[0] = offset = temp; + } else { + offset = seqState->prevOffset[0]; + } + } else { + seqState->prevOffset[2] = seqState->prevOffset[1]; + seqState->prevOffset[1] = seqState->prevOffset[0]; + seqState->prevOffset[0] = offset; + } + seq.offset = offset; + } + + seq.matchLength = mlBase + ((mlBits>0) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */ + if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32)) + BIT_reloadDStream(&seqState->DStream); + if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog))) + BIT_reloadDStream(&seqState->DStream); + /* Verify that there is enough bits to read the rest of the data in 64-bit mode. */ + ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64); + + seq.litLength = llBase + ((llBits>0) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */ + if (MEM_32bits()) + BIT_reloadDStream(&seqState->DStream); + + { size_t const pos = seqState->pos + seq.litLength; + const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart; + seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted. + * No consequence though : no memory access will occur, overly large offset will be detected in ZSTD_execSequenceLong() */ + seqState->pos = pos + seq.matchLength; + } + + /* ANS state update */ + ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */ + ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */ + if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ + ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */ + + return seq; +} + +FORCE_INLINE_TEMPLATE size_t +ZSTD_decompressSequencesLong_body( + ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + const BYTE* ip = (const BYTE*)seqStart; + const BYTE* const iend = ip + seqSize; + BYTE* const ostart = (BYTE* const)dst; + BYTE* const oend = ostart + maxDstSize; + BYTE* op = ostart; + const BYTE* litPtr = dctx->litPtr; + const BYTE* const litEnd = litPtr + dctx->litSize; + const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart); + const BYTE* const dictStart = (const BYTE*) (dctx->virtualStart); + const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd); + + /* Regen sequences */ + if (nbSeq) { +#define STORED_SEQS 4 +#define STOSEQ_MASK (STORED_SEQS-1) +#define ADVANCED_SEQS 4 + seq_t sequences[STORED_SEQS]; + int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS); + seqState_t seqState; + int seqNb; + dctx->fseEntropy = 1; + { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; } + seqState.prefixStart = prefixStart; + seqState.pos = (size_t)(op-prefixStart); + seqState.dictEnd = dictEnd; + CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected); + ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); + ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); + ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); + + /* prepare in advance */ + for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb<seqAdvance); seqNb++) { + sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset); + } + if (seqNb<seqAdvance) return ERROR(corruption_detected); + + /* decode and decompress */ + for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) { + seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, isLongOffset); + size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd); + if (ZSTD_isError(oneSeqSize)) return oneSeqSize; + PREFETCH(sequence.match); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */ + sequences[seqNb&STOSEQ_MASK] = sequence; + op += oneSeqSize; + } + if (seqNb<nbSeq) return ERROR(corruption_detected); + + /* finish queue */ + seqNb -= seqAdvance; + for ( ; seqNb<nbSeq ; seqNb++) { + size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb&STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd); + if (ZSTD_isError(oneSeqSize)) return oneSeqSize; + op += oneSeqSize; + } + + /* save reps for next block */ + { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); } +#undef STORED_SEQS +#undef STOSEQ_MASK +#undef ADVANCED_SEQS + } + + /* last literal segment */ + { size_t const lastLLSize = litEnd - litPtr; + if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall); + memcpy(op, litPtr, lastLLSize); + op += lastLLSize; + } + + return op-ostart; +} + +static size_t +ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} + + + +#if DYNAMIC_BMI2 + +static TARGET_ATTRIBUTE("bmi2") size_t +ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} + +static TARGET_ATTRIBUTE("bmi2") size_t +ZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} + +#endif + +typedef size_t (*ZSTD_decompressSequences_t)( + ZSTD_DCtx *dctx, void *dst, size_t maxDstSize, + const void *seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset); + +static size_t ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + DEBUGLOG(5, "ZSTD_decompressSequences"); +#if DYNAMIC_BMI2 + if (dctx->bmi2) { + return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); + } +#endif + return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} + +static size_t ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + DEBUGLOG(5, "ZSTD_decompressSequencesLong"); +#if DYNAMIC_BMI2 + if (dctx->bmi2) { + return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); + } +#endif + return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} + +/* ZSTD_getLongOffsetsShare() : + * condition : offTable must be valid + * @return : "share" of long offsets (arbitrarily defined as > (1<<23)) + * compared to maximum possible of (1<<OffFSELog) */ +static unsigned +ZSTD_getLongOffsetsShare(const ZSTD_seqSymbol* offTable) +{ + const void* ptr = offTable; + U32 const tableLog = ((const ZSTD_seqSymbol_header*)ptr)[0].tableLog; + const ZSTD_seqSymbol* table = offTable + 1; + U32 const max = 1 << tableLog; + U32 u, total = 0; + DEBUGLOG(5, "ZSTD_getLongOffsetsShare: (tableLog=%u)", tableLog); + + assert(max <= (1 << OffFSELog)); /* max not too large */ + for (u=0; u<max; u++) { + if (table[u].nbAdditionalBits > 22) total += 1; + } + + assert(tableLog <= OffFSELog); + total <<= (OffFSELog - tableLog); /* scale to OffFSELog */ + + return total; +} + + +static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, const int frame) +{ /* blockType == blockCompressed */ + const BYTE* ip = (const BYTE*)src; + /* isLongOffset must be true if there are long offsets. + * Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN. + * We don't expect that to be the case in 64-bit mode. + * In block mode, window size is not known, so we have to be conservative. + * (note: but it could be evaluated from current-lowLimit) + */ + ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN))); + DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize); + + if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); + + /* Decode literals section */ + { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize); + DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : %u", (U32)litCSize); + if (ZSTD_isError(litCSize)) return litCSize; + ip += litCSize; + srcSize -= litCSize; + } + + /* Build Decoding Tables */ + { int nbSeq; + size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, srcSize); + if (ZSTD_isError(seqHSize)) return seqHSize; + ip += seqHSize; + srcSize -= seqHSize; + + if ( (!frame || dctx->fParams.windowSize > (1<<24)) + && (nbSeq>0) ) { /* could probably use a larger nbSeq limit */ + U32 const shareLongOffsets = ZSTD_getLongOffsetsShare(dctx->OFTptr); + U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */ + if (shareLongOffsets >= minShare) + return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset); + } + + return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset); + } +} + + +static void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst) +{ + if (dst != dctx->previousDstEnd) { /* not contiguous */ + dctx->dictEnd = dctx->previousDstEnd; + dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart)); + dctx->prefixStart = dst; + dctx->previousDstEnd = dst; + } +} + +size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize) +{ + size_t dSize; + ZSTD_checkContinuity(dctx, dst); + dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0); + dctx->previousDstEnd = (char*)dst + dSize; + return dSize; +} + + +/** ZSTD_insertBlock() : + insert `src` block into `dctx` history. Useful to track uncompressed blocks. */ +ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize) +{ + ZSTD_checkContinuity(dctx, blockStart); + dctx->previousDstEnd = (const char*)blockStart + blockSize; + return blockSize; +} + + +static size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE value, size_t length) +{ + if (length > dstCapacity) return ERROR(dstSize_tooSmall); + memset(dst, value, length); + return length; +} + +/** ZSTD_findFrameCompressedSize() : + * compatible with legacy mode + * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame + * `srcSize` must be at least as large as the frame contained + * @return : the compressed size of the frame starting at `src` */ +size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize) +{ +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) + if (ZSTD_isLegacy(src, srcSize)) + return ZSTD_findFrameCompressedSizeLegacy(src, srcSize); +#endif + if ( (srcSize >= ZSTD_skippableHeaderSize) + && (MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START ) { + return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE*)src + ZSTD_FRAMEIDSIZE); + } else { + const BYTE* ip = (const BYTE*)src; + const BYTE* const ipstart = ip; + size_t remainingSize = srcSize; + ZSTD_frameHeader zfh; + + /* Extract Frame Header */ + { size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize); + if (ZSTD_isError(ret)) return ret; + if (ret > 0) return ERROR(srcSize_wrong); + } + + ip += zfh.headerSize; + remainingSize -= zfh.headerSize; + + /* Loop on each block */ + while (1) { + blockProperties_t blockProperties; + size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); + if (ZSTD_isError(cBlockSize)) return cBlockSize; + + if (ZSTD_blockHeaderSize + cBlockSize > remainingSize) + return ERROR(srcSize_wrong); + + ip += ZSTD_blockHeaderSize + cBlockSize; + remainingSize -= ZSTD_blockHeaderSize + cBlockSize; + + if (blockProperties.lastBlock) break; + } + + if (zfh.checksumFlag) { /* Final frame content checksum */ + if (remainingSize < 4) return ERROR(srcSize_wrong); + ip += 4; + } + + return ip - ipstart; + } +} + +/*! ZSTD_decompressFrame() : +* @dctx must be properly initialized */ +static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void** srcPtr, size_t *srcSizePtr) +{ + const BYTE* ip = (const BYTE*)(*srcPtr); + BYTE* const ostart = (BYTE* const)dst; + BYTE* const oend = ostart + dstCapacity; + BYTE* op = ostart; + size_t remainingSize = *srcSizePtr; + + /* check */ + if (remainingSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) + return ERROR(srcSize_wrong); + + /* Frame Header */ + { size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix); + if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize; + if (remainingSize < frameHeaderSize+ZSTD_blockHeaderSize) + return ERROR(srcSize_wrong); + CHECK_F( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) ); + ip += frameHeaderSize; remainingSize -= frameHeaderSize; + } + + /* Loop on each block */ + while (1) { + size_t decodedSize; + blockProperties_t blockProperties; + size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); + if (ZSTD_isError(cBlockSize)) return cBlockSize; + + ip += ZSTD_blockHeaderSize; + remainingSize -= ZSTD_blockHeaderSize; + if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); + + switch(blockProperties.blockType) + { + case bt_compressed: + decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1); + break; + case bt_raw : + decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize); + break; + case bt_rle : + decodedSize = ZSTD_generateNxBytes(op, oend-op, *ip, blockProperties.origSize); + break; + case bt_reserved : + default: + return ERROR(corruption_detected); + } + + if (ZSTD_isError(decodedSize)) return decodedSize; + if (dctx->fParams.checksumFlag) + XXH64_update(&dctx->xxhState, op, decodedSize); + op += decodedSize; + ip += cBlockSize; + remainingSize -= cBlockSize; + if (blockProperties.lastBlock) break; + } + + if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) { + if ((U64)(op-ostart) != dctx->fParams.frameContentSize) { + return ERROR(corruption_detected); + } } + if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */ + U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); + U32 checkRead; + if (remainingSize<4) return ERROR(checksum_wrong); + checkRead = MEM_readLE32(ip); + if (checkRead != checkCalc) return ERROR(checksum_wrong); + ip += 4; + remainingSize -= 4; + } + + /* Allow caller to get size read */ + *srcPtr = ip; + *srcSizePtr = remainingSize; + return op-ostart; +} + +static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict, size_t dictSize, + const ZSTD_DDict* ddict) +{ + void* const dststart = dst; + int moreThan1Frame = 0; + + DEBUGLOG(5, "ZSTD_decompressMultiFrame"); + assert(dict==NULL || ddict==NULL); /* either dict or ddict set, not both */ + + if (ddict) { + dict = ZSTD_DDictDictContent(ddict); + dictSize = ZSTD_DDictDictSize(ddict); + } + + while (srcSize >= ZSTD_frameHeaderSize_prefix) { + +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) + if (ZSTD_isLegacy(src, srcSize)) { + size_t decodedSize; + size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize); + if (ZSTD_isError(frameSize)) return frameSize; + /* legacy support is not compatible with static dctx */ + if (dctx->staticSize) return ERROR(memory_allocation); + + decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize); + + dst = (BYTE*)dst + decodedSize; + dstCapacity -= decodedSize; + + src = (const BYTE*)src + frameSize; + srcSize -= frameSize; + + continue; + } +#endif + + { U32 const magicNumber = MEM_readLE32(src); + DEBUGLOG(4, "reading magic number %08X (expecting %08X)", + (U32)magicNumber, (U32)ZSTD_MAGICNUMBER); + if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { + size_t skippableSize; + if (srcSize < ZSTD_skippableHeaderSize) + return ERROR(srcSize_wrong); + skippableSize = MEM_readLE32((const BYTE*)src + ZSTD_FRAMEIDSIZE) + + ZSTD_skippableHeaderSize; + if (srcSize < skippableSize) return ERROR(srcSize_wrong); + + src = (const BYTE *)src + skippableSize; + srcSize -= skippableSize; + continue; + } } + + if (ddict) { + /* we were called from ZSTD_decompress_usingDDict */ + CHECK_F(ZSTD_decompressBegin_usingDDict(dctx, ddict)); + } else { + /* this will initialize correctly with no dict if dict == NULL, so + * use this in all cases but ddict */ + CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize)); + } + ZSTD_checkContinuity(dctx, dst); + + { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity, + &src, &srcSize); + if ( (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown) + && (moreThan1Frame==1) ) { + /* at least one frame successfully completed, + * but following bytes are garbage : + * it's more likely to be a srcSize error, + * specifying more bytes than compressed size of frame(s). + * This error message replaces ERROR(prefix_unknown), + * which would be confusing, as the first header is actually correct. + * Note that one could be unlucky, it might be a corruption error instead, + * happening right at the place where we expect zstd magic bytes. + * But this is _much_ less likely than a srcSize field error. */ + return ERROR(srcSize_wrong); + } + if (ZSTD_isError(res)) return res; + /* no need to bound check, ZSTD_decompressFrame already has */ + dst = (BYTE*)dst + res; + dstCapacity -= res; + } + moreThan1Frame = 1; + } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */ + + if (srcSize) return ERROR(srcSize_wrong); /* input not entirely consumed */ + + return (BYTE*)dst - (BYTE*)dststart; +} + +size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict, size_t dictSize) +{ + return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL); +} + + +size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) +{ + return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0); +} + + +size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize) +{ +#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1) + size_t regenSize; + ZSTD_DCtx* const dctx = ZSTD_createDCtx(); + if (dctx==NULL) return ERROR(memory_allocation); + regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize); + ZSTD_freeDCtx(dctx); + return regenSize; +#else /* stack mode */ + ZSTD_DCtx dctx; + ZSTD_initDCtx_internal(&dctx); + return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize); +#endif +} + + +/*-************************************** +* Advanced Streaming Decompression API +* Bufferless and synchronous +****************************************/ +size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; } + +ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) { + switch(dctx->stage) + { + default: /* should not happen */ + assert(0); + case ZSTDds_getFrameHeaderSize: + case ZSTDds_decodeFrameHeader: + return ZSTDnit_frameHeader; + case ZSTDds_decodeBlockHeader: + return ZSTDnit_blockHeader; + case ZSTDds_decompressBlock: + return ZSTDnit_block; + case ZSTDds_decompressLastBlock: + return ZSTDnit_lastBlock; + case ZSTDds_checkChecksum: + return ZSTDnit_checksum; + case ZSTDds_decodeSkippableHeader: + case ZSTDds_skipFrame: + return ZSTDnit_skippableFrame; + } +} + +static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; } + +/** ZSTD_decompressContinue() : + * srcSize : must be the exact nb of bytes expected (see ZSTD_nextSrcSizeToDecompress()) + * @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity) + * or an error code, which can be tested using ZSTD_isError() */ +size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) +{ + DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (U32)srcSize); + /* Sanity check */ + if (srcSize != dctx->expected) return ERROR(srcSize_wrong); /* not allowed */ + if (dstCapacity) ZSTD_checkContinuity(dctx, dst); + + switch (dctx->stage) + { + case ZSTDds_getFrameHeaderSize : + assert(src != NULL); + if (dctx->format == ZSTD_f_zstd1) { /* allows header */ + assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */ + if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ + memcpy(dctx->headerBuffer, src, srcSize); + dctx->expected = ZSTD_skippableHeaderSize - srcSize; /* remaining to load to get full skippable frame header */ + dctx->stage = ZSTDds_decodeSkippableHeader; + return 0; + } } + dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format); + if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize; + memcpy(dctx->headerBuffer, src, srcSize); + dctx->expected = dctx->headerSize - srcSize; + dctx->stage = ZSTDds_decodeFrameHeader; + return 0; + + case ZSTDds_decodeFrameHeader: + assert(src != NULL); + memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize); + CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize)); + dctx->expected = ZSTD_blockHeaderSize; + dctx->stage = ZSTDds_decodeBlockHeader; + return 0; + + case ZSTDds_decodeBlockHeader: + { blockProperties_t bp; + size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp); + if (ZSTD_isError(cBlockSize)) return cBlockSize; + dctx->expected = cBlockSize; + dctx->bType = bp.blockType; + dctx->rleSize = bp.origSize; + if (cBlockSize) { + dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock; + return 0; + } + /* empty block */ + if (bp.lastBlock) { + if (dctx->fParams.checksumFlag) { + dctx->expected = 4; + dctx->stage = ZSTDds_checkChecksum; + } else { + dctx->expected = 0; /* end of frame */ + dctx->stage = ZSTDds_getFrameHeaderSize; + } + } else { + dctx->expected = ZSTD_blockHeaderSize; /* jump to next header */ + dctx->stage = ZSTDds_decodeBlockHeader; + } + return 0; + } + + case ZSTDds_decompressLastBlock: + case ZSTDds_decompressBlock: + DEBUGLOG(5, "ZSTD_decompressContinue: case ZSTDds_decompressBlock"); + { size_t rSize; + switch(dctx->bType) + { + case bt_compressed: + DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed"); + rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1); + break; + case bt_raw : + rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize); + break; + case bt_rle : + rSize = ZSTD_setRleBlock(dst, dstCapacity, src, srcSize, dctx->rleSize); + break; + case bt_reserved : /* should never happen */ + default: + return ERROR(corruption_detected); + } + if (ZSTD_isError(rSize)) return rSize; + DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (U32)rSize); + dctx->decodedSize += rSize; + if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize); + + if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */ + DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (U32)dctx->decodedSize); + if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) { + if (dctx->decodedSize != dctx->fParams.frameContentSize) { + return ERROR(corruption_detected); + } } + if (dctx->fParams.checksumFlag) { /* another round for frame checksum */ + dctx->expected = 4; + dctx->stage = ZSTDds_checkChecksum; + } else { + dctx->expected = 0; /* ends here */ + dctx->stage = ZSTDds_getFrameHeaderSize; + } + } else { + dctx->stage = ZSTDds_decodeBlockHeader; + dctx->expected = ZSTD_blockHeaderSize; + dctx->previousDstEnd = (char*)dst + rSize; + } + return rSize; + } + + case ZSTDds_checkChecksum: + assert(srcSize == 4); /* guaranteed by dctx->expected */ + { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); + U32 const check32 = MEM_readLE32(src); + DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", h32, check32); + if (check32 != h32) return ERROR(checksum_wrong); + dctx->expected = 0; + dctx->stage = ZSTDds_getFrameHeaderSize; + return 0; + } + + case ZSTDds_decodeSkippableHeader: + assert(src != NULL); + assert(srcSize <= ZSTD_skippableHeaderSize); + memcpy(dctx->headerBuffer + (ZSTD_skippableHeaderSize - srcSize), src, srcSize); /* complete skippable header */ + dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */ + dctx->stage = ZSTDds_skipFrame; + return 0; + + case ZSTDds_skipFrame: + dctx->expected = 0; + dctx->stage = ZSTDds_getFrameHeaderSize; + return 0; + + default: + return ERROR(GENERIC); /* impossible */ + } +} + + +static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) +{ + dctx->dictEnd = dctx->previousDstEnd; + dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart)); + dctx->prefixStart = dict; + dctx->previousDstEnd = (const char*)dict + dictSize; + return 0; +} + +/*! ZSTD_loadEntropy() : + * dict : must point at beginning of a valid zstd dictionary. + * @return : size of entropy tables read */ +static size_t ZSTD_loadEntropy(ZSTD_entropyDTables_t* entropy, + const void* const dict, size_t const dictSize) +{ + const BYTE* dictPtr = (const BYTE*)dict; + const BYTE* const dictEnd = dictPtr + dictSize; + + if (dictSize <= 8) return ERROR(dictionary_corrupted); + assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */ + dictPtr += 8; /* skip header = magic + dictID */ + + ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, OFTable) == offsetof(ZSTD_entropyDTables_t, LLTable) + sizeof(entropy->LLTable)); + ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, MLTable) == offsetof(ZSTD_entropyDTables_t, OFTable) + sizeof(entropy->OFTable)); + ZSTD_STATIC_ASSERT(sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable) >= HUF_DECOMPRESS_WORKSPACE_SIZE); + { void* const workspace = &entropy->LLTable; /* use fse tables as temporary workspace; implies fse tables are grouped together */ + size_t const workspaceSize = sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable); + size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable, + dictPtr, dictEnd - dictPtr, + workspace, workspaceSize); + if (HUF_isError(hSize)) return ERROR(dictionary_corrupted); + dictPtr += hSize; + } + + { short offcodeNCount[MaxOff+1]; + U32 offcodeMaxValue = MaxOff, offcodeLog; + size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); + if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted); + if (offcodeMaxValue > MaxOff) return ERROR(dictionary_corrupted); + if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted); + ZSTD_buildFSETable( entropy->OFTable, + offcodeNCount, offcodeMaxValue, + OF_base, OF_bits, + offcodeLog); + dictPtr += offcodeHeaderSize; + } + + { short matchlengthNCount[MaxML+1]; + unsigned matchlengthMaxValue = MaxML, matchlengthLog; + size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); + if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted); + if (matchlengthMaxValue > MaxML) return ERROR(dictionary_corrupted); + if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted); + ZSTD_buildFSETable( entropy->MLTable, + matchlengthNCount, matchlengthMaxValue, + ML_base, ML_bits, + matchlengthLog); + dictPtr += matchlengthHeaderSize; + } + + { short litlengthNCount[MaxLL+1]; + unsigned litlengthMaxValue = MaxLL, litlengthLog; + size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); + if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted); + if (litlengthMaxValue > MaxLL) return ERROR(dictionary_corrupted); + if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted); + ZSTD_buildFSETable( entropy->LLTable, + litlengthNCount, litlengthMaxValue, + LL_base, LL_bits, + litlengthLog); + dictPtr += litlengthHeaderSize; + } + + if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted); + { int i; + size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12)); + for (i=0; i<3; i++) { + U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4; + if (rep==0 || rep >= dictContentSize) return ERROR(dictionary_corrupted); + entropy->rep[i] = rep; + } } + + return dictPtr - (const BYTE*)dict; +} + +static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) +{ + if (dictSize < 8) return ZSTD_refDictContent(dctx, dict, dictSize); + { U32 const magic = MEM_readLE32(dict); + if (magic != ZSTD_MAGIC_DICTIONARY) { + return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */ + } } + dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE); + + /* load entropy tables */ + { size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize); + if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted); + dict = (const char*)dict + eSize; + dictSize -= eSize; + } + dctx->litEntropy = dctx->fseEntropy = 1; + + /* reference dictionary content */ + return ZSTD_refDictContent(dctx, dict, dictSize); +} + +size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx) +{ + assert(dctx != NULL); + dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */ + dctx->stage = ZSTDds_getFrameHeaderSize; + dctx->decodedSize = 0; + dctx->previousDstEnd = NULL; + dctx->prefixStart = NULL; + dctx->virtualStart = NULL; + dctx->dictEnd = NULL; + dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */ + dctx->litEntropy = dctx->fseEntropy = 0; + dctx->dictID = 0; + ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue)); + memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */ + dctx->LLTptr = dctx->entropy.LLTable; + dctx->MLTptr = dctx->entropy.MLTable; + dctx->OFTptr = dctx->entropy.OFTable; + dctx->HUFptr = dctx->entropy.hufTable; + return 0; +} + +size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) +{ + CHECK_F( ZSTD_decompressBegin(dctx) ); + if (dict && dictSize) + CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted); + return 0; +} + + +/* ====== ZSTD_DDict ====== */ + +struct ZSTD_DDict_s { + void* dictBuffer; + const void* dictContent; + size_t dictSize; + ZSTD_entropyDTables_t entropy; + U32 dictID; + U32 entropyPresent; + ZSTD_customMem cMem; +}; /* typedef'd to ZSTD_DDict within "zstd.h" */ + +static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict) +{ + assert(ddict != NULL); + return ddict->dictContent; +} + +static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict) +{ + assert(ddict != NULL); + return ddict->dictSize; +} + +size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict) +{ + DEBUGLOG(4, "ZSTD_decompressBegin_usingDDict"); + assert(dctx != NULL); + if (ddict) { + dctx->ddictIsCold = (dctx->dictEnd != (const char*)ddict->dictContent + ddict->dictSize); + DEBUGLOG(4, "DDict is %s", + dctx->ddictIsCold ? "~cold~" : "hot!"); + } + CHECK_F( ZSTD_decompressBegin(dctx) ); + if (ddict) { /* NULL ddict is equivalent to no dictionary */ + dctx->dictID = ddict->dictID; + dctx->prefixStart = ddict->dictContent; + dctx->virtualStart = ddict->dictContent; + dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize; + dctx->previousDstEnd = dctx->dictEnd; + if (ddict->entropyPresent) { + dctx->litEntropy = 1; + dctx->fseEntropy = 1; + dctx->LLTptr = ddict->entropy.LLTable; + dctx->MLTptr = ddict->entropy.MLTable; + dctx->OFTptr = ddict->entropy.OFTable; + dctx->HUFptr = ddict->entropy.hufTable; + dctx->entropy.rep[0] = ddict->entropy.rep[0]; + dctx->entropy.rep[1] = ddict->entropy.rep[1]; + dctx->entropy.rep[2] = ddict->entropy.rep[2]; + } else { + dctx->litEntropy = 0; + dctx->fseEntropy = 0; + } + } + return 0; +} + +static size_t +ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict, + ZSTD_dictContentType_e dictContentType) +{ + ddict->dictID = 0; + ddict->entropyPresent = 0; + if (dictContentType == ZSTD_dct_rawContent) return 0; + + if (ddict->dictSize < 8) { + if (dictContentType == ZSTD_dct_fullDict) + return ERROR(dictionary_corrupted); /* only accept specified dictionaries */ + return 0; /* pure content mode */ + } + { U32 const magic = MEM_readLE32(ddict->dictContent); + if (magic != ZSTD_MAGIC_DICTIONARY) { + if (dictContentType == ZSTD_dct_fullDict) + return ERROR(dictionary_corrupted); /* only accept specified dictionaries */ + return 0; /* pure content mode */ + } + } + ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE); + + /* load entropy tables */ + CHECK_E( ZSTD_loadEntropy(&ddict->entropy, + ddict->dictContent, ddict->dictSize), + dictionary_corrupted ); + ddict->entropyPresent = 1; + return 0; +} + + +static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType) +{ + if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) { + ddict->dictBuffer = NULL; + ddict->dictContent = dict; + if (!dict) dictSize = 0; + } else { + void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem); + ddict->dictBuffer = internalBuffer; + ddict->dictContent = internalBuffer; + if (!internalBuffer) return ERROR(memory_allocation); + memcpy(internalBuffer, dict, dictSize); + } + ddict->dictSize = dictSize; + ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */ + + /* parse dictionary content */ + CHECK_F( ZSTD_loadEntropy_inDDict(ddict, dictContentType) ); + + return 0; +} + +ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_customMem customMem) +{ + if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + + { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem); + if (ddict == NULL) return NULL; + ddict->cMem = customMem; + { size_t const initResult = ZSTD_initDDict_internal(ddict, + dict, dictSize, + dictLoadMethod, dictContentType); + if (ZSTD_isError(initResult)) { + ZSTD_freeDDict(ddict); + return NULL; + } } + return ddict; + } +} + +/*! ZSTD_createDDict() : +* Create a digested dictionary, to start decompression without startup delay. +* `dict` content is copied inside DDict. +* Consequently, `dict` can be released after `ZSTD_DDict` creation */ +ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize) +{ + ZSTD_customMem const allocator = { NULL, NULL, NULL }; + return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, allocator); +} + +/*! ZSTD_createDDict_byReference() : + * Create a digested dictionary, to start decompression without startup delay. + * Dictionary content is simply referenced, it will be accessed during decompression. + * Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */ +ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize) +{ + ZSTD_customMem const allocator = { NULL, NULL, NULL }; + return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, allocator); +} + + +const ZSTD_DDict* ZSTD_initStaticDDict( + void* sBuffer, size_t sBufferSize, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType) +{ + size_t const neededSpace = sizeof(ZSTD_DDict) + + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize); + ZSTD_DDict* const ddict = (ZSTD_DDict*)sBuffer; + assert(sBuffer != NULL); + assert(dict != NULL); + if ((size_t)sBuffer & 7) return NULL; /* 8-aligned */ + if (sBufferSize < neededSpace) return NULL; + if (dictLoadMethod == ZSTD_dlm_byCopy) { + memcpy(ddict+1, dict, dictSize); /* local copy */ + dict = ddict+1; + } + if (ZSTD_isError( ZSTD_initDDict_internal(ddict, + dict, dictSize, + ZSTD_dlm_byRef, dictContentType) )) + return NULL; + return ddict; +} + + +size_t ZSTD_freeDDict(ZSTD_DDict* ddict) +{ + if (ddict==NULL) return 0; /* support free on NULL */ + { ZSTD_customMem const cMem = ddict->cMem; + ZSTD_free(ddict->dictBuffer, cMem); + ZSTD_free(ddict, cMem); + return 0; + } +} + +/*! ZSTD_estimateDDictSize() : + * Estimate amount of memory that will be needed to create a dictionary for decompression. + * Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */ +size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod) +{ + return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize); +} + +size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict) +{ + if (ddict==NULL) return 0; /* support sizeof on NULL */ + return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ; +} + +/*! ZSTD_getDictID_fromDict() : + * Provides the dictID stored within dictionary. + * if @return == 0, the dictionary is not conformant with Zstandard specification. + * It can still be loaded, but as a content-only dictionary. */ +unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize) +{ + if (dictSize < 8) return 0; + if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0; + return MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE); +} + +/*! ZSTD_getDictID_fromDDict() : + * Provides the dictID of the dictionary loaded into `ddict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict) +{ + if (ddict==NULL) return 0; + return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize); +} + +/*! ZSTD_getDictID_fromFrame() : + * Provides the dictID required to decompresse frame stored within `src`. + * If @return == 0, the dictID could not be decoded. + * This could for one of the following reasons : + * - The frame does not require a dictionary (most common case). + * - The frame was built with dictID intentionally removed. + * Needed dictionary is a hidden information. + * Note : this use case also happens when using a non-conformant dictionary. + * - `srcSize` is too small, and as a result, frame header could not be decoded. + * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`. + * - This is not a Zstandard frame. + * When identifying the exact failure cause, it's possible to use + * ZSTD_getFrameHeader(), which will provide a more precise error code. */ +unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize) +{ + ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 }; + size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize); + if (ZSTD_isError(hError)) return 0; + return zfp.dictID; +} + + +/*! ZSTD_decompress_usingDDict() : +* Decompression using a pre-digested Dictionary +* Use dictionary without significant overhead. */ +size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_DDict* ddict) +{ + /* pass content and size in case legacy frames are encountered */ + return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, + NULL, 0, + ddict); +} + + +/*===================================== +* Streaming decompression +*====================================*/ + +ZSTD_DStream* ZSTD_createDStream(void) +{ + DEBUGLOG(3, "ZSTD_createDStream"); + return ZSTD_createDStream_advanced(ZSTD_defaultCMem); +} + +ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize) +{ + return ZSTD_initStaticDCtx(workspace, workspaceSize); +} + +ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem) +{ + return ZSTD_createDCtx_advanced(customMem); +} + +size_t ZSTD_freeDStream(ZSTD_DStream* zds) +{ + return ZSTD_freeDCtx(zds); +} + + +/* *** Initialization *** */ + +size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; } +size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; } + +size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType) +{ + if (dctx->streamStage != zdss_init) return ERROR(stage_wrong); + ZSTD_freeDDict(dctx->ddictLocal); + if (dict && dictSize >= 8) { + dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem); + if (dctx->ddictLocal == NULL) return ERROR(memory_allocation); + } else { + dctx->ddictLocal = NULL; + } + dctx->ddict = dctx->ddictLocal; + return 0; +} + +size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) +{ + return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto); +} + +size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) +{ + return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto); +} + +size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType) +{ + return ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType); +} + +size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize) +{ + return ZSTD_DCtx_refPrefix_advanced(dctx, prefix, prefixSize, ZSTD_dct_rawContent); +} + + +/* ZSTD_initDStream_usingDict() : + * return : expected size, aka ZSTD_frameHeaderSize_prefix. + * this function cannot fail */ +size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize) +{ + DEBUGLOG(4, "ZSTD_initDStream_usingDict"); + zds->streamStage = zdss_init; + zds->noForwardProgress = 0; + CHECK_F( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) ); + return ZSTD_frameHeaderSize_prefix; +} + +/* note : this variant can't fail */ +size_t ZSTD_initDStream(ZSTD_DStream* zds) +{ + DEBUGLOG(4, "ZSTD_initDStream"); + return ZSTD_initDStream_usingDict(zds, NULL, 0); +} + +/* ZSTD_initDStream_usingDDict() : + * ddict will just be referenced, and must outlive decompression session + * this function cannot fail */ +size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict) +{ + size_t const initResult = ZSTD_initDStream(dctx); + dctx->ddict = ddict; + return initResult; +} + +/* ZSTD_resetDStream() : + * return : expected size, aka ZSTD_frameHeaderSize_prefix. + * this function cannot fail */ +size_t ZSTD_resetDStream(ZSTD_DStream* dctx) +{ + DEBUGLOG(4, "ZSTD_resetDStream"); + dctx->streamStage = zdss_loadHeader; + dctx->lhSize = dctx->inPos = dctx->outStart = dctx->outEnd = 0; + dctx->legacyVersion = 0; + dctx->hostageByte = 0; + return ZSTD_frameHeaderSize_prefix; +} + +size_t ZSTD_setDStreamParameter(ZSTD_DStream* dctx, + ZSTD_DStreamParameter_e paramType, unsigned paramValue) +{ + if (dctx->streamStage != zdss_init) return ERROR(stage_wrong); + switch(paramType) + { + default : return ERROR(parameter_unsupported); + case DStream_p_maxWindowSize : + DEBUGLOG(4, "setting maxWindowSize = %u KB", paramValue >> 10); + dctx->maxWindowSize = paramValue ? paramValue : (U32)(-1); + break; + } + return 0; +} + +size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict) +{ + if (dctx->streamStage != zdss_init) return ERROR(stage_wrong); + dctx->ddict = ddict; + return 0; +} + +size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize) +{ + if (dctx->streamStage != zdss_init) return ERROR(stage_wrong); + dctx->maxWindowSize = maxWindowSize; + return 0; +} + +size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format) +{ + DEBUGLOG(4, "ZSTD_DCtx_setFormat : %u", (unsigned)format); + if (dctx->streamStage != zdss_init) return ERROR(stage_wrong); + dctx->format = format; + return 0; +} + + +size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx) +{ + return ZSTD_sizeof_DCtx(dctx); +} + +size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize) +{ + size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX); + unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2); + unsigned long long const neededSize = MIN(frameContentSize, neededRBSize); + size_t const minRBSize = (size_t) neededSize; + if ((unsigned long long)minRBSize != neededSize) return ERROR(frameParameter_windowTooLarge); + return minRBSize; +} + +size_t ZSTD_estimateDStreamSize(size_t windowSize) +{ + size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX); + size_t const inBuffSize = blockSize; /* no block can be larger */ + size_t const outBuffSize = ZSTD_decodingBufferSize_min(windowSize, ZSTD_CONTENTSIZE_UNKNOWN); + return ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize; +} + +size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize) +{ + U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable */ + ZSTD_frameHeader zfh; + size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize); + if (ZSTD_isError(err)) return err; + if (err>0) return ERROR(srcSize_wrong); + if (zfh.windowSize > windowSizeMax) + return ERROR(frameParameter_windowTooLarge); + return ZSTD_estimateDStreamSize((size_t)zfh.windowSize); +} + + +/* ***** Decompression ***** */ + +MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize) +{ + size_t const length = MIN(dstCapacity, srcSize); + memcpy(dst, src, length); + return length; +} + + +size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input) +{ + const char* const istart = (const char*)(input->src) + input->pos; + const char* const iend = (const char*)(input->src) + input->size; + const char* ip = istart; + char* const ostart = (char*)(output->dst) + output->pos; + char* const oend = (char*)(output->dst) + output->size; + char* op = ostart; + U32 someMoreWork = 1; + + DEBUGLOG(5, "ZSTD_decompressStream"); + if (input->pos > input->size) { /* forbidden */ + DEBUGLOG(5, "in: pos: %u vs size: %u", + (U32)input->pos, (U32)input->size); + return ERROR(srcSize_wrong); + } + if (output->pos > output->size) { /* forbidden */ + DEBUGLOG(5, "out: pos: %u vs size: %u", + (U32)output->pos, (U32)output->size); + return ERROR(dstSize_tooSmall); + } + DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos)); + + while (someMoreWork) { + switch(zds->streamStage) + { + case zdss_init : + DEBUGLOG(5, "stage zdss_init => transparent reset "); + ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */ + /* fall-through */ + + case zdss_loadHeader : + DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip)); +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) + if (zds->legacyVersion) { + /* legacy support is incompatible with static dctx */ + if (zds->staticSize) return ERROR(memory_allocation); + { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input); + if (hint==0) zds->streamStage = zdss_init; + return hint; + } } +#endif + { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format); + DEBUGLOG(5, "header size : %u", (U32)hSize); + if (ZSTD_isError(hSize)) { +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) + U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart); + if (legacyVersion) { + const void* const dict = zds->ddict ? zds->ddict->dictContent : NULL; + size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0; + DEBUGLOG(5, "ZSTD_decompressStream: detected legacy version v0.%u", legacyVersion); + /* legacy support is incompatible with static dctx */ + if (zds->staticSize) return ERROR(memory_allocation); + CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext, + zds->previousLegacyVersion, legacyVersion, + dict, dictSize)); + zds->legacyVersion = zds->previousLegacyVersion = legacyVersion; + { size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input); + if (hint==0) zds->streamStage = zdss_init; /* or stay in stage zdss_loadHeader */ + return hint; + } } +#endif + return hSize; /* error */ + } + if (hSize != 0) { /* need more input */ + size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */ + size_t const remainingInput = (size_t)(iend-ip); + assert(iend >= ip); + if (toLoad > remainingInput) { /* not enough input to load full header */ + if (remainingInput > 0) { + memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput); + zds->lhSize += remainingInput; + } + input->pos = input->size; + return (MAX(ZSTD_frameHeaderSize_min, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */ + } + assert(ip != NULL); + memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad; + break; + } } + + /* check for single-pass mode opportunity */ + if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */ + && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) { + size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart); + if (cSize <= (size_t)(iend-istart)) { + /* shortcut : using single-pass mode */ + size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, zds->ddict); + if (ZSTD_isError(decompressedSize)) return decompressedSize; + DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()") + ip = istart + cSize; + op += decompressedSize; + zds->expected = 0; + zds->streamStage = zdss_init; + someMoreWork = 0; + break; + } } + + /* Consume header (see ZSTDds_decodeFrameHeader) */ + DEBUGLOG(4, "Consume header"); + CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict)); + + if ((MEM_readLE32(zds->headerBuffer) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ + zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE); + zds->stage = ZSTDds_skipFrame; + } else { + CHECK_F(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize)); + zds->expected = ZSTD_blockHeaderSize; + zds->stage = ZSTDds_decodeBlockHeader; + } + + /* control buffer memory usage */ + DEBUGLOG(4, "Control max memory usage (%u KB <= max %u KB)", + (U32)(zds->fParams.windowSize >>10), + (U32)(zds->maxWindowSize >> 10) ); + zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN); + if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge); + + /* Adapt buffer sizes to frame header instructions */ + { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); + size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize); + if ((zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize)) { + size_t const bufferSize = neededInBuffSize + neededOutBuffSize; + DEBUGLOG(4, "inBuff : from %u to %u", + (U32)zds->inBuffSize, (U32)neededInBuffSize); + DEBUGLOG(4, "outBuff : from %u to %u", + (U32)zds->outBuffSize, (U32)neededOutBuffSize); + if (zds->staticSize) { /* static DCtx */ + DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize); + assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */ + if (bufferSize > zds->staticSize - sizeof(ZSTD_DCtx)) + return ERROR(memory_allocation); + } else { + ZSTD_free(zds->inBuff, zds->customMem); + zds->inBuffSize = 0; + zds->outBuffSize = 0; + zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem); + if (zds->inBuff == NULL) return ERROR(memory_allocation); + } + zds->inBuffSize = neededInBuffSize; + zds->outBuff = zds->inBuff + zds->inBuffSize; + zds->outBuffSize = neededOutBuffSize; + } } + zds->streamStage = zdss_read; + /* fall-through */ + + case zdss_read: + DEBUGLOG(5, "stage zdss_read"); + { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds); + DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize); + if (neededInSize==0) { /* end of frame */ + zds->streamStage = zdss_init; + someMoreWork = 0; + break; + } + if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */ + int const isSkipFrame = ZSTD_isSkipFrame(zds); + size_t const decodedSize = ZSTD_decompressContinue(zds, + zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart), + ip, neededInSize); + if (ZSTD_isError(decodedSize)) return decodedSize; + ip += neededInSize; + if (!decodedSize && !isSkipFrame) break; /* this was just a header */ + zds->outEnd = zds->outStart + decodedSize; + zds->streamStage = zdss_flush; + break; + } } + if (ip==iend) { someMoreWork = 0; break; } /* no more input */ + zds->streamStage = zdss_load; + /* fall-through */ + + case zdss_load: + { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds); + size_t const toLoad = neededInSize - zds->inPos; + int const isSkipFrame = ZSTD_isSkipFrame(zds); + size_t loadedSize; + if (isSkipFrame) { + loadedSize = MIN(toLoad, (size_t)(iend-ip)); + } else { + if (toLoad > zds->inBuffSize - zds->inPos) return ERROR(corruption_detected); /* should never happen */ + loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip); + } + ip += loadedSize; + zds->inPos += loadedSize; + if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */ + + /* decode loaded input */ + { size_t const decodedSize = ZSTD_decompressContinue(zds, + zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart, + zds->inBuff, neededInSize); + if (ZSTD_isError(decodedSize)) return decodedSize; + zds->inPos = 0; /* input is consumed */ + if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */ + zds->outEnd = zds->outStart + decodedSize; + } } + zds->streamStage = zdss_flush; + /* fall-through */ + + case zdss_flush: + { size_t const toFlushSize = zds->outEnd - zds->outStart; + size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize); + op += flushedSize; + zds->outStart += flushedSize; + if (flushedSize == toFlushSize) { /* flush completed */ + zds->streamStage = zdss_read; + if ( (zds->outBuffSize < zds->fParams.frameContentSize) + && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) { + DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)", + (int)(zds->outBuffSize - zds->outStart), + (U32)zds->fParams.blockSizeMax); + zds->outStart = zds->outEnd = 0; + } + break; + } } + /* cannot complete flush */ + someMoreWork = 0; + break; + + default: return ERROR(GENERIC); /* impossible */ + } } + + /* result */ + input->pos = (size_t)(ip - (const char*)(input->src)); + output->pos = (size_t)(op - (char*)(output->dst)); + if ((ip==istart) && (op==ostart)) { /* no forward progress */ + zds->noForwardProgress ++; + if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) { + if (op==oend) return ERROR(dstSize_tooSmall); + if (ip==iend) return ERROR(srcSize_wrong); + assert(0); + } + } else { + zds->noForwardProgress = 0; + } + { size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds); + if (!nextSrcSizeHint) { /* frame fully decoded */ + if (zds->outEnd == zds->outStart) { /* output fully flushed */ + if (zds->hostageByte) { + if (input->pos >= input->size) { + /* can't release hostage (not present) */ + zds->streamStage = zdss_read; + return 1; + } + input->pos++; /* release hostage */ + } /* zds->hostageByte */ + return 0; + } /* zds->outEnd == zds->outStart */ + if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */ + input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */ + zds->hostageByte=1; + } + return 1; + } /* nextSrcSizeHint==0 */ + nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block); /* preload header of next block */ + assert(zds->inPos <= nextSrcSizeHint); + nextSrcSizeHint -= zds->inPos; /* part already loaded*/ + return nextSrcSizeHint; + } +} + + +size_t ZSTD_decompress_generic(ZSTD_DCtx* dctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input) +{ + return ZSTD_decompressStream(dctx, output, input); +} + +size_t ZSTD_decompress_generic_simpleArgs ( + ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, size_t* dstPos, + const void* src, size_t srcSize, size_t* srcPos) +{ + ZSTD_outBuffer output = { dst, dstCapacity, *dstPos }; + ZSTD_inBuffer input = { src, srcSize, *srcPos }; + /* ZSTD_compress_generic() will check validity of dstPos and srcPos */ + size_t const cErr = ZSTD_decompress_generic(dctx, &output, &input); + *dstPos = output.pos; + *srcPos = input.pos; + return cErr; +} + +void ZSTD_DCtx_reset(ZSTD_DCtx* dctx) +{ + (void)ZSTD_initDStream(dctx); + dctx->format = ZSTD_f_zstd1; + dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; +} diff --git a/grub-core/lib/zstd/zstd_errors.h b/grub-core/lib/zstd/zstd_errors.h new file mode 100644 index 0000000..57533f2 --- /dev/null +++ b/grub-core/lib/zstd/zstd_errors.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_ERRORS_H_398273423 +#define ZSTD_ERRORS_H_398273423 + +#if defined (__cplusplus) +extern "C" { +#endif + +/*===== dependency =====*/ +#include <stddef.h> /* size_t */ + + +/* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */ +#ifndef ZSTDERRORLIB_VISIBILITY +# if defined(__GNUC__) && (__GNUC__ >= 4) +# define ZSTDERRORLIB_VISIBILITY __attribute__ ((visibility ("default"))) +# else +# define ZSTDERRORLIB_VISIBILITY +# endif +#endif +#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) +# define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBILITY +#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) +# define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +#else +# define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBILITY +#endif + +/*-********************************************* + * Error codes list + *-********************************************* + * Error codes _values_ are pinned down since v1.3.1 only. + * Therefore, don't rely on values if you may link to any version < v1.3.1. + * + * Only values < 100 are considered stable. + * + * note 1 : this API shall be used with static linking only. + * dynamic linking is not yet officially supported. + * note 2 : Prefer relying on the enum than on its value whenever possible + * This is the only supported way to use the error list < v1.3.1 + * note 3 : ZSTD_isError() is always correct, whatever the library version. + **********************************************/ +typedef enum { + ZSTD_error_no_error = 0, + ZSTD_error_GENERIC = 1, + ZSTD_error_prefix_unknown = 10, + ZSTD_error_version_unsupported = 12, + ZSTD_error_frameParameter_unsupported = 14, + ZSTD_error_frameParameter_windowTooLarge = 16, + ZSTD_error_corruption_detected = 20, + ZSTD_error_checksum_wrong = 22, + ZSTD_error_dictionary_corrupted = 30, + ZSTD_error_dictionary_wrong = 32, + ZSTD_error_dictionaryCreation_failed = 34, + ZSTD_error_parameter_unsupported = 40, + ZSTD_error_parameter_outOfBound = 42, + ZSTD_error_tableLog_tooLarge = 44, + ZSTD_error_maxSymbolValue_tooLarge = 46, + ZSTD_error_maxSymbolValue_tooSmall = 48, + ZSTD_error_stage_wrong = 60, + ZSTD_error_init_missing = 62, + ZSTD_error_memory_allocation = 64, + ZSTD_error_workSpace_tooSmall= 66, + ZSTD_error_dstSize_tooSmall = 70, + ZSTD_error_srcSize_wrong = 72, + /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */ + ZSTD_error_frameIndex_tooLarge = 100, + ZSTD_error_seekableIO = 102, + ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */ +} ZSTD_ErrorCode; + +/*! ZSTD_getErrorCode() : + convert a `size_t` function result into a `ZSTD_ErrorCode` enum type, + which can be used to compare with enum list published above */ +ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult); +ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code); /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */ + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_ERRORS_H_398273423 */ diff --git a/grub-core/lib/zstd/zstd_internal.h b/grub-core/lib/zstd/zstd_internal.h new file mode 100644 index 0000000..e75adfa --- /dev/null +++ b/grub-core/lib/zstd/zstd_internal.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_CCOMMON_H_MODULE +#define ZSTD_CCOMMON_H_MODULE + +/* this module contains definitions which must be identical + * across compression, decompression and dictBuilder. + * It also contains a few functions useful to at least 2 of them + * and which benefit from being inlined */ + +/*-************************************* +* Dependencies +***************************************/ +#include "compiler.h" +#include "mem.h" +#include "debug.h" /* assert, DEBUGLOG, RAWLOG, g_debuglevel */ +#include "error_private.h" +#define ZSTD_STATIC_LINKING_ONLY +#include "zstd.h" +#define FSE_STATIC_LINKING_ONLY +#include "fse.h" +#define HUF_STATIC_LINKING_ONLY +#include "huf.h" +#ifndef XXH_STATIC_LINKING_ONLY +# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */ +#endif +#include "xxhash.h" /* XXH_reset, update, digest */ + + +#if defined (__cplusplus) +extern "C" { +#endif + +/* ---- static assert (debug) --- */ +#define ZSTD_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) + + +/*-************************************* +* shared macros +***************************************/ +#undef MIN +#undef MAX +#define MIN(a,b) ((a)<(b) ? (a) : (b)) +#define MAX(a,b) ((a)>(b) ? (a) : (b)) +#define CHECK_F(f) { size_t const errcod = f; if (ERR_isError(errcod)) return errcod; } /* check and Forward error code */ +#define CHECK_E(f, e) { size_t const errcod = f; if (ERR_isError(errcod)) return ERROR(e); } /* check and send Error code */ + + +/*-************************************* +* Common constants +***************************************/ +#define ZSTD_OPT_NUM (1<<12) + +#define ZSTD_REP_NUM 3 /* number of repcodes */ +#define ZSTD_REP_MOVE (ZSTD_REP_NUM-1) +static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; + +#define KB *(1 <<10) +#define MB *(1 <<20) +#define GB *(1U<<30) + +#define BIT7 128 +#define BIT6 64 +#define BIT5 32 +#define BIT4 16 +#define BIT1 2 +#define BIT0 1 + +#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10 +#define ZSTD_WINDOWLOG_DEFAULTMAX 27 /* Default maximum allowed window log */ +static const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 }; +static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 }; + +#define ZSTD_FRAMEIDSIZE 4 /* magic number size */ + +#define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */ +static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; +typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e; + +#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */ +#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */ + +#define HufLog 12 +typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e; + +#define LONGNBSEQ 0x7F00 + +#define MINMATCH 3 + +#define Litbits 8 +#define MaxLit ((1<<Litbits) - 1) +#define MaxML 52 +#define MaxLL 35 +#define DefaultMaxOff 28 +#define MaxOff 31 +#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */ +#define MLFSELog 9 +#define LLFSELog 9 +#define OffFSELog 8 +#define MaxFSELog MAX(MAX(MLFSELog, LLFSELog), OffFSELog) + +static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, + 4, 6, 7, 8, 9,10,11,12, + 13,14,15,16 }; +static const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 2, 1, 1, 1, 1, 1, + -1,-1,-1,-1 }; +#define LL_DEFAULTNORMLOG 6 /* for static allocation */ +static const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG; + +static const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, + 4, 4, 5, 7, 8, 9,10,11, + 12,13,14,15,16 }; +static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1,-1,-1, + -1,-1,-1,-1,-1 }; +#define ML_DEFAULTNORMLOG 6 /* for static allocation */ +static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG; + +static const S16 OF_defaultNorm[DefaultMaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + -1,-1,-1,-1,-1 }; +#define OF_DEFAULTNORMLOG 5 /* for static allocation */ +static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG; + + +/*-******************************************* +* Shared functions to include for inlining +*********************************************/ +static void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); } +#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; } + +/*! ZSTD_wildcopy() : + * custom version of memcpy(), can overwrite up to WILDCOPY_OVERLENGTH bytes (if length==0) */ +#define WILDCOPY_OVERLENGTH 8 +MEM_STATIC void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length) +{ + const BYTE* ip = (const BYTE*)src; + BYTE* op = (BYTE*)dst; + BYTE* const oend = op + length; + do + COPY8(op, ip) + while (op < oend); +} + +MEM_STATIC void ZSTD_wildcopy_e(void* dst, const void* src, void* dstEnd) /* should be faster for decoding, but strangely, not verified on all platform */ +{ + const BYTE* ip = (const BYTE*)src; + BYTE* op = (BYTE*)dst; + BYTE* const oend = (BYTE*)dstEnd; + do + COPY8(op, ip) + while (op < oend); +} + + +/*-******************************************* +* Private declarations +*********************************************/ +typedef struct seqDef_s { + U32 offset; + U16 litLength; + U16 matchLength; +} seqDef; + +typedef struct { + seqDef* sequencesStart; + seqDef* sequences; + BYTE* litStart; + BYTE* lit; + BYTE* llCode; + BYTE* mlCode; + BYTE* ofCode; + size_t maxNbSeq; + size_t maxNbLit; + U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */ + U32 longLengthPos; +} seqStore_t; + +const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */ +void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */ + +/* custom memory allocation functions */ +void* ZSTD_malloc(size_t size, ZSTD_customMem customMem); +void* ZSTD_calloc(size_t size, ZSTD_customMem customMem); +void ZSTD_free(void* ptr, ZSTD_customMem customMem); + + +MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */ +{ + assert(val != 0); + { +# if defined(_MSC_VER) /* Visual */ + unsigned long r=0; + _BitScanReverse(&r, val); + return (unsigned)r; +# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ + return 31 - __builtin_clz(val); +# else /* Software version */ + static const U32 DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; + U32 v = val; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + return DeBruijnClz[(v * 0x07C4ACDDU) >> 27]; +# endif + } +} + + +/* ZSTD_invalidateRepCodes() : + * ensures next compression will not use repcodes from previous block. + * Note : only works with regular variant; + * do not use with extDict variant ! */ +void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx); /* zstdmt, adaptive_compression (shouldn't get this definition from here) */ + + +typedef struct { + blockType_e blockType; + U32 lastBlock; + U32 origSize; +} blockProperties_t; + +/*! ZSTD_getcBlockSize() : + * Provides the size of compressed block from block header `src` */ +/* Used by: decompress, fullbench (does not get its definition from here) */ +size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, + blockProperties_t* bpPtr); + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_CCOMMON_H_MODULE */ |