/* Copyright 2017 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* Base-32 encoding/decoding */ #include "common.h" #include "base32.h" #include "util.h" static const unsigned char crc5_table1[] = { 0x00, 0x0E, 0x1C, 0x12, 0x11, 0x1F, 0x0D, 0x03, 0x0B, 0x05, 0x17, 0x19, 0x1A, 0x14, 0x06, 0x08 }; static const unsigned char crc5_table0[] = { 0x00, 0x16, 0x05, 0x13, 0x0A, 0x1C, 0x0F, 0x19, 0x14, 0x02, 0x11, 0x07, 0x1E, 0x08, 0x1B, 0x0D }; uint8_t crc5_sym(uint8_t sym, uint8_t previous_crc) { uint8_t tmp = sym ^ previous_crc; return crc5_table1[tmp & 0x0F] ^ crc5_table0[(tmp >> 4) & 0x0F]; } /* A-Z0-9 with I,O,0,1 removed */ const char base32_map[33] = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; /** * Decode a base32 symbol. * * @param sym Input symbol * @return The symbol value or -1 if error. */ static int decode_sym(int sym) { int i = 0; for (i = 0; i < 32; i++) { if (sym == base32_map[i]) return i; } return -1; } int base32_encode(char *dest, int destlen_chars, const void *srcbits, int srclen_bits, int add_crc_every) { const uint8_t *src = srcbits; int destlen_needed; int crc = 0, crc_count = 0; int didx = 0; int i; *dest = 0; /* Make sure destination is big enough */ destlen_needed = (srclen_bits + 4) / 5; /* Symbols before adding CRC */ if (add_crc_every) { /* Must be an exact number of groups to add CRC */ if (destlen_needed % add_crc_every) return EC_ERROR_INVAL; destlen_needed += destlen_needed / add_crc_every; } destlen_needed++; /* For terminating null */ if (destlen_chars < destlen_needed) return EC_ERROR_INVAL; for (i = 0; i < srclen_bits; i += 5) { int sym; int sidx = i / 8; int bit_offs = i % 8; if (bit_offs <= 3) { /* Entire symbol fits in that byte */ sym = src[sidx] >> (3 - bit_offs); } else { /* Use the bits we have left */ sym = src[sidx] << (bit_offs - 3); /* Use the bits from the next byte, if any */ if (i + 1 < srclen_bits) sym |= src[sidx + 1] >> (11 - bit_offs); } sym &= 0x1f; /* Pad incomplete symbol with 0 bits */ if (srclen_bits - i < 5) sym &= 0x1f << (5 + i - srclen_bits); dest[didx++] = base32_map[sym]; /* Add CRC if needed */ if (add_crc_every) { crc = crc5_sym(sym, crc); if (++crc_count == add_crc_every) { dest[didx++] = base32_map[crc]; crc_count = crc = 0; } } } /* Terminate string and return */ dest[didx] = 0; return EC_SUCCESS; } int base32_decode(uint8_t *dest, int destlen_bits, const char *src, int crc_after_every) { int crc = 0, crc_count = 0; int out_bits = 0; for (; *src; src++) { int sym, sbits, dbits, b; if (isspace(*src) || *src == '-') continue; sym = decode_sym(*src); if (sym < 0) return -1; /* Bad input symbol */ /* Check CRC if needed */ if (crc_after_every) { if (crc_count == crc_after_every) { if (crc != sym) return -1; crc_count = crc = 0; continue; } else { crc = crc5_sym(sym, crc); crc_count++; } } /* * Stop if we're out of space. Have to do this after checking * the CRC, or we might not check the last CRC. */ if (out_bits >= destlen_bits) break; /* See how many bits we get to use from this symbol */ sbits = MIN(5, destlen_bits - out_bits); if (sbits < 5) sym >>= (5 - sbits); /* Fill up the rest of the current byte */ dbits = 8 - (out_bits & 7); b = MIN(dbits, sbits); if (dbits == 8) dest[out_bits / 8] = 0; /* Starting a new byte */ dest[out_bits / 8] |= (sym << (dbits - b)) >> (sbits - b); out_bits += b; sbits -= b; /* Start the next byte if there's space */ if (sbits > 0) { dest[out_bits / 8] = sym << (8 - sbits); out_bits += sbits; } } /* If we have CRCs, should have a full group */ if (crc_after_every && crc_count) return -1; return out_bits; }