/** * oath_base32_encode: * @in: input string with binary data of length @inlen * @inlen: length of input data @in * @out: pointer to newly allocated output string of length @outlen, or NULL * @outlen: pointer to output variable holding length of @out, or NULL * * Encode binary data into a string with base32 data. * * The @in parameter should contain @inlen bytes of data to encode. * The function allocates a new string in *@out to hold the encoded * data, and sets *@outlen to the length of the data. The output * string *@out is zero-terminated (ASCII NUL), but the NUL is not * counted in *@outlen. * * If @out is NULL, then *@outlen will be set to what would have been * the length of *@out on successful encoding. * * If the caller is not interested in knowing the length of the output * data @out, then @outlen may be set to NULL. * * It is permitted but useless to have both @out and @outlen NULL. * * Returns: On success %OATH_OK (zero) is returned, * %OATH_BASE32_OVERFLOW is returned if the output would be too large * to store, and %OATH_MALLOC_ERROR is returned on memory allocation * errors. * * Since: 1.12.0 **/ int oath_base32_encode (const char *in, size_t inlen, char **out, size_t * outlen) { char *tmp; size_t len = base32_encode_alloc (in, inlen, &tmp); if (len == 0 && tmp == NULL) return OATH_BASE32_OVERFLOW; else if (tmp == NULL) return OATH_MALLOC_ERROR; if (outlen) *outlen = len; if (out) *out = tmp; else free (tmp); return OATH_OK; }
int main (void) { const char *in = "abcdefghijklmnop"; const char *b32in = "MFRGGZDFMZTWQ2LKNNWG23TPOA======"; char out[255]; size_t len; bool ok; char *p; memset (out, 0x42, sizeof (out)); base32_encode (in, 0, out, 0); ASSERT (out[0] == '\x42'); memset (out, 0x42, sizeof (out)); base32_encode (in, 1, out, 10); ASSERT (memcmp (out, "ME======", 1) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 1, out, 2); ASSERT (memcmp (out, "ME======", 2) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 1, out, 3); ASSERT (memcmp (out, "ME======", 3) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 1, out, 4); ASSERT (memcmp (out, "ME======", 4) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 1, out, 8); ASSERT (memcmp (out, "ME======", 8) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 2, out, 8); ASSERT (memcmp (out, "MFRA====", 8) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 3, out, 8); ASSERT (memcmp (out, "MFRGG===", 8) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 4, out, 8); ASSERT (memcmp (out, "MFRGGZA=", 8) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 5, out, 8); ASSERT (memcmp (out, "MFRGGZDF", 8) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 6, out, 16); ASSERT (memcmp (out, "MFRGGZDFMY======", 16) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 6, out, 100); ASSERT (memcmp (out, "MFRGGZDFMY======", 16) == 0); /* Decode. */ memset (out, 0x42, sizeof (out)); len = 0; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 0); memset (out, 0x42, sizeof (out)); len = 1; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 1); ASSERT (memcmp (out, "abcdefghijklmnop", 1) == 0); memset (out, 0x42, sizeof (out)); len = 2; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 2); ASSERT (memcmp (out, "abcdefghijklmnop", 2) == 0); memset (out, 0x42, sizeof (out)); len = 3; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 3); ASSERT (memcmp (out, "abcdefghijklmnop", 3) == 0); memset (out, 0x42, sizeof (out)); len = 4; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 4); ASSERT (memcmp (out, "abcdefghijklmnop", 4) == 0); memset (out, 0x42, sizeof (out)); len = 5; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 5); ASSERT (memcmp (out, "abcdefghijklmnop", 5) == 0); memset (out, 0x42, sizeof (out)); len = 6; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 5); ASSERT (memcmp (out, "abcdefghijklmnop", 5) == 0); memset (out, 0x42, sizeof (out)); len = 100; ok = base32_decode (b32in, strlen (b32in), out, &len); ASSERT (ok); ASSERT (len == 16); ASSERT (memcmp (out, "abcdefghijklmnop", 16) == 0); /* Allocating encode */ len = base32_encode_alloc (in, strlen (in), &p); ASSERT (len == 32); ASSERT (strcmp (p, "MFRGGZDFMZTWQ2LKNNWG23TPOA======") == 0); free (p); len = base32_encode_alloc (in, SIZE_MAX - 5, &p); ASSERT (len == 0); /* Decode context function */ { struct base32_decode_context ctx; base32_decode_ctx_init (&ctx); len = sizeof (out); ok = base32_decode_ctx (&ctx, b32in, strlen (b32in), out, &len); ASSERT (ok); ASSERT (len == 16); ASSERT (memcmp (out, "abcdefghijklmnop", len) == 0); } /* Allocating decode context function */ ok = base32_decode_alloc_ctx (NULL, b32in, strlen (b32in), &p, &len); ASSERT (ok); ASSERT (len == 16); ASSERT (memcmp (out, "abcdefghijklmnop", len) == 0); free (p); { struct base32_decode_context ctx; const char *newlineb32 = "MFRG\nGZDFMZTWQ2LKNNW\nG23TPOA======"; base32_decode_ctx_init (&ctx); ok = base32_decode_alloc_ctx (&ctx, newlineb32, strlen (newlineb32), &p, &len); ASSERT (ok); ASSERT (len == strlen (in)); ASSERT (memcmp (p, in, len) == 0); free (p); } { struct base32_decode_context ctx; base32_decode_ctx_init (&ctx); ok = base32_decode_alloc_ctx (&ctx, "MFRGGZDFM\nZTWQ2LK", 17, &p, &len); ASSERT (ok); ASSERT (len == 10); ASSERT (memcmp (p, "abcdefghij", len) == 0); free (p); base32_decode_ctx_init (&ctx); ok = base32_decode_alloc_ctx (&ctx, "MF\n", 3, &p, &len); ASSERT (ok); ASSERT (len == 0); free (p); ok = base32_decode_alloc_ctx (&ctx, "RGGZDFMZ", 8, &p, &len); ASSERT (ok); ASSERT (len == 5); ASSERT (memcmp (p, "abcde", len) == 0); free (p); ok = base32_decode_alloc_ctx (&ctx, "TWQ2LK", 6, &p, &len); ASSERT (ok); ASSERT (len == 5); ASSERT (memcmp (p, "fghij", len) == 0); free (p); ok = base32_decode_alloc_ctx (&ctx, "", 0, &p, &len); ASSERT (ok); free (p); } { struct base32_decode_context ctx; const char *newlineb32 = "\n\n\n\n\n"; base32_decode_ctx_init (&ctx); ok = base32_decode_alloc_ctx (&ctx, newlineb32, strlen (newlineb32), &p, &len); ASSERT (ok); ASSERT (len == 0); free (p); } ok = base32_decode_alloc_ctx (NULL, " ! ", 3, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "ABC\nDEF", 7, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AA", 2, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AA=", 3, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AABBAAxx", 8, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AABBAA=X", 8, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AABBAA=X", 8, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AABBAA=A", 8, &p, &len); ASSERT (!ok); return 0; }