Changeset 770 in openpam


Ignore:
Timestamp:
Mar 6, 2014, 12:35:47 PM (7 years ago)
Author:
Dag-Erling Smørgrav
Message:

Fix base{32,64}_decode(). The former handled padding incorrectly; the
latter was derived from the former, and had a couple of copy-paste bugs
in addition to the padding bug.

Location:
trunk/lib/liboath
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/liboath/oath_base32.c

    r646 r770  
    11/*-
    2  * Copyright (c) 2013 Universitetet i Oslo
     2 * Copyright (c) 2013-2014 Universitetet i Oslo
    33 * All rights reserved.
    44 *
     
    121121        int shift;
    122122
    123         for (len = 0, bits = 0, shift = 40; ilen && *in; --ilen, ++in) {
     123        for (len = 0, bits = 0, shift = 40; ilen && *in && *in != '='; --ilen, ++in) {
    124124                if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n') {
    125125                        continue;
     
    133133                        shift -= 5;
    134134                        bits |= (uint64_t)(*in - '2' + 26) << shift;
    135                 } else if (*in == '=' &&
    136                     (shift == 30 || shift == 20 || shift == 15 || shift == 5)) {
    137                         /* hack: assume the rest of the padding is ok */
    138                         shift = 0;
     135                } else if (*in == '=') {
     136                        /* handled below */
     137                        break;
    139138                } else {
    140                         *olen = 0;
    141                         return (-1);
     139                        goto bad;
    142140                }
    143141                if (shift == 0) {
    144142                        if ((len += 5) <= *olen) {
    145                                 out[0] = (bits >> 32) & 0xff;
    146                                 out[1] = (bits >> 24) & 0xff;
    147                                 out[2] = (bits >> 16) & 0xff;
    148                                 out[3] = (bits >> 8) & 0xff;
    149                                 out[4] = bits & 0xff;
    150                                 out += 5;
     143                                *out++ = (bits >> 32) & 0xff;
     144                                *out++ = (bits >> 24) & 0xff;
     145                                *out++ = (bits >> 16) & 0xff;
     146                                *out++ = (bits >> 8) & 0xff;
     147                                *out++ = bits & 0xff;
    151148                        }
    152149                        bits = 0;
    153150                        shift = 40;
    154151                }
    155                 if (*in == '=')
     152        }
     153        if (ilen && *in == '=' &&
     154            (shift == 30 || shift == 20 || shift == 15 || shift == 5)) {
     155                /*
     156                 * Padding:
     157                 *
     158                 * 00            8 AA====== 30
     159                 * 00 00        16 AAAA==== 20
     160                 * 00 00 00     24 AAAAA=== 15
     161                 * 00 00 00 00  32 AAAAAAA= 5
     162                 *
     163                 * XXX We should check that the last few bits before the
     164                 * padding starts are zero.
     165                 */
     166                switch (shift) {
     167                case 5:
     168                        if (++len <= *olen)
     169                                *out++ = (bits >> 32) & 0xff;
     170                        bits <<= 8;
     171                case 15:
     172                        if (++len <= *olen)
     173                                *out++ = (bits >> 32) & 0xff;
     174                        bits <<= 8;
     175                case 20:
     176                        if (++len <= *olen)
     177                                *out++ = (bits >> 32) & 0xff;
     178                        bits <<= 8;
     179                case 30:
     180                        if (++len <= *olen)
     181                                *out++ = (bits >> 32) & 0xff;
     182                        bits <<= 8;
    156183                        break;
    157         }
    158         if (len > *olen) {
    159                 *olen = len;
     184                default:
     185                        goto bad;
     186                }
     187                /* consume remaining padding and whitespace */
     188                for (; ilen && *in; --ilen, ++in) {
     189                        if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n')
     190                                continue;
     191                        else if (*in == '=' && shift)
     192                                shift -= 5;
     193                        else
     194                                goto bad;
     195                }
     196        }
     197        if (ilen)
     198                goto bad;
     199        *olen = len;
     200        if (len > *olen)
    160201                return (-1);
    161         }
    162         *olen = len;
    163202        return (0);
     203bad:
     204        *olen = 0;
     205        return (-1);
    164206}
  • trunk/lib/liboath/oath_base64.c

    r646 r770  
    11/*-
    2  * Copyright (c) 2013 Universitetet i Oslo
     2 * Copyright (c) 2013-2014 Universitetet i Oslo
    33 * All rights reserved.
    44 *
     
    120120                } else if (*in >= '0' && *in <= '9') {
    121121                        shift -= 6;
    122                         bits |= (uint32_t)(*in - '2' + 52) << shift;
     122                        bits |= (uint32_t)(*in - '0' + 52) << shift;
    123123                } else if (*in == '+') {
    124124                        shift -= 6;
     
    127127                        shift -= 6;
    128128                        bits |= (uint32_t)63 << shift;
    129                 } else if (*in == '=' && (shift == 12 || shift == 6)) {
    130                         /* hack: assume the rest of the padding is ok */
    131                         shift = 0;
     129                } else if (*in == '=') {
     130                        /* handled below */
     131                        break;
    132132                } else {
    133                         *olen = 0;
    134                         return (-1);
     133                        goto bad;
    135134                }
    136135                if (shift == 0) {
    137136                        if ((len += 3) <= *olen) {
    138                                 out[1] = (bits >> 16) & 0xff;
    139                                 out[1] = (bits >> 8) & 0xff;
    140                                 out[2] = bits & 0xff;
    141                                 out += 3;
     137                                *out++ = (bits >> 16) & 0xff;
     138                                *out++ = (bits >> 8) & 0xff;
     139                                *out++ = bits & 0xff;
    142140                        }
    143141                        bits = 0;
    144142                        shift = 24;
    145143                }
    146                 if (*in == '=')
     144        }
     145        if (ilen && *in == '=' && (shift == 12 || shift == 6)) {
     146                /*
     147                 * Padding:
     148                 *
     149                 * 00            8 AA== 12
     150                 * 00 00        16 AAA=  6
     151                 *
     152                 * XXX We should check that the last few bits before the
     153                 * padding starts are zero.
     154                 */
     155                switch (shift) {
     156                case 6:
     157                        if (++len <= *olen)
     158                                *out++ = (bits >> 16) & 0xff;
     159                        bits <<= 8;
     160                case 12:
     161                        if (++len <= *olen)
     162                                *out++ = (bits >> 16) & 0xff;
     163                        bits <<= 8;
    147164                        break;
     165                default:
     166                        goto bad;
     167                }
     168                /* consume remaining padding and whitespace */
     169                for (; ilen && *in; --ilen, ++in) {
     170                        if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n')
     171                                continue;
     172                        else if (*in == '=' && shift)
     173                                shift -= 6;
     174                        else
     175                                goto bad;
     176                }
    148177        }
    149         if (len > *olen) {
    150                 *olen = len;
     178        if (ilen)
     179                goto bad;
     180        *olen = len;
     181        if (len > *olen)
    151182                return (-1);
    152         }
    153         *olen = len;
    154183        return (0);
     184bad:
     185        *olen = 0;
     186        return (-1);
    155187}
Note: See TracChangeset for help on using the changeset viewer.